diff --git a/examples/contact_mechanics/contact_explicit_static.cc b/examples/contact_mechanics/contact_explicit_static.cc
new file mode 100644
index 000000000..3df2e58c3
--- /dev/null
+++ b/examples/contact_mechanics/contact_explicit_static.cc
@@ -0,0 +1,97 @@
+/**
+ * @file   test_contact_mechanics_model.cc
+ *
+ * @author Mohit Pundir <mohit.pundir@epfl.ch>
+ *
+ * @date creation: Tue Apr 30 2019
+ * @date last modification: Tue Apr 30 2019
+ *
+ * @brief  Test for contact mechanics model class
+ *
+ * @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.hh"
+#include "contact_mechanics_model.hh"
+#include "coupler_solid_contact.hh"
+#include "non_linear_solver.hh"
+#include "surface_selector.hh"
+/* -------------------------------------------------------------------------- */
+
+using namespace akantu;
+
+/* -------------------------------------------------------------------------- */
+int main(int argc, char *argv[]) {
+
+  
+  const UInt spatial_dimension = 2;
+  initialize("material.dat", argc, argv);
+   
+  Mesh mesh(spatial_dimension);
+  mesh.read("hertz.msh");
+  
+  CouplerSolidContact coupler(mesh);
+
+  auto & solid   = coupler.getSolidMechanicsModel();
+  auto & contact = coupler.getContactMechanicsModel();
+
+  auto && selector = std::make_shared<MeshDataMaterialSelector<std::string>>(
+		     "physical_names",solid);
+  solid.setMaterialSelector(selector);
+  
+  solid.initFull(  _analysis_method = _static);
+  contact.initFull(_analysis_method = _implicit_contact);
+
+  auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(mesh);
+  contact.getContactDetector().setSurfaceSelector(surface_selector);
+ 
+  solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "bottom");
+  solid.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "bottom");
+  solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "top");
+
+  coupler.initFull(_analysis_method = _implicit_contact);
+  
+  coupler.setBaseName("contact-explicit-static");
+  coupler.addDumpFieldVector("displacement");
+  coupler.addDumpFieldVector("velocity");
+  coupler.addDumpFieldVector("normals");
+  coupler.addDumpFieldVector("contact_force");
+  coupler.addDumpFieldVector("external_force");
+  coupler.addDumpFieldVector("internal_force");
+  coupler.addDumpField("gaps");
+  coupler.addDumpField("areas");
+  coupler.addDumpField("blocked_dofs");
+  coupler.addDumpField("grad_u");
+  coupler.addDumpField("stress");
+ 
+  for (auto i : arange(max_steps)) {
+
+    auto increment = 1e-4;
+    solid.applyBC(BC::Dirichlet::IncrementValue(-increment, _y), "top"); 
+
+    coupler.solveStep();    
+    coupler.dump();
+  }
+
+  finalize();
+  return EXIT_SUCCESS;
+}
+
diff --git a/test/test_model/test_contact_mechanics_model/flat_on_flat.geo b/test/test_model/test_contact_mechanics_model/flat_on_flat.geo
new file mode 100644
index 000000000..62e58fb90
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/flat_on_flat.geo
@@ -0,0 +1,40 @@
+h = 4.0;
+height = 1.0;
+length = 1.0;
+epsilon=1e-3;
+
+Point(1) = {0,  0, 0, h*0.1};
+Point(2) = {length, 0, 0, h*0.1};
+Point(3) = {length, height/2-epsilon, 0, h*0.1};
+Point(4) = {length, height, 0, h*0.2};
+Point(5) = {0, height, 0, h*0.2};
+Point(6) = {0, height/2+epsilon, 0, h*0.2};
+Point(7) = {length, height/2+epsilon, 0, h*0.2};
+Point(8) = {0, height/2-epsilon, 0, h*0.1};
+
+Line(1) = {1, 2};
+Line(2) = {2, 3};
+Line(3) = {7, 4};
+Line(4) = {4, 5};
+Line(5) = {5, 6};
+Line(6) = {6, 7};
+Line(7) = {8, 1};
+Line(8) = {3, 8};
+
+Line Loop(1) = {1, 2, 8, 7};
+Line Loop(2) = {3, 4, 5, 6};
+
+Plane Surface(1) = {1};
+Plane Surface(2) = {2};
+
+Physical Line ("top") = {4};
+Physical Line ("bottom") = {1};
+
+Physical Line ("contact_top") = {6};
+Physical Line ("contact_bottom") = {8};
+
+Physical Surface("bot_body") = {1};
+Physical Surface("top_body") = {2};
+
+Transfinite Surface{1, 2};
+Recombine Surface{1, 2};
\ No newline at end of file
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_1D.geo b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_1D.geo
new file mode 100644
index 000000000..ce535838e
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_1D.geo
@@ -0,0 +1,18 @@
+h = 0.5;
+
+Point(1) = { 1., 0., 0., h};
+Point(3) = { 0., 0., 0., h};
+Point(4) = { 0., 0., 0., h};
+Point(2) = {-1., 0., 0., h};
+
+Line(1) = {2, 3};
+Line(2) = {4, 1};
+
+Physical Point ("loading") = {1};
+Physical Point ("fixed") = {2};
+
+Physical Point ("master") = {3};
+Physical Point ("slave") = {4};
+
+Physical Line ("master_body") = {1};
+Physical Line ("slave_body") = {2};
\ No newline at end of file
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D.geo b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D.geo
new file mode 100644
index 000000000..29491a861
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D.geo
@@ -0,0 +1,39 @@
+h = 0.4;
+
+y = 1;
+x = 2;
+
+Point(1) = { x/2., y/2, 0, h};
+Point(2) = {-x/2., y/2, 0, h};
+Point(3) = {-x/2.,-y/2, 0, h};
+Point(4) = { x/2.,-y/2, 0, h};
+Point(5) = {-x/2.,   0, 0, h};
+Point(6) = { x/2.,   0, 0, h};
+Point(7) = {-x/2.,   0, 0, h};
+Point(8) = { x/2.,   0, 0, h};
+
+Line(1) = {1, 2};
+Line(2) = {2, 5};
+Line(3) = {5, 6};
+Line(4) = {6, 1};
+
+Line(5) = {7, 3};
+Line(6) = {3, 4};
+Line(7) = {4, 8};
+Line(8) = {8, 7};
+
+Line Loop(1) = {1, 2, 3, 4};
+Line Loop(2) = {5, 6, 7, 8};
+
+Plane Surface(1) = {1};
+Plane Surface(2) = {2};
+
+Physical Line("fixed") = {6};
+Physical Line("loading") = {1};
+Physical Line("master") = {3};
+Physical Line("slave") = {8};
+
+Physical Line("sides") = {2, 5, 7, 4};
+
+Physical Surface("master_body") = {1};
+Physical Surface("slave_body") = {2};
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D.msh b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D.msh
new file mode 100644
index 000000000..f9a6e5773
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D.msh
@@ -0,0 +1,51 @@
+$MeshFormat
+2.2 0 8
+$EndMeshFormat
+$PhysicalNames
+4
+1 1 "fixed"
+1 2 "loading"
+1 3 "insertion"
+2 4 "body"
+$EndPhysicalNames
+$Nodes
+13
+1 1 1 0
+2 -1 1 0
+3 -1 -1 0
+4 1 -1 0
+5 -1 0 0
+6 1 0 0
+7 2.752797989558076e-12 1 0
+8 -2.752797989558076e-12 0 0
+9 -2.752797989558076e-12 -1 0
+10 -0.4999999999986235 0.5000000000027528 0
+11 0.5000000000013765 0.5 0
+12 0.4999999999986235 -0.5 0
+13 -0.5000000000013765 -0.5 0
+$EndNodes
+$Elements
+22
+1 1 4 2 1 1 1 1 7
+2 1 4 2 1 1 1 7 2
+3 1 2 3 3 5 8
+4 1 2 3 3 8 6
+5 1 4 1 6 1 3 3 9
+6 1 4 1 6 1 3 9 4
+7 2 5 4 1 2 1 -2 11 7 10
+8 2 5 4 1 2 2 -1 8 11 10
+9 2 5 4 1 2 1 -2 2 10 7
+10 2 6 4 1 3 2 -1 -3 6 11 8
+11 2 6 4 1 3 1 -2 -3 1 11 6
+12 2 6 4 1 3 1 -2 -3 2 5 10
+13 2 6 4 1 3 2 -1 -3 5 8 10
+14 2 5 4 1 2 1 -2 1 7 11
+15 2 5 4 2 2 2 -3 12 8 13
+16 2 5 4 2 2 3 -2 9 12 13
+17 2 5 4 2 2 3 -2 4 12 9
+18 2 6 4 2 3 2 -1 -3 6 8 12
+19 2 6 4 2 3 3 -1 -2 3 13 5
+20 2 6 4 2 3 3 -1 -2 4 6 12
+21 2 5 4 2 2 3 -2 3 9 13
+22 2 6 4 2 3 2 -1 -3 5 13 8
+$EndElements
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D_mixte.geo b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D_mixte.geo
new file mode 100644
index 000000000..eac33c855
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D_mixte.geo
@@ -0,0 +1,43 @@
+h = 0.4;
+
+y = 1;
+x = 2;
+
+Point(1) = { x/2., y/2, 0, h};
+Point(2) = {-x/2., y/2, 0, h};
+Point(3) = {-x/2.,-y/2, 0, h};
+Point(4) = { x/2.,-y/2, 0, h};
+Point(5) = {-x/2.,   0, 0, h};
+Point(6) = { x/2.,   0, 0, h};
+Point(7) = {-x/2.,   0, 0, h};
+Point(8) = { x/2.,   0, 0, h};
+
+Line(1) = {1, 2};
+Line(2) = {2, 5};
+Line(3) = {5, 6};
+Line(4) = {6, 1};
+
+Line(5) = {7, 3};
+Line(6) = {3, 4};
+Line(7) = {4, 8};
+Line(8) = {8, 7};
+
+Line Loop(1) = {1, 2, 3, 4};
+Line Loop(2) = {5, 6, 7, 8};
+
+Plane Surface(1) = {1};
+Plane Surface(2) = {2};
+
+Physical Line("fixed") = {6};
+Physical Line("loading") = {1};
+Physical Line("master") = {3};
+Physical Line("slave") = {8};
+
+Physical Line("sides") = {2, 5, 7, 4};
+
+Physical Surface("master_body") = {1};
+Physical Surface("slave_body") = {2};
+
+Recombine Surface {2};
+Transfinite Surface {2};
+Mesh.SecondOrderIncomplete = 1;
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D_structured.geo b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D_structured.geo
new file mode 100644
index 000000000..07974bcd7
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_2D_structured.geo
@@ -0,0 +1,43 @@
+h = 0.2;
+
+y = 1;
+x = 2;
+
+Point(1) = { x/2., y/2, 0, h};
+Point(2) = {-x/2., y/2, 0, h};
+Point(3) = {-x/2.,-y/2, 0, h};
+Point(4) = { x/2.,-y/2, 0, h};
+Point(5) = {-x/2.,   0, 0, h};
+Point(6) = { x/2.,   0, 0, h};
+Point(7) = {-x/2.,   0, 0, h};
+Point(8) = { x/2.,   0, 0, h};
+
+Line(1) = {1, 2};
+Line(2) = {2, 5};
+Line(3) = {5, 6};
+Line(4) = {6, 1};
+
+Line(5) = {7, 3};
+Line(6) = {3, 4};
+Line(7) = {4, 8};
+Line(8) = {8, 7};
+
+Line Loop(1) = {1, 2, 3, 4};
+Line Loop(2) = {5, 6, 7, 8};
+
+Plane Surface(1) = {1};
+Plane Surface(2) = {2};
+
+Physical Line("fixed") = {6};
+Physical Line("loading") = {1};
+Physical Line("master") = {3};
+Physical Line("slave") = {8};
+
+Physical Line("sides") = {2, 5, 7, 4};
+
+Physical Surface("master_body") = {1};
+Physical Surface("slave_body") = {2};
+
+Recombine Surface "*";
+Transfinite Surface "*";
+Mesh.SecondOrderIncomplete = 1;
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_3D.geo b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_3D.geo
new file mode 100644
index 000000000..3242a10d2
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_3D.geo
@@ -0,0 +1,37 @@
+h = 0.7;
+
+z = 1;
+y = 2;
+x = 2;
+
+Point(1) = { x/2, y/2, -z/2, h};
+Point(2) = {-x/2, y/2, -z/2, h};
+Point(3) = {-x/2,-y/2, -z/2, h};
+Point(4) = { x/2,-y/2, -z/2, h};
+
+Point(5) = {-x/2, 0,  -z/2, h};
+Point(6) = { x/2, 0,  -z/2, h};
+
+Line(1) = {1, 2};
+Line(2) = {2, 5};
+Line(3) = {5, 6};
+Line(4) = {6, 1};
+
+Line(5) = {5, 3};
+Line(6) = {3, 4};
+Line(7) = {4, 6};
+
+Line Loop(1) = {1, 2, 3, 4};
+Line Loop(2) = {-3, 5, 6, 7};
+Plane Surface(1) = {1};
+Plane Surface(2) = {2};
+Extrude {0, 0, z} {
+  Surface{1}; Surface{2};
+}
+
+Physical Surface("fixed") = {46};
+Physical Surface("insertion") = {24};
+Physical Surface("loading") = {16};
+Physical Surface("sides") = {1, 20, 29, 28, 50, 2, 51, 42};
+
+Physical Volume("body") = {1, 2};
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_3D_structured.geo b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_3D_structured.geo
new file mode 100644
index 000000000..c54ed8705
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/data/cohesive_strait_3D_structured.geo
@@ -0,0 +1,40 @@
+h = 0.5;
+
+Point(1) = { 1, 1, -.5, h};
+Point(2) = {-1, 1, -.5, h};
+Point(3) = {-1,-1, -.5, h};
+Point(4) = { 1,-1, -.5, h};
+
+Point(5) = {-1, 0, -.5, h};
+Point(6) = { 1, 0, -.5, h};
+
+Line(1) = {1, 2};
+Line(2) = {2, 5};
+Line(3) = {5, 6};
+Line(4) = {6, 1};
+
+Line(5) = {5, 3};
+Line(6) = {3, 4};
+Line(7) = {4, 6};
+
+Line Loop(1) = {1, 2, 3, 4};
+Line Loop(2) = {-3, 5, 6, 7};
+Plane Surface(1) = {1};
+Plane Surface(2) = {2};
+Extrude {0, 0, 1} {
+  Surface{1}; Surface{2};
+}
+
+Physical Surface("fixed") = {46};
+Physical Surface("insertion") = {24};
+Physical Surface("loading") = {16};
+Physical Surface("sides") = {1, 20, 29, 28, 50, 2, 51, 42};
+
+Physical Volume("body") = {1, 2};
+
+Transfinite Surface "*";
+Transfinite Volume "*";
+
+Recombine Surface "*";
+
+Mesh.SecondOrderIncomplete = 1;
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/data/test.msh b/test/test_model/test_contact_mechanics_model/test_detector/data/test.msh
new file mode 100644
index 000000000..1d659722f
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/data/test.msh
@@ -0,0 +1,51 @@
+$MeshFormat
+2.2 0 8
+$EndMeshFormat
+$PhysicalNames
+4
+1 1 "fixed"
+1 2 "loading"
+1 3 "insertion"
+2 4 "body"
+$EndPhysicalNames
+$Nodes
+13
+1 1 1 0
+2 -1 1 0
+3 -1 -1 0
+4 1 -1 0
+5 -1 0 0
+6 1 0 0
+7 2.752797989558076e-12 1 0
+8 -2.752797989558076e-12 0 0
+9 -2.752797989558076e-12 -1 0
+10 -0.4999999999986235 0.5000000000027528 0
+11 0.5000000000013765 0.5 0
+12 0.4999999999986235 -0.5 0
+13 -0.5000000000013765 -0.5 0
+$EndNodes
+$Elements
+22
+1 1 2 2 1 1 7
+2 1 2 2 1 7 2
+3 1 2 3 3 5 8
+4 1 2 3 3 8 6
+5 1 2 1 6 3 9
+6 1 2 1 6 9 4
+7 2 2 4 1 11 7 10
+8 2 2 4 1 8 11 10
+9 2 2 4 1 2 10 7
+10 2 2 4 1 6 11 8
+11 2 2 4 1 1 11 6
+12 2 2 4 1 2 5 10
+13 2 2 4 1 5 8 10
+14 2 2 4 1 1 7 11
+15 2 2 4 2 12 8 13
+16 2 2 4 2 9 12 13
+17 2 2 4 2 4 12 9
+18 2 2 4 2 6 8 12
+19 2 2 4 2 3 13 5
+20 2 2 4 2 4 6 12
+21 2 2 4 2 3 9 13
+22 2 2 4 2 5 13 8
+$EndElements
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/test_detection.cc b/test/test_model/test_contact_mechanics_model/test_detector/test_detection.cc
new file mode 100644
index 000000000..4e5ba3fee
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/test_detection.cc
@@ -0,0 +1,61 @@
+/**
+ * @file   test_detection.cc
+ *
+ * @author Mohit Pundir <mohit.pundir@epfl.ch>
+ *
+ * @date creation: Sat Feb 29 2020
+ * @date last modification: Sat Feb 29 2020
+ *
+ * @brief  Generic test for detection between different element types
+ *
+ * @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 "aka_iterators.hh"
+#include "communicator.hh"
+#include "test_detection_fixture.hh"
+/* -------------------------------------------------------------------------- */
+
+
+TYPED_TEST(TestCMMDFixture, Implicit) {
+
+  this->analysis_method = _static;
+  this->detection_type = _implicit_contact;
+
+  this->testImplicit();
+
+  this->checkGap();
+  
+}
+
+
+TYPED_TEST(TestCMMDFixture, Explicit) {
+
+  this->analysis_method = _static;
+  this->detection_type = _explicit_contact;
+
+  this->testExplicit();
+
+  this->checkGap();
+  
+}
+
+
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/test_detection_fixture.hh b/test/test_model/test_contact_mechanics_model/test_detector/test_detection_fixture.hh
new file mode 100644
index 000000000..779295793
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_detector/test_detection_fixture.hh
@@ -0,0 +1,224 @@
+/**
+ * @file   test_detection_fixture.hh
+ *
+ * @author Mohit Pundir <mohit.pundir@epfl.ch>
+ *
+ * @date creation: Sat Feb 29 2020
+ * @date last modification: Sat Feb 29 2020
+ *
+ * @brief  Contact detection test fixture
+ *
+ * @section LICENSE
+ *
+ * Copyright (©) 2016-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 "contact_mechanics_mdoel.hh"
+#include "solid_mechanics_model.hh"
+#include "test_gtest_utils.hh"
+/* -------------------------------------------------------------------------- */
+#include <gtest/gtest.h>
+#include <vector>
+/* -------------------------------------------------------------------------- */
+
+#ifndef __AKANTU_TEST_DETECTION_FIXTURE_HH__
+#define __AKANTU_TEST_DETECTION_FIXTURE_HH__
+
+using namespace akantu;
+
+template <::akantu::AnalysisMethod t>
+using analysis_method_t std::integral_constant<::akantu::AnalysisMethod, t>;
+
+class StrainIncrement : public BC::Functor {
+public:
+  StrainIncrement(const Matrix<Real> & strain, BC::Axis dir)
+      : strain_inc(strain), dir(dir) {}
+
+  void operator()(UInt /*node*/, Vector<bool> & flags, Vector<Real> & primal,
+                  const Vector<Real> & coord) const {
+    if (std::abs(coord(dir)) < 1e-8) {
+      return;
+    }
+
+    flags.set(true);
+    primal += strain_inc * coord;
+  }
+
+  static const BC::Functor::Type type = BC::Functor::_dirichlet;
+
+private:
+  Matrix<Real> strain_inc;
+  BC::Axis dir;
+};
+
+template <typename param_> class TestCMMDFixture : public ::testing::Test {
+public:
+
+  static constexpr ElementType type_1 = std::tuple_element_t<1, param_>::value;
+  static constexpr ElementType type_2 = std::tuple_element_t<2, param_>::value;
+
+  void Setup() override {
+    mesh = std::make_unique<Mesh>(this->dim);
+    if (Communicator::getStaticCommunicator().whoAmI() == 0) {
+      ASSERT_NO_THROW({ mesh->read(this->mesh_name); });
+    }
+    mesh->distribute();
+  }
+
+  void TearDown() override {
+    solid.reset(nullptr);
+    contact.reset(nullptr);
+    mesh.reset(nullptr);
+  }
+
+  void createModel() {
+    solid = std::make_unique<SolidmechanicsModel>(*mesh);
+    solid->initFull(_analysis_method = this->analysis_method);
+    
+    contact = std::make_unique<ContactMechanicsModel>(*mesh);
+    contact->initFull(_analysis_method = this->detection_type);
+    auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(*mesh);
+    contact->getContactDetector().setSurfaceSelector(surface_selector);
+  }
+
+  void setInitialCondition(const Matrix<Real> & strain) {
+    for (auto && data :
+         zip(make_view(this->mesh->getNodes(), this->dim),
+             make_view(this->solid->getDisplacement(), this->dim))) {
+      const auto & pos = std::get<0>(data);
+      auto & disp = std::get<1>(data);
+      disp = strain * pos;
+    }
+  }
+
+  void steps(const Matrix<Real> & strain) {
+    StrainIncrement functor((1. / 300) * strain, this->dim == 1 ? _x : _y);
+
+    for (auto _ [[gnu::unused]] : arange(nb_steps)) {
+      this->solid->applyBC(functor, "loading");
+      this->solid->applyBC(functor, "fixed");
+      this->solid->solveStep();
+    }
+  }
+
+  void testImplicit() {
+    this->createModel();
+    auto & mat_el = this->solid->getMaterial("body");
+
+    SCOPED_TRACE(std::to_string(this->dim) + "D - " + std::to_string(type_1) +
+                 ":" + std::to_string(type_2));
+    
+    if (this->dim > 1)
+      this->model->applyBC(BC::Dirichlet::FlagOnly(_y), "sides");
+    if (this->dim > 2)
+      this->model->applyBC(BC::Dirichlet::FlagOnly(_z), "sides");
+
+    Real E = mat_el.get("E");
+    Real nu = mat_el.get("nu");
+
+    
+    Matrix<Real> strain;
+    if (dim == 1) {
+      strain = {{1.}};
+    } else if (dim == 2) {
+      strain = {{-nu, 0.}, {0., 1. - nu}};
+      strain *= (1. + nu);
+    } else if (dim == 3) {
+      strain = {{-nu, 0., 0.}, {0., 1., 0.}, {0., 0., -nu}};
+    }
+        
+    this->setInitialCondition((1 - 1e-5) * strain);
+    this->steps(1e-2 * strain);
+
+    this->contact->search();
+  }
+
+  void testExplicit() {
+    this->createModel();
+    auto & mat_el = this->solid->getMaterial("body");
+
+    SCOPED_TRACE(std::to_string(this->dim) + "D - " + std::to_string(type_1) +
+                 ":" + std::to_string(type_2));
+    
+    if (this->dim > 1)
+      this->model->applyBC(BC::Dirichlet::FlagOnly(_y), "sides");
+    if (this->dim > 2)
+      this->model->applyBC(BC::Dirichlet::FlagOnly(_z), "sides");
+
+    Real E = mat_el.get("E");
+    Real nu = mat_el.get("nu");
+
+    
+    Matrix<Real> strain;
+    if (dim == 1) {
+      strain = {{-1.}};
+    } else if (dim == 2) {
+      strain = {{-nu, 0.}, {0., 1. - nu}};
+      strain *= (1. + nu);
+    } else if (dim == 3) {
+      strain = {{-nu, 0., 0.}, {0., 1., 0.}, {0., 0., -nu}};
+    }
+        
+    this->setInitialCondition((1 - 1e-5) * strain);
+    this->steps(1e-2 * strain);
+
+    this->contact->search();
+
+  }
+
+  bool checkGap() {
+
+  }
+
+  bool checkNormal() {
+
+  }
+
+  bool checkCovariantBasis() {
+
+  }
+
+  
+
+protected:
+  std::unique_ptr<Mesh> mesh;
+  std::unique_ptr<SolidMechanicsModel> solid;
+  std::unique_ptr<ContactMechanicsModel> contact;
+
+  std::string mesh_name{std::to_string(detection_type) + std::to_string(type_1) +
+                        (type_1 == type_2 ? "" : std::to_string(type_2)) +
+                        ".msh"};
+  
+  AnalysisMethod analysis_method;
+  DetectionType detection_type;
+};
+
+/* -------------------------------------------------------------------------- */
+
+
+using element_types = gtest_list_t<std::tuple<
+  std::tuple<_element_type_segment_2, _element_type_segement_2>,
+  std::tuple< _element_type_triangle_3, _element_type_triangle_3>,
+  std::tuple<_element_type_triangle_3, _element_type_quadrangle_4>,
+  std::tuple<_element_type_quadrangle_4, _element_type_quadrange_4>,
+  std::tuple<_element_type_tetrahedron_6, _element_type_tetrahedron_6> >>;
+
+
+TYPED_TEST_SUITE(TestCMMDFixture, detection_types)
+
+#endif
diff --git a/test/test_model/test_contact_mechanics_model/test_explicit_dynamic.cc b/test/test_model/test_contact_mechanics_model/test_explicit_dynamic.cc
new file mode 100644
index 000000000..10ca5c71b
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_explicit_dynamic.cc
@@ -0,0 +1,114 @@
+/* -------------------------------------------------------------------------- */
+#include "contact_mechanics_model.hh"
+#include "coupler_solid_contact.hh"
+#include "non_linear_solver.hh"
+#include "solid_mechanics_model.hh"
+#include "surface_selector.hh"
+/* -------------------------------------------------------------------------- */
+
+using namespace akantu;
+
+int main(int argc, char * argv[]) {
+
+  UInt max_steps        = 20000;
+  Real max_weight       = 0.02;
+  UInt damping_interval = 10;
+  Real damping_ratio    = 0.9;
+
+  std::string mesh_file     = "flat_on_flat.msh";
+  std::string material_file = "material.dat";
+
+  const UInt spatial_dimension = 2;
+
+  initialize(material_file, argc, argv);
+
+  Mesh mesh(spatial_dimension);
+  mesh.read(mesh_file);
+
+  CouplerSolidContact coupler(mesh);
+
+  auto & solid = coupler.getSolidMechanicsModel();
+  auto & contact = coupler.getContactMechanicsModel();
+
+  auto && material_selector =
+      std::make_shared<MeshDataMaterialSelector<std::string>>("physical_names",
+                                                              solid);
+  solid.setMaterialSelector(material_selector);
+
+  solid.initFull(_analysis_method   = _explicit_lumped_mass);
+  contact.initFull(_analysis_method = _explicit_dynamic_contact);
+
+  auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(mesh);
+  contact.getContactDetector().setSurfaceSelector(surface_selector);
+
+  solid.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "bottom");
+  solid.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "bottom");
+
+  Vector<Real> weight = {0, -max_weight};
+  solid.applyBC(BC::Neumann::FromSameDim(weight), "top");
+
+  coupler.initFull(_analysis_method = _explicit_dynamic_contact);
+
+  Real time_step = solid.getStableTimeStep();
+  time_step *= 0.1;
+
+  coupler.setTimeStep(time_step);
+
+  coupler.setBaseName("flat-on-flat");
+  coupler.addDumpFieldVector("displacement");
+  coupler.addDumpFieldVector("normals");
+  coupler.addDumpFieldVector("contact_force");
+  coupler.addDumpFieldVector("external_force");
+  coupler.addDumpFieldVector("internal_force");
+  coupler.addDumpField("gaps");
+  coupler.addDumpField("areas");
+  coupler.addDumpField("blocked_dofs");
+  coupler.addDumpField("strain");
+  coupler.addDumpField("stress");
+
+  auto & velocity = solid.getVelocity();
+
+  for (UInt s : arange(max_steps)) {
+
+    coupler.solveStep();
+
+    if (s % damping_interval == 0) {
+      for (auto & v : make_view(velocity))
+        v *= damping_ratio;
+    }
+
+    if (s % 100 == 0) {
+      coupler.dump();
+    }
+  }
+
+  const ElementType element_type =  _quad_4;
+  const Array<Real> & stress_vect = model.getMaterial("top_body").getStress(element_type);
+  
+  auto stress_it = stress_vect.begin(spatial_dimension, spatial_dimension);
+  auto stress_end = stress_vect.end(spatial_dimension, spatial_dimension);
+
+  Real stress_tolerance = 1e-13;
+
+  Matrix<Real> presc_stress;
+  
+  for (; stress_it != stress_end; ++stress_it) {
+    const auto & stress = *stress_it;
+    Matrix<Real> diff(spatial_dimension, spatial_dimension);
+
+    diff = stress;
+    diff -= presc_stress;
+    Real stress_error = diff.norm<L_inf>() / stress.norm<L_inf>();
+
+    if (stress_error > stress_tolerance) {
+      std::cerr << "stress error: " << stress_error << " > " << stress_tolerance
+                << std::endl;
+      std::cerr << "stress: " << stress << std::endl
+                << "prescribed stress: " << presc_stress << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+  
+  finalize();
+  return EXIT_SUCCESS;
+}
diff --git a/test/test_model/test_contact_mechanics_model/test_selector/CMakeLists.txt b/test/test_model/test_contact_mechanics_model/test_selector/CMakeLists.txt
new file mode 100644
index 000000000..530b5d7cf
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_selector/CMakeLists.txt
@@ -0,0 +1,47 @@
+#===============================================================================
+# @file   CMakeLists.txt
+#
+# @author Mohit Pundir <mohit.pundir@epfl.ch>
+#
+# @date creation: Sat Feb 29 2020
+# @date last modification: Sat feb 29 2020
+#
+# @brief  configuration for node selection tests
+#
+# @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/>.
+#
+# @section DESCRIPTION
+#
+#===============================================================================
+
+set(_meshes)
+
+add_mesh(selection_seg data/selection_1D.geo
+  DIM 2 ORDER 1
+  OUTPUT _selection_segment_2.msh)
+list(APPEND _meshes selection_2D)
+
+add_mesh(selection_tri data/selection_2D.geo
+  DIM 2 ORDER 1
+  OUTPUT _selection_triangle_3.msh)
+list(APPEND _meshes selection_2D)
+
+add_mesh(detection_tet data/selection_3D.geo
+  DIM 3 ORDER 1
+  OUTPUT _selection_tetrahedron_4.msh)
+list(APPEND _meshes selection_3D)
+
+register_gtest_sources(
+  SOURCES test_selection.cc
+  PACKAGE contact_mechanics
+  DEPENDS ${_meshes}
+  FILES_TO_COPY material.dat
+  )
diff --git a/test/test_model/test_contact_mechanics_model/test_selector/data/selection_1D.geo b/test/test_model/test_contact_mechanics_model/test_selector/data/selection_1D.geo
new file mode 100644
index 000000000..ce535838e
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_selector/data/selection_1D.geo
@@ -0,0 +1,18 @@
+h = 0.5;
+
+Point(1) = { 1., 0., 0., h};
+Point(3) = { 0., 0., 0., h};
+Point(4) = { 0., 0., 0., h};
+Point(2) = {-1., 0., 0., h};
+
+Line(1) = {2, 3};
+Line(2) = {4, 1};
+
+Physical Point ("loading") = {1};
+Physical Point ("fixed") = {2};
+
+Physical Point ("master") = {3};
+Physical Point ("slave") = {4};
+
+Physical Line ("master_body") = {1};
+Physical Line ("slave_body") = {2};
\ No newline at end of file
diff --git a/test/test_model/test_contact_mechanics_model/test_selector/data/selection_2D.geo b/test/test_model/test_contact_mechanics_model/test_selector/data/selection_2D.geo
new file mode 100644
index 000000000..29491a861
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_selector/data/selection_2D.geo
@@ -0,0 +1,39 @@
+h = 0.4;
+
+y = 1;
+x = 2;
+
+Point(1) = { x/2., y/2, 0, h};
+Point(2) = {-x/2., y/2, 0, h};
+Point(3) = {-x/2.,-y/2, 0, h};
+Point(4) = { x/2.,-y/2, 0, h};
+Point(5) = {-x/2.,   0, 0, h};
+Point(6) = { x/2.,   0, 0, h};
+Point(7) = {-x/2.,   0, 0, h};
+Point(8) = { x/2.,   0, 0, h};
+
+Line(1) = {1, 2};
+Line(2) = {2, 5};
+Line(3) = {5, 6};
+Line(4) = {6, 1};
+
+Line(5) = {7, 3};
+Line(6) = {3, 4};
+Line(7) = {4, 8};
+Line(8) = {8, 7};
+
+Line Loop(1) = {1, 2, 3, 4};
+Line Loop(2) = {5, 6, 7, 8};
+
+Plane Surface(1) = {1};
+Plane Surface(2) = {2};
+
+Physical Line("fixed") = {6};
+Physical Line("loading") = {1};
+Physical Line("master") = {3};
+Physical Line("slave") = {8};
+
+Physical Line("sides") = {2, 5, 7, 4};
+
+Physical Surface("master_body") = {1};
+Physical Surface("slave_body") = {2};
diff --git a/test/test_model/test_contact_mechanics_model/test_selector/data/selection_3D.geo b/test/test_model/test_contact_mechanics_model/test_selector/data/selection_3D.geo
new file mode 100644
index 000000000..3242a10d2
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_selector/data/selection_3D.geo
@@ -0,0 +1,37 @@
+h = 0.7;
+
+z = 1;
+y = 2;
+x = 2;
+
+Point(1) = { x/2, y/2, -z/2, h};
+Point(2) = {-x/2, y/2, -z/2, h};
+Point(3) = {-x/2,-y/2, -z/2, h};
+Point(4) = { x/2,-y/2, -z/2, h};
+
+Point(5) = {-x/2, 0,  -z/2, h};
+Point(6) = { x/2, 0,  -z/2, h};
+
+Line(1) = {1, 2};
+Line(2) = {2, 5};
+Line(3) = {5, 6};
+Line(4) = {6, 1};
+
+Line(5) = {5, 3};
+Line(6) = {3, 4};
+Line(7) = {4, 6};
+
+Line Loop(1) = {1, 2, 3, 4};
+Line Loop(2) = {-3, 5, 6, 7};
+Plane Surface(1) = {1};
+Plane Surface(2) = {2};
+Extrude {0, 0, z} {
+  Surface{1}; Surface{2};
+}
+
+Physical Surface("fixed") = {46};
+Physical Surface("insertion") = {24};
+Physical Surface("loading") = {16};
+Physical Surface("sides") = {1, 20, 29, 28, 50, 2, 51, 42};
+
+Physical Volume("body") = {1, 2};
diff --git a/test/test_model/test_contact_mechanics_model/test_selector/material.dat b/test/test_model/test_contact_mechanics_model/test_selector/material.dat
new file mode 100644
index 000000000..2c44b1584
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_selector/material.dat
@@ -0,0 +1,5 @@
+contact_detector [
+  type = implicit		 			
+  master = master
+  slave = master
+]
diff --git a/test/test_model/test_contact_mechanics_model/test_selector/test_selection.cc b/test/test_model/test_contact_mechanics_model/test_selector/test_selection.cc
new file mode 100644
index 000000000..c8cd6cf87
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_selector/test_selection.cc
@@ -0,0 +1,46 @@
+/**
+ * @file   test_selection.cc
+ *
+ * @author Mohit Pundir <mohit.pundir@epfl.ch>
+ *
+ * @date creation: Sun Mar 01 2020
+ * @date last modification: Sun Mar 01 2020
+ *
+ * @brief  Generic test for surface selection
+ *
+ * @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 "test_selection_fixture.hh"
+/* -------------------------------------------------------------------------- */
+
+using namespace akantu;
+
+TYPED_TEST(TestSurfaceSelectionFixture, PhysicalSurface) {
+
+  auto & actual_slave_nodes = this->mesh.getElementgroup("slave").getNodes();
+  auto nb_slave_nodes = actual_slave_nodes.size();
+  this->checkNbSlaveNodes(nb_slave_nodes);
+
+  auto & actual_master_nodes = this->mesh.getElementgroup("master").getNodes();
+  auto nb_master_nodes = actual_master_nodes.size();
+  this->checkNbMasterNodes(nb_master_nodes);
+}
diff --git a/test/test_model/test_contact_mechanics_model/test_selector/test_selection_fixture.hh b/test/test_model/test_contact_mechanics_model/test_selector/test_selection_fixture.hh
new file mode 100644
index 000000000..55c8afeab
--- /dev/null
+++ b/test/test_model/test_contact_mechanics_model/test_selector/test_selection_fixture.hh
@@ -0,0 +1,85 @@
+/**
+ * @file   test_selection.cc
+ *
+ * @author Mohit Pundir <mohit.pundir@epfl.ch>
+ *
+ * @date creation: Sat Feb 29 2020
+ * @date last modification: Sat Feb 29 2020
+ *
+ * @brief  Generic test for selection of nodes across different surfaces
+ *
+ * @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 "aka_iterators.hh"
+#include "communicator.hh"
+#include "surface_selector.hh"
+/* -------------------------------------------------------------------------- */
+#include "test_gtest_utils.hh"
+/* -------------------------------------------------------------------------- */
+#include <gtest/gtest.h>
+#include <vector>
+/* -------------------------------------------------------------------------- */
+
+
+using namespace akantu;
+
+template <typename dim_>
+class TestSurfaceSelecionFixture : public ::testing::Test {
+public:
+  static constexpr size_t spatial_dimension = dim_::value;
+    
+  void Setup() override {
+    mesh = std::make_unique<Mesh>(spatial_dimension);
+    mesh->read("selection_" + std::string(spatial_dimension) + "D.msh");
+    selector = make_unique<PhysicalSurfaceSelector>(*mesh);
+  }
+
+  void TearDown() {
+    mesh.reset(nullptr);
+    selector.reset(nullptr);
+  }
+
+
+  bool checkNbSlaveNodes(UInt & act_slave_nodes) {
+    auto & slave_list = this->selectior->getSlaveList();
+    auto nb_slave_nodes = slave_list.size();
+    EXCEP_EQ(nb_slave_nodes, act_slave_nodes)
+  }
+
+  
+  bool checkNbmasterNodes(UInt & act_master_nodes) {
+    auto & master_list = this->selectior->getMasterList();
+    auto nb_master_nodes = master_list.size();
+    EXCEP_EQ(nb_master_nodes, act_master_nodes)
+  }
+  
+  
+  protected:
+  std::unique_ptr<Mesh> mesh;
+  std::unique_ptr<PhysicalSurfaceSelector> selector
+};
+
+
+using dim_types = gtest_list_t<std::tuple<1, 2, 3>>;
+
+
+TYPED_TEST_SUITE(TestSurfaceSelectionFixture, dim_types);