diff --git a/akantu_simtools.hh b/akantu_simtools.hh
index 7637f5c91..bba41616d 100644
--- a/akantu_simtools.hh
+++ b/akantu_simtools.hh
@@ -1,13 +1,15 @@
 // ast common
 #include "ast_common.hh"
 #include "syncronized_array.hh"
+#include "parameter_reader.hh"
 
 // ntn contact/friction
 #include "ntn_contact.hh"
 #include "ntn_friction.hh"
 #include "ntn_friction_coulomb.hh"
 #include "ntn_friction_linear_slip_weakening.hh"
 
 // ntrf contact/friction
 #include "ntrf_contact.hh"
 #include "ntrf_friction.hh"
+
diff --git a/ntn_contact/ntn_contact.cc b/ntn_contact/ntn_contact.cc
index e0f810ad7..82885742c 100644
--- a/ntn_contact/ntn_contact.cc
+++ b/ntn_contact/ntn_contact.cc
@@ -1,658 +1,632 @@
 /**
  * @file   ntn_contact.cc
  * @author David Kammer <david.kammer@epfl.ch>
  * @date   Thu Mar 14 11:52:00 2013
  *
  * @brief  implementation of ntn_contact
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 // simtools
 #include "ntn_contact.hh"
 
 __BEGIN_SIMTOOLS__
 
 /* -------------------------------------------------------------------------- */
 NTNContact::NTNContact(SolidMechanicsModel & model,
-		       const ContactID & id,
-		       const MemoryID & memory_id) : 
+                       const ContactID & id,
+                       const MemoryID & memory_id) : 
   Memory(memory_id), id(id), model(model),
   slaves(0,1,0,id+":slaves",std::numeric_limits<UInt>::quiet_NaN(),"slaves"),
   masters(0,1,0,id+":masters",std::numeric_limits<UInt>::quiet_NaN(),"masters"),
   normals(0,model.getSpatialDimension(),0,id+":normals",
-	  std::numeric_limits<Real>::quiet_NaN(),"normals"),
+  std::numeric_limits<Real>::quiet_NaN(),"normals"),
   contact_pressure(0,model.getSpatialDimension(),0,id+":contact_pressure",
-		   std::numeric_limits<Real>::quiet_NaN(),"contact_pressure"),
+  std::numeric_limits<Real>::quiet_NaN(),"contact_pressure"),
   is_in_contact(0,1,false,id+":is_in_contact",false,"is_in_contact"),
   lumped_boundary(0,2,0,id+":lumped_boundary",
-		  std::numeric_limits<Real>::quiet_NaN(),"lumped_boundary"),
+  std::numeric_limits<Real>::quiet_NaN(),"lumped_boundary"),
   impedance(0,1,0,id+":impedance",std::numeric_limits<Real>::quiet_NaN(),"impedance"),
   contact_surfaces()
 {
   AKANTU_DEBUG_IN();
 
   FEM & boundary_fem = this->model.getFEMBoundary();
   boundary_fem.initShapeFunctions();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-void NTNContact::addSurfacePair(Surface slave, Surface master, UInt surface_normal_dir) {
+void NTNContact::addSurfacePair(const Surface & slave, const Surface & master, UInt surface_normal_dir) {
   AKANTU_DEBUG_IN();
 
   UInt dim = this->model.getSpatialDimension();
   AKANTU_DEBUG_ASSERT(surface_normal_dir < dim, "Model is of " << dim << " dimensions"
 		      << " and cannot have direction " << surface_normal_dir
 		      << " for surface normal");
 
-  this->contact_surfaces.insert(slave);
-  this->contact_surfaces.insert(master);
+  const Mesh & mesh_ref = this->model.getFEM().getMesh();
+  
+  const SubBoundary & slave_boundary = mesh_ref.getSubBoundary(slave);
+  const SubBoundary & master_boundary = mesh_ref.getSubBoundary(master);
+  
+  this->contact_surfaces.insert(&slave_boundary);
+  this->contact_surfaces.insert(&master_boundary);
 
   // offset for projection computation
   UInt offset[dim-1];
   for (UInt i=0, j=0; i<dim; ++i) {
     if (surface_normal_dir != i) {
       offset[j] = i;
       ++j;
     }
   }
 
-  // get all nodes for all surfaces
-  CSR<UInt> all_surface_nodes;
-  MeshUtils::buildNodesPerSurface(this->model.getFEM().getMesh(), all_surface_nodes);
-
-  // find slave nodes
-  Array<UInt> slave_nodes(0);
-  for(CSR<UInt>::iterator snode = all_surface_nodes.begin(slave); 
-      snode != all_surface_nodes.end(slave); 
-      ++snode) {
-    UInt n = *snode;
-    slave_nodes.push_back(n);
-  }
-  
-  // find master nodes
-  Array<UInt> master_nodes(0);
-  for (CSR<UInt>::iterator mnode = all_surface_nodes.begin(master);
-       mnode != all_surface_nodes.end(master);
-       ++mnode) {
-    UInt n = *mnode;
-    master_nodes.push_back(n);
-  }
-
   // find projected node coordinates
-  const Array<Real> & coordinates = this->model.getFEM().getMesh().getNodes();
-
-  Array<Real> proj_slave_coord(slave_nodes.getSize(),dim-1,0.);
-  for (UInt n=0; n<slave_nodes.getSize(); ++n) {
+  const Array<Real> & coordinates = mesh_ref.getNodes();
+  
+  // find slave nodes
+  Array<Real> proj_slave_coord(slave_boundary.getNbNodes(),dim-1,0.);
+  Array<UInt> slave_nodes(slave_boundary.getNbNodes());
+  UInt n(0);
+  for(SubBoundary::nodes_const_iterator nodes_it(slave_boundary.nodes_begin()); nodes_it!= slave_boundary.nodes_end(); ++nodes_it) {
     for (UInt d=0; d<dim-1; ++d) {
-      proj_slave_coord(n,d) = coordinates(slave_nodes(n),offset[d]);
+      proj_slave_coord(n,d) = coordinates(*nodes_it,offset[d]);
+      slave_nodes(n)=*nodes_it;
     }
+    ++n;
   }
-
-  Array<Real> proj_master_coord(master_nodes.getSize(),dim-1,0.);
-  for (UInt n=0; n<master_nodes.getSize(); ++n) {
+  
+  // find master nodes
+  Array<Real> proj_master_coord(master_boundary.getNbNodes(),dim-1,0.);
+  Array<UInt> master_nodes(master_boundary.getNbNodes());
+  n=0;
+  for(SubBoundary::nodes_const_iterator nodes_it(master_boundary.nodes_begin()); nodes_it!= master_boundary.nodes_end(); ++nodes_it) {
     for (UInt d=0; d<dim-1; ++d) {
-      proj_master_coord(n,d) = coordinates(master_nodes(n),offset[d]);
+      proj_master_coord(n,d) = coordinates(*nodes_it,offset[d]);
+      master_nodes(n)=*nodes_it;
     }
+    ++n;
   }
 
   // find minimum distance between slave nodes to define tolerance
   Real min_dist = std::numeric_limits<Real>::max();
-  for (UInt i=0; i<slave_nodes.getSize(); ++i) {
-    for (UInt j=i+1; j<slave_nodes.getSize(); ++j) {
+  for (UInt i=0; i<proj_slave_coord.getSize(); ++i) {
+    for (UInt j=i+1; j<proj_slave_coord.getSize(); ++j) {
       Real dist = 0.;
       for (UInt d=0; d<dim-1; ++d) {
-	dist += (proj_slave_coord(i,d) - proj_slave_coord(j,d)) 
+	      dist += (proj_slave_coord(i,d) - proj_slave_coord(j,d)) 
 	      * (proj_slave_coord(i,d) - proj_slave_coord(j,d));
       }
-      if (dist < min_dist)
-	min_dist = dist;
+      if (dist < min_dist) {
+	      min_dist = dist;
+	    }
     }
   }
   min_dist = std::sqrt(min_dist);
   Real local_tol = 0.1*min_dist;
 
   // find master slave node pairs
-  for (UInt i=0; i<slave_nodes.getSize(); ++i) {
-    for (UInt j=0; j<master_nodes.getSize(); ++j) {
+  for (UInt i=0; i<proj_slave_coord.getSize(); ++i) {
+    for (UInt j=0; j<proj_master_coord.getSize(); ++j) {
       Real dist = 0.;
       for (UInt d=0; d<dim-1; ++d) {
-	dist += (proj_slave_coord(i,d) - proj_master_coord(j,d)) 
+	      dist += (proj_slave_coord(i,d) - proj_master_coord(j,d)) 
 	      * (proj_slave_coord(i,d) - proj_master_coord(j,d));
       }
       dist = std::sqrt(dist);
       if (dist < local_tol) { // it is a pair
-
-	this->addNodePair(slave_nodes(i), master_nodes(j));
-
-	/*
-	this->slaves.push_back(slave_nodes(i));
-	this->masters.push_back(master_nodes(j));
-	this->is_in_contact.push_back(false);
-	this->contact_pressure.push_back(std::numeric_limits<Real>::quiet_NaN());
-	this->impedance.push_back(std::numeric_limits<Real>::quiet_NaN());
-
-	Real nan_two[2];
-	nan_two[0] = std::numeric_limits<Real>::quiet_NaN();
-	nan_two[1] = std::numeric_limits<Real>::quiet_NaN();
-	this->lumped_boundary.push_back(nan_two);
-
-	Real nan_normal[dim];
-	for (UInt d=0; d<dim; ++d)
-	  nan_normal[d] = std::numeric_limits<Real>::quiet_NaN();
-	this->normals.push_back(nan_normal);
-	*/
-
-	continue; // found master do not need to search further for this slave
+	      this->addNodePair(slave_nodes(i), master_nodes(j));
+	      continue; // found master do not need to search further for this slave
       }
     }
   }
 
   // synchronize with depending nodes
   updateInternalData();
   syncArrays(_added);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::addNodePair(UInt slave, UInt master) {
   AKANTU_DEBUG_IN();
 
   UInt dim = this->model.getSpatialDimension();
   
   // add nodes to the node arrays
   this->slaves.push_back(slave);
   this->masters.push_back(master);
 
   // set contact as false
   this->is_in_contact.push_back(false);
 
   // before initializing 
   // set contact pressure, impedance, normal, lumped_boundary to Nan
   this->contact_pressure.push_back(std::numeric_limits<Real>::quiet_NaN());
   this->impedance.push_back(std::numeric_limits<Real>::quiet_NaN());
   
   Real nan_two[2];
   nan_two[0] = std::numeric_limits<Real>::quiet_NaN();
   nan_two[1] = std::numeric_limits<Real>::quiet_NaN();
   this->lumped_boundary.push_back(nan_two);
   
   Real nan_normal[dim];
   for (UInt d=0; d<dim; ++d)
     nan_normal[d] = std::numeric_limits<Real>::quiet_NaN();
   this->normals.push_back(nan_normal);
 
   AKANTU_DEBUG_OUT();  
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::addNodePairs(Array<UInt> & pairs) {
   AKANTU_DEBUG_IN();
   
   AKANTU_DEBUG_ASSERT(pairs.getNbComponent() == 2, 
 		      "Array of node pairs should have nb_component = 2," << 
 		      " but has nb_component = " << pairs.getNbComponent());
   UInt nb_pairs = pairs.getSize();
   for (UInt n=0; n<nb_pairs; ++n) {
     this->addNodePair(pairs(n,0), pairs(n,1));
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 /*
   This function only works for surface elements with one quad point. For 
   surface elements with more quad points, it computes still, but the result 
   might not be what you are looking for.
  */
 void NTNContact::updateNormals() {
   AKANTU_DEBUG_IN();
 
   UInt dim = this->model.getSpatialDimension();
   const Array<Real> & cur_pos = this->model.getCurrentPosition();
   FEM & boundary_fem = this->model.getFEMBoundary();
 
   // contact information
   UInt nb_contact_nodes = this->masters.getSize();
 
   // set normals to zero
   this->normals.clear();
 
   const Mesh & mesh = this->model.getFEM().getMesh();
   Mesh::type_iterator it = mesh.firstType(dim-1);
   Mesh::type_iterator last = mesh.lastType(dim-1);
   for (; it != last; ++it) {
     // get elements connected to each node
     CSR<UInt> node_to_element;
     MeshUtils::buildNode2ElementsByElementType(mesh, *it, node_to_element);
     // compute the normals
     Array<Real> quad_normals(0,dim);
     boundary_fem.computeNormalsOnControlPoints(cur_pos, quad_normals, *it);
 
     UInt nb_quad_points = boundary_fem.getNbQuadraturePoints(*it);
 
     // add up normals to all master nodes
     for (UInt n=0; n<nb_contact_nodes; ++n) {
       UInt master = this->masters(n);
       CSR<UInt>::iterator elem = node_to_element.begin(master);
       // loop over all elements connected to this master node
       for (; elem != node_to_element.end(master); ++elem) {
 	UInt e = *elem;
 	// loop over all quad points of this element
 	for (UInt q=0; q<nb_quad_points; ++q) {
 	  // add quad normal to master normal
 	  for (UInt d=0; d<dim; ++d) {
 	    this->normals(n,d) += quad_normals(e*nb_quad_points + q, d);
 	  }
 	}
       }
     }
   }
 
   // normalize normals
   Real * master_normals = this->normals.storage();
   for (UInt n=0; n<nb_contact_nodes; ++n) {
     if (dim==2) 
       Math::normalize2(&(master_normals[n*dim]));
     else if (dim==3)
       Math::normalize3(&(master_normals[n*dim]));
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::registerSyncronizedArray(SyncronizedArrayBase & array) {
   AKANTU_DEBUG_IN();
   
   this->slaves.registerDependingArray(array);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::dumpRestart(const std::string & file_name) const {
   AKANTU_DEBUG_IN();
   
   this->slaves.dumpRestartFile(file_name);
   this->masters.dumpRestartFile(file_name);
   this->normals.dumpRestartFile(file_name);
   this->is_in_contact.dumpRestartFile(file_name);
   this->contact_pressure.dumpRestartFile(file_name);
   this->lumped_boundary.dumpRestartFile(file_name);
   this->impedance.dumpRestartFile(file_name);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::readRestart(const std::string & file_name) {
   AKANTU_DEBUG_IN();
   
   this->slaves.readRestartFile(file_name);
   this->masters.readRestartFile(file_name);
   this->normals.readRestartFile(file_name);
   this->is_in_contact.readRestartFile(file_name);
   this->contact_pressure.readRestartFile(file_name);
   this->lumped_boundary.readRestartFile(file_name);
   this->impedance.readRestartFile(file_name);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::updateInternalData() {
   AKANTU_DEBUG_IN();
   
   updateNormals();
   updateLumpedBoundary();
   updateImpedance();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::updateImpedance() {
   AKANTU_DEBUG_IN();
 
   UInt nb_ntn_pairs = getNbContactNodes();
   Real delta_t = this->model.getTimeStep();
   AKANTU_DEBUG_ASSERT(delta_t != NAN, "Time step is NAN. Have you set it already?");
 
   const Array<Real> & mass = this->model.getMass();
 
   for (UInt n=0; n<nb_ntn_pairs; ++n) {  
     UInt master = this->masters(n);
     UInt slave = this->slaves(n);
 
     Real imp = (this->lumped_boundary(n,0) / mass(master)) + (this->lumped_boundary(n,1) / mass(slave));
     imp = 2 / delta_t / imp;
     this->impedance(n) = imp;
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::updateLumpedBoundary() {
   AKANTU_DEBUG_IN();
 
   // set all values in lumped_boundary to zero
   this->lumped_boundary.clear();
 
   UInt dim = this->model.getSpatialDimension(); 
   UInt nb_contact_nodes = getNbContactNodes();
 
   const FEM & boundary_fem = this->model.getFEMBoundary();
 
   const Mesh & mesh = this->model.getFEM().getMesh();
   Mesh::type_iterator it = mesh.firstType(dim-1);
   Mesh::type_iterator last = mesh.lastType(dim-1);
   for (; it != last; ++it) {
     // get elements connected to each node
     CSR<UInt> node_to_element;
     MeshUtils::buildNode2ElementsByElementType(mesh, *it, node_to_element);
 
     UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it);
     const Array<UInt> & connectivity = mesh.getConnectivity(*it);
 
     // get shapes and compute integral 
     const Array<Real> & shapes = boundary_fem.getShapes(*it);
     Array<Real> area(mesh.getNbElement(*it),nb_nodes_per_element);
     boundary_fem.integrate(shapes,area,nb_nodes_per_element,*it);
 
     // get surface id information
-    const Array<UInt> & surface_id = mesh.getSurfaceID(*it);
-    std::set<UInt>::iterator pos;
-    std::set<UInt>::iterator end = this->contact_surfaces.end();
+//    const Array<UInt> & surface_id = mesh.getSurfaceID(*it);
+//    std::set<UInt>::iterator pos;
+//    std::set<UInt>::iterator end = this->contact_surfaces.end();
 
     // loop over contact nodes
     for (UInt i=0; i<2*nb_contact_nodes; ++i) {
       // first round on masters, second round on slaves
       UInt node = std::numeric_limits<UInt>::quiet_NaN();
       UInt n = 0;
       UInt index = 0;
       if (i<nb_contact_nodes) {
-	n = i;
-	node = this->masters(n);
-	index = 0;
+	      n = i;
+	      node = this->masters(n);
+	      index = 0;
       }
       else {
-	n = i-nb_contact_nodes;
-	node = this->slaves(n);
-	index = 1;
+	      n = i-nb_contact_nodes;
+	      node = this->slaves(n);
+	      index = 1;
       }
 
       CSR<UInt>::iterator elem = node_to_element.begin(node);
       // loop over all elements connected to this node
       for (; elem != node_to_element.end(node); ++elem) {
-	UInt e = *elem;
-
-	// if element is not at interface continue
-	pos = this->contact_surfaces.find(surface_id(e));
-	if (pos == end)
-	  continue;
-
-	// loop over all points of this element
-	for (UInt q=0; q<nb_nodes_per_element; ++q) {
-	  if (connectivity(e,q) == node) {
-	    this->lumped_boundary(n,index) += area(e,q);
-	  }
-	}
+	      UInt e = *elem;
+
+	      // if element is not at interface continue
+//	      pos = this->contact_surfaces.find(surface_id(e));
+//	      if (pos == end)
+//	        continue;
+
+	      // loop over all points of this element
+	      for (UInt q=0; q<nb_nodes_per_element; ++q) {
+	        if (connectivity(e,q) == node) {
+	          this->lumped_boundary(n,index) += area(e,q);
+	        }
+	      }
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::computeContactPressure() {
   AKANTU_DEBUG_IN();
 
   UInt dim = this->model.getSpatialDimension();
   Real delta_t = this->model.getTimeStep();
   UInt nb_ntn_pairs = getNbContactNodes();
 
   // pre-compute the acceleration 
   // (not increment acceleration, because residual is still Kf)
   Array<Real> acceleration(this->model.getFEM().getMesh().getNbNodes(),dim);
   this->model.solveLumped(acceleration,
 			  this->model.getMass(),
 			  this->model.getResidual(),
 			  this->model.getBoundary(),
 			  this->model.getF_M2A());
 
   const Array<Real> & residual = this->model.getResidual();
   /*
   for (UInt i=0; i<nb_ntn_pairs; ++i) {
     std::cout << "Master residual = " << residual(masters(i),0) << ", " << residual(masters(i),1) << std::endl;
     std::cout << "Master acceleration = " << acceleration(masters(i),0) << ", " << acceleration(masters(i),1) << std::endl;
     std::cout << "Slave residual = " << residual(slaves(i),0) << ", " << residual(slaves(i),1) << std::endl;
     std::cout << "Slave acceleration = " << acceleration(slaves(i),0) << ", " << acceleration(slaves(i),1) << std::endl;
   }
   */
 
   // compute relative normal fields of displacement, velocity and acceleration 
   Array<Real> r_disp(0,1);
   Array<Real> r_velo(0,1);
   Array<Real> r_acce(0,1);
   Array<Real> r_old_acce(0,1);
   computeRelativeNormalField(this->model.getCurrentPosition(), r_disp);
   computeRelativeNormalField(this->model.getVelocity(),        r_velo);
   computeRelativeNormalField(acceleration,                     r_acce);
   computeRelativeNormalField(this->model.getAcceleration(),    r_old_acce);
 
   AKANTU_DEBUG_ASSERT(r_disp.getSize() == nb_ntn_pairs, 
 		      "computeRelativeNormalField does not give back arrays " 
 		      << "size == nb_ntn_pairs. nb_ntn_pairs = " << nb_ntn_pairs
 		      << " | array size = " << r_disp.getSize());
 
   // compute gap array for all nodes
   Array<Real> gap(nb_ntn_pairs, 1);
   Real * gap_p = gap.storage();
   Real * r_disp_p = r_disp.storage();
   Real * r_velo_p = r_velo.storage();
   Real * r_acce_p = r_acce.storage();
   Real * r_old_acce_p = r_old_acce.storage();
   for (UInt i=0; i<nb_ntn_pairs; ++i) {
     //std::cout << "gap elements: " << *r_disp_p << " " << *r_velo_p << " " << *r_acce_p << std::endl;
     *gap_p = *r_disp_p + delta_t * *r_velo_p + delta_t * delta_t * *r_acce_p - 0.5 * delta_t * delta_t * *r_old_acce_p;
     // increment pointers
     gap_p++;
     r_disp_p++;
     r_velo_p++;
     r_acce_p++;
     r_old_acce_p++;
   }
 
   // check if gap is negative -> is in contact
   for (UInt n=0; n<nb_ntn_pairs; ++n) {
     if (gap(n) < 0.) {
       for (UInt d=0; d<dim; ++d) {
 	this->contact_pressure(n,d) = this->impedance(n) * gap(n) / (2 * delta_t) 
 	                            * this->normals(n,d);
       }
       this->is_in_contact(n) = true;
     }
     else {
       for (UInt d=0; d<dim; ++d)
 	this->contact_pressure(n,d) = 0.;
       this->is_in_contact(n) = false;
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::applyContactPressure() {
   AKANTU_DEBUG_IN();
 
   UInt nb_ntn_pairs = getNbContactNodes();
   UInt dim = this->model.getSpatialDimension();
 
   Array<Real> & residual = this->model.getResidual();
 
   for (UInt n=0; n<nb_ntn_pairs; ++n) {
     UInt master = this->masters(n);
     UInt slave = this->slaves(n);
     
     for (UInt d=0; d<dim; ++d) {
       //if (n==0 && d==1) std::cout << std::setprecision(14) << "mas_res=" << residual(master,d) << " slv_res=" << residual(slave,d) << " " << std::abs(residual(slave,d))-std::abs(residual(master,d)) << std::endl;
       residual(master,d) += this->lumped_boundary(n,0) * this->contact_pressure(n,d);
       residual(slave, d) -= this->lumped_boundary(n,1) * this->contact_pressure(n,d);
       
       /*
       if (n==0 && d==1) {
 	std::cout << std::setprecision(14) << "mas_b=" << lumped_boundary(n,0) << " skv_b=" << lumped_boundary(n,1) << std::endl;
 	std::cout << std::setprecision(14) << "mas+=" << lumped_boundary(n,0)*contact_pressure(n,d) << " slv+=" << lumped_boundary(n,1)*contact_pressure(n,d) << std::endl;
 	std::cout << std::setprecision(14) << "mas_res=" << residual(master,d) << " slv_res=" << residual(slave,d) << std::endl;
 	}*/
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::computeRelativeTangentialField(const Array<Real> & field,
 						Array<Real> & rel_tang_field) const {
   AKANTU_DEBUG_IN();
   
   // resize arrays to zero
   rel_tang_field.resize(0);
   
   UInt dim = this->model.getSpatialDimension();
   Real * field_p = field.storage();
   Real * normals_p = this->normals.storage();
 
   UInt nb_contact_nodes = this->slaves.getSize();
   for (UInt n=0; n<nb_contact_nodes; ++n) {
     // nodes
     UInt slave = this->slaves(n);
     UInt master = this->masters(n);
 
     // compute relative field to master
     Real rel_array[dim];
     for (UInt d=0; d<dim; ++d) {
       rel_array[d] = field_p[slave*dim + d] - field_p[master*dim + d];
     }
 
     // compute dot product with normal of master
     Real dot_prod = Math::vectorDot(&(normals_p[n*dim]), rel_array, dim);
     
     // compute the tangential projection of the relative field to the master
     for (UInt d=0; d<dim; ++d)
       rel_array[d] -= dot_prod * normals_p[n*dim +d];
     
     rel_tang_field.push_back(rel_array);
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::computeRelativeNormalField(const Array<Real> & field,
 					    Array<Real> & rel_normal_field) const {
   AKANTU_DEBUG_IN();
   
   // resize arrays to zero
   rel_normal_field.resize(0);
   
   UInt dim = this->model.getSpatialDimension();
   Real * field_p = field.storage();
   Real * normals_p = this->normals.storage();
 
   UInt nb_contact_nodes = this->getNbContactNodes();
   for (UInt n=0; n<nb_contact_nodes; ++n) {
     // nodes
     UInt slave = this->slaves(n);
     UInt master = this->masters(n);
 
     // compute relative field to master
     Real rel_array[dim];
     for (UInt d=0; d<dim; ++d) {
       rel_array[d] = field_p[slave*dim + d] - field_p[master*dim + d];
     }
 
     // compute dot product with normal of master
     Real dot_prod = Math::vectorDot(&(normals_p[n*dim]), rel_array, dim);
         
     rel_normal_field.push_back(dot_prod);
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Int NTNContact::getNodeIndex(UInt node) const {
   AKANTU_DEBUG_IN();
 
   Int slave_i  = this->slaves.find(node);
   Int master_i = this->masters.find(node);
 
   AKANTU_DEBUG_OUT();
   return std::max(slave_i,master_i);
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::printself(std::ostream & stream, int indent) const {
   AKANTU_DEBUG_IN();
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
   
   stream << space << "NTNContact [" << std::endl;
   stream << space << " + id            : " << id << std::endl;
   stream << space << " + slaves        : " << std::endl;
   this->slaves.printself(stream, indent + 2);
   stream << space << " + masters       : " << std::endl;
   this->masters.printself(stream, indent + 2);
   stream << space << " + normals       : " << std::endl;
   this->normals.printself(stream, indent + 2);
   stream << space << " + contact_pressure : " << std::endl;
   this->contact_pressure.printself(stream, indent + 2);
 
   stream << space << "]" << std::endl;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTNContact::syncArrays(SyncChoice sync_choice) {
   AKANTU_DEBUG_IN();
   
   this->slaves.syncElements(sync_choice);
   this->masters.syncElements(sync_choice);
   this->normals.syncElements(sync_choice);
   this->is_in_contact.syncElements(sync_choice);
   this->contact_pressure.syncElements(sync_choice);
   this->lumped_boundary.syncElements(sync_choice);
   this->impedance.syncElements(sync_choice);
   
   AKANTU_DEBUG_OUT();
 }
 
 __END_SIMTOOLS__
diff --git a/ntn_contact/ntn_contact.hh b/ntn_contact/ntn_contact.hh
index acda43875..010ced7b5 100644
--- a/ntn_contact/ntn_contact.hh
+++ b/ntn_contact/ntn_contact.hh
@@ -1,178 +1,178 @@
 /**
  * @file   ntn_contact.hh
  * @author David Kammer <david.kammer@epfl.ch>
  * @date   Mon Feb 20 15:13:23 2012
  *
  * @brief  contact for node to node discretization
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AST_NTN_CONTACT_HH__
 #define __AST_NTN_CONTACT_HH__
 
 /* -------------------------------------------------------------------------- */
 // akantu
 #include "solid_mechanics_model.hh"
 
 // simtools
 #include "syncronized_array.hh"
 
 __BEGIN_SIMTOOLS__
 
 /* -------------------------------------------------------------------------- */
 using namespace akantu;
 
 /* -------------------------------------------------------------------------- */
 class NTNContact : protected Memory {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   
   NTNContact(SolidMechanicsModel & model,
 	     const ContactID & id = "contact",
 	     const MemoryID & memory_id = 0);
   virtual ~NTNContact() {};
   
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   /// add surface pair and pair nodes according to the surface normal
-  void addSurfacePair(Surface slave, Surface master, UInt surface_normal_dir);
+  void addSurfacePair(const Surface & slave, const Surface & master, UInt surface_normal_dir);
   
   /// add node pair
   void addNodePair(UInt slave, UInt master);
 
   // add node pairs from a list with pairs(*,0)=slaves and pairs(*,1)=masters
   void addNodePairs(Array<UInt> & pairs);
 
   /// update normals, lumped boundary, and impedance
   void updateInternalData();
 
   /// update (compute the normals on the master nodes)
   void updateNormals();
 
   /// update the lumped boundary B matrix
   void updateLumpedBoundary();
 
   /// update the impedance matrix
   void updateImpedance();
 
   /// compute the normal contact force
   void computeContactPressure();
 
   /// impose the normal contact force
   void applyContactPressure();
 
   /// register syncronizedarrays for sync
   void registerSyncronizedArray(SyncronizedArrayBase & array);
 
   /// dump restart file
   void dumpRestart(const std::string & file_name) const;
 
   /// read restart file
   void readRestart(const std::string & file_name);
 
   /// compute relative normal field (only value that has to be multiplied with the normal)
   /// relative to master nodes
   void computeRelativeNormalField(const Array<Real> & field,
 				  Array<Real> & rel_normal_field) const;
 
   /// compute relative tangential field (complet array)
   /// relative to master nodes
   void computeRelativeTangentialField(const Array<Real> & field,
 				      Array<Real> & rel_tang_field) const;
   
   /// function to print the contain of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
   
 protected:
   /// synchronize arrays
   void syncArrays(SyncChoice sync_choice);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO(Model, model, SolidMechanicsModel &)
 
   AKANTU_GET_MACRO(Slaves,                    slaves, const SyncronizedArray<UInt> &)
   AKANTU_GET_MACRO(Masters,                  masters, const SyncronizedArray<UInt> &)
   AKANTU_GET_MACRO(Normals,                  normals, const SyncronizedArray<Real> &)
   AKANTU_GET_MACRO(ContactPressure, contact_pressure, const SyncronizedArray<Real> &)
   AKANTU_GET_MACRO(LumpedBoundary,   lumped_boundary, const SyncronizedArray<Real> &)
   AKANTU_GET_MACRO(Impedance,              impedance, const SyncronizedArray<Real> &)
   AKANTU_GET_MACRO(IsInContact,        is_in_contact, const SyncronizedArray<bool> &)
 
   /// get number of contact nodes
   UInt getNbContactNodes() const { return this->slaves.getSize(); };
 
   /// get index of node in either slaves or masters array
   /// if node is in neither of them, return -1
   Int getNodeIndex(UInt node) const;
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   ContactID id;
 
   SolidMechanicsModel & model;
 
   /// array of slave nodes
   SyncronizedArray<UInt> slaves;
   /// array of master nodes
   SyncronizedArray<UInt> masters;
   /// array of normals on master nodes
   SyncronizedArray<Real> normals;
   /// array indicating if nodes are in contact
   SyncronizedArray<Real> contact_pressure;
   /// array indicating if nodes are in contact
   SyncronizedArray<bool> is_in_contact;
   /// boundary matrix, lumped_boundary[:,0] master nodes, lumped_boundary[:,1] slave nodes
   SyncronizedArray<Real> lumped_boundary;
   /// impedance matrix
   SyncronizedArray<Real> impedance;
 
   /// contact surface
-  std::set<Surface> contact_surfaces;
+  std::set<const SubBoundary *> contact_surfaces;
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 //#include "ntn_contact_inline_impl.cc"
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const NTNContact & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 __END_SIMTOOLS__
 
 #endif /* __AST_NTN_CONTACT_HH__ */
diff --git a/ntrf_contact/ntrf_contact.cc b/ntrf_contact/ntrf_contact.cc
index 5c5aabae1..5796964a1 100644
--- a/ntrf_contact/ntrf_contact.cc
+++ b/ntrf_contact/ntrf_contact.cc
@@ -1,499 +1,497 @@
 /**
  * @file   ntrf_contact.cc
  * @author David Kammer <david.kammer@epfl.ch>
  * @date   Thu Mar 14 14:16:07 2013
  *
  * @brief  
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 // simtools
 #include "ntrf_contact.hh"
 
 __BEGIN_SIMTOOLS__
 
 /* -------------------------------------------------------------------------- */
 NTRFContact::NTRFContact(SolidMechanicsModel & model,
 		       const ContactID & id,
 		       const MemoryID & memory_id) : 
   Memory(memory_id), id(id), model(model),
   slaves(0,1,0,id+":slaves",std::numeric_limits<UInt>::quiet_NaN(),"slaves"),
   contact_pressure(0,model.getSpatialDimension(),0,id+":contact_pressure",
 		   std::numeric_limits<Real>::quiet_NaN(),"contact_pressure"),
   is_in_contact(0,1,false,id+":is_in_contact",false,"is_in_contact"),
   lumped_boundary(0,1,0,id+":lumped_boundary",
 		  std::numeric_limits<Real>::quiet_NaN(),"lumped_boundary"),
   reference_point(0,model.getSpatialDimension()),
   normal(0,model.getSpatialDimension()),
   contact_surfaces()
 {
   AKANTU_DEBUG_IN();
 
   FEM & boundary_fem = this->model.getFEMBoundary();
   boundary_fem.initShapeFunctions();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::setReferencePoint(Real x, Real y, Real z) {
   AKANTU_DEBUG_IN();
 
   Real coord[3];
   coord[0] = x;
   coord[1] = y;
   coord[2] = z;
 
   this->reference_point.resize(1);  
 
   UInt dim = this->model.getSpatialDimension();
   for (UInt d=0; d<dim; ++d)
     this->reference_point(0,d) = coord[d];
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::setNormal(Real x, Real y, Real z) {
   AKANTU_DEBUG_IN();
 
   UInt dim = this->model.getSpatialDimension();
   
   Real coord[3];
   coord[0] = x;
   coord[1] = y;
   coord[2] = z;
 
   if (dim == 2)
     Math::normalize2(coord);
   else if (dim == 3)
     Math::normalize3(coord);
   else
     AKANTU_DEBUG_ERROR("setNormal in NTRFContact not implemented for dimension " << dim);
 
   this->normal.resize(1);
 
   for (UInt d=0; d<dim; ++d)
     this->normal(0,d) = coord[d];
   
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
-void NTRFContact::addSurface(Surface surf) {
+void NTRFContact::addSurface(const Surface & surf) {
   AKANTU_DEBUG_IN();
   
   UInt dim = this->model.getSpatialDimension();
-  this->contact_surfaces.insert(surf);
-
-  // get all nodes for all surfaces
-  CSR<UInt> all_surface_nodes;
-  MeshUtils::buildNodesPerSurface(this->model.getFEM().getMesh(), all_surface_nodes);
 
+  const Mesh & mesh_ref = this->model.getFEM().getMesh();
+  
+  const SubBoundary & boundary = mesh_ref.getSubBoundary(surf);
+  this->contact_surfaces.insert(&boundary);
+  
   // find slave nodes
-  for(CSR<UInt>::iterator snode = all_surface_nodes.begin(surf); 
-      snode != all_surface_nodes.end(surf); 
-      ++snode) {
-    this->addNode(*snode);
+  for(SubBoundary::nodes_const_iterator nodes_it(boundary.nodes_begin()); nodes_it!= boundary.nodes_end(); ++nodes_it) {
+    this->addNode(*nodes_it);
   }
   
   // synchronize with depending nodes
   updateInternalData();
   syncArrays(_added);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::addNode(UInt node) {
   AKANTU_DEBUG_IN();
   
   UInt dim = this->model.getSpatialDimension();
   
   // add to node arrays
   this->slaves.push_back(node);
   
   // set contact as false
   this->is_in_contact.push_back(false);
 
   // before initializing 
   // set contact pressure, normal, lumped_boundary to Nan
   this->contact_pressure.push_back(std::numeric_limits<Real>::quiet_NaN());
   this->lumped_boundary.push_back(std::numeric_limits<Real>::quiet_NaN());
   
   AKANTU_DEBUG_OUT();  
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::addNodes(Array<UInt> & nodes) {
   AKANTU_DEBUG_IN();
   
   UInt nb_nodes = nodes.getSize();
   UInt nb_compo = nodes.getNbComponent();
   for (UInt n=0; n<nb_nodes; ++n) {
     for (UInt c=0; c<nb_compo; ++c) {
       this->addNode(nodes(n,c));
     }
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::registerSyncronizedArray(SyncronizedArrayBase & array) {
   AKANTU_DEBUG_IN();
   
   this->slaves.registerDependingArray(array);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::dumpRestart(const std::string & file_name) const {
   AKANTU_DEBUG_IN();
   
   this->slaves.dumpRestartFile(file_name);
   this->is_in_contact.dumpRestartFile(file_name);
   this->contact_pressure.dumpRestartFile(file_name);
   this->lumped_boundary.dumpRestartFile(file_name);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::readRestart(const std::string & file_name) {
   AKANTU_DEBUG_IN();
   
   this->slaves.readRestartFile(file_name);
   this->is_in_contact.readRestartFile(file_name);
   this->contact_pressure.readRestartFile(file_name);
   this->lumped_boundary.readRestartFile(file_name);
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::updateInternalData() {
   AKANTU_DEBUG_IN();
   
   updateLumpedBoundary();
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::updateLumpedBoundary() {
   AKANTU_DEBUG_IN();
 
   // set all values in lumped_boundary to zero
   this->lumped_boundary.clear();
 
   UInt dim = this->model.getSpatialDimension(); 
   UInt nb_contact_nodes = getNbContactNodes();
 
   const FEM & boundary_fem = this->model.getFEMBoundary();
 
   const Mesh & mesh = this->model.getFEM().getMesh();
   Mesh::type_iterator it = mesh.firstType(dim-1);
   Mesh::type_iterator last = mesh.lastType(dim-1);
   for (; it != last; ++it) {
     // get elements connected to each node
     CSR<UInt> node_to_element;
     MeshUtils::buildNode2ElementsByElementType(mesh, *it, node_to_element);
 
     UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it);
     const Array<UInt> & connectivity = mesh.getConnectivity(*it);
 
     // get shapes and compute integral 
     const Array<Real> & shapes = boundary_fem.getShapes(*it);
     Array<Real> area(mesh.getNbElement(*it),nb_nodes_per_element);
     boundary_fem.integrate(shapes,area,nb_nodes_per_element,*it);
 
     // get surface id information
-    const Array<UInt> & surface_id = mesh.getSurfaceID(*it);
-    std::set<UInt>::iterator pos;
-    std::set<UInt>::iterator end = this->contact_surfaces.end();
+//    const Array<UInt> & surface_id = mesh.getSurfaceID(*it);
+//    std::set<UInt>::iterator pos;
+//    std::set<UInt>::iterator end = this->contact_surfaces.end();
 
     if (this->contact_surfaces.size() == 0)
       std::cerr << "No surfaces in ntrf contact. You have to define the lumped boundary by yourself." << std::endl;
 
     // loop over contact nodes
     for (UInt i=0; i<nb_contact_nodes; ++i) {
       UInt node = this->slaves(i);
       
       CSR<UInt>::iterator elem = node_to_element.begin(node);
       // loop over all elements connected to this node
       for (; elem != node_to_element.end(node); ++elem) {
 	UInt e = *elem;
 
 	// if element is not at interface continue
-	pos = this->contact_surfaces.find(surface_id(e));
-	if (pos == end)
-	  continue;
+//	pos = this->contact_surfaces.find(surface_id(e));
+//	if (pos == end)
+//	  continue;
 
 	// loop over all points of this element
 	for (UInt q=0; q<nb_nodes_per_element; ++q) {
 	  if (connectivity(e,q) == node) {
 	    this->lumped_boundary(i) += area(e,q);
 	  }
 	}
       }
     }
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::computeContactPressure() {
   AKANTU_DEBUG_IN();
 
   UInt dim = this->model.getSpatialDimension();
   Real delta_t = this->model.getTimeStep();
   UInt nb_contact_nodes = getNbContactNodes();
 
   // pre-compute the acceleration 
   // (not increment acceleration, because residual is still Kf)
   Array<Real> acceleration(this->model.getFEM().getMesh().getNbNodes(),dim);
   this->model.solveLumped(acceleration,
 			  this->model.getMass(),
 			  this->model.getResidual(),
 			  this->model.getBoundary(),
 			  this->model.getF_M2A());
 
   const Array<Real> & residual = this->model.getResidual();
   const Array<Real> & mass = this->model.getMass();
 
   // compute relative normal fields of displacement, velocity and acceleration 
   Array<Real> r_disp(0,1);
   Array<Real> r_velo(0,1);
   Array<Real> r_acce(0,1);
   Array<Real> r_old_acce(0,1);
   computeNormalGap(r_disp);
   computeRelativeNormalField(this->model.getVelocity(),        r_velo);
   computeRelativeNormalField(acceleration,                     r_acce);
   computeRelativeNormalField(this->model.getAcceleration(),    r_old_acce);
 
   AKANTU_DEBUG_ASSERT(r_disp.getSize() == nb_contact_nodes, 
 		      "computeNormalGap does not give back arrays " 
 		      << "size == nb_contact_nodes. nb_contact_nodes = " 
 		      << nb_contact_nodes << " | array size = " 
 		      << r_disp.getSize());
   AKANTU_DEBUG_ASSERT(r_velo.getSize() == nb_contact_nodes, 
 		      "computeRelativeNormalField does not give back arrays " 
 		      << "size == nb_contact_nodes. nb_contact_nodes = " 
 		      << nb_contact_nodes << " | array size = " 
 		      << r_velo.getSize());
 
   // compute gap array for all nodes
   Array<Real> gap(nb_contact_nodes, 1);
   Real * gap_p = gap.storage();
   Real * r_disp_p = r_disp.storage();
   Real * r_velo_p = r_velo.storage();
   Real * r_acce_p = r_acce.storage();
   Real * r_old_acce_p = r_old_acce.storage();
   for (UInt i=0; i<nb_contact_nodes; ++i) {
     *gap_p = *r_disp_p + delta_t * *r_velo_p + delta_t * delta_t * *r_acce_p - 0.5 * delta_t * delta_t * *r_old_acce_p;
     // increment pointers
     gap_p++;
     r_disp_p++;
     r_velo_p++;
     r_acce_p++;
     r_old_acce_p++;
   }
 
   // check if gap is negative -> is in contact
   for (UInt n=0; n<nb_contact_nodes; ++n) {
     if (gap(n) < 0.) {
       UInt node = this->slaves(n);
       for (UInt d=0; d<dim; ++d) {
 	this->contact_pressure(n,d) = mass(node) / delta_t / delta_t 
 	  / this->lumped_boundary(n) * gap(n) * this->normal(0,d);
 	/*
 	// from the ntn_contact:
 	this->contact_pressure(n,d) = this->impedance(n) * gap(n) / (2 * delta_t) 
 	* this->normal(0,d);
 	*/
       }
       this->is_in_contact(n) = true;
     }
     else {
       for (UInt d=0; d<dim; ++d)
 	this->contact_pressure(n,d) = 0.;
       this->is_in_contact(n) = false;
     }
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::applyContactPressure() {
   AKANTU_DEBUG_IN();
 
   UInt nb_contact_nodes = getNbContactNodes();
   UInt dim = this->model.getSpatialDimension();
   
   Array<Real> & residual = this->model.getResidual();
   
   for (UInt n=0; n<nb_contact_nodes; ++n) {
     UInt node = this->slaves(n);
     for (UInt d=0; d<dim; ++d) {
       residual(node, d) -= this->lumped_boundary(n) * this->contact_pressure(n,d);
     }
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::computeRelativeTangentialField(const Array<Real> & field,
 						Array<Real> & rel_tang_field) const {
   AKANTU_DEBUG_IN();
   
   // resize arrays to zero
   rel_tang_field.resize(0);
   
   UInt dim = this->model.getSpatialDimension();
   Real * field_p = field.storage();
   Real * normals_p = this->normal.storage();
 
   UInt nb_contact_nodes = this->slaves.getSize();
   for (UInt n=0; n<nb_contact_nodes; ++n) {
     // nodes
     UInt node = this->slaves(n);
 
     // compute relative field to master
     Real rel_array[dim];
     for (UInt d=0; d<dim; ++d) {
       rel_array[d] = field_p[node*dim + d];
     }
 
     // compute dot product with normal of master
     Real dot_prod = Math::vectorDot(normals_p, rel_array, dim);
     
     // compute the tangential projection of the relative field to the master
     for (UInt d=0; d<dim; ++d)
       rel_array[d] -= dot_prod * normals_p[d];
     
     rel_tang_field.push_back(rel_array);
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::computeNormalGap(Array<Real> & gap) const {
   AKANTU_DEBUG_IN();
   
   gap.resize(0);
   
   UInt dim = this->model.getSpatialDimension();
   Real * cur_pos = this->model.getCurrentPosition().storage();
   Real * normals_p = this->normal.storage();
 
   UInt nb_contact_nodes = this->getNbContactNodes();
   for (UInt n=0; n<nb_contact_nodes; ++n) {
     // nodes
     UInt node = this->slaves(n);
     
     // compute relative field to master
     Real rel_array[dim];
     for (UInt d=0; d<dim; ++d) {
       rel_array[d] = cur_pos[node*dim + d] - this->reference_point(0,d);
     }
 
     // compute dot product with normal of master
     Real dot_prod = Math::vectorDot(normals_p, rel_array, dim);
         
     gap.push_back(dot_prod);
   }
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::computeRelativeNormalField(const Array<Real> & field,
 					    Array<Real> & rel_normal_field) const {
   AKANTU_DEBUG_IN();
   
   // resize arrays to zero
   rel_normal_field.resize(0);
   
   UInt dim = this->model.getSpatialDimension();
   Real * field_p = field.storage();
   Real * normals_p = this->normal.storage();
 
   UInt nb_contact_nodes = this->getNbContactNodes();
   for (UInt n=0; n<nb_contact_nodes; ++n) {
     // nodes
     UInt node = this->slaves(n);
     
     // compute dot product with normal of master
     Real dot_prod = Math::vectorDot(normals_p, &(field_p[node*dim]), dim);
         
     rel_normal_field.push_back(dot_prod);
   }
   
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 Int NTRFContact::getNodeIndex(UInt node) const {
   AKANTU_DEBUG_IN();
 
   AKANTU_DEBUG_OUT();
   return this->slaves.find(node);
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::printself(std::ostream & stream, int indent) const {
   AKANTU_DEBUG_IN();
   std::string space;
   for(Int i = 0; i < indent; i++, space += AKANTU_INDENT);
   
   stream << space << "NTRFContact [" << std::endl;
   stream << space << " + id            : " << id << std::endl;
   stream << space << " + slaves        : " << std::endl;
   this->slaves.printself(stream, indent + 2);
   stream << space << " + contact_pressure : " << std::endl;
   this->contact_pressure.printself(stream, indent + 2);
 
   stream << space << "]" << std::endl;
 
   AKANTU_DEBUG_OUT();
 }
 
 /* -------------------------------------------------------------------------- */
 void NTRFContact::syncArrays(SyncChoice sync_choice) {
   AKANTU_DEBUG_IN();
   
   this->slaves.syncElements(sync_choice);
   this->is_in_contact.syncElements(sync_choice);
   this->contact_pressure.syncElements(sync_choice);
   this->lumped_boundary.syncElements(sync_choice);
   
   AKANTU_DEBUG_OUT();
 }
 
 __END_SIMTOOLS__
diff --git a/ntrf_contact/ntrf_contact.hh b/ntrf_contact/ntrf_contact.hh
index 69e9778fd..899e31cba 100644
--- a/ntrf_contact/ntrf_contact.hh
+++ b/ntrf_contact/ntrf_contact.hh
@@ -1,171 +1,171 @@
 /**
  * @file   ntrf_contact.hh
  * @author David Kammer <david.kammer@epfl.ch>
  * @date   Fri Nov  2 17:33:49 2012
  *
  * @brief  contact for node to rigid flat interface
  *
  * @section LICENSE
  *
  * Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
  * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
  *
  * Akantu is free  software: you can redistribute it and/or  modify it under the
  * terms  of the  GNU Lesser  General Public  License as  published by  the Free
  * Software Foundation, either version 3 of the License, or (at your option) any
  * later version.
  *
  * Akantu is  distributed in the  hope that it  will be useful, but  WITHOUT ANY
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A  PARTICULAR PURPOSE. See  the GNU  Lesser General  Public License  for more
  * details.
  *
  * You should  have received  a copy  of the GNU  Lesser General  Public License
  * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 /* -------------------------------------------------------------------------- */
 
 #ifndef __AST_NTRF_CONTACT_HH__
 #define __AST_NTRF_CONTACT_HH__
 
 /* -------------------------------------------------------------------------- */
 #include "solid_mechanics_model.hh"
 #include "syncronized_array.hh"
 
 __BEGIN_SIMTOOLS__
 
 /* -------------------------------------------------------------------------- */
 using namespace akantu;
 
 /* -------------------------------------------------------------------------- */
 class NTRFContact : protected Memory {
   /* ------------------------------------------------------------------------ */
   /* Constructors/Destructors                                                 */
   /* ------------------------------------------------------------------------ */
 public:
   
   NTRFContact(SolidMechanicsModel & model,
 	      const ContactID & id = "contact",
 	      const MemoryID & memory_id = 0);
   virtual ~NTRFContact() {};
   
   /* ------------------------------------------------------------------------ */
   /* Methods                                                                  */
   /* ------------------------------------------------------------------------ */
 public:
   void setReferencePoint(Real x=0., Real y=0., Real z=0.);
   void setNormal(Real x=1., Real y=0., Real z=0.);
 
   /// add surface and nodes according to the surface normal
-  void addSurface(Surface surf);
+  void addSurface(const Surface & surf);
   
   /// add node
   void addNode(UInt node);
 
   // add nodes from a list
   void addNodes(Array<UInt> & nodes);
 
   /// update normals, lumped boundary, and impedance
   void updateInternalData();
 
   /// update the lumped boundary B matrix
   void updateLumpedBoundary();
 
   /// compute the normal contact force
   void computeContactPressure();
 
   /// impose the normal contact force
   void applyContactPressure();
 
   /// register syncronizedarrays for sync
   void registerSyncronizedArray(SyncronizedArrayBase & array);
 
   /// dump restart file
   void dumpRestart(const std::string & file_name) const;
 
   /// read restart file
   void readRestart(const std::string & file_name);
 
   /// compute the normal gap 
   void computeNormalGap(Array<Real> & gap) const;
 
   /// compute relative normal field (only value that has to be multiplied with the normal)
   /// relative to master nodes
   void computeRelativeNormalField(const Array<Real> & field,
 				  Array<Real> & rel_normal_field) const;
 
   /// compute relative tangential field (complet array)
   /// relative to master nodes
   void computeRelativeTangentialField(const Array<Real> & field,
 				      Array<Real> & rel_tang_field) const;
   
   /// function to print the contain of the class
   virtual void printself(std::ostream & stream, int indent = 0) const;
   
 protected:
   /// synchronize arrays
   void syncArrays(SyncChoice sync_choice);
 
   /* ------------------------------------------------------------------------ */
   /* Accessors                                                                */
   /* ------------------------------------------------------------------------ */
 public:
   AKANTU_GET_MACRO(Model, model, SolidMechanicsModel &)
 
   AKANTU_GET_MACRO(Slaves,                    slaves, const SyncronizedArray<UInt> &)
   AKANTU_GET_MACRO(ContactPressure, contact_pressure, const SyncronizedArray<Real> &)
   AKANTU_GET_MACRO(LumpedBoundary,   lumped_boundary, const SyncronizedArray<Real> &)
   AKANTU_GET_MACRO(IsInContact,        is_in_contact, const SyncronizedArray<bool> &)
 
   /// get number of contact nodes
   UInt getNbContactNodes() const { return this->slaves.getSize(); };
 
   /// get index of node in either slaves or masters array
   /// if node is in neither of them, return -1
   Int getNodeIndex(UInt node) const;
 
   /* ------------------------------------------------------------------------ */
   /* Class Members                                                            */
   /* ------------------------------------------------------------------------ */
 private:
   ContactID id;
 
   SolidMechanicsModel & model;
 
   /// array of slave nodes
   SyncronizedArray<UInt> slaves;
   /// array indicating if nodes are in contact
   SyncronizedArray<Real> contact_pressure;
   /// array indicating if nodes are in contact
   SyncronizedArray<bool> is_in_contact;
   /// boundary matrix, lumped_boundary[:,0] slave nodes
   SyncronizedArray<Real> lumped_boundary;
 
   /// reference point for rigid flat surface
   Array<Real> reference_point;
   /// outpointing normal of rigid flat surface
   Array<Real> normal;
 
   /// contact surface
-  std::set<Surface> contact_surfaces;
+  std::set<const SubBoundary *> contact_surfaces;
 };
 
 
 /* -------------------------------------------------------------------------- */
 /* inline functions                                                           */
 /* -------------------------------------------------------------------------- */
 
 //#include "ntrf_contact_inline_impl.cc"
 
 /// standard output stream operator
 inline std::ostream & operator <<(std::ostream & stream, const NTRFContact & _this)
 {
   _this.printself(stream);
   return stream;
 }
 
 __END_SIMTOOLS__
 
 #endif /* __AST_NTRF_CONTACT_HH__ */