diff --git a/packages/cohesive_element.cmake b/packages/cohesive_element.cmake
index da63bcf54..de704fb3e 100644
--- a/packages/cohesive_element.cmake
+++ b/packages/cohesive_element.cmake
@@ -1,135 +1,139 @@
 #===============================================================================
 # @file   cohesive_element.cmake
 #
 # @author Mauro Corrado <mauro.corrado@epfl.ch>
 # @author Nicolas Richart <nicolas.richart@epfl.ch>
 # @author Marco Vocialta <marco.vocialta@epfl.ch>
 #
 # @date creation: Tue Oct 16 2012
 # @date last modification: Tue Jan 12 2016
 #
 # @brief  package description for cohesive elements
 #
 # @section LICENSE
 #
 # Copyright (©)  2010-2012, 2014,  2015 EPFL  (Ecole Polytechnique  Fédérale de
 # Lausanne)  Laboratory (LSMS  -  Laboratoire de  Simulation  en Mécanique  des
 # Solides)
 #
 # Akantu is free  software: you can redistribute it and/or  modify it under the
 # terms  of the  GNU Lesser  General Public  License as  published by  the Free
 # Software Foundation, either version 3 of the License, or (at your option) any
 # later version.
 #
 # Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 # A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
 # details.
 #
 # You should  have received  a copy  of the GNU  Lesser General  Public License
 # along with Akantu. If not, see <http://www.gnu.org/licenses/>.
 #
 #===============================================================================
 
 package_declare(cohesive_element
   DESCRIPTION "Use cohesive_element package of Akantu"
   DEPENDS lapack solid_mechanics)
 
 package_declare_sources(cohesive_element
   fe_engine/cohesive_element.hh
   fe_engine/fe_engine_template_cohesive.cc
   fe_engine/shape_cohesive.hh
   fe_engine/shape_cohesive_inline_impl.cc
 
   mesh_utils/cohesive_element_inserter.cc
   mesh_utils/cohesive_element_inserter.hh
   mesh_utils/cohesive_element_inserter_inline_impl.cc
   mesh_utils/cohesive_element_inserter_parallel.cc
 
   model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/fragment_manager.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh
 
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.hh
-  model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc
+  model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_tmpl.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
+  model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_coulomb.cc
+  model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_coulomb.hh
+  model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_slipweakening.cc
+  model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_slipweakening.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.hh
 
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_includes.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_inline_impl.cc
 
   model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.hh
   model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.cc
   model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc
   )
 
 
 package_declare_elements(cohesive_element
   ELEMENT_TYPES
   _cohesive_1d_2
   _cohesive_2d_4
   _cohesive_2d_6
   _cohesive_3d_12
   _cohesive_3d_16
   _cohesive_3d_6
   _cohesive_3d_8
   KIND cohesive
   GEOMETRICAL_TYPES
   _gt_cohesive_1d_2
   _gt_cohesive_2d_4
   _gt_cohesive_2d_6
   _gt_cohesive_3d_12
   _gt_cohesive_3d_16
   _gt_cohesive_3d_6
   _gt_cohesive_3d_8
   FE_ENGINE_LISTS
   compute_normals_on_integration_points
   contains
   get_shapes_derivatives
   gradient_on_integration_points
   interpolate_on_integration_points
   inverse_map
   lagrange_base
   )
 
 package_declare_material_infos(cohesive_element
   LIST AKANTU_COHESIVE_MATERIAL_LIST
   INCLUDE material_cohesive_includes.hh
   )
 
 
 package_declare_documentation_files(cohesive_element
   manual-cohesive_elements.tex
   manual-cohesive_elements_insertion.tex
   manual-cohesive_laws.tex
   manual-appendix-materials-cohesive.tex
 
   figures/cohesive2d.pdf
   figures/cohesive_exponential.pdf
   figures/linear_cohesive_law.pdf
   figures/bilinear_cohesive_law.pdf
   )
 
 package_declare_documentation(cohesive_element
   "This package activates the cohesive elements engine within Akantu."
   "It depends on:"
   "\\begin{itemize}"
   "  \\item A fortran compiler."
   "  \\item An implementation of BLAS/LAPACK."
   "\\end{itemize}"
   )
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc
index c3f4c5a98..d6ec686f0 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc
@@ -1,422 +1,461 @@
 /**
  * @file   material_cohesive_linear.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Feb 22 2012
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
  * random stress definition for extrinsic type
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_cohesive_linear.hh"
 #include "dof_synchronizer.hh"
 #include "solid_mechanics_model_cohesive.hh"
 #include "sparse_matrix.hh"
 /* -------------------------------------------------------------------------- */
 #include <algorithm>
 #include <numeric>
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 MaterialCohesiveLinear<spatial_dimension>::MaterialCohesiveLinear(
     SolidMechanicsModel & model, const ID & id)
     : MaterialCohesive(model, id), sigma_c_eff("sigma_c_eff", *this),
       delta_c_eff("delta_c_eff", *this),
-      insertion_stress("insertion_stress", *this) {
+      insertion_stress("insertion_stress", *this),
+      insertion_compression("insertion_compression", *this) {
   AKANTU_DEBUG_IN();
 
   this->registerParam("beta", beta, Real(0.), _pat_parsable | _pat_readable,
                       "Beta parameter");
 
   this->registerParam("G_c", G_c, Real(0.), _pat_parsable | _pat_readable,
                       "Mode I fracture energy");
 
   this->registerParam("penalty", penalty, Real(0.),
                       _pat_parsable | _pat_readable, "Penalty coefficient");
 
   this->registerParam("volume_s", volume_s, Real(0.),
                       _pat_parsable | _pat_readable,
                       "Reference volume for sigma_c scaling");
 
   this->registerParam("m_s", m_s, Real(1.), _pat_parsable | _pat_readable,
                       "Weibull exponent for sigma_c scaling");
 
   this->registerParam("kappa", kappa, Real(1.), _pat_parsable | _pat_readable,
                       "Kappa parameter");
 
   this->registerParam(
-      "contact_after_breaking", contact_after_breaking, false,
+      "contact_after_breaking", contact_after_breaking, true,
       _pat_parsable | _pat_readable,
       "Activation of contact when the elements are fully damaged");
 
   this->registerParam("max_quad_stress_insertion", max_quad_stress_insertion,
                       false, _pat_parsable | _pat_readable,
                       "Insertion of cohesive element when stress is high "
                       "enough just on one quadrature point");
 
   this->registerParam("recompute", recompute, false,
                       _pat_parsable | _pat_modifiable, "recompute solution");
 
   this->use_previous_delta_max = true;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::initMaterial() {
   AKANTU_DEBUG_IN();
 
   MaterialCohesive::initMaterial();
 
   sigma_c_eff.initialize(1);
   delta_c_eff.initialize(1);
   insertion_stress.initialize(spatial_dimension);
+  insertion_compression.initialize(spatial_dimension);
 
   if (not Math::are_float_equal(delta_c, 0.))
     delta_c_eff.setDefaultValue(delta_c);
   else
     delta_c_eff.setDefaultValue(2 * G_c / sigma_c);
 
   if (model->getIsExtrinsic())
     scaleInsertionTraction();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::updateInternalParameters() {
   /// compute scalars
   beta2_kappa2 = beta * beta / kappa / kappa;
   beta2_kappa = beta * beta / kappa;
 
   if (Math::are_float_equal(beta, 0))
     beta2_inv = 0;
   else
     beta2_inv = 1. / beta / beta;
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::scaleInsertionTraction() {
   AKANTU_DEBUG_IN();
 
   // do nothing if volume_s hasn't been specified by the user
   if (Math::are_float_equal(volume_s, 0.))
     return;
 
   const Mesh & mesh_facets = model->getMeshFacets();
   const auto & fe_engine = model->getFEEngine();
   const auto & fe_engine_facet = model->getFEEngine("FacetsFEEngine");
 
   Real base_sigma_c = sigma_c;
 
   for (auto && type_facet : mesh_facets.elementTypes(spatial_dimension - 1)) {
     const Array<std::vector<Element>> & facet_to_element =
         mesh_facets.getElementToSubelement(type_facet);
 
     UInt nb_facet = facet_to_element.size();
     UInt nb_quad_per_facet = fe_engine_facet.getNbIntegrationPoints(type_facet);
 
     // iterator to modify sigma_c for all the quadrature points of a facet
     auto sigma_c_iterator =
         sigma_c(type_facet).begin_reinterpret(nb_quad_per_facet, nb_facet);
 
     for (UInt f = 0; f < nb_facet; ++f, ++sigma_c_iterator) {
 
       const std::vector<Element> & element_list = facet_to_element(f);
 
       // compute bounding volume
       Real volume = 0;
 
       auto elem = element_list.begin();
       auto elem_end = element_list.end();
 
       for (; elem != elem_end; ++elem) {
         if (*elem == ElementNull)
           continue;
 
         // unit vector for integration in order to obtain the volume
         UInt nb_quadrature_points =
             fe_engine.getNbIntegrationPoints(elem->type);
         Vector<Real> unit_vector(nb_quadrature_points, 1);
 
         volume += fe_engine.integrate(unit_vector, elem->type, elem->element,
                                       elem->ghost_type);
       }
 
       // scale sigma_c
       *sigma_c_iterator -= base_sigma_c;
       *sigma_c_iterator *= std::pow(volume_s / volume, 1. / m_s);
       *sigma_c_iterator += base_sigma_c;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::checkInsertion(
     bool check_only) {
   AKANTU_DEBUG_IN();
 
-  const Mesh & mesh_facets = model->getMeshFacets();
-  CohesiveElementInserter & inserter = model->getElementInserter();
+  // get mesh and inserter
+  Mesh & mesh = this->model->getMesh();
+  const Mesh & mesh_facets = this->model->getMeshFacets();
+  CohesiveElementInserter & inserter = this->model->getElementInserter();
+
+  // get nodal fields
+  auto & shift = mesh.getNodalData<Real>("shift", spatial_dimension);
+  shift.resize(mesh.getNbNodes());
 
   for (auto && type_facet : mesh_facets.elementTypes(spatial_dimension - 1)) {
     ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
     const auto & facets_check = inserter.getCheckFacets(type_facet);
     auto & f_insertion = inserter.getInsertionFacets(type_facet);
     auto & f_filter = facet_filter(type_facet);
     auto & sig_c_eff = sigma_c_eff(type_cohesive);
     auto & del_c = delta_c_eff(type_cohesive);
     auto & ins_stress = insertion_stress(type_cohesive);
+    auto & ins_comp = insertion_compression(type_cohesive);
     auto & trac_old = tractions.previous(type_cohesive);
     const auto & f_stress = model->getStressOnFacets(type_facet);
     const auto & sigma_lim = sigma_c(type_facet);
+    const auto & connectivity = mesh_facets.getConnectivity(type_facet);
+    auto conn_it = make_view(connectivity, connectivity.getNbComponent()).begin();
 
     UInt nb_quad_facet =
         model->getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
 
 #ifndef AKANTU_NDEBUG
     UInt nb_quad_cohesive = model->getFEEngine("CohesiveFEEngine")
                                 .getNbIntegrationPoints(type_cohesive);
 
     AKANTU_DEBUG_ASSERT(nb_quad_cohesive == nb_quad_facet,
                         "The cohesive element and the corresponding facet do "
                         "not have the same numbers of integration points");
 #endif
 
     UInt nb_facet = f_filter.size();
     //  if (nb_facet == 0) continue;
 
     auto sigma_lim_it = sigma_lim.begin();
 
     Matrix<Real> stress_tmp(spatial_dimension, spatial_dimension);
     Matrix<Real> normal_traction(spatial_dimension, nb_quad_facet);
+    Matrix<Real> normal_compression(spatial_dimension, nb_quad_facet);
     Vector<Real> stress_check(nb_quad_facet);
     UInt sp2 = spatial_dimension * spatial_dimension;
 
     const auto & tangents = model->getTangents(type_facet);
     const auto & normals = model->getFEEngine("FacetsFEEngine")
                                .getNormalsOnIntegrationPoints(type_facet);
     auto normal_begin = normals.begin(spatial_dimension);
     auto tangent_begin = tangents.begin(tangents.getNbComponent());
     auto facet_stress_begin =
         f_stress.begin(spatial_dimension, spatial_dimension * 2);
 
     std::vector<Real> new_sigmas;
     std::vector<Vector<Real>> new_normal_traction;
+    std::vector<Vector<Real>> new_normal_compression;
     std::vector<Real> new_delta_c;
 
     // loop over each facet belonging to this material
     for (UInt f = 0; f < nb_facet; ++f, ++sigma_lim_it) {
       UInt facet = f_filter(f);
       // skip facets where check shouldn't be realized
       if (!facets_check(facet))
         continue;
 
       // compute the effective norm on each quadrature point of the facet
+      Vector<Real> avg_compression(spatial_dimension);
       for (UInt q = 0; q < nb_quad_facet; ++q) {
         UInt current_quad = facet * nb_quad_facet + q;
         const Vector<Real> & normal = normal_begin[current_quad];
         const Vector<Real> & tangent = tangent_begin[current_quad];
         const Matrix<Real> & facet_stress_it = facet_stress_begin[current_quad];
 
         // compute average stress on the current quadrature point
         Matrix<Real> stress_1(facet_stress_it.storage(), spatial_dimension,
                               spatial_dimension);
 
         Matrix<Real> stress_2(facet_stress_it.storage() + sp2,
                               spatial_dimension, spatial_dimension);
 
         stress_tmp.copy(stress_1);
         stress_tmp += stress_2;
         stress_tmp /= 2.;
 
         Vector<Real> normal_traction_vec(normal_traction(q));
-
         // compute normal and effective stress
         stress_check(q) = computeEffectiveNorm(stress_tmp, normal, tangent,
                                                normal_traction_vec);
+        // compute compression
+        normal_compression(q) = normal;
+        normal_compression(q) *= std::min(0., normal_traction_vec.dot(normal));
+        avg_compression += std::min(0., normal_traction_vec.dot(normal))*normal;
+        // remove compression from traction
+        normal_traction_vec -=
+                           std::min(0., normal_traction_vec.dot(normal))*normal;
       }
+      avg_compression /= nb_quad_facet;
 
       // verify if the effective stress overcomes the threshold
       Real final_stress = stress_check.mean();
       if (max_quad_stress_insertion)
         final_stress = *std::max_element(
             stress_check.storage(), stress_check.storage() + nb_quad_facet);
 
       if (final_stress > *sigma_lim_it) {
         f_insertion(facet) = true;
 
         if (check_only)
           continue;
 
         // store the new cohesive material parameters for each quadrature
         // point
         for (UInt q = 0; q < nb_quad_facet; ++q) {
           Real new_sigma = stress_check(q);
           Vector<Real> normal_traction_vec(normal_traction(q));
 
-          if (spatial_dimension != 3)
+          if (spatial_dimension != 3) {
             normal_traction_vec *= -1.;
-
+            normal_compression(q) *= -1.;
+          }
           new_sigmas.push_back(new_sigma);
           new_normal_traction.push_back(normal_traction_vec);
+          new_normal_compression.push_back(normal_compression(q));
 
           Real new_delta;
 
           // set delta_c in function of G_c or a given delta_c value
           if (Math::are_float_equal(delta_c, 0.))
             new_delta = 2 * G_c / new_sigma;
           else
             new_delta = (*sigma_lim_it) / new_sigma * delta_c;
 
           new_delta_c.push_back(new_delta);
         }
+        if (spatial_dimension != 3)
+          avg_compression *= -1.;
+
+        // set initial interpenetration in case of compression
+        Vector<UInt> conn = conn_it[f];
+  			for (auto && node : conn) {
+          for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+            shift(node, dim) = avg_compression(dim) / this->penalty;
+          }
+  			}
       }
     }
 
     // update material data for the new elements
     UInt old_nb_quad_points = sig_c_eff.size();
     UInt new_nb_quad_points = new_sigmas.size();
     sig_c_eff.resize(old_nb_quad_points + new_nb_quad_points);
     ins_stress.resize(old_nb_quad_points + new_nb_quad_points);
+    ins_comp.resize(old_nb_quad_points + new_nb_quad_points);
     trac_old.resize(old_nb_quad_points + new_nb_quad_points);
     del_c.resize(old_nb_quad_points + new_nb_quad_points);
 
     for (UInt q = 0; q < new_nb_quad_points; ++q) {
       sig_c_eff(old_nb_quad_points + q) = new_sigmas[q];
       del_c(old_nb_quad_points + q) = new_delta_c[q];
       for (UInt dim = 0; dim < spatial_dimension; ++dim) {
         ins_stress(old_nb_quad_points + q, dim) = new_normal_traction[q](dim);
+        ins_comp(old_nb_quad_points + q, dim) = new_normal_compression[q](dim);
         trac_old(old_nb_quad_points + q, dim) = new_normal_traction[q](dim);
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::computeTraction(
     const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   auto traction_it = tractions(el_type, ghost_type).begin(spatial_dimension);
   auto opening_it = opening(el_type, ghost_type).begin(spatial_dimension);
   auto contact_traction_it =
       contact_tractions(el_type, ghost_type).begin(spatial_dimension);
   auto contact_opening_it =
       contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   auto normal_it = normal.begin(spatial_dimension);
   auto traction_end = tractions(el_type, ghost_type).end(spatial_dimension);
   auto sigma_c_it = sigma_c_eff(el_type, ghost_type).begin();
   auto delta_max_it = delta_max(el_type, ghost_type).begin();
   auto delta_c_it = delta_c_eff(el_type, ghost_type).begin();
   auto damage_it = damage(el_type, ghost_type).begin();
   auto insertion_stress_it =
       insertion_stress(el_type, ghost_type).begin(spatial_dimension);
+  auto insertion_compression_it =
+      insertion_compression(el_type, ghost_type).begin(spatial_dimension);
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   /// loop on each quadrature point
   for (; traction_it != traction_end;
        ++traction_it, ++opening_it, ++normal_it, ++sigma_c_it, ++delta_max_it,
        ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it,
        ++contact_opening_it) {
 
     Real normal_opening_norm, tangential_opening_norm;
     bool penetration;
+
     this->computeTractionOnQuad(
         *traction_it, *opening_it, *normal_it, *delta_max_it, *delta_c_it,
-        *insertion_stress_it, *sigma_c_it, normal_opening, tangential_opening,
-        normal_opening_norm, tangential_opening_norm, *damage_it, penetration,
+        *insertion_stress_it, *insertion_compression_it, *sigma_c_it,
+        normal_opening, tangential_opening, normal_opening_norm,
+        tangential_opening_norm, *damage_it, penetration,
         *contact_traction_it, *contact_opening_it);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt spatial_dimension>
 void MaterialCohesiveLinear<spatial_dimension>::computeTangentTraction(
     const ElementType & el_type, Array<Real> & tangent_matrix,
     const Array<Real> & normal, GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   /// define iterators
   auto tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension);
 
   auto tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension);
 
   auto normal_it = normal.begin(spatial_dimension);
 
   auto opening_it = opening(el_type, ghost_type).begin(spatial_dimension);
 
   /// NB: delta_max_it points on delta_max_previous, i.e. the
   /// delta_max related to the solution of the previous incremental
   /// step
   auto delta_max_it = delta_max.previous(el_type, ghost_type).begin();
   auto sigma_c_it = sigma_c_eff(el_type, ghost_type).begin();
   auto delta_c_it = delta_c_eff(el_type, ghost_type).begin();
   auto damage_it = damage(el_type, ghost_type).begin();
   auto contact_opening_it =
       contact_opening(el_type, ghost_type).begin(spatial_dimension);
 
   Vector<Real> normal_opening(spatial_dimension);
   Vector<Real> tangential_opening(spatial_dimension);
 
   for (; tangent_it != tangent_end; ++tangent_it, ++normal_it, ++opening_it,
                                     ++delta_max_it, ++sigma_c_it, ++delta_c_it,
                                     ++damage_it, ++contact_opening_it) {
 
     Real normal_opening_norm, tangential_opening_norm;
     bool penetration;
     this->computeTangentTractionOnQuad(
         *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it,
         *normal_it, normal_opening, tangential_opening, normal_opening_norm,
         tangential_opening_norm, *damage_it, penetration, *contact_opening_it);
   }
 
   AKANTU_DEBUG_OUT();
 }
 /* -------------------------------------------------------------------------- */
 
 INSTANTIATE_MATERIAL(cohesive_linear, MaterialCohesiveLinear);
 
 } // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh
index a954a6953..05e5e5dad 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh
@@ -1,188 +1,191 @@
 /**
  * @file   material_cohesive_linear.hh
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
  * random stress definition for extrinsic type
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_cohesive.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__
 #define __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__
 
 namespace akantu {
 
 /**
  * Cohesive material linear damage for extrinsic case
  *
  * parameters in the material files :
  *   - sigma_c   : critical stress sigma_c  (default: 0)
  *   - beta      : weighting parameter for sliding and normal opening (default:
  * 0)
  *   - G_cI      : fracture energy for mode I (default: 0)
  *   - G_cII     : fracture energy for mode II (default: 0)
  *   - penalty   : stiffness in compression to prevent penetration
  */
 template <UInt spatial_dimension>
 class MaterialCohesiveLinear : public MaterialCohesive {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   MaterialCohesiveLinear(SolidMechanicsModel & model, const ID & id = "");
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the material parameters
   void initMaterial() override;
 
   void updateInternalParameters() override;
 
   /// check stress for cohesive elements' insertion
   void checkInsertion(bool check_only = false) override;
 
   /// compute effective stress norm for insertion check
   Real computeEffectiveNorm(const Matrix<Real> & stress,
                             const Vector<Real> & normal,
                             const Vector<Real> & tangent,
                             Vector<Real> & normal_stress) const;
 
 protected:
   /// constitutive law
   void computeTraction(const Array<Real> & normal, ElementType el_type,
                        GhostType ghost_type = _not_ghost) override;
 
   /// compute tangent stiffness matrix
   void computeTangentTraction(const ElementType & el_type,
                               Array<Real> & tangent_matrix,
                               const Array<Real> & normal,
                               GhostType ghost_type) override;
 
   /**
    * Scale insertion traction sigma_c according to the volume of the
    * two elements surrounding a facet
    *
    * see the article: F. Zhou and J. F. Molinari "Dynamic crack
    * propagation with cohesive elements: a methodology to address mesh
    * dependency" International Journal for Numerical Methods in
    * Engineering (2004)
    */
   void scaleInsertionTraction();
 
   /// compute the traction for a given quadrature point
   inline void computeTractionOnQuad(
       Vector<Real> & traction, Vector<Real> & opening,
       const Vector<Real> & normal, Real & delta_max, const Real & delta_c,
-      const Vector<Real> & insertion_stress, const Real & sigma_c,
+      const Vector<Real> & insertion_stress,
+      const Vector<Real> & insertion_compression, const Real & sigma_c,
       Vector<Real> & normal_opening, Vector<Real> & tangential_opening,
-      Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage,
-      bool & penetration, Vector<Real> & contact_traction,
+      Real & normal_opening_norm, Real & tangential_opening_norm,
+      Real & damage, bool & penetration, Vector<Real> & contact_traction,
       Vector<Real> & contact_opening);
 
   inline void computeTangentTractionOnQuad(
       Matrix<Real> & tangent, Real & delta_max, const Real & delta_c,
       const Real & sigma_c, Vector<Real> & opening, const Vector<Real> & normal,
       Vector<Real> & normal_opening, Vector<Real> & tangential_opening,
       Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage,
       bool & penetration, Vector<Real> & contact_opening);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// get sigma_c_eff
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(InsertionTraction, sigma_c_eff, Real);
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// beta parameter
   Real beta;
 
   /// beta square inverse to compute effective norm
   Real beta2_inv;
 
   /// mode I fracture energy
   Real G_c;
 
   /// kappa parameter
   Real kappa;
 
   /// constitutive law scalar to compute delta
   Real beta2_kappa2;
 
   /// constitutive law scalar to compute traction
   Real beta2_kappa;
 
   /// penalty coefficient
   Real penalty;
 
   /// reference volume used to scale sigma_c
   Real volume_s;
 
   /// weibull exponent used to scale sigma_c
   Real m_s;
 
   /// variable defining if we are recomputing the last loading step
   /// after load_reduction
   bool recompute;
 
   /// critical effective stress
   RandomInternalField<Real, CohesiveInternalField> sigma_c_eff;
 
   /// effective critical displacement (each element can have a
   /// different value)
   CohesiveInternalField<Real> delta_c_eff;
 
   /// stress at insertion
   CohesiveInternalField<Real> insertion_stress;
+  /// compression at insertion
+  CohesiveInternalField<Real> insertion_compression;
 
   /// variable saying if there should be penalty contact also after
   /// breaking the cohesive elements
   bool contact_after_breaking;
 
   /// insertion of cohesive element when stress is high enough just on
   /// one quadrature point
   bool max_quad_stress_insertion;
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 } // namespace akantu
 
 #include "material_cohesive_linear_inline_impl.cc"
 
 #endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc
deleted file mode 100644
index eec417b08..000000000
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc
+++ /dev/null
@@ -1,277 +0,0 @@
-/**
- * @file   material_cohesive_linear_friction.cc
- *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- *
- * @date creation: Tue Jan 12 2016
- * @date last modification: Wed Feb 21 2018
- *
- * @brief  Linear irreversible cohesive law of mixed mode loading with
- * random stress definition for extrinsic type
- *
- * @section LICENSE
- *
- * Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * Akantu is free  software: you can redistribute it and/or  modify it under the
- * terms  of the  GNU Lesser  General Public  License as published by  the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
- * details.
- *
- * You should  have received  a copy  of the GNU  Lesser General  Public License
- * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-#include "material_cohesive_linear_friction.hh"
-#include "solid_mechanics_model_cohesive.hh"
-
-namespace akantu {
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-MaterialCohesiveLinearFriction<spatial_dimension>::
-    MaterialCohesiveLinearFriction(SolidMechanicsModel & model, const ID & id)
-    : MaterialParent(model, id), residual_sliding("residual_sliding", *this),
-      friction_force("friction_force", *this) {
-  AKANTU_DEBUG_IN();
-
-  this->registerParam("mu", mu_max, Real(0.), _pat_parsable | _pat_readable,
-                      "Maximum value of the friction coefficient");
-
-  this->registerParam("penalty_for_friction", friction_penalty, Real(0.),
-                      _pat_parsable | _pat_readable,
-                      "Penalty parameter for the friction behavior");
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearFriction<spatial_dimension>::initMaterial() {
-  AKANTU_DEBUG_IN();
-
-  MaterialParent::initMaterial();
-
-  friction_force.initialize(spatial_dimension);
-  residual_sliding.initialize(1);
-  residual_sliding.initializeHistory();
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearFriction<spatial_dimension>::computeTraction(
-    __attribute__((unused)) const Array<Real> & normal, ElementType el_type,
-    GhostType ghost_type) {
-  AKANTU_DEBUG_IN();
-
-  residual_sliding.resize();
-  friction_force.resize();
-
-  /// define iterators
-  auto traction_it =
-      this->tractions(el_type, ghost_type).begin(spatial_dimension);
-  auto traction_end =
-      this->tractions(el_type, ghost_type).end(spatial_dimension);
-  auto opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension);
-  auto previous_opening_it =
-      this->opening.previous(el_type, ghost_type).begin(spatial_dimension);
-  auto contact_traction_it =
-      this->contact_tractions(el_type, ghost_type).begin(spatial_dimension);
-  auto contact_opening_it =
-      this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
-  auto normal_it = this->normal.begin(spatial_dimension);
-  auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
-  auto delta_max_it = this->delta_max(el_type, ghost_type).begin();
-  auto delta_max_prev_it =
-      this->delta_max.previous(el_type, ghost_type).begin();
-  auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
-  auto damage_it = this->damage(el_type, ghost_type).begin();
-  auto insertion_stress_it =
-      this->insertion_stress(el_type, ghost_type).begin(spatial_dimension);
-  auto res_sliding_it = this->residual_sliding(el_type, ghost_type).begin();
-  auto res_sliding_prev_it =
-      this->residual_sliding.previous(el_type, ghost_type).begin();
-  auto friction_force_it =
-      this->friction_force(el_type, ghost_type).begin(spatial_dimension);
-
-  Vector<Real> normal_opening(spatial_dimension);
-  Vector<Real> tangential_opening(spatial_dimension);
-
-  if (not this->model->isDefaultSolverExplicit())
-    this->delta_max(el_type, ghost_type)
-        .copy(this->delta_max.previous(el_type, ghost_type));
-
-  /// loop on each quadrature point
-  for (; traction_it != traction_end;
-       ++traction_it, ++opening_it, ++normal_it, ++sigma_c_it, ++delta_max_it,
-       ++delta_c_it, ++damage_it, ++contact_traction_it, ++insertion_stress_it,
-       ++contact_opening_it, ++delta_max_prev_it, ++res_sliding_it,
-       ++res_sliding_prev_it, ++friction_force_it, ++previous_opening_it) {
-
-    Real normal_opening_norm, tangential_opening_norm;
-    bool penetration;
-    this->computeTractionOnQuad(
-        *traction_it, *opening_it, *normal_it, *delta_max_it, *delta_c_it,
-        *insertion_stress_it, *sigma_c_it, normal_opening, tangential_opening,
-        normal_opening_norm, tangential_opening_norm, *damage_it, penetration,
-        *contact_traction_it, *contact_opening_it);
-
-    if (penetration) {
-      /// the friction coefficient mu increases with the damage. It
-      /// equals the maximum value when damage = 1.
-      //      Real damage = std::min(*delta_max_prev_it / *delta_c_it,
-      //      Real(1.));
-      Real mu = mu_max; // * damage;
-
-      /// the definition of tau_max refers to the opening
-      /// (penetration) of the previous incremental step
-      Real normal_opening_prev_norm =
-          std::min(previous_opening_it->dot(*normal_it), Real(0.));
-
-      //      Vector<Real> normal_opening_prev = (*normal_it);
-      //      normal_opening_prev *= normal_opening_prev_norm;
-      Real tau_max = mu * this->penalty * (std::abs(normal_opening_prev_norm));
-      Real delta_sliding_norm =
-          std::abs(tangential_opening_norm - *res_sliding_prev_it);
-
-      /// tau is the norm of the friction force, acting tangentially to the
-      /// surface
-      Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max);
-
-      if ((tangential_opening_norm - *res_sliding_prev_it) < 0.0)
-        tau = -tau;
-
-      /// from tau get the x and y components of friction, to be added in the
-      /// force vector
-      Vector<Real> tangent_unit_vector(spatial_dimension);
-      tangent_unit_vector = tangential_opening / tangential_opening_norm;
-      *friction_force_it = tau * tangent_unit_vector;
-
-      /// update residual_sliding
-      *res_sliding_it =
-          tangential_opening_norm - (std::abs(tau) / friction_penalty);
-    } else {
-      friction_force_it->clear();
-    }
-
-    *traction_it += *friction_force_it;
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <UInt spatial_dimension>
-void MaterialCohesiveLinearFriction<spatial_dimension>::computeTangentTraction(
-    const ElementType & el_type, Array<Real> & tangent_matrix,
-    __attribute__((unused)) const Array<Real> & normal, GhostType ghost_type) {
-  AKANTU_DEBUG_IN();
-
-  /// define iterators
-  auto tangent_it = tangent_matrix.begin(spatial_dimension, spatial_dimension);
-  auto tangent_end = tangent_matrix.end(spatial_dimension, spatial_dimension);
-
-  auto normal_it = this->normal.begin(spatial_dimension);
-
-  auto opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension);
-  auto previous_opening_it =
-      this->opening.previous(el_type, ghost_type).begin(spatial_dimension);
-
-  /**
-   * NB: delta_max_it points on delta_max_previous, i.e. the
-   * delta_max related to the solution of the previous incremental
-   * step
-   */
-  auto delta_max_it = this->delta_max.previous(el_type, ghost_type).begin();
-  auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
-  auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
-  auto damage_it = this->damage(el_type, ghost_type).begin();
-
-  auto contact_opening_it =
-      this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
-
-  auto res_sliding_prev_it =
-      this->residual_sliding.previous(el_type, ghost_type).begin();
-
-  Vector<Real> normal_opening(spatial_dimension);
-  Vector<Real> tangential_opening(spatial_dimension);
-
-  for (; tangent_it != tangent_end;
-       ++tangent_it, ++normal_it, ++opening_it, ++previous_opening_it,
-       ++delta_max_it, ++sigma_c_it, ++delta_c_it, ++damage_it,
-       ++contact_opening_it, ++res_sliding_prev_it) {
-
-    Real normal_opening_norm, tangential_opening_norm;
-    bool penetration;
-    this->computeTangentTractionOnQuad(
-        *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it,
-        *normal_it, normal_opening, tangential_opening, normal_opening_norm,
-        tangential_opening_norm, *damage_it, penetration, *contact_opening_it);
-
-    if (penetration) {
-      //      Real damage = std::min(*delta_max_it / *delta_c_it, Real(1.));
-      Real mu = mu_max; // * damage;
-
-      Real normal_opening_prev_norm =
-          std::min(previous_opening_it->dot(*normal_it), Real(0.));
-      //      Vector<Real> normal_opening_prev = (*normal_it);
-      //      normal_opening_prev *= normal_opening_prev_norm;
-
-      Real tau_max = mu * this->penalty * (std::abs(normal_opening_prev_norm));
-      Real delta_sliding_norm =
-          std::abs(tangential_opening_norm - *res_sliding_prev_it);
-
-      // tau is the norm of the friction force, acting tangentially to the
-      // surface
-      Real tau = std::min(friction_penalty * delta_sliding_norm, tau_max);
-
-      if (tau < tau_max && tau_max > Math::getTolerance()) {
-        Matrix<Real> I(spatial_dimension, spatial_dimension);
-        I.eye(1.);
-
-        Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
-        n_outer_n.outerProduct(*normal_it, *normal_it);
-
-        Matrix<Real> nn(n_outer_n);
-        I -= nn;
-        *tangent_it += I * friction_penalty;
-      }
-    }
-
-    // check if the tangential stiffness matrix is symmetric
-    //    for (UInt h = 0; h < spatial_dimension; ++h){
-    //      for (UInt l = h; l < spatial_dimension; ++l){
-    //        if (l > h){
-    //          Real k_ls = (*tangent_it)[spatial_dimension*h+l];
-    //          Real k_us =  (*tangent_it)[spatial_dimension*l+h];
-    //          //          std::cout << "k_ls = " << k_ls << std::endl;
-    //          //          std::cout << "k_us = " << k_us << std::endl;
-    //          if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){
-    //            Real error = std::abs((k_ls - k_us) / k_us);
-    //            if (error > 1e-10){
-    //	      std::cout << "non symmetric cohesive matrix" << std::endl;
-    //	      //  std::cout << "error " << error << std::endl;
-    //            }
-    //          }
-    //        }
-    //      }
-    //    }
-  }
-
-  AKANTU_DEBUG_OUT();
-}
-/* -------------------------------------------------------------------------- */
-
-INSTANTIATE_MATERIAL(cohesive_linear_friction, MaterialCohesiveLinearFriction);
-
-} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
index 780ce1922..14936e21f 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
@@ -1,105 +1,103 @@
 /**
  * @file   material_cohesive_linear_friction.hh
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
  * random stress definition for extrinsic type
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #include "material_cohesive_linear.hh"
 
 /* -------------------------------------------------------------------------- */
 #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__
 #define __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__
 
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /**
  * Cohesive material linear with friction force
  *
  * parameters in the material files :
  *   - mu   : friction coefficient
  *   - penalty_for_friction : Penalty parameter for the friction behavior
  */
 template <UInt spatial_dimension>
 class MaterialCohesiveLinearFriction
     : public MaterialCohesiveLinear<spatial_dimension> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
   using MaterialParent = MaterialCohesiveLinear<spatial_dimension>;
 
 public:
   MaterialCohesiveLinearFriction(SolidMechanicsModel & model,
                                  const ID & id = "");
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the material parameters
   void initMaterial() override;
 
 protected:
-  /// constitutive law
-  void computeTraction(const Array<Real> & normal, ElementType el_type,
-                       GhostType ghost_type = _not_ghost) override;
-
-  /// compute tangent stiffness matrix
-  void computeTangentTraction(const ElementType & el_type,
-                              Array<Real> & tangent_matrix,
-                              const Array<Real> & normal,
-                              GhostType ghost_type) override;
+  /// check stress for cohesive elements insertion
+  void checkInsertion(bool check_only = false) override;
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
-  /// maximum value of the friction coefficient
-  Real mu_max;
-
   /// penalty parameter for the friction law
   Real friction_penalty;
 
+  /// friction at insertion
+  RandomInternalField<Real, FacetInternalField> mu_insertion;
+
+  /// friction coefficient
+  CohesiveInternalField<Real> mu_eff;
+
   /// history parameter for the friction law
   CohesiveInternalField<Real> residual_sliding;
 
   /// friction force
   CohesiveInternalField<Real> friction_force;
 };
 
 } // namespace akantu
 
+#include "material_cohesive_linear_friction_tmpl.hh"
+
 #endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_coulomb.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_coulomb.cc
new file mode 100644
index 000000000..0ff6dac87
--- /dev/null
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_coulomb.cc
@@ -0,0 +1,251 @@
+/**
+ * @file   material_cohesive_linear_friction_coulomb.cc
+ *
+ * @author Mauro Corrado <mauro.corrado@epfl.ch>
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Mathias Lebihain <mathias.lebihain@epfl.ch>
+ *
+ * @date creation: Tue Jan 12 2016
+ * @date last modification: Wed Feb 21 2018
+ *
+ * @brief  Linear irreversible cohesive law of mixed mode loading with
+ * random stress definition for extrinsic type
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* -------------------------------------------------------------------------- */
+#include "material_cohesive_linear_friction_coulomb.hh"
+#include "solid_mechanics_model_cohesive.hh"
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <UInt dim>
+MaterialCohesiveLinearFrictionCoulomb<
+    dim>::MaterialCohesiveLinearFrictionCoulomb(SolidMechanicsModel & model,
+                                                const ID & id)
+    : MaterialParent(model, id) {
+  AKANTU_DEBUG_IN();
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+/** \todo Frictional contributions might be computed from the contact_tractions,
+ * and delta_max at the previous time step
+ */
+template <UInt dim>
+void MaterialCohesiveLinearFrictionCoulomb<dim>::computeTraction(
+    const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
+  AKANTU_DEBUG_IN();
+
+  Vector<Real> normal_opening(dim);
+  Vector<Real> tangential_opening(dim);
+
+  /// loop on each quadrature point
+  for (auto && data :
+       zip(make_view(this->insertion_stress(el_type, ghost_type), dim),
+           make_view(this->insertion_compression(el_type, ghost_type), dim),
+           this->sigma_c_eff(el_type, ghost_type),
+           this->delta_c_eff(el_type, ghost_type),
+           this->mu_eff(el_type, ghost_type), make_view(normal, dim),
+           this->delta_max(el_type, ghost_type),
+           this->damage(el_type, ghost_type),
+           make_view(this->tractions(el_type, ghost_type), dim),
+           make_view(this->contact_tractions(el_type, ghost_type), dim),
+           make_view(this->friction_force(el_type, ghost_type), dim),
+           make_view(this->opening(el_type, ghost_type), dim),
+           make_view(this->contact_opening(el_type, ghost_type), dim),
+           this->residual_sliding(el_type, ghost_type),
+           this->residual_sliding.previous(el_type, ghost_type))) {
+    auto && insertion_traction = std::get<0>(data);
+    auto && insertion_compression = std::get<1>(data);
+    auto && sigma_c = std::get<2>(data);
+    auto && delta_c = std::get<3>(data);
+    auto && mu = std::get<4>(data);
+    auto && normal = std::get<5>(data);
+    auto && delta_max = std::get<6>(data);
+    auto && damage = std::get<7>(data);
+    auto && traction = std::get<8>(data);
+    auto && contact_traction = std::get<9>(data);
+    auto && friction_force = std::get<10>(data);
+    auto && opening = std::get<11>(data);
+    auto && contact_opening = std::get<12>(data);
+    auto && res_sliding = std::get<13>(data);
+    auto && res_sliding_prev = std::get<14>(data);
+
+    Real normal_opening_norm, tangential_opening_norm;
+    bool penetration;
+
+    this->computeTractionOnQuad(
+        traction, opening, normal, delta_max, delta_c, insertion_traction,
+        insertion_compression, sigma_c, normal_opening, tangential_opening,
+        normal_opening_norm, tangential_opening_norm, damage, penetration,
+        contact_traction, contact_opening);
+
+    if (penetration) {
+      /// the definition of tau_max refers to
+      /// the current contact_traction computed in computeTractionOnQuad
+      Real tau_max = mu * contact_traction.norm();
+
+      // elastic sliding
+      Real delta_sliding_norm =
+          std::abs(tangential_opening_norm - res_sliding_prev);
+
+      /// tau is the norm of the friction force, acting tangentially to the
+      /// surface
+      Real tau = std::min(this->friction_penalty * delta_sliding_norm, tau_max);
+
+      if ((tangential_opening_norm - res_sliding_prev) < 0.0)
+        tau = -tau;
+
+      /// from tau get the x and y components of friction, to be added in the
+      /// force vector
+      auto tangent_unit_vector = tangential_opening / tangential_opening_norm;
+      friction_force = tau * tangent_unit_vector;
+
+      /// update residual_sliding
+      res_sliding =
+          tangential_opening_norm - (std::abs(tau) / this->friction_penalty);
+    } else {
+      friction_force.clear();
+    }
+    traction += friction_force;
+  }
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+/** \todo The frictional contribution to the tangent stiffness matrix might be
+ * missing from implicit computations
+ */
+// template <UInt dim>
+// void MaterialCohesiveLinearFrictionCoulomb<dim>::computeTangentTraction(
+//     const ElementType & el_type, Array<Real> & tangent_matrix,
+//     __attribute__((unused)) const Array<Real> & normal, GhostType ghost_type)
+//     {
+//   AKANTU_DEBUG_IN();
+//
+//   /// define iterators
+//   auto tangent_it = tangent_matrix.begin(dim, dim);
+//   auto tangent_end = tangent_matrix.end(dim, dim);
+//
+//   auto normal_it = this->normal.begin(dim);
+//
+//   auto opening_it = this->opening(el_type, ghost_type).begin(dim);
+//
+//   /**
+//    * NB: delta_max_it points on delta_max_previous, i.e. the
+//    * delta_max related to the solution of the previous incremental
+//    * step
+//    */
+//   auto delta_max_it = this->delta_max.previous(el_type, ghost_type).begin();
+//   auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
+//   auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
+//   auto damage_it = this->damage(el_type, ghost_type).begin();
+//   auto contact_traction_it =
+//       this->contact_tractions(el_type, ghost_type).begin(dim);
+//   auto contact_opening_it =
+//       this->contact_opening(el_type, ghost_type).begin(dim);
+//   auto res_sliding_prev_it =
+//       this->residual_sliding.previous(el_type, ghost_type).begin();
+//
+//   Vector<Real> normal_opening(dim);
+//   Vector<Real> tangential_opening(dim);
+//
+//   for (; tangent_it != tangent_end;
+//        ++tangent_it, ++normal_it, ++opening_it, ++delta_max_it, ++sigma_c_it,
+//        ++delta_c_it, ++damage_it, ++contact_opening_it,
+//        ++res_sliding_prev_it,
+//        ++contact_traction_it) {
+//
+//     Real normal_opening_norm, tangential_opening_norm;
+//     bool penetration;
+//
+//     this->computeTangentTractionOnQuad(
+//         *tangent_it, *delta_max_it, *delta_c_it, *sigma_c_it, *opening_it,
+//         *normal_it, normal_opening, tangential_opening, normal_opening_norm,
+//         tangential_opening_norm, *damage_it, penetration,
+//         *contact_opening_it);
+//
+//     if (penetration) {
+//       // Real damage = std::min(*delta_max_it / *delta_c_it, Real(1.));
+//       // Real mu = mu_max * damage;
+//       Real mu = mu_max;
+//
+//       // Real normal_opening_norm =
+//       //     std::min(contact_opening_it->dot(*normal_it), Real(0.));
+//       // Real tau_max = mu * this->penalty * (std::abs(normal_opening_norm));
+//
+//       Real tau_max = mu * (*contact_traction_it).norm();
+//
+//       // elastic sliding
+//       Real delta_sliding_norm =
+//           std::abs(tangential_opening_norm - *res_sliding_prev_it);
+//
+//       /// tau is the norm of the friction force, acting tangentially to the
+//       /// surface
+//       Real tau = std::min(this->friction_penalty * delta_sliding_norm,
+//       tau_max);
+//
+//       if (tau < tau_max && tau_max > Math::getTolerance()) {
+//         Matrix<Real> I(dim, dim);
+//         I.eye(1.);
+//
+//         Matrix<Real> n_outer_n(dim, dim);
+//         n_outer_n.outerProduct(*normal_it, *normal_it);
+//
+//         Matrix<Real> nn(n_outer_n);
+//         I -= nn;
+//         *tangent_it += I * this->friction_penalty;
+//       }
+//     }
+//
+//     // check if the tangential stiffness matrix is symmetric
+//     //    for (UInt h = 0; h < dim; ++h){
+//     //      for (UInt l = h; l < dim; ++l){
+//     //        if (l > h){
+//     //          Real k_ls = (*tangent_it)[dim*h+l];
+//     //          Real k_us =  (*tangent_it)[dim*l+h];
+//     //          //          std::cout << "k_ls = " << k_ls << std::endl;
+//     //          //          std::cout << "k_us = " << k_us << std::endl;
+//     //          if (std::abs(k_ls) > 1e-13 && std::abs(k_us) > 1e-13){
+//     //            Real error = std::abs((k_ls - k_us) / k_us);
+//     //            if (error > 1e-10){
+//     //	      std::cout << "non symmetric cohesive matrix" << std::endl;
+//     //	      //  std::cout << "error " << error << std::endl;
+//     //            }
+//     //          }
+//     //        }
+//     //      }
+//     //    }
+//   }
+//
+//   AKANTU_DEBUG_OUT();
+// }
+
+/* -------------------------------------------------------------------------- */
+
+INSTANTIATE_MATERIAL(cohesive_linear_friction_coulomb,
+                     MaterialCohesiveLinearFrictionCoulomb);
+
+} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_coulomb.hh
similarity index 53%
copy from src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
copy to src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_coulomb.hh
index 780ce1922..82a5f51bc 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_coulomb.hh
@@ -1,105 +1,78 @@
 /**
- * @file   material_cohesive_linear_friction.hh
+ * @file   material_cohesive_linear_friction_coulomb.hh
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Mathias Lebihain <mathias.lebihain@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
  * random stress definition for extrinsic type
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
-#include "material_cohesive_linear.hh"
+#include "material_cohesive_linear_friction.hh"
 
 /* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__
-#define __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__
+#ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_COULOMB_HH__
+#define __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_COULOMB_HH__
 
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /**
- * Cohesive material linear with friction force
- *
- * parameters in the material files :
- *   - mu   : friction coefficient
- *   - penalty_for_friction : Penalty parameter for the friction behavior
+ * Cohesive material linear with coulomb friction force
  */
 template <UInt spatial_dimension>
-class MaterialCohesiveLinearFriction
-    : public MaterialCohesiveLinear<spatial_dimension> {
+class MaterialCohesiveLinearFrictionCoulomb
+    : public MaterialCohesiveLinearFriction<spatial_dimension> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
-  using MaterialParent = MaterialCohesiveLinear<spatial_dimension>;
+  using MaterialParent = MaterialCohesiveLinearFriction<spatial_dimension>;
 
 public:
-  MaterialCohesiveLinearFriction(SolidMechanicsModel & model,
-                                 const ID & id = "");
+  MaterialCohesiveLinearFrictionCoulomb(SolidMechanicsModel & model,
+                                        const ID & id = "");
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
-public:
-  /// initialize the material parameters
-  void initMaterial() override;
-
 protected:
   /// constitutive law
   void computeTraction(const Array<Real> & normal, ElementType el_type,
                        GhostType ghost_type = _not_ghost) override;
 
-  /// compute tangent stiffness matrix
-  void computeTangentTraction(const ElementType & el_type,
-                              Array<Real> & tangent_matrix,
-                              const Array<Real> & normal,
-                              GhostType ghost_type) override;
-
-  /* ------------------------------------------------------------------------ */
-  /* Accessors                                                                */
-  /* ------------------------------------------------------------------------ */
-public:
-  /* ------------------------------------------------------------------------ */
-  /* Class Members                                                            */
-  /* ------------------------------------------------------------------------ */
-protected:
-  /// maximum value of the friction coefficient
-  Real mu_max;
-
-  /// penalty parameter for the friction law
-  Real friction_penalty;
-
-  /// history parameter for the friction law
-  CohesiveInternalField<Real> residual_sliding;
-
-  /// friction force
-  CohesiveInternalField<Real> friction_force;
+  // /// compute tangent stiffness matrix
+  // void computeTangentTraction(const ElementType & el_type,
+  //                             Array<Real> & tangent_matrix,
+  //                             const Array<Real> & normal,
+  //                             GhostType ghost_type) override;
 };
 
 } // namespace akantu
 
-#endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__ */
+#endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_COULOMB_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_slipweakening.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_slipweakening.cc
new file mode 100644
index 000000000..8111920ce
--- /dev/null
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_slipweakening.cc
@@ -0,0 +1,165 @@
+/**
+ * @file   material_cohesive_linear_slipweakening.cc
+ *
+ * @author Mathias Lebihain <mathias.lebihain@epfl.ch>
+ *
+ * @date creation: Fri Mar 06 2020
+ * @date last modification: Fri Mar 06 2020
+ *
+ * @brief  Linear irreversible cohesive law of mixed mode loading with
+ * Mohr-Coulomb insertion criterion and slip-weakening friction for
+ * extrinsic type
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* -------------------------------------------------------------------------- */
+#include "material_cohesive_linear_friction_slipweakening.hh"
+#include "solid_mechanics_model_cohesive.hh"
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <UInt dim>
+MaterialCohesiveLinearFrictionSlipWeakening<dim>::
+    MaterialCohesiveLinearFrictionSlipWeakening(SolidMechanicsModel & model,
+                                                const ID & id)
+    : MaterialParent(model, id), mu_dynamic("mu_dynamic", *this) {
+  AKANTU_DEBUG_IN();
+
+  this->registerParam("mu_static", this->mu_insertion,
+                      _pat_parsable | _pat_readable,
+                      "Static value of the friction coefficient");
+
+  this->registerParam("mu_dynamic", this->mu_dynamic,
+                      _pat_parsable | _pat_readable,
+                      "Dynamic value of the friction coefficient");
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <UInt dim>
+void MaterialCohesiveLinearFrictionSlipWeakening<dim>::initMaterial() {
+  AKANTU_DEBUG_IN();
+
+  MaterialParent::initMaterial();
+
+  mu_dynamic.initialize(1);
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+/** \todo Frictional contributions might be computed from the contact_tractions,
+ * and delta_max at the previous time step
+ */
+template <UInt dim>
+void MaterialCohesiveLinearFrictionSlipWeakening<dim>::computeTraction(
+    const Array<Real> & normal, ElementType el_type, GhostType ghost_type) {
+  AKANTU_DEBUG_IN();
+
+  Vector<Real> normal_opening(dim);
+  Vector<Real> tangential_opening(dim);
+
+  /// loop on each quadrature point
+  for (auto && data :
+       zip(make_view(this->insertion_stress(el_type, ghost_type), dim),
+           make_view(this->insertion_compression(el_type, ghost_type), dim),
+           this->sigma_c_eff(el_type, ghost_type),
+           this->delta_c_eff(el_type, ghost_type),
+           this->mu_eff(el_type, ghost_type),
+           this->mu_dynamic(el_type, ghost_type), make_view(normal, dim),
+           this->delta_max(el_type, ghost_type),
+           this->damage(el_type, ghost_type),
+           make_view(this->tractions(el_type, ghost_type), dim),
+           make_view(this->contact_tractions(el_type, ghost_type), dim),
+           make_view(this->friction_force(el_type, ghost_type), dim),
+           make_view(this->opening(el_type, ghost_type), dim),
+           make_view(this->contact_opening(el_type, ghost_type), dim),
+           this->residual_sliding(el_type, ghost_type),
+           this->residual_sliding.previous(el_type, ghost_type))) {
+
+    auto && insertion_traction = std::get<0>(data);
+    auto && insertion_compression = std::get<1>(data);
+    auto && sigma_c = std::get<2>(data);
+    auto && delta_c = std::get<3>(data);
+    auto && mu_static = std::get<4>(data);
+    auto && mu_dynamic = std::get<5>(data);
+    auto && normal = std::get<6>(data);
+    auto && delta_max = std::get<7>(data);
+    auto && damage = std::get<8>(data);
+    auto && traction = std::get<9>(data);
+    auto && contact_traction = std::get<10>(data);
+    auto && friction_force = std::get<11>(data);
+    auto && opening = std::get<12>(data);
+    auto && contact_opening = std::get<13>(data);
+    auto && res_sliding = std::get<14>(data);
+    auto && res_sliding_prev = std::get<15>(data);
+
+    Real normal_opening_norm, tangential_opening_norm;
+    bool penetration;
+
+    this->computeTractionOnQuad(
+        traction, opening, normal, delta_max, delta_c, insertion_traction,
+        insertion_compression, sigma_c, normal_opening, tangential_opening,
+        normal_opening_norm, tangential_opening_norm, damage, penetration,
+        contact_traction, contact_opening);
+
+    if (penetration) {
+      /// current friction coefficient
+      Real mu = mu_static + (mu_dynamic - mu_static) * damage;
+      /// the definition of tau_max refers to
+      /// the current contact_traction computed in computeTractionOnQuad
+      Real tau_max = mu * contact_traction.norm();
+
+      // elastic sliding
+      Real delta_sliding_norm =
+          std::abs(tangential_opening_norm - res_sliding_prev);
+
+      /// tau is the norm of the friction force, acting tangentially to the
+      /// surface
+      Real tau = std::min(this->friction_penalty * delta_sliding_norm, tau_max);
+
+      if ((tangential_opening_norm - res_sliding_prev) < 0.0)
+        tau = -tau;
+
+      /// from tau get the x and y components of friction, to be added in the
+      /// force vector
+      auto tangent_unit_vector = tangential_opening / tangential_opening_norm;
+      friction_force = tau * tangent_unit_vector;
+
+      /// update residual_sliding
+      res_sliding =
+          tangential_opening_norm - (std::abs(tau) / this->friction_penalty);
+    } else {
+      friction_force.clear();
+    }
+    traction += friction_force;
+  }
+
+  AKANTU_DEBUG_OUT();
+}
+/* -------------------------------------------------------------------------- */
+
+INSTANTIATE_MATERIAL(cohesive_linear_friction_slipweakening,
+                     MaterialCohesiveLinearFrictionSlipWeakening);
+
+} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_slipweakening.hh
similarity index 61%
copy from src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
copy to src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_slipweakening.hh
index 780ce1922..3ffbdd44f 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_slipweakening.hh
@@ -1,105 +1,88 @@
 /**
- * @file   material_cohesive_linear_friction.hh
+ * @file   material_cohesive_linear_slipweakening.hh
  *
- * @author Mauro Corrado <mauro.corrado@epfl.ch>
- * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Mathias Lebihain <mathias.lebihain@epfl.ch>
  *
- * @date creation: Fri Jun 18 2010
- * @date last modification: Wed Feb 21 2018
+ * @date creation: Fri Mar 06 2020
+ * @date last modification: Fri Mar 06 2020
  *
  * @brief  Linear irreversible cohesive law of mixed mode loading with
- * random stress definition for extrinsic type
+ * Mohr-Coulomb insertion criterion and slip-weakening friction for
+ * extrinsic type
  *
  * @section LICENSE
  *
- * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Copyright (©)  2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
-#include "material_cohesive_linear.hh"
+#include "material_cohesive_linear_friction.hh"
 
 /* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__
-#define __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__
-
+#ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_SLIPWEAKENING_HH__
+#define __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_SLIPWEAKENING_HH__
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /**
- * Cohesive material linear with friction force
+ * Cohesive material linear with slip-weakening friction force
  *
  * parameters in the material files :
- *   - mu   : friction coefficient
- *   - penalty_for_friction : Penalty parameter for the friction behavior
+ *   - mu_d   : dynamic friction coefficient
  */
 template <UInt spatial_dimension>
-class MaterialCohesiveLinearFriction
-    : public MaterialCohesiveLinear<spatial_dimension> {
+class MaterialCohesiveLinearFrictionSlipWeakening
+    : public MaterialCohesiveLinearFriction<spatial_dimension> {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
-  using MaterialParent = MaterialCohesiveLinear<spatial_dimension>;
+  using MaterialParent = MaterialCohesiveLinearFriction<spatial_dimension>;
 
 public:
-  MaterialCohesiveLinearFriction(SolidMechanicsModel & model,
-                                 const ID & id = "");
+  MaterialCohesiveLinearFrictionSlipWeakening(SolidMechanicsModel & model,
+                                              const ID & id = "");
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the material parameters
   void initMaterial() override;
 
 protected:
   /// constitutive law
   void computeTraction(const Array<Real> & normal, ElementType el_type,
                        GhostType ghost_type = _not_ghost) override;
 
-  /// compute tangent stiffness matrix
-  void computeTangentTraction(const ElementType & el_type,
-                              Array<Real> & tangent_matrix,
-                              const Array<Real> & normal,
-                              GhostType ghost_type) override;
-
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
-  /// maximum value of the friction coefficient
-  Real mu_max;
-
-  /// penalty parameter for the friction law
-  Real friction_penalty;
-
-  /// history parameter for the friction law
-  CohesiveInternalField<Real> residual_sliding;
-
-  /// friction force
-  CohesiveInternalField<Real> friction_force;
+  /// dynamic friction coefficient
+  RandomInternalField<Real, CohesiveInternalField> mu_dynamic;
 };
 
 } // namespace akantu
 
-#endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_HH__ */
+#endif /* __AKANTU_MATERIAL_COHESIVE_LINEAR_FRICTION_SLIPWEAKENING_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_tmpl.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_tmpl.hh
new file mode 100644
index 000000000..b5d3d429b
--- /dev/null
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction_tmpl.hh
@@ -0,0 +1,335 @@
+/**
+ * @file   material_cohesive_linear_friction.cc
+ *
+ * @author Mauro Corrado <mauro.corrado@epfl.ch>
+ *
+ * @date creation: Tue Jan 12 2016
+ * @date last modification: Wed Feb 21 2018
+ *
+ * @brief  Linear irreversible cohesive law of mixed mode loading with
+ * random stress definition for extrinsic type
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * Akantu is free  software: you can redistribute it and/or  modify it under the
+ * terms  of the  GNU Lesser  General Public  License as published by  the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
+ * details.
+ *
+ * You should  have received  a copy  of the GNU  Lesser General  Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+/* -------------------------------------------------------------------------- */
+#include "material_cohesive_linear_friction.hh"
+#include "solid_mechanics_model_cohesive.hh"
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <UInt spatial_dimension>
+MaterialCohesiveLinearFriction<spatial_dimension>::
+    MaterialCohesiveLinearFriction(SolidMechanicsModel & model, const ID & id)
+    : MaterialParent(model, id), mu_insertion("mu_insertion", *this),
+      mu_eff("mu_eff", *this), residual_sliding("residual_sliding", *this),
+      friction_force("friction_force", *this) {
+  AKANTU_DEBUG_IN();
+
+  this->registerParam("mu", mu_insertion, _pat_parsable | _pat_readable,
+                      "Value of the friction coefficient at insertion");
+
+  this->registerParam("penalty_for_friction", friction_penalty, Real(0.),
+                      _pat_parsable | _pat_readable,
+                      "Penalty parameter for the friction behavior");
+
+  this->use_previous_contact_opening = true;
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <UInt spatial_dimension>
+void MaterialCohesiveLinearFriction<spatial_dimension>::initMaterial() {
+  AKANTU_DEBUG_IN();
+
+  MaterialParent::initMaterial();
+
+  mu_insertion.initialize(1);
+  mu_eff.initialize(1);
+  friction_force.initialize(spatial_dimension);
+  residual_sliding.initialize(1);
+  residual_sliding.initializeHistory();
+
+  AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <UInt spatial_dimension>
+void MaterialCohesiveLinearFriction<spatial_dimension>::checkInsertion(
+    bool check_only) {
+  AKANTU_DEBUG_IN();
+
+  // get mesh and inserter
+  const Mesh & mesh_facets = this->model->getMeshFacets();
+  CohesiveElementInserter & inserter = this->model->getElementInserter();
+
+  for (auto && type_facet : mesh_facets.elementTypes(spatial_dimension - 1)) {
+    ElementType type_cohesive = FEEngine::getCohesiveElementType(type_facet);
+    const auto & facets_check = inserter.getCheckFacets(type_facet);
+    auto & f_insertion = inserter.getInsertionFacets(type_facet);
+    auto & f_filter = this->facet_filter(type_facet);
+    auto & sig_c_eff = this->sigma_c_eff(type_cohesive);
+    auto & mu_eff = this->mu_eff(type_cohesive);
+    auto & del_c_eff = this->delta_c_eff(type_cohesive);
+    auto & ins_stress = this->insertion_stress(type_cohesive);
+    auto & ins_comp = this->insertion_compression(type_cohesive);
+    auto & trac_old = this->tractions.previous(type_cohesive);
+
+    UInt nb_quad_facet = this->model->getFEEngine("FacetsFEEngine")
+                             .getNbIntegrationPoints(type_facet);
+
+#ifndef AKANTU_NDEBUG
+    UInt nb_quad_cohesive = this->model->getFEEngine("CohesiveFEEngine")
+                                .getNbIntegrationPoints(type_cohesive);
+
+    AKANTU_DEBUG_ASSERT(nb_quad_cohesive == nb_quad_facet,
+                        "The cohesive element and the corresponding facet do "
+                        "not have the same numbers of integration points");
+#endif
+
+    UInt nb_facet = f_filter.size();
+    if (nb_facet == 0)
+      continue;
+
+    // get cohesive stress
+    const auto & sigma_lim = this->sigma_c(type_facet);
+    // get friction at insertion
+    const auto & mu_insert = this->mu_insertion(type_facet);
+    // get stress on facets
+    const auto & f_stress = this->model->getStressOnFacets(type_facet);
+    // get normals and tangents to facets
+    const auto & tangents = this->model->getTangents(type_facet);
+    const auto & normals = this->model->getFEEngine("FacetsFEEngine")
+                               .getNormalsOnIntegrationPoints(type_facet);
+    // associated iterators
+    auto sigma_lim_it = sigma_lim.begin();
+    auto mu_insert_it = mu_insert.begin();
+    auto facet_stress_begin =
+        f_stress.begin(spatial_dimension, spatial_dimension * 2);
+    auto normal_begin = normals.begin(spatial_dimension);
+    auto tangent_begin = tangents.begin(tangents.getNbComponent());
+
+    // loop utils
+    UInt sp2 = spatial_dimension * spatial_dimension;
+
+    Matrix<Real> stress_quad(spatial_dimension, spatial_dimension);
+    Matrix<Real> normal_traction_quad(spatial_dimension, nb_quad_facet);
+    Vector<Real> normal_compression_quad(nb_quad_facet);
+    Vector<Real> effective_stress_quad(nb_quad_facet);
+    Vector<Real> mu_insert_quad(nb_quad_facet);
+    Vector<Real> sigma_lim_quad(nb_quad_facet);
+
+    std::vector<Real> new_sigmas;
+    std::vector<Real> new_mus;
+    std::vector<Vector<Real>> new_normal_tractions;
+    std::vector<Vector<Real>> new_normal_compressions;
+    std::vector<Real> new_delta_cs;
+
+    // loop over each facet belonging to this material
+    for (UInt f = 0; f < nb_facet; ++f, ++sigma_lim_it, ++mu_insert_it) {
+      // facet id
+      UInt facet = f_filter(f);
+
+      // skip facets where check shouldn't be realized
+      if (!facets_check(facet))
+        continue;
+
+      // initialization for average activation
+      Vector<Real> avg_normal(spatial_dimension);
+      Vector<Real> avg_tangent(spatial_dimension);
+      Vector<Real> avg_normal_traction(spatial_dimension);
+      Real avg_normal_compression = 0.;
+      Real mu_insert_avg = 0.;
+      Real sigma_lim_avg = 0.;
+
+      // compute the effective norm on each quadrature point of the facet
+      Real normal_compression_q;
+      for (UInt q = 0; q < nb_quad_facet; ++q) {
+        UInt current_quad = facet * nb_quad_facet + q;
+        const Vector<Real> & normal = normal_begin[current_quad];
+        const Vector<Real> & tangent = tangent_begin[current_quad];
+        const Matrix<Real> & facet_stress_it = facet_stress_begin[current_quad];
+
+        // compute average stress on the current quadrature point
+        Matrix<Real> stress_1(facet_stress_it.storage(), spatial_dimension,
+                              spatial_dimension);
+        Matrix<Real> stress_2(facet_stress_it.storage() + sp2,
+                              spatial_dimension, spatial_dimension);
+        stress_quad.copy(stress_1);
+        stress_quad += stress_2;
+        stress_quad /= 2.;
+
+        // compute normal and effective stress taking into account the sole
+        // tensile contribution of the facet tractions
+        Vector<Real> normal_traction_vec(normal_traction_quad(q));
+        effective_stress_quad(q) = this->computeEffectiveNorm(
+            stress_quad, normal, tangent, normal_traction_vec);
+
+        // normal traction on quad
+        normal_compression_q = normal_traction_vec.dot(normal);
+        // compressive contribution of the normal traction
+        normal_compression_quad(q) = std::min(0., normal_compression_q);
+        // traction minus compressive part
+        normal_traction_quad(q) =
+            normal_traction_vec - normal * normal_compression_quad(q);
+
+        // store quad and average infos
+        avg_normal_compression += normal_compression_q;
+        avg_normal_traction += normal_traction_vec;
+        avg_normal += normal;
+        avg_tangent += tangent;
+        sigma_lim_avg += *sigma_lim_it;
+        sigma_lim_quad(q) = *sigma_lim_it;
+        mu_insert_avg += *mu_insert_it;
+        mu_insert_quad(q) = *mu_insert_it;
+      }
+      // rescale averages
+      sigma_lim_avg /= nb_quad_facet;
+      mu_insert_avg /= nb_quad_facet;
+      avg_normal /= nb_quad_facet;
+      avg_tangent /= nb_quad_facet;
+      avg_normal_traction /= nb_quad_facet;
+      avg_normal_compression /= nb_quad_facet;
+
+      // compressive contribution of the average normal traction
+      avg_normal_compression = std::min(0., avg_normal_compression);
+      // average traction minus compressive part
+      avg_normal_traction -= avg_normal * avg_normal_compression;
+
+      // verify if the effective stress overcomes the threshold
+      Real crit;
+      if (this->max_quad_stress_insertion) {
+        Vector<Real> crit_quad(nb_quad_facet);
+        for (UInt q = 0; q < nb_quad_facet; ++q) {
+          crit_quad(q) = effective_stress_quad(q) -
+                         (sigma_lim_quad(q) - mu_insert_quad(q) / this->beta *
+                                                  normal_compression_quad(q));
+        }
+        crit = *std::max_element(crit_quad.storage(),
+                                 crit_quad.storage() + nb_quad_facet);
+        // we must then ensure that the average value we set to
+        // new_sigma is above zero
+        if (effective_stress_quad.mean() +
+                mu_insert_avg / this->beta * avg_normal_compression <
+            0) {
+          crit = effective_stress_quad.mean() -
+                 (sigma_lim_avg -
+                  mu_insert_avg / this->beta * avg_normal_compression);
+        }
+      } else {
+        crit = effective_stress_quad.mean() -
+               (sigma_lim_avg -
+                mu_insert_avg / this->beta * avg_normal_compression);
+      }
+
+      if (crit > -Math::getTolerance()) {
+        // facet will be inserted
+        f_insertion(facet) = true;
+        // only if insertion is considered
+        if (check_only)
+          continue;
+
+        // add tangential friction part to traction
+        avg_normal_traction +=
+            mu_insert_avg * avg_normal_compression * avg_tangent;
+        if (spatial_dimension != 3) {
+          avg_normal_traction *= -1.;
+          avg_normal_compression *= -1.;
+        }
+
+        // store the new cohesive material parameters for each quadrature point
+        for (UInt q = 0; q < nb_quad_facet; ++q) {
+          // extract tangent
+          UInt current_quad = facet * nb_quad_facet + q;
+          const Vector<Real> & normal = normal_begin[current_quad];
+          const Vector<Real> & tangent = tangent_begin[current_quad];
+
+          // effective stress at insertion
+          Real new_sigma =
+              effective_stress_quad(q) +
+              mu_insert_quad(q) / this->beta * normal_compression_quad(q);
+
+          // friction coefficient
+          Real new_mu = mu_insert_quad(q);
+
+          // traction at insertion with friction component
+          Vector<Real> new_normal_traction(normal_traction_quad(q));
+          new_normal_traction +=
+              mu_insert_quad(q) * normal_compression_quad(q) * tangent;
+          Vector<Real> new_normal_compression =
+              normal_compression_quad(q) * normal;
+          if (spatial_dimension != 3) {
+            new_normal_traction *= -1.;
+            new_normal_compression *= -1.;
+          }
+
+          if (new_sigma < 0.05 * sigma_lim_quad(q)) {
+            new_mu = mu_insert_avg;
+            new_sigma = effective_stress_quad.mean() +
+                        mu_insert_avg / this->beta * avg_normal_compression;
+            new_normal_traction = avg_normal_traction;
+            new_normal_compression = avg_normal_compression * avg_normal;
+          }
+
+          // set delta_c in function of G_c or a given delta_c value
+          Real new_delta_c;
+          if (Math::are_float_equal(this->delta_c, 0.))
+            new_delta_c = 2 * this->G_c / new_sigma;
+          else
+            new_delta_c = (*sigma_lim_it) / new_sigma * this->delta_c;
+
+          // push to insertion list
+          new_sigmas.push_back(new_sigma);
+          new_mus.push_back(new_mu);
+          new_normal_tractions.push_back(new_normal_traction);
+          new_normal_compressions.push_back(new_normal_compression);
+          new_delta_cs.push_back(new_delta_c);
+        }
+      }
+    }
+
+    // update material data for the new elements
+    UInt old_nb_quad_points = sig_c_eff.size();
+    UInt new_nb_quad_points = new_sigmas.size();
+    sig_c_eff.resize(old_nb_quad_points + new_nb_quad_points);
+    mu_eff.resize(old_nb_quad_points + new_nb_quad_points);
+    del_c_eff.resize(old_nb_quad_points + new_nb_quad_points);
+    ins_stress.resize(old_nb_quad_points + new_nb_quad_points);
+    ins_comp.resize(old_nb_quad_points + new_nb_quad_points);
+    trac_old.resize(old_nb_quad_points + new_nb_quad_points);
+
+    for (UInt q = 0; q < new_nb_quad_points; ++q) {
+      sig_c_eff(old_nb_quad_points + q) = new_sigmas[q];
+      mu_eff(old_nb_quad_points + q) = new_mus[q];
+      del_c_eff(old_nb_quad_points + q) = new_delta_cs[q];
+      for (UInt dim = 0; dim < spatial_dimension; ++dim) {
+        ins_stress(old_nb_quad_points + q, dim) = new_normal_tractions[q](dim);
+        ins_comp(old_nb_quad_points + q, dim) = new_normal_compressions[q](dim);
+        trac_old(old_nb_quad_points + q, dim) = new_normal_tractions[q](dim);
+      }
+    }
+  }
+
+  AKANTU_DEBUG_OUT();
+}
+
+} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.cc
index 87c4ee528..8da2df437 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.cc
@@ -1,266 +1,265 @@
 /**
  * @file   material_cohesive_linear_inline_impl.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Apr 22 2015
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Inline functions of the MaterialCohesiveLinear
  *
  * @section LICENSE
  *
  * Copyright (©) 2015-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_cohesive_linear.hh"
 #include "solid_mechanics_model_cohesive.hh"
 /* -------------------------------------------------------------------------- */
 
 /* -------------------------------------------------------------------------- */
 #ifndef __AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_CC__
 #define __AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_CC__
 
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 inline Real MaterialCohesiveLinear<dim>::computeEffectiveNorm(
     const Matrix<Real> & stress, const Vector<Real> & normal,
     const Vector<Real> & tangent, Vector<Real> & normal_traction) const {
   normal_traction.mul<false>(stress, normal);
 
   Real normal_contrib = normal_traction.dot(normal);
 
   /// in 3D tangential components must be summed
   Real tangent_contrib = 0;
 
   if (dim == 2) {
     Real tangent_contrib_tmp = normal_traction.dot(tangent);
     tangent_contrib += tangent_contrib_tmp * tangent_contrib_tmp;
   } else if (dim == 3) {
     for (UInt s = 0; s < dim - 1; ++s) {
       const Vector<Real> tangent_v(tangent.storage() + s * dim, dim);
       Real tangent_contrib_tmp = normal_traction.dot(tangent_v);
       tangent_contrib += tangent_contrib_tmp * tangent_contrib_tmp;
     }
   }
 
   tangent_contrib = std::sqrt(tangent_contrib);
   normal_contrib = std::max(Real(0.), normal_contrib);
 
   return std::sqrt(normal_contrib * normal_contrib +
                    tangent_contrib * tangent_contrib * beta2_inv);
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 inline void MaterialCohesiveLinear<dim>::computeTractionOnQuad(
     Vector<Real> & traction, Vector<Real> & opening,
     const Vector<Real> & normal, Real & delta_max, const Real & delta_c,
-    const Vector<Real> & insertion_stress, const Real & sigma_c,
+    const Vector<Real> & insertion_stress,
+    const Vector<Real> & insertion_compression, const Real & sigma_c,
     Vector<Real> & normal_opening, Vector<Real> & tangential_opening,
-    Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage,
-    bool & penetration, Vector<Real> & contact_traction,
+    Real & normal_opening_norm, Real & tangential_opening_norm,
+    Real & damage, bool & penetration, Vector<Real> & contact_traction,
     Vector<Real> & contact_opening) {
 
   /// compute normal and tangential opening vectors
   normal_opening_norm = opening.dot(normal);
   normal_opening = normal;
   normal_opening *= normal_opening_norm;
 
   tangential_opening = opening;
   tangential_opening -= normal_opening;
   tangential_opening_norm = tangential_opening.norm();
 
   /**
    * compute effective opening displacement
    * @f$ \delta = \sqrt{
    * \frac{\beta^2}{\kappa^2} \Delta_t^2 + \Delta_n^2 } @f$
    */
   Real delta =
       tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
 
   penetration = normal_opening_norm / delta_c < -Math::getTolerance();
   // penetration = normal_opening_norm < 0.;
   if (this->contact_after_breaking == false &&
       Math::are_float_equal(damage, 1.))
     penetration = false;
 
   if (penetration) {
     /// use penalty coefficient in case of penetration
     contact_traction = normal_opening;
     contact_traction *= this->penalty;
     contact_opening = normal_opening;
 
     /// don't consider penetration contribution for delta
     opening = tangential_opening;
     normal_opening.clear();
   } else {
     delta += normal_opening_norm * normal_opening_norm;
     contact_traction.clear();
     contact_opening.clear();
   }
 
   delta = std::sqrt(delta);
 
   /// update maximum displacement and damage
   delta_max = std::max(delta_max, delta);
   damage = std::min(delta_max / delta_c, Real(1.));
 
   /**
    * Compute traction @f$ \mathbf{T} = \left(
    * \frac{\beta^2}{\kappa} \Delta_t \mathbf{t} + \Delta_n
    * \mathbf{n} \right) \frac{\sigma_c}{\delta} \left( 1-
    * \frac{\delta}{\delta_c} \right)@f$
    */
 
   if (Math::are_float_equal(damage, 1.))
     traction.clear();
   else if (Math::are_float_equal(damage, 0.)) {
-    if (penetration)
-      traction.clear();
-    else
-      traction = insertion_stress;
+    traction = insertion_stress;
+    contact_traction = insertion_compression;
   } else {
     traction = tangential_opening;
     traction *= this->beta2_kappa;
     traction += normal_opening;
 
     AKANTU_DEBUG_ASSERT(delta_max != 0.,
                         "Division by zero, tolerance might be too low");
 
     traction *= sigma_c / delta_max * (1. - damage);
   }
 }
 
 /* -------------------------------------------------------------------------- */
 template <UInt dim>
 inline void MaterialCohesiveLinear<dim>::computeTangentTractionOnQuad(
     Matrix<Real> & tangent, Real & delta_max, const Real & delta_c,
     const Real & sigma_c, Vector<Real> & opening, const Vector<Real> & normal,
     Vector<Real> & normal_opening, Vector<Real> & tangential_opening,
     Real & normal_opening_norm, Real & tangential_opening_norm, Real & damage,
     bool & penetration, Vector<Real> & contact_opening) {
 
   /**
    * During the update of the residual the interpenetrations are
    * stored in the array "contact_opening", therefore, in the case
    * of penetration, in the array "opening" there are only the
    * tangential components.
    */
   opening += contact_opening;
 
   /// compute normal and tangential opening vectors
   normal_opening_norm = opening.dot(normal);
   normal_opening = normal;
   normal_opening *= normal_opening_norm;
 
   tangential_opening = opening;
   tangential_opening -= normal_opening;
   tangential_opening_norm = tangential_opening.norm();
 
   Real delta =
       tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
 
   penetration = normal_opening_norm < 0.0;
   if (this->contact_after_breaking == false &&
       Math::are_float_equal(damage, 1.))
     penetration = false;
 
   Real derivative = 0; // derivative = d(t/delta)/ddelta
   Real t = 0;
 
   Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
   n_outer_n.outerProduct(normal, normal);
 
   if (penetration) {
     /// stiffness in compression given by the penalty parameter
     tangent += n_outer_n;
     tangent *= penalty;
 
     opening = tangential_opening;
     normal_opening_norm = opening.dot(normal);
     normal_opening = normal;
     normal_opening *= normal_opening_norm;
   } else {
     delta += normal_opening_norm * normal_opening_norm;
   }
 
   delta = std::sqrt(delta);
 
   /**
    * Delta has to be different from 0 to have finite values of
    * tangential stiffness.  At the element insertion, delta =
    * 0. Therefore, a fictictious value is defined, for the
    * evaluation of the first value of K.
    */
   if (delta < Math::getTolerance())
     delta = delta_c / 1000.;
 
   if (delta >= delta_max) {
     if (delta <= delta_c) {
       derivative = -sigma_c / (delta * delta);
       t = sigma_c * (1 - delta / delta_c);
     } else {
       derivative = 0.;
       t = 0.;
     }
   } else if (delta < delta_max) {
     Real tmax = sigma_c * (1 - delta_max / delta_c);
     t = tmax / delta_max * delta;
   }
 
   /// computation of the derivative of the constitutive law (dT/ddelta)
   Matrix<Real> I(spatial_dimension, spatial_dimension);
   I.eye(this->beta2_kappa);
 
   Matrix<Real> nn(n_outer_n);
   nn *= (1. - this->beta2_kappa);
   nn += I;
   nn *= t / delta;
 
   Vector<Real> t_tilde(normal_opening);
   t_tilde *= (1. - this->beta2_kappa2);
 
   Vector<Real> mm(opening);
   mm *= this->beta2_kappa2;
   t_tilde += mm;
 
   Vector<Real> t_hat(normal_opening);
   t_hat += this->beta2_kappa * tangential_opening;
 
   Matrix<Real> prov(spatial_dimension, spatial_dimension);
   prov.outerProduct(t_hat, t_tilde);
   prov *= derivative / delta;
   prov += nn;
 
   Matrix<Real> prov_t = prov.transpose();
   tangent += prov_t;
 }
 
 /* -------------------------------------------------------------------------- */
 } // namespace akantu
 
 /* -------------------------------------------------------------------------- */
 #endif //__AKANTU_MATERIAL_COHESIVE_LINEAR_INLINE_IMPL_CC__
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
index 1c31d8d0a..9b9a9fc60 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc
@@ -1,558 +1,560 @@
 /**
  * @file   material_cohesive.cc
  *
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Wed Feb 22 2012
  * @date last modification: Mon Feb 19 2018
  *
  * @brief  Specialization of the material class for cohesive elements
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material_cohesive.hh"
 #include "aka_random_generator.hh"
 #include "dof_synchronizer.hh"
 #include "fe_engine_template.hh"
 #include "integrator_gauss.hh"
 #include "shape_cohesive.hh"
 #include "solid_mechanics_model_cohesive.hh"
 #include "sparse_matrix.hh"
 /* -------------------------------------------------------------------------- */
 
 namespace 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),
       tractions("tractions", *this),
       contact_tractions("contact_tractions", *this),
       contact_opening("contact_opening", *this), delta_max("delta max", *this),
       use_previous_delta_max(false), use_previous_opening(false),
-      damage("damage", *this), sigma_c("sigma_c", *this),
-      normal(0, spatial_dimension, "normal") {
+      use_previous_contact_opening(false), damage("damage", *this),
+      sigma_c("sigma_c", *this),  normal(0, spatial_dimension, "normal") {
 
   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, Real(0.),
                       _pat_parsable | _pat_readable, "Critical displacement");
 
   this->element_filter.initialize(this->model->getMesh(),
                                   _spatial_dimension = spatial_dimension,
                                   _element_kind = _ek_cohesive);
   // this->model->getMesh().initElementTypeMapArray(
   //     this->element_filter, 1, spatial_dimension, false, _ek_cohesive);
 
   if (this->model->getIsExtrinsic())
     this->facet_filter.initialize(this->model->getMeshFacets(),
                                   _spatial_dimension = spatial_dimension - 1,
                                   _element_kind = _ek_regular);
   // this->model->getMeshFacets().initElementTypeMapArray(facet_filter, 1,
   //                                                      spatial_dimension -
   //                                                      1);
 
   this->reversible_energy.initialize(1);
   this->total_energy.initialize(1);
 
   this->tractions.initialize(spatial_dimension);
   this->tractions.initializeHistory();
 
   this->contact_tractions.initialize(spatial_dimension);
   this->contact_opening.initialize(spatial_dimension);
 
   this->opening.initialize(spatial_dimension);
   this->opening.initializeHistory();
 
   this->delta_max.initialize(1);
   this->damage.initialize(1);
 
   if (this->model->getIsExtrinsic())
     this->sigma_c.initialize(1);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 MaterialCohesive::~MaterialCohesive() = default;
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::initMaterial() {
   AKANTU_DEBUG_IN();
   Material::initMaterial();
   if (this->use_previous_delta_max)
     this->delta_max.initializeHistory();
   if (this->use_previous_opening)
     this->opening.initializeHistory();
+  if (this->use_previous_contact_opening)
+    this->contact_opening.initializeHistory();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::assembleInternalForces(GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
 #if defined(AKANTU_DEBUG_TOOLS)
   debug::element_manager.printData(debug::_dm_material_cohesive,
                                    "Cohesive Tractions", tractions);
 #endif
 
   auto & internal_force = const_cast<Array<Real> &>(model->getInternalForce());
 
   for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type,
                                                _ek_cohesive)) {
     auto & elem_filter = element_filter(type, ghost_type);
     UInt nb_element = elem_filter.size();
     if (nb_element == 0)
       continue;
 
     const auto & shapes = fem_cohesive.getShapes(type, ghost_type);
     auto & traction = tractions(type, ghost_type);
     auto & contact_traction = contact_tractions(type, ghost_type);
 
     UInt size_of_shapes = shapes.getNbComponent();
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
     UInt nb_quadrature_points =
         fem_cohesive.getNbIntegrationPoints(type, 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);
 
     auto traction_it = traction.begin(spatial_dimension, 1);
     auto contact_traction_it = contact_traction.begin(spatial_dimension, 1);
     auto shapes_filtered_begin = shapes.begin(1, size_of_shapes);
     auto 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> * partial_int_t_N = new Array<Real>(
         nb_element, spatial_dimension * size_of_shapes, "int_t_N");
 
     fem_cohesive.integrate(*traction_cpy, *partial_int_t_N,
                            spatial_dimension * size_of_shapes, type, ghost_type,
                            elem_filter);
 
     delete traction_cpy;
 
     Array<Real> * int_t_N = new Array<Real>(
         nb_element, 2 * spatial_dimension * size_of_shapes, "int_t_N");
 
     Real * int_t_N_val = int_t_N->storage();
     Real * partial_int_t_N_val = partial_int_t_N->storage();
     for (UInt el = 0; el < nb_element; ++el) {
       std::copy_n(partial_int_t_N_val, size_of_shapes * spatial_dimension,
                   int_t_N_val);
       std::copy_n(partial_int_t_N_val, size_of_shapes * spatial_dimension,
                   int_t_N_val + size_of_shapes * spatial_dimension);
 
       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;
       partial_int_t_N_val += size_of_shapes * spatial_dimension;
     }
 
     delete partial_int_t_N;
 
     /// assemble
     model->getDOFManager().assembleElementalArrayLocalArray(
         *int_t_N, internal_force, type, ghost_type, 1, elem_filter);
 
     delete int_t_N;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::assembleStiffnessMatrix(GhostType ghost_type) {
 
   AKANTU_DEBUG_IN();
 
   for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type,
                                                _ek_cohesive)) {
     UInt nb_quadrature_points =
         fem_cohesive.getNbIntegrationPoints(type, ghost_type);
     UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
 
     const Array<Real> & shapes = fem_cohesive.getShapes(type, ghost_type);
     Array<UInt> & elem_filter = element_filter(type, ghost_type);
 
     UInt nb_element = elem_filter.size();
 
     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_filtered_val = shapes_filtered->storage();
     UInt * elem_filter_val = elem_filter.storage();
 
     for (UInt el = 0; el < nb_element; ++el) {
       auto 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;
     }
 
     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;
     }
 
     /// 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");
     normal.resize(nb_quadrature_points);
 
     computeNormal(model->getCurrentPosition(), normal, type, ghost_type);
 
     /// compute openings @f$\mathbf{\delta}@f$
     // computeOpening(model->getDisplacement(), opening(type, ghost_type), type,
     // ghost_type);
 
     tangent_stiffness_matrix->clear();
 
     computeTangentTraction(type, *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, type,
                            ghost_type, elem_filter);
 
     delete at_nt_d_n_a;
 
     model->getDOFManager().assembleElementalMatricesToMatrix(
         "K", "displacement", *K_e, type, ghost_type, _unsymmetric, 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
 
   for (auto & type : element_filter.elementTypes(spatial_dimension, ghost_type,
                                                  _ek_cohesive)) {
     Array<UInt> & elem_filter = element_filter(type, ghost_type);
 
     UInt nb_element = elem_filter.size();
     if (nb_element == 0)
       continue;
 
     UInt nb_quadrature_points =
         nb_element * fem_cohesive.getNbIntegrationPoints(type, ghost_type);
 
     normal.resize(nb_quadrature_points);
 
     /// compute normals @f$\mathbf{n}@f$
     computeNormal(model->getCurrentPosition(), normal, type, ghost_type);
 
     /// compute openings @f$\mathbf{\delta}@f$
     computeOpening(model->getDisplacement(), opening(type, ghost_type), type,
                    ghost_type);
 
     /// compute traction @f$\mathbf{t}@f$
     computeTraction(normal, type, ghost_type);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void MaterialCohesive::computeNormal(const Array<Real> & position,
                                      Array<Real> & normal, ElementType type,
                                      GhostType ghost_type) {
   AKANTU_DEBUG_IN();
 
   auto & fem_cohesive =
       this->model->getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine");
 
   normal.clear();
 
 #define COMPUTE_NORMAL(type)                                                   \
   fem_cohesive.getShapeFunctions()                                             \
       .computeNormalsOnIntegrationPoints<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();
 
   auto & fem_cohesive =
       this->model->getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine");
 
 #define COMPUTE_OPENING(type)                                                  \
   fem_cohesive.getShapeFunctions()                                             \
       .interpolateOnIntegrationPoints<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::updateEnergies(ElementType type) {
   AKANTU_DEBUG_IN();
 
   if (Mesh::getKind(type) != _ek_cohesive)
     return;
 
   Vector<Real> b(spatial_dimension);
   Vector<Real> h(spatial_dimension);
   auto erev = reversible_energy(type).begin();
   auto etot = total_energy(type).begin();
   auto traction_it = tractions(type).begin(spatial_dimension);
   auto traction_old_it = tractions.previous(type).begin(spatial_dimension);
   auto opening_it = opening(type).begin(spatial_dimension);
   auto opening_old_it = opening.previous(type).begin(spatial_dimension);
 
   auto traction_end = tractions(type).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);
   }
 
   /// update old values
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getReversibleEnergy() {
   AKANTU_DEBUG_IN();
   Real erev = 0.;
 
   /// integrate reversible energy for each type of elements
   for (auto & type : element_filter.elementTypes(spatial_dimension, _not_ghost,
                                                  _ek_cohesive)) {
     erev +=
         fem_cohesive.integrate(reversible_energy(type, _not_ghost), type,
                                _not_ghost, element_filter(type, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return erev;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getDissipatedEnergy() {
   AKANTU_DEBUG_IN();
   Real edis = 0.;
 
   /// integrate dissipated energy for each type of elements
   for (auto & type : element_filter.elementTypes(spatial_dimension, _not_ghost,
                                                  _ek_cohesive)) {
     Array<Real> dissipated_energy(total_energy(type, _not_ghost));
     dissipated_energy -= reversible_energy(type, _not_ghost);
     edis += fem_cohesive.integrate(dissipated_energy, type, _not_ghost,
                                    element_filter(type, _not_ghost));
   }
 
   AKANTU_DEBUG_OUT();
   return edis;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getContactEnergy() {
   AKANTU_DEBUG_IN();
   Real econ = 0.;
 
   /// integrate contact energy for each type of elements
   for (auto & type : element_filter.elementTypes(spatial_dimension, _not_ghost,
                                                  _ek_cohesive)) {
 
     auto & el_filter = element_filter(type, _not_ghost);
     UInt nb_quad_per_el = fem_cohesive.getNbIntegrationPoints(type, _not_ghost);
     UInt nb_quad_points = el_filter.size() * nb_quad_per_el;
     Array<Real> contact_energy(nb_quad_points);
 
     auto contact_traction_it =
         contact_tractions(type, _not_ghost).begin(spatial_dimension);
     auto contact_opening_it =
         contact_opening(type, _not_ghost).begin(spatial_dimension);
 
     /// loop on each quadrature point
     for (UInt q = 0; q < nb_quad_points;
          ++contact_traction_it, ++contact_opening_it, ++q) {
 
       contact_energy(q) = .5 * contact_traction_it->dot(*contact_opening_it);
     }
 
     econ += fem_cohesive.integrate(contact_energy, type, _not_ghost, el_filter);
   }
 
   AKANTU_DEBUG_OUT();
   return econ;
 }
 
 /* -------------------------------------------------------------------------- */
 Real MaterialCohesive::getEnergy(const 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.;
 }
 
 /* -------------------------------------------------------------------------- */
 } // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh
index 187730ead..239cf0dfe 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh
@@ -1,237 +1,242 @@
 /**
  * @file   material_cohesive.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Seyedeh Mohadeseh Taheri Mousavi <mohadeseh.taherimousavi@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Fri Jun 18 2010
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Specialization of the material class for cohesive elements
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 #include "material.hh"
 /* -------------------------------------------------------------------------- */
 #include "cohesive_internal_field.hh"
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AKANTU_MATERIAL_COHESIVE_HH__
 #define __AKANTU_MATERIAL_COHESIVE_HH__
 
 /* -------------------------------------------------------------------------- */
 namespace akantu {
 class SolidMechanicsModelCohesive;
 }
 
 namespace akantu {
 
 class MaterialCohesive : public Material {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   using MyFEEngineCohesiveType =
       FEEngineTemplate<IntegratorGauss, ShapeLagrange, _ek_cohesive>;
 
 public:
   MaterialCohesive(SolidMechanicsModel & model, const ID & id = "");
   ~MaterialCohesive() override;
 
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// initialize the material computed parameter
   void initMaterial() override;
 
   /// compute tractions (including normals and openings)
   void computeTraction(GhostType ghost_type = _not_ghost);
 
   /// assemble residual
   void assembleInternalForces(GhostType ghost_type = _not_ghost) override;
 
   /// check stress for cohesive elements' insertion, by default it
   /// also updates the cohesive elements' data
   virtual void checkInsertion(bool /*check_only*/ = false) {
     AKANTU_TO_IMPLEMENT();
   }
 
   /// interpolate   stress  on   given   positions  for   each  element   (empty
   /// implemantation to avoid the generic call to be done on cohesive elements)
   virtual void interpolateStress(const ElementType /*type*/,
                                  Array<Real> & /*result*/) {}
 
   /// compute the stresses
   void computeAllStresses(GhostType /*ghost_type*/ = _not_ghost) override{};
 
   // add the facet to be handled by the material
   UInt addFacet(const Element & element);
 
 protected:
   virtual void computeTangentTraction(const ElementType & /*el_type*/,
                                       Array<Real> & /*tangent_matrix*/,
                                       const Array<Real> & /*normal*/,
                                       GhostType /*ghost_type*/ = _not_ghost) {
     AKANTU_TO_IMPLEMENT();
   }
 
   /// compute the normal
   void computeNormal(const Array<Real> & position, Array<Real> & normal,
                      ElementType type, GhostType ghost_type);
 
   /// compute the opening
   void computeOpening(const Array<Real> & displacement, Array<Real> & opening,
                       ElementType type, GhostType ghost_type);
 
   template <ElementType type>
   void computeNormal(const Array<Real> & position, Array<Real> & normal,
                      GhostType ghost_type);
 
   /// assemble stiffness
   void assembleStiffnessMatrix(GhostType ghost_type) override;
 
   /// constitutive law
   virtual void computeTraction(const Array<Real> & normal, ElementType el_type,
                                GhostType ghost_type = _not_ghost) = 0;
 
   /// parallelism functions
   inline UInt getNbData(const Array<Element> & elements,
                         const SynchronizationTag & tag) const override;
 
   inline void packData(CommunicationBuffer & buffer,
                        const Array<Element> & elements,
                        const SynchronizationTag & tag) const override;
 
   inline void unpackData(CommunicationBuffer & buffer,
                          const Array<Element> & elements,
                          const SynchronizationTag & tag) override;
 
 protected:
   void updateEnergies(ElementType el_type) override;
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   /// get the opening
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Opening, opening, Real);
 
   /// get the traction
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Traction, tractions, Real);
 
   /// get damage
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real);
 
   /// get facet filter
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetFilter, facet_filter, UInt);
   AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetFilter, facet_filter, UInt);
   AKANTU_GET_MACRO(FacetFilter, facet_filter,
                    const ElementTypeMapArray<UInt> &);
   // AKANTU_GET_MACRO(ElementFilter, element_filter, const
   // ElementTypeMapArray<UInt> &);
 
   /// compute reversible energy
   Real getReversibleEnergy();
 
   /// compute dissipated energy
   Real getDissipatedEnergy();
 
   /// compute contact energy
   Real getContactEnergy();
 
   /// get energy
   Real getEnergy(const std::string & type) override;
 
   /// return the energy (identified by id) for the provided element
   Real getEnergy(const std::string & energy_id, ElementType type,
                  UInt index) override {
     return Material::getEnergy(energy_id, type, index);
   }
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 protected:
   /// list of facets assigned to this material
   ElementTypeMapArray<UInt> facet_filter;
 
   /// Link to the cohesive fem object in the model
   FEEngine & fem_cohesive;
 
 private:
   /// reversible energy by quadrature point
   CohesiveInternalField<Real> reversible_energy;
 
   /// total energy by quadrature point
   CohesiveInternalField<Real> total_energy;
 
 protected:
   /// opening in all elements and quadrature points
   CohesiveInternalField<Real> opening;
 
   /// traction in all elements and quadrature points
   CohesiveInternalField<Real> tractions;
 
   /// traction due to contact
   CohesiveInternalField<Real> contact_tractions;
 
   /// normal openings for contact tractions
   CohesiveInternalField<Real> contact_opening;
 
   /// maximum displacement
   CohesiveInternalField<Real> delta_max;
 
   /// tell if the previous delta_max state is needed (in iterative schemes)
   bool use_previous_delta_max;
 
   /// tell if the previous opening state is needed (in iterative schemes)
   bool use_previous_opening;
 
+  /// tell if the previous contact_opening state is needed (in iterative schemes)
+  bool use_previous_contact_opening;
+
+  /// tell if the
+
   /// damage
   CohesiveInternalField<Real> damage;
 
   /// pointer to the solid mechanics model for cohesive elements
   SolidMechanicsModelCohesive * model;
 
   /// critical stress
   RandomInternalField<Real, FacetInternalField> sigma_c;
 
   /// critical displacement
   Real delta_c;
 
   /// array to temporarily store the normals
   Array<Real> normal;
 };
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 #include "material_cohesive_inline_impl.cc"
 
 } // namespace akantu
 
 #include "cohesive_internal_field_tmpl.hh"
 
 #endif /* __AKANTU_MATERIAL_COHESIVE_HH__ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_includes.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_includes.hh
index 6bb8476c1..c16b4fd48 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_includes.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_includes.hh
@@ -1,49 +1,52 @@
 /**
  * @file   material_cohesive_includes.hh
  *
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  *
  * @date creation: Sun Sep 26 2010
  * @date last modification: Fri Oct 13 2017
  *
  * @brief  List of includes for cohesive elements
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 // /* --------------------------------------------------------------------------
 // */
 // #ifndef AKANTU_CMAKE_LIST_MATERIALS
 // #include "material_cohesive.hh"
 // #include "material_cohesive_bilinear.hh"
 // #include "material_cohesive_exponential.hh"
 // #include "material_cohesive_linear.hh"
 // #include "material_cohesive_linear_fatigue.hh"
 // #include "material_cohesive_linear_friction.hh"
 // #include "material_cohesive_linear_uncoupled.hh"
 // #endif
 
 #define AKANTU_COHESIVE_MATERIAL_LIST                                          \
   ((2, (cohesive_linear, MaterialCohesiveLinear)))(                            \
       (2, (cohesive_linear_fatigue, MaterialCohesiveLinearFatigue)))(          \
-      (2, (cohesive_linear_friction, MaterialCohesiveLinearFriction)))(        \
+      (2, (cohesive_linear_friction_coulomb,                                   \
+           MaterialCohesiveLinearFrictionCoulomb)))(                           \
+      (2, (cohesive_linear_friction_slipweakening,                             \
+           MaterialCohesiveLinearFrictionSlipWeakening)))(                     \
       (2, (cohesive_linear_uncoupled, MaterialCohesiveLinearUncoupled)))(      \
       (2, (cohesive_bilinear, MaterialCohesiveBilinear)))(                     \
       (2, (cohesive_exponential, MaterialCohesiveExponential)))
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
index 8a549afc0..9b7577f9b 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc
@@ -1,708 +1,708 @@
 /**
  * @file   solid_mechanics_model_cohesive.cc
  *
  * @author Fabian Barras <fabian.barras@epfl.ch>
  * @author Mauro Corrado <mauro.corrado@epfl.ch>
  * @author Nicolas Richart <nicolas.richart@epfl.ch>
  * @author Marco Vocialta <marco.vocialta@epfl.ch>
  *
  * @date creation: Tue May 08 2012
  * @date last modification: Wed Feb 21 2018
  *
  * @brief  Solid mechanics model for cohesive elements
  *
  * @section LICENSE
  *
  * Copyright (©)  2010-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 /* -------------------------------------------------------------------------- */
 #include "solid_mechanics_model_cohesive.hh"
 #include "aka_iterators.hh"
 #include "cohesive_element_inserter.hh"
 #include "element_synchronizer.hh"
 #include "facet_synchronizer.hh"
 #include "fe_engine_template.hh"
 #include "global_ids_updater.hh"
 #include "integrator_gauss.hh"
 #include "material_cohesive.hh"
 #include "mesh_accessor.hh"
 #include "mesh_global_data_updater.hh"
 #include "parser.hh"
 #include "shape_cohesive.hh"
 /* -------------------------------------------------------------------------- */
 #include "dumpable_inline_impl.hh"
 #ifdef AKANTU_USE_IOHELPER
 #include "dumper_iohelper_paraview.hh"
 #endif
 /* -------------------------------------------------------------------------- */
 #include <algorithm>
 /* -------------------------------------------------------------------------- */
 
 namespace akantu {
 
 class CohesiveMeshGlobalDataUpdater : public MeshGlobalDataUpdater {
 public:
   CohesiveMeshGlobalDataUpdater(SolidMechanicsModelCohesive & model)
       : model(model), mesh(model.getMesh()),
         global_ids_updater(model.getMesh(), *model.cohesive_synchronizer) {}
 
   /* ------------------------------------------------------------------------ */
   std::tuple<UInt, UInt>
   updateData(NewNodesEvent & nodes_event,
              NewElementsEvent & elements_event) override {
     auto cohesive_nodes_event =
         dynamic_cast<CohesiveNewNodesEvent *>(&nodes_event);
     if (not cohesive_nodes_event)
       return std::make_tuple(nodes_event.getList().size(),
                              elements_event.getList().size());
 
     /// update nodes type
     auto & new_nodes = cohesive_nodes_event->getList();
     auto & old_nodes = cohesive_nodes_event->getOldNodesList();
 
     auto local_nb_new_nodes = new_nodes.size();
     auto nb_new_nodes = local_nb_new_nodes;
 
     if (mesh.isDistributed()) {
       MeshAccessor mesh_accessor(mesh);
       auto & nodes_flags = mesh_accessor.getNodesFlags();
       auto nb_old_nodes = nodes_flags.size();
       nodes_flags.resize(nb_old_nodes + local_nb_new_nodes);
 
       for (auto && data : zip(old_nodes, new_nodes)) {
         UInt old_node, new_node;
         std::tie(old_node, new_node) = data;
         nodes_flags(new_node) = nodes_flags(old_node);
       }
 
       model.updateCohesiveSynchronizers();
       nb_new_nodes = global_ids_updater.updateGlobalIDs(new_nodes.size());
     }
 
     Vector<UInt> nb_new_stuff = {nb_new_nodes, elements_event.getList().size()};
     const auto & comm = mesh.getCommunicator();
     comm.allReduce(nb_new_stuff, SynchronizerOperation::_sum);
 
     if (nb_new_stuff(1) > 0) {
       mesh.sendEvent(elements_event);
       MeshUtils::resetFacetToDouble(mesh.getMeshFacets());
     }
 
     if (nb_new_stuff(0) > 0) {
       mesh.sendEvent(nodes_event);
       // mesh.sendEvent(global_ids_updater.getChangedNodeEvent());
     }
 
     return std::make_tuple(nb_new_stuff(0), nb_new_stuff(1));
   }
 
 private:
   SolidMechanicsModelCohesive & model;
   Mesh & mesh;
   GlobalIdsUpdater global_ids_updater;
 };
 
 /* -------------------------------------------------------------------------- */
 SolidMechanicsModelCohesive::SolidMechanicsModelCohesive(
     Mesh & mesh, UInt dim, const ID & id, const MemoryID & memory_id)
     : SolidMechanicsModel(mesh, dim, id, memory_id,
                           ModelType::_solid_mechanics_model_cohesive),
       tangents("tangents", id), facet_stress("facet_stress", id),
       facet_material("facet_material", id) {
   AKANTU_DEBUG_IN();
 
   registerFEEngineObject<MyFEEngineCohesiveType>("CohesiveFEEngine", mesh,
                                                  Model::spatial_dimension);
 
   auto && tmp_material_selector =
       std::make_shared<DefaultMaterialCohesiveSelector>(*this);
 
   tmp_material_selector->setFallback(this->material_selector);
   this->material_selector = tmp_material_selector;
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.registerDumper<DumperParaview>("cohesive elements", id);
   this->mesh.addDumpMeshToDumper("cohesive elements", mesh,
                                  Model::spatial_dimension, _not_ghost,
                                  _ek_cohesive);
 #endif
 
   if (this->mesh.isDistributed()) {
     /// create the distributed synchronizer for cohesive elements
     this->cohesive_synchronizer = std::make_unique<ElementSynchronizer>(
         mesh, "cohesive_distributed_synchronizer");
 
     auto & synchronizer = mesh.getElementSynchronizer();
     this->cohesive_synchronizer->split(synchronizer, [](auto && el) {
       return Mesh::getKind(el.type) == _ek_cohesive;
     });
 
     this->registerSynchronizer(*cohesive_synchronizer,
                                SynchronizationTag::_material_id);
     this->registerSynchronizer(*cohesive_synchronizer,
                                SynchronizationTag::_smm_stress);
     this->registerSynchronizer(*cohesive_synchronizer,
                                SynchronizationTag::_smm_boundary);
   }
 
   this->inserter = std::make_unique<CohesiveElementInserter>(
       this->mesh, id + ":cohesive_element_inserter");
 
   registerFEEngineObject<MyFEEngineFacetType>(
       "FacetsFEEngine", mesh.getMeshFacets(), Model::spatial_dimension - 1);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 SolidMechanicsModelCohesive::~SolidMechanicsModelCohesive() = default;
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::setTimeStep(Real time_step,
                                               const ID & solver_id) {
   SolidMechanicsModel::setTimeStep(time_step, solver_id);
 
 #if defined(AKANTU_USE_IOHELPER)
   this->mesh.getDumper("cohesive elements").setTimeStep(time_step);
 #endif
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initFullImpl(const ModelOptions & options) {
   AKANTU_DEBUG_IN();
 
   const auto & smmc_options =
       aka::as_type<SolidMechanicsModelCohesiveOptions>(options);
 
   this->is_extrinsic = smmc_options.is_extrinsic;
 
   inserter->setIsExtrinsic(is_extrinsic);
 
   if (mesh.isDistributed()) {
     auto & mesh_facets = inserter->getMeshFacets();
     auto & synchronizer =
         aka::as_type<FacetSynchronizer>(mesh_facets.getElementSynchronizer());
 
     // synchronizeGhostFacetsConnectivity();
 
     /// create the facet synchronizer for extrinsic simulations
     if (is_extrinsic) {
       facet_stress_synchronizer = std::make_unique<ElementSynchronizer>(
           synchronizer, id + ":facet_stress_synchronizer");
       facet_stress_synchronizer->swapSendRecv();
       this->registerSynchronizer(*facet_stress_synchronizer,
                                  SynchronizationTag::_smmc_facets_stress);
     }
   }
 
   MeshAccessor mesh_accessor(mesh);
   mesh_accessor.registerGlobalDataUpdater(
       std::make_unique<CohesiveMeshGlobalDataUpdater>(*this));
 
   ParserSection section;
   bool is_empty;
   std::tie(section, is_empty) = this->getParserSection();
 
   if (not is_empty) {
     auto inserter_section =
         section.getSubSections(ParserType::_cohesive_inserter);
     if (inserter_section.begin() != inserter_section.end()) {
       inserter->parseSection(*inserter_section.begin());
     }
   }
 
   SolidMechanicsModel::initFullImpl(options);
 
   AKANTU_DEBUG_OUT();
 } // namespace akantu
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initMaterials() {
   AKANTU_DEBUG_IN();
 
   // make sure the material are instantiated
   if (not are_materials_instantiated)
     instantiateMaterials();
 
   /// find the first cohesive material
   UInt cohesive_index = UInt(-1);
 
   for (auto && material : enumerate(materials)) {
     if (dynamic_cast<MaterialCohesive *>(std::get<1>(material).get())) {
       cohesive_index = std::get<0>(material);
       break;
     }
   }
 
   if (cohesive_index == UInt(-1))
     AKANTU_EXCEPTION("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
   // to know what material to call for stress checks
 
   const Mesh & mesh_facets = inserter->getMeshFacets();
   facet_material.initialize(
       mesh_facets, _spatial_dimension = spatial_dimension - 1,
       _with_nb_element = true,
       _default_value = material_selector->getFallbackValue());
 
   for_each_element(
       mesh_facets,
       [&](auto && element) {
         auto mat_index = (*material_selector)(element);
         auto & mat = aka::as_type<MaterialCohesive>(*materials[mat_index]);
         facet_material(element) = mat_index;
         if (is_extrinsic) {
           mat.addFacet(element);
         }
       },
       _spatial_dimension = spatial_dimension - 1, _ghost_type = _not_ghost);
 
   SolidMechanicsModel::initMaterials();
 
   if (is_extrinsic) {
     this->initAutomaticInsertion();
   } else {
     this->insertIntrinsicElements();
   }
 
   AKANTU_DEBUG_OUT();
 } // namespace akantu
 
 /* -------------------------------------------------------------------------- */
 /**
  * Initialize the model,basically it  pre-compute the shapes, shapes derivatives
  * and jacobian
  */
 void SolidMechanicsModelCohesive::initModel() {
   AKANTU_DEBUG_IN();
 
   SolidMechanicsModel::initModel();
 
   /// add cohesive type connectivity
   ElementType type = _not_defined;
   for (auto && type_ghost : ghost_types) {
     for (const auto & tmp_type :
          mesh.elementTypes(spatial_dimension, type_ghost)) {
       const auto & connectivity = mesh.getConnectivity(tmp_type, type_ghost);
       if (connectivity.size() == 0)
         continue;
 
       type = tmp_type;
       auto type_facet = Mesh::getFacetType(type);
       auto 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);
 
   if (is_extrinsic) {
     getFEEngine("FacetsFEEngine").initShapeFunctions(_not_ghost);
     getFEEngine("FacetsFEEngine").initShapeFunctions(_ghost);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::insertIntrinsicElements() {
   AKANTU_DEBUG_IN();
   inserter->insertIntrinsicElements();
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initAutomaticInsertion() {
   AKANTU_DEBUG_IN();
 
   this->inserter->limitCheckFacets();
   this->updateFacetStressSynchronizer();
   this->resizeFacetStress();
 
   /// compute normals on facets
   this->computeNormals();
 
   this->initStressInterpolation();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::updateAutomaticInsertion() {
   AKANTU_DEBUG_IN();
 
   this->inserter->limitCheckFacets();
   this->updateFacetStressSynchronizer();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::initStressInterpolation() {
   Mesh & mesh_facets = inserter->getMeshFacets();
 
   /// compute quadrature points coordinates on facets
   Array<Real> & position = mesh.getNodes();
 
   ElementTypeMapArray<Real> quad_facets("quad_facets", id);
   quad_facets.initialize(mesh_facets, _nb_component = Model::spatial_dimension,
                          _spatial_dimension = Model::spatial_dimension - 1);
   // mesh_facets.initElementTypeMapArray(quad_facets, Model::spatial_dimension,
   //                                     Model::spatial_dimension - 1);
 
   getFEEngine("FacetsFEEngine")
       .interpolateOnIntegrationPoints(position, quad_facets);
 
   /// compute elements quadrature point positions and build
   /// element-facet quadrature points data structure
   ElementTypeMapArray<Real> elements_quad_facets("elements_quad_facets", id);
 
   elements_quad_facets.initialize(
       mesh, _nb_component = Model::spatial_dimension,
       _spatial_dimension = Model::spatial_dimension);
   // mesh.initElementTypeMapArray(elements_quad_facets,
   // Model::spatial_dimension,
   //                              Model::spatial_dimension);
 
   for (auto elem_gt : ghost_types) {
     for (auto & type : mesh.elementTypes(Model::spatial_dimension, elem_gt)) {
       UInt nb_element = mesh.getNbElement(type, elem_gt);
       if (nb_element == 0)
         continue;
 
       /// compute elements' quadrature points and list of facet
       /// quadrature points positions by element
       const auto & facet_to_element =
           mesh_facets.getSubelementToElement(type, elem_gt);
       auto & el_q_facet = elements_quad_facets(type, elem_gt);
 
       auto facet_type = Mesh::getFacetType(type);
       auto nb_quad_per_facet =
           getFEEngine("FacetsFEEngine").getNbIntegrationPoints(facet_type);
       auto nb_facet_per_elem = facet_to_element.getNbComponent();
 
       // small hack in the loop to skip boundary elements, they are silently
       // initialized to NaN to see if this causes problems
       el_q_facet.resize(nb_element * nb_facet_per_elem * nb_quad_per_facet,
                         std::numeric_limits<Real>::quiet_NaN());
 
       for (auto && data :
            zip(make_view(facet_to_element),
                make_view(el_q_facet, spatial_dimension, nb_quad_per_facet))) {
         const auto & global_facet = std::get<0>(data);
         auto & el_q = std::get<1>(data);
 
         if (global_facet == ElementNull)
           continue;
 
         Matrix<Real> quad_f =
             make_view(quad_facets(global_facet.type, global_facet.ghost_type),
                       spatial_dimension, nb_quad_per_facet)
                 .begin()[global_facet.element];
 
         el_q = quad_f;
 
         // for (UInt q = 0; q < nb_quad_per_facet; ++q) {
         //   for (UInt s = 0; s < Model::spatial_dimension; ++s) {
         //     el_q_facet(el * nb_facet_per_elem * nb_quad_per_facet +
         //                    f * nb_quad_per_facet + q,
         //                s) = quad_f(global_facet * nb_quad_per_facet + q,
         //                s);
         //   }
         // }
         //}
       }
     }
   }
 
   /// loop over non cohesive materials
   for (auto && material : materials) {
     if (dynamic_cast<MaterialCohesive *>(material.get()))
       continue;
     /// initialize the interpolation function
     material->initElementalFieldInterpolation(elements_quad_facets);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::assembleInternalForces() {
   AKANTU_DEBUG_IN();
 
   // f_int += f_int_cohe
   for (auto & material : this->materials) {
     try {
       auto & mat = aka::as_type<MaterialCohesive>(*material);
       mat.computeTraction(_not_ghost);
     } catch (std::bad_cast & bce) {
     }
   }
 
   SolidMechanicsModel::assembleInternalForces();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::computeNormals() {
   AKANTU_DEBUG_IN();
 
   Mesh & mesh_facets = this->inserter->getMeshFacets();
   this->getFEEngine("FacetsFEEngine")
       .computeNormalsOnIntegrationPoints(_not_ghost);
 
   /**
    *  @todo store tangents while computing normals instead of
    *  recomputing them as follows:
    */
   /* ------------------------------------------------------------------------ */
   UInt tangent_components =
       Model::spatial_dimension * (Model::spatial_dimension - 1);
 
   tangents.initialize(mesh_facets, _nb_component = tangent_components,
                       _spatial_dimension = Model::spatial_dimension - 1);
   // mesh_facets.initElementTypeMapArray(tangents, tangent_components,
   //                                     Model::spatial_dimension - 1);
 
   for (auto facet_type :
        mesh_facets.elementTypes(Model::spatial_dimension - 1)) {
     const Array<Real> & normals =
         this->getFEEngine("FacetsFEEngine")
             .getNormalsOnIntegrationPoints(facet_type);
 
     Array<Real> & tangents = this->tangents(facet_type);
 
     Math::compute_tangents(normals, tangents);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::interpolateStress() {
   ElementTypeMapArray<Real> by_elem_result("temporary_stress_by_facets", id);
 
   for (auto & material : materials) {
     auto * mat = dynamic_cast<MaterialCohesive *>(material.get());
     if (mat == nullptr)
       /// interpolate stress on facet quadrature points positions
       material->interpolateStressOnFacets(facet_stress, by_elem_result);
   }
 
   this->synchronize(SynchronizationTag::_smmc_facets_stress);
 }
 
 /* -------------------------------------------------------------------------- */
 UInt SolidMechanicsModelCohesive::checkCohesiveStress() {
   AKANTU_DEBUG_IN();
 
   if (not is_extrinsic) {
     AKANTU_EXCEPTION(
         "This function can only be used for extrinsic cohesive elements");
   }
 
   interpolateStress();
 
   for (auto & mat : materials) {
     auto * mat_cohesive = dynamic_cast<MaterialCohesive *>(mat.get());
     if (mat_cohesive) {
       /// check which not ghost cohesive elements are to be created
       mat_cohesive->checkInsertion();
     }
   }
 
   /// communicate data among processors
   // this->synchronize(SynchronizationTag::_smmc_facets);
 
   /// insert cohesive elements
   UInt nb_new_elements = inserter->insertElements();
 
   // if (nb_new_elements > 0) {
   //   this->reinitializeSolver();
   // }
 
   AKANTU_DEBUG_OUT();
 
   return nb_new_elements;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::onElementsAdded(
     const Array<Element> & element_list, const NewElementsEvent & event) {
   AKANTU_DEBUG_IN();
 
   SolidMechanicsModel::onElementsAdded(element_list, event);
 
   if (is_extrinsic)
     resizeFacetStress();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::onNodesAdded(const Array<UInt> & new_nodes,
                                                const NewNodesEvent & event) {
   AKANTU_DEBUG_IN();
 
   SolidMechanicsModel::onNodesAdded(new_nodes, event);
 
   const CohesiveNewNodesEvent * cohesive_event;
   if ((cohesive_event = dynamic_cast<const CohesiveNewNodesEvent *>(&event)) ==
       nullptr)
     return;
 
   const auto & old_nodes = cohesive_event->getOldNodesList();
 
   auto copy = [this, &new_nodes, &old_nodes](auto & arr) {
     UInt new_node, old_node;
 
     auto view = make_view(arr, spatial_dimension);
     auto begin = view.begin();
 
     for (auto && pair : zip(new_nodes, old_nodes)) {
       std::tie(new_node, old_node) = pair;
 
       auto old_ = begin + old_node;
       auto new_ = begin + new_node;
 
       *new_ = *old_;
     }
   };
-
   copy(*displacement);
+
   copy(*blocked_dofs);
 
   if (velocity)
     copy(*velocity);
 
   if (acceleration)
     copy(*acceleration);
 
   if (current_position)
     copy(*current_position);
 
   if (previous_displacement)
     copy(*previous_displacement);
 
   // if (external_force)
   //   copy(*external_force);
   // if (internal_force)
   //   copy(*internal_force);
 
   if (displacement_increment)
     copy(*displacement_increment);
 
   copy(getDOFManager().getSolution("displacement"));
   // this->assembleMassLumped();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::afterSolveStep(bool converged) {
   AKANTU_DEBUG_IN();
 
   /*
    * This is required because the Cauchy stress is the stress measure that
    * is used to check the insertion of cohesive elements
    */
   if (converged) {
     for (auto & mat : materials) {
       if (mat->isFiniteDeformation())
         mat->computeAllCauchyStresses(_not_ghost);
     }
   }
 
   SolidMechanicsModel::afterSolveStep(converged);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::printself(std::ostream & stream,
                                             int indent) const {
   std::string space(indent, AKANTU_INDENT);
 
   stream << space << "SolidMechanicsModelCohesive ["
          << "\n";
   SolidMechanicsModel::printself(stream, indent + 2);
   stream << space << "]" << std::endl;
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::resizeFacetStress() {
   AKANTU_DEBUG_IN();
 
   this->facet_stress.initialize(getFEEngine("FacetsFEEngine"),
                                 _nb_component =
                                     2 * spatial_dimension * spatial_dimension,
                                 _spatial_dimension = spatial_dimension - 1);
 
   // for (auto && ghost_type : ghost_types) {
   //   for (const auto & type :
   //        mesh_facets.elementTypes(spatial_dimension - 1, ghost_type)) {
   //     UInt nb_facet = mesh_facets.getNbElement(type, ghost_type);
 
   //     UInt nb_quadrature_points = getFEEngine("FacetsFEEngine")
   //                                     .getNbIntegrationPoints(type,
   //                                     ghost_type);
 
   //     UInt new_size = nb_facet * nb_quadrature_points;
 
   //     facet_stress(type, ghost_type).resize(new_size);
   //   }
   // }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void SolidMechanicsModelCohesive::addDumpGroupFieldToDumper(
     const std::string & dumper_name, const std::string & field_id,
     const std::string & group_name, const ElementKind & element_kind,
     bool padding_flag) {
   AKANTU_DEBUG_IN();
 
   UInt spatial_dimension = Model::spatial_dimension;
   ElementKind _element_kind = element_kind;
   if (dumper_name == "cohesive elements") {
     _element_kind = _ek_cohesive;
   } else if (dumper_name == "facets") {
     spatial_dimension = Model::spatial_dimension - 1;
   }
   SolidMechanicsModel::addDumpGroupFieldToDumper(dumper_name, field_id,
                                                  group_name, spatial_dimension,
                                                  _element_kind, padding_flag);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 
 void SolidMechanicsModelCohesive::onDump() {
   this->flattenAllRegisteredInternals(_ek_cohesive);
   SolidMechanicsModel::onDump();
 }
 
 /* -------------------------------------------------------------------------- */
 
 } // namespace akantu