From 42fb61c2709f5cf5643ac15c92b976620a05ac41 Mon Sep 17 00:00:00 2001
From: Jeanne Pellerin <jeanne.pellerin@uclouvain.be>
Date: Thu, 17 Nov 2016 15:35:31 +0000
Subject: [PATCH]  - put back necessary ifnedf in GModel.h for linking on
 Windows with python bindings  - new options to create all possible tets for a
 Gregion with createTetrahedralMesh  - changes in yamaka.h and cpp - put const
 and inline functions

---
 Geo/GModel.h                         |   5 +-
 Mesh/Generator.h                     |   2 +-
 Mesh/meshDiscreteRegion.cpp          |  74 ++-
 Mesh/meshGRegionBoundaryRecovery.cpp |   2 +
 Mesh/yamakawa.cpp                    | 859 +++++++--------------------
 Mesh/yamakawa.h                      | 260 +++++---
 6 files changed, 475 insertions(+), 727 deletions(-)

diff --git a/Geo/GModel.h b/Geo/GModel.h
index c094e88655..af4f0505ce 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -164,10 +164,11 @@ class GModel
  public:
   GModel(std::string name="");
   virtual ~GModel();
-
-
+// Required for python bindings on Windows
+#ifndef SWIG
   // the static list of all loaded models
   static std::vector<GModel*> list;
+# endif
 
   // return the current model, and sets the current model index if
   // index >= 0
diff --git a/Mesh/Generator.h b/Mesh/Generator.h
index 6d59607831..c135923257 100644
--- a/Mesh/Generator.h
+++ b/Mesh/Generator.h
@@ -19,7 +19,7 @@ void SmoothMesh(GModel *m);
 void RefineMesh(GModel *m, bool linear, bool splitIntoQuads=false,
                 bool splitIntoHexas=false);
 void RecombineMesh(GModel *m);
-GRegion * createTetrahedralMesh ( GModel *gm, fullMatrix<double> & pts, fullMatrix<int> &triangles ) ;
+GRegion * createTetrahedralMesh ( GModel *gm, fullMatrix<double> & pts, fullMatrix<int> &triangles, bool all_tets=false ) ;
   //GRegion * createTetrahedralMesh ( GModel *gm, unsigned int nbPts , double *pts, unsigned int nbTriangles, int *triangles );
 
 #endif
diff --git a/Mesh/meshDiscreteRegion.cpp b/Mesh/meshDiscreteRegion.cpp
index f0522a8e42..218535883e 100644
--- a/Mesh/meshDiscreteRegion.cpp
+++ b/Mesh/meshDiscreteRegion.cpp
@@ -32,11 +32,49 @@
 #include "MPrism.h"
 #include "MHexahedron.h"
 
+// Recursive function to generate all combinations of 4 indices between start 
+// and end indices included 
+// Jeanne - HEXTREME
+void combination_of_4( int combination[4], int start, int end, int index,
+  const std::vector<MVertex*>& vertices, std::vector<MTetrahedron*>& tets)
+{
+  if (index == 4 ) {
+    // Create the tet and get out
+    MVertex* v1 = vertices[combination[0]];
+    MVertex* v2 = vertices[combination[1]];
+    MVertex* v3 = vertices[combination[2]];
+    MVertex* v4 = vertices[combination[3]];
+    MTetrahedron* tet = new MTetrahedron(v1, v2, v3, v4);
+    tets.push_back(tet);
+    return;
+  }
+  for (int i = start; i <= end+1 -(4-index); i++) {
+    combination[index] = i;
+    combination_of_4(combination, i+1, end, index+1, vertices, tets);
+  }
+}
+
+// Fill a region with all possible tets genereated from the
+// combination of points assigned to it 
+// Jeanne - HEXTREME
+void create_all_possible_tets(GRegion* region, const std::vector<MVertex*>& vertices) {
+  unsigned int nb_points = vertices.size();
+
+  int combinaison[4];
+  std::vector<MTetrahedron*> tets;
+  combination_of_4(combinaison, 0, nb_points - 1, 0, vertices, tets);
+  std::cout << " Number of tets created - all possible combinations - " << tets.size() << std::endl;
+
+  for (int i = 0; i < tets.size(); ++i) {
+    region->addTetrahedron(tets[i]);
+  }
+}
+
 // triangles are defining the boundary
 // internal points are allowed
 // This has been done for HEXTREME
 GRegion * createDiscreteRegionFromRawData(GModel *gm, fullMatrix<double> &pts,
-                                          fullMatrix<int> &triangles)
+                                          fullMatrix<int> &triangles, bool all_tets)
 {
   GRegion *gr = new discreteRegion(gm, NEWREG());
   GFace *gf = new discreteFace(gm, NEWREG());
@@ -61,8 +99,8 @@ GRegion * createDiscreteRegionFromRawData(GModel *gm, fullMatrix<double> &pts,
       vs[i] = v;
     }
     else {
-      MVertex *v = new MFaceVertex(pts(i,0), pts(i,1), pts(i,2), gr, 0, 0);
-      gr->mesh_vertices.push_back(v);
+      MVertex *v = new MFaceVertex(pts(i,0), pts(i,1), pts(i,2), gf, 0, 0);
+      gf->mesh_vertices.push_back(v);
       vs[i] = v;
     }
   }
@@ -75,24 +113,32 @@ GRegion * createDiscreteRegionFromRawData(GModel *gm, fullMatrix<double> &pts,
     gf->triangles.push_back(t);
   }
 
-  delaunayTriangulation(1, 1, vs, gr->tetrahedra);
+//  delaunayTriangulation(1, 1, vs, gr->tetrahedra); // tetrahedralization is done when recovering the boundary
+
+  // create all tets
+  if (all_tets) {
+    create_all_possible_tets(gr, vs);
+  }
 
   return gr;
 }
 
 GRegion *createTetrahedralMesh(GModel *gm, fullMatrix<double> &pts,
-                               fullMatrix<int> &triangles)
+                               fullMatrix<int> &triangles, bool all_tets)
 {
-  GRegion *gr = createDiscreteRegionFromRawData(gm, pts, triangles);
-  try{
-    meshGRegionBoundaryRecovery(gr);
-  }
-  catch(int err){
-    if(err == 3){
-      Msg::Warning("Self-intersecting surface mesh: TODO!");
+  GRegion *gr = createDiscreteRegionFromRawData(gm, pts, triangles, all_tets);
+
+  if (!all_tets){
+    try {
+      meshGRegionBoundaryRecovery(gr);
     }
-    else{
-      Msg::Error("Could not recover boundary: error %d", err);
+    catch (int err) {
+      if (err == 3) {
+        Msg::Warning("Self-intersecting surface mesh: TODO!");
+      }
+      else {
+        Msg::Error("Could not recover boundary: error %d", err);
+      }
     }
   }
   return gr;
diff --git a/Mesh/meshGRegionBoundaryRecovery.cpp b/Mesh/meshGRegionBoundaryRecovery.cpp
index b13a248845..2ba637757c 100644
--- a/Mesh/meshGRegionBoundaryRecovery.cpp
+++ b/Mesh/meshGRegionBoundaryRecovery.cpp
@@ -135,6 +135,8 @@ bool tetgenmesh::reconstructmesh(void *p)
         all.insert(gv->points[i]->getVertex(0));
       }
     }
+    all.insert(_gr->mesh_vertices.begin(), _gr->mesh_vertices.end());
+
     _vertices.insert(_vertices.begin(), all.begin(), all.end());
   }
 
diff --git a/Mesh/yamakawa.cpp b/Mesh/yamakawa.cpp
index a4f852b3ef..283b710954 100644
--- a/Mesh/yamakawa.cpp
+++ b/Mesh/yamakawa.cpp
@@ -29,6 +29,19 @@
 #include "qualityMeasuresJacobian.h"
 
 
+std::ostream& operator<<(std::ostream& os, const Hex& hex)
+{
+  os << " vertices "
+    << " A " << hex.get_a()->getNum()
+    << " B " << hex.get_b()->getNum()
+    << " C " << hex.get_c()->getNum()
+    << " D " << hex.get_d()->getNum()
+    << " E " << hex.get_e()->getNum()
+    << " F " << hex.get_f()->getNum()
+    << " G " << hex.get_g()->getNum()
+    << " H " << hex.get_h()->getNum();
+  return os;
+}
 
 void export_gregion_mesh(GRegion *gr, string filename)
 {
@@ -843,139 +856,6 @@ bool compare_hex_ptr_by_quality (Hex *a,Hex *b)
   return (a->get_quality()>(b->get_quality()));
 }
 
-/*****************************************/
-/****************class Hex****************/
-/*****************************************/
-
-Hex::Hex():hash(0.),a(NULL),b(NULL),c(NULL),d(NULL),e(NULL),f(NULL),g(NULL),h(NULL){}
-
-Hex::Hex(MVertex* a2,MVertex* b2,MVertex* c2,MVertex* d2,MVertex* e2,MVertex* f2,MVertex* g2,MVertex* h2){
-  a = a2;
-  b = b2;
-  c = c2;
-  d = d2;
-  e = e2;
-  f = f2;
-  g = g2;
-  h = h2;
-  set_hash();
-}
-
-void Hex::set_hash(){
-  hash = (a->getNum() + b->getNum() + c->getNum() + d->getNum() + e->getNum() + f->getNum() + g->getNum() + h->getNum());
-}
-
-unsigned long long Hex::get_hash(){
-  if ((hash==0.)&&(a)) set_hash();
-  return hash;
-}
-
-bool Hex::hasVertex(const MVertex *v){
-  for (int i=0;i<8;i++)
-    if (getVertex(i)==v) return true;
-  return false;
-}
-
-
-bool Hex::same_vertices(Hex *h){
-  for (int i=0;i<8;i++)
-    if (!(h->hasVertex(getVertex(i))))
-      return false;
-  return true;
-}
-
-Hex::~Hex(){}
-
-double Hex::get_quality(){
-  return quality;
-}
-
-void Hex::set_quality(double new_quality){
-  quality = new_quality;
-}
-
-MVertex* Hex::get_a(){
-  return a;
-}
-
-MVertex* Hex::get_b(){
-  return b;
-}
-
-MVertex* Hex::get_c(){
-  return c;
-}
-
-MVertex* Hex::get_d(){
-  return d;
-}
-
-MVertex* Hex::get_e(){
-  return e;
-}
-
-MVertex* Hex::get_f(){
-  return f;
-}
-
-MVertex* Hex::get_g(){
-  return g;
-}
-
-MVertex* Hex::get_h(){
-  return h;
-}
-
-MVertex* Hex::getVertex(int n){
-  MVertex *v;
-  switch (n){
-  case 0:
-    v = get_a();
-    break;
-  case 1:
-    v = get_b();
-    break;
-  case 2:
-    v = get_c();
-    break;
-  case 3:
-    v = get_d();
-    break;
-  case 4:
-    v = get_e();
-    break;
-  case 5:
-    v = get_f();
-    break;
-  case 6:
-    v = get_g();
-    break;
-  case 7:
-    v = get_h();
-    break;
-  default:
-    cout << "Hex: unknown vertex number " << n << endl;
-    throw;
-  }
-  return v;
-}
-
-
-void Hex::set_vertices(MVertex* a2,MVertex* b2,MVertex* c2,MVertex* d2,MVertex* e2,MVertex* f2,MVertex* g2,MVertex* h2){
-  a = a2;
-  b = b2;
-  c = c2;
-  d = d2;
-  e = e2;
-  f = f2;
-  g = g2;
-  h = h2;
-}
-
-bool Hex::operator<(Hex& hex){
-  return quality>hex.get_quality();
-}
-
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -1076,231 +956,6 @@ PEQuadrangle::PEQuadrangle(const vector<const MVertex*> &_v):PEEntity(_v){
 size_t PEQuadrangle::get_max_nb_vertices()const{return 4;};
 
 
-/*******************************************/
-/****************class Facet****************/
-/*******************************************/
-
-Facet::Facet(){}
-
-Facet::Facet(MVertex* a2,MVertex* b2,MVertex* c2){
-  a = a2;
-  b = b2;
-  c = c2;
-  compute_hash();
-}
-
-Facet::~Facet(){}
-
-MVertex* Facet::get_a(){
-  return a;
-}
-
-MVertex* Facet::get_b(){
-  return b;
-}
-
-MVertex* Facet::get_c(){
-  return c;
-}
-
-void Facet::set_vertices(MVertex* a2,MVertex* b2,MVertex* c2){
-  a = a2;
-  b = b2;
-  c = c2;
-  compute_hash();
-}
-
-bool Facet::same_vertices(Facet facet){
-  bool c1,c2,c3;
-
-  c1 = (a==facet.get_a()) || (a==facet.get_b()) || (a==facet.get_c());
-  c2 = (b==facet.get_a()) || (b==facet.get_b()) || (b==facet.get_c());
-  c3 = (c==facet.get_a()) || (c==facet.get_b()) || (c==facet.get_c());
-
-  return c1 && c2 && c3;
-}
-
-void Facet::compute_hash(){
-//  hash = a->getNum() + b->getNum() + c->getNum();
-  num[0] = a->getNum();
-  num[1] = b->getNum();
-  num[2] = c->getNum();
-  std::sort(num, num+3);
-  hash = num[2] + 1e4*num[1] + 1e8*num[0];
-}
-
-unsigned long long Facet::get_hash() const{
-  return hash;
-}
-
-bool Facet::operator<(const Facet& facet) const{
-  return hash<facet.get_hash();
-}
-
-/**********************************************/
-/****************class Diagonal****************/
-/**********************************************/
-
-Diagonal::Diagonal(){}
-
-Diagonal::Diagonal(MVertex* a2,MVertex* b2){
-  a = a2;
-  b = b2;
-  compute_hash();
-}
-
-Diagonal::~Diagonal(){}
-
-MVertex* Diagonal::get_a(){
-  return a;
-}
-
-MVertex* Diagonal::get_b(){
-  return b;
-}
-
-void Diagonal::set_vertices(MVertex* a2,MVertex* b2){
-  a = a2;
-  b = b2;
-  compute_hash();
-}
-
-bool Diagonal::same_vertices(Diagonal diagonal){
-  bool c1,c2;
-
-  c1 = (a==diagonal.get_a()) || (a==diagonal.get_b());
-  c2 = (b==diagonal.get_a()) || (b==diagonal.get_b());
-
-  return c1 && c2;
-}
-
-void Diagonal::compute_hash(){
-  hash = a->getNum() + b->getNum();
-}
-
-unsigned long long Diagonal::get_hash() const{
-  return hash;
-}
-
-bool Diagonal::operator<(const Diagonal& diagonal) const{
-  return hash<diagonal.get_hash();
-}
-
-/**********************************************/
-/******************class Tuple*****************/
-/**********************************************/
-
-Tuple::Tuple(){}
-
-Tuple::Tuple(MVertex* a,MVertex* b,MVertex* c,MElement* element2,GFace* gf2){
-  if(a<=b && a<=c){
-    v1 = a;
-  }
-  else if(b<=a && b<=c){
-    v1 = b;
-  }
-  else{
-    v1 = c;
-  }
-
-  if(a>=b && a>=c){
-    v3 = a;
-  }
-  else if(b>=a && b>=c){
-    v3 = b;
-  }
-  else{
-    v3 = c;
-  }
-
-  if(a!=v1 && a!=v3){
-    v2 = a;
-  }
-  else if(b!=v1 && b!=v3){
-    v2 = b;
-  }
-  else{
-    v2 = c;
-  }
-
-  element = element2;
-  gf = gf2;
-  hash = a->getNum() + b->getNum() + c->getNum();
-}
-
-Tuple::Tuple(MVertex* a,MVertex* b,MVertex* c){
-  if(a<=b && a<=c){
-    v1 = a;
-  }
-  else if(b<=a && b<=c){
-    v1 = b;
-  }
-  else{
-    v1 = c;
-  }
-
-  if(a>=b && a>=c){
-    v3 = a;
-  }
-  else if(b>=a && b>=c){
-    v3 = b;
-  }
-  else{
-    v3 = c;
-  }
-
-  if(a!=v1 && a!=v3){
-    v2 = a;
-  }
-  else if(b!=v1 && b!=v3){
-    v2 = b;
-  }
-  else{
-    v2 = c;
-  }
-
-  hash = a->getNum() + b->getNum() + c->getNum();
-}
-
-Tuple::~Tuple(){}
-
-MVertex* Tuple::get_v1(){
-  return v1;
-}
-
-MVertex* Tuple::get_v2(){
-  return v2;
-}
-
-MVertex* Tuple::get_v3(){
-  return v3;
-}
-
-MElement* Tuple::get_element() const{
-  return element;
-}
-
-GFace* Tuple::get_gf() const{
-  return gf;
-}
-
-bool Tuple::same_vertices(Tuple tuple){
-  if(v1==tuple.get_v1() && v2==tuple.get_v2() && v3==tuple.get_v3()){
-    return 1;
-  }
-  else{
-    return 0;
-  }
-}
-
-unsigned long long Tuple::get_hash() const{
-  return hash;
-}
-
-bool Tuple::operator<(const Tuple& tuple) const{
-  return hash<tuple.get_hash();
-}
-
 /**************************************************/
 /****************class Recombinator****************/
 /**************************************************/
@@ -1352,13 +1007,13 @@ void Recombinator::execute(GRegion* gr){
   std::sort(potential.begin(),potential.end(),compare_hex_ptr_by_quality);
 
 
-  //  /// SORTIE TOUS HEX POT
-  //  cout << "__________________________ START POT HEX LISTING ____________________ " << endl;
-  //  for (std::vector<Hex*>::iterator it = potential.begin();it!=potential.end();it++){
-  //    cout << "--- pot hex : " << *it << "   " << (*it)->get_quality() << endl;
-  //  }
-  //  cout << "__________________________ END POT HEX LISTING ____________________ " << endl;
-  //  /// END
+  ///// SORTIE TOUS HEX POT
+  //cout << "__________________________ START POT HEX LISTING ____________________ " << endl;
+  //for (std::vector<Hex*>::iterator it = potential.begin();it!=potential.end();it++){
+  //  cout << "--- Potential hex : " << *(*it) << "   " << (*it)->get_quality() << endl;
+  //}
+  //cout << "__________________________ END POT HEX LISTING ____________________ " << endl;
+  ///// END
 
   hash_tableA.clear();
   hash_tableB.clear();
@@ -1385,78 +1040,62 @@ void Recombinator::init_markings(GRegion* gr){
   }
 }
 
-void Recombinator::pattern1(GRegion* gr){
-  size_t i;
-  int index;
-  double quality;
-  MElement* element;
-  MVertex *a,*b,*c,*d;
-  MVertex *p,*q,*r,*s;
-  std::vector<MVertex*> already;
-  std::set<MVertex*> bin1;
-  std::set<MVertex*> bin2;
-  std::set<MVertex*> bin3;
-  std::set<MVertex*> bin4;
-  std::set<MVertex*>::iterator it1;
-  std::set<MVertex*>::iterator it2;
-  std::set<MVertex*>::iterator it3;
-  std::set<MVertex*>::iterator it4;
-  Hex *hex;
-
-  for(i=0;i<gr->getNumMeshElements();i++){
-    element = gr->getMeshElement(i);
-    for(index=0;index<4;index++){
-    //max_scaled_jacobian(element,index);
-
-    a = element->getVertex(index);
-    b = element->getVertex((index+1)%4);
-    c = element->getVertex((index+2)%4);
-    d = element->getVertex((index+3)%4);
-
-    already.clear();
-    already.push_back(a);
-    already.push_back(b);
-    already.push_back(c);
-    already.push_back(d);
-    bin1.clear();
-    bin2.clear();
-    bin3.clear();
-    find(b,d,already,bin1);
-    find(b,c,already,bin2);
-    find(c,d,already,bin3);
-
-    for(it1=bin1.begin();it1!=bin1.end();it1++){
-      p = *it1;
-      for(it2=bin2.begin();it2!=bin2.end();it2++){
-        q = *it2;
-        for(it3=bin3.begin();it3!=bin3.end();it3++){
-          r = *it3;
-          if(p!=q && p!=r && q!=r){
-            already.clear();
-            already.push_back(a);
-            already.push_back(b);
-            already.push_back(c);
-            already.push_back(d);
-            already.push_back(p);
-            already.push_back(q);
-            already.push_back(r);
-            bin4.clear();
-            find(p,q,r,already,bin4);
-            for(it4=bin4.begin();it4!=bin4.end();it4++){
-              s = *it4;
-              hex = new Hex(a,b,q,c,d,p,s,r);
-              quality = min_scaled_jacobian(*hex);
-              hex->set_quality(quality);
-              if(valid(*hex)){
-                potential.push_back(hex);
+void Recombinator::pattern1(GRegion* gr) {
+
+  for (unsigned int i = 0; i < gr->getNumMeshElements(); i++) {
+    MElement* element = gr->getMeshElement(i);
+
+    for (int index = 0; index < 4; index++) {
+      //max_scaled_jacobian(element,index);
+      MVertex *a = element->getVertex(index);
+      MVertex *b = element->getVertex((index + 1) % 4);
+      MVertex *c = element->getVertex((index + 2) % 4);
+      MVertex *d = element->getVertex((index + 3) % 4);
+
+      std::vector<MVertex*> already(4);
+      already[0]= a; 
+      already[1]= b;
+      already[2]= c;
+      already[3]= d;
+
+      std::set<MVertex*> bin1;
+      std::set<MVertex*> bin2;
+      std::set<MVertex*> bin3;
+
+      find(b, d, already, bin1); // candidates for F - p
+      find(b, c, already, bin2); // candidates for C - q
+      find(c, d, already, bin3); // candidates for H - r
+
+      already.resize(7);
+      for (std::set<MVertex*>::iterator it1 = bin1.begin(); it1 != bin1.end(); it1++) {
+        MVertex* p = *it1;
+        already[4] = p;
+        for (std::set<MVertex*>::iterator it2 = bin2.begin(); it2 != bin2.end(); it2++) {
+          MVertex* q = *it2;
+          already[5] = q;
+          for (std::set<MVertex*>::iterator it3 = bin3.begin(); it3 != bin3.end(); it3++) {
+            MVertex* r = *it3;
+            already[6] = r;
+            if (p != q && p != r && q != r) {              
+              std::set<MVertex*> bin4;  // candidates for G - s vertices linked to p,q and r
+              find(p, q, r, already, bin4);
+              
+              for (std::set<MVertex*>::iterator it4 = bin4.begin(); it4 != bin4.end(); it4++) {
+                MVertex* s = *it4;
+                Hex* hex = new Hex(a, b, q, c, d, p, s, r);
+                double quality = min_scaled_jacobian(*hex);
+                hex->set_quality(quality);
+                if (valid(*hex)) {
+                  potential.push_back(hex);
+                } else {
+                  delete hex;
+                }
               }
-              else delete hex;
             }
           }
         }
       }
     }
-    }
   }
 }
 
@@ -2316,8 +1955,8 @@ bool Recombinator::valid(Hex &hex,const std::set<MElement*>& parts){
   }
 }
 
-bool validFace(MVertex *a, MVertex *b, MVertex *c, MVertex *d, std::map<MVertex*,std::set<MElement*> > &vertexToElements){
-  std::map<MVertex*,std::set<MElement*> >::iterator itElV[4];
+bool validFace(MVertex *a, MVertex *b, MVertex *c, MVertex *d, const std::map<MVertex*,std::set<MElement*> > &vertexToElements){
+  std::map<MVertex*,std::set<MElement*> >::const_iterator itElV[4];
   MVertex *faceV[4] = {a, b, c, d};
   for (int iV = 0; iV < 4; iV++){
     itElV[iV] = vertexToElements.find(faceV[iV]);
@@ -2325,19 +1964,21 @@ bool validFace(MVertex *a, MVertex *b, MVertex *c, MVertex *d, std::map<MVertex*
   size_t tris[4][3] = {{0, 1, 2}, {0, 2, 3}, {0, 1, 3}, {1, 2, 3}};
   size_t other[4] = {3, 1, 2, 0};
   size_t nbTris[4];
-  std::set<MElement*> buf1, buf2;
+
   for (int iTri = 0; iTri < 4; iTri++){
     //We count the number of elements sharing the considered triangle
+    std::set<MElement*> buf1;
+    std::set_intersection(itElV[tris[iTri][0]]->second.begin(),itElV[tris[iTri][0]]->second.end(),
+      itElV[tris[iTri][1]]->second.begin(),itElV[tris[iTri][1]]->second.end(),std::inserter(buf1,buf1.end()));
+    std::set<MElement*> buf2;
+    std::set_intersection(buf1.begin(),buf1.end(),
+      itElV[tris[iTri][2]]->second.begin(),itElV[tris[iTri][2]]->second.end(),std::inserter(buf2,buf2.end()));
     buf1.clear();
-    std::set_intersection(itElV[tris[iTri][0]]->second.begin(),itElV[tris[iTri][0]]->second.end(),itElV[tris[iTri][1]]->second.begin(),itElV[tris[iTri][1]]->second.end(),std::inserter(buf1,buf1.end()));
-    buf2.clear();
-    std::set_intersection(buf1.begin(),buf1.end(),itElV[tris[iTri][2]]->second.begin(),itElV[tris[iTri][2]]->second.end(),std::inserter(buf2,buf2.end()));
-    buf1.clear();
-    std::set_difference(buf2.begin(),buf2.end(),itElV[other[iTri]]->second.begin(),itElV[other[iTri]]->second.end(),std::inserter(buf1,buf1.end()));
+    std::set_difference(buf2.begin(),buf2.end(),
+      itElV[other[iTri]]->second.begin(),itElV[other[iTri]]->second.end(),std::inserter(buf1,buf1.end()));
     nbTris[iTri] = buf1.size();
   }
 
-
   bool valid = false;
   // All sub-faces inside (2 elements)
   if (nbTris[0]== 2 && nbTris[1] == 2 && nbTris[2] == 0 && nbTris[3] == 0) valid = true;
@@ -2355,9 +1996,9 @@ bool validFace(MVertex *a, MVertex *b, MVertex *c, MVertex *d, std::map<MVertex*
   if (c->onWhat()->dim() < 3) nbBndNodes++;
   if (d->onWhat()->dim() < 3) nbBndNodes++;
   if (nbBndNodes == 4){
-    SVector3 vec1 = SVector3(b->x()-a->x(),b->y()-a->y(),b->z()-a->z()).unit();
-    SVector3 vec2 = SVector3(c->x()-a->x(),c->y()-a->y(),c->z()-a->z()).unit();
-    SVector3 vec3 = SVector3(d->x()-a->x(),d->y()-a->y(),d->z()-a->z()).unit();
+    SVector3 vec1 = SVector3(a->point(), b->point()).unit();
+    SVector3 vec2 = SVector3(a->point(), c->point()).unit();
+    SVector3 vec3 = SVector3(a->point(), d->point()).unit();
 
     SVector3 crossVec1Vec2 = crossprod(vec1, vec2);
     double angle = fabs(acos(dot(crossVec1Vec2, vec3))*180/M_PI);
@@ -2366,8 +2007,6 @@ bool validFace(MVertex *a, MVertex *b, MVertex *c, MVertex *d, std::map<MVertex*
   }
 
   return valid;
-
-
 }
 
 
@@ -2452,56 +2091,45 @@ bool PostOp::valid(MPyramid *pyr){
 //  return true;
 //}
 
-bool validFaces(Hex &hex, std::map<MVertex*,std::set<MElement*> > &vertexToElements){
-  bool v1, v2, v3, v4, v5, v6;
-  MVertex *a,*b,*c,*d;
-  MVertex *e,*f,*g,*h;
-
-  a = hex.get_a();
-  b = hex.get_b();
-  c = hex.get_c();
-  d = hex.get_d();
-  e = hex.get_e();
-  f = hex.get_f();
-  g = hex.get_g();
-  h = hex.get_h();
-
-  v1 = validFace(a,b,c,d,vertexToElements);  //SHOULD CHECK GEOMETRY
-  v2 = validFace(e,f,g,h,vertexToElements);
-  v3 = validFace(a,b,f,e,vertexToElements);
-  v4 = validFace(b,c,g,f,vertexToElements);
-  v5 = validFace(d,c,g,h,vertexToElements);
-  v6 = validFace(d,a,e,h,vertexToElements);
+bool validFaces(const Hex &hex, const std::map<MVertex*,std::set<MElement*> > &vertexToElements) {
+  MVertex *a = hex.get_a();
+  MVertex *b = hex.get_b();
+  MVertex *c = hex.get_c();
+  MVertex *d = hex.get_d();
+  MVertex *e = hex.get_e();
+  MVertex *f = hex.get_f();
+  MVertex *g = hex.get_g();
+  MVertex *h = hex.get_h();
+
+  bool v1 = validFace(a,b,c,d,vertexToElements);  //SHOULD CHECK GEOMETRY
+  bool v2 = validFace(e,f,g,h,vertexToElements);
+  bool v3 = validFace(a,b,f,e,vertexToElements);
+  bool v4 = validFace(b,c,g,f,vertexToElements);
+  bool v5 = validFace(d,c,g,h,vertexToElements);
+  bool v6 = validFace(d,a,e,h,vertexToElements);
 
   return v1 && v2 && v3 && v4 && v5 && v6;
 }
 
 // renvoie true si le "MQuadrangle::etaShapeMeasure" des 6 faces est plus grand que 0.000001
-bool Recombinator::valid(Hex &hex){
-  double k;
-  double eta1,eta2,eta3;
-  double eta4,eta5,eta6;
-  MVertex *a,*b,*c,*d;
-  MVertex *e,*f,*g,*h;
-
-  k = 0.000001;
-
-  a = hex.get_a();
-  b = hex.get_b();
-  c = hex.get_c();
-  d = hex.get_d();
-  e = hex.get_e();
-  f = hex.get_f();
-  g = hex.get_g();
-  h = hex.get_h();
-
-  eta1 = eta(a,b,c,d);
-  eta2 = eta(e,f,g,h);
-  eta3 = eta(a,b,f,e);
-  eta4 = eta(b,c,g,f);
-  eta5 = eta(d,a,e,h);
-  eta6 = eta(d,c,g,h);
-
+bool Recombinator::valid(Hex &hex) const{
+  MVertex *a = hex.get_a();
+  MVertex *b = hex.get_b();
+  MVertex *c = hex.get_c();
+  MVertex *d = hex.get_d();
+  MVertex *e = hex.get_e();
+  MVertex *f = hex.get_f();
+  MVertex *g = hex.get_g();
+  MVertex *h = hex.get_h();
+
+  double eta1 = eta(a,b,c,d);
+  double eta2 = eta(e,f,g,h);
+  double eta3 = eta(a,b,f,e);
+  double eta4 = eta(b,c,g,f);
+  double eta5 = eta(d,a,e,h);
+  double eta6 = eta(d,c,g,h);
+
+  double k = 0.000001; // This test seems wrong, I'd guess it returns wrong if one angle is 90 deg. Jeanne
   if(eta1>k && eta2>k && eta3>k && eta4>k && eta5>k && eta6>k){
     return validFaces(hex,vertex_to_elements);
   }
@@ -2510,14 +2138,9 @@ bool Recombinator::valid(Hex &hex){
   }
 }
 
-double Recombinator::eta(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
-  double val;
-  MQuadrangle* quad;
-
-  quad = new MQuadrangle(a,b,c,d);
-  val = quad->etaShapeMeasure();
-  delete quad;
-  return val;
+double Recombinator::eta(MVertex* a,MVertex* b,MVertex* c,MVertex* d) const{
+  MQuadrangle quad(a,b,c,d);
+  return quad.etaShapeMeasure();  
 }
 
 bool Recombinator::linked(MVertex* v1,MVertex* v2){
@@ -2538,46 +2161,34 @@ bool Recombinator::linked(MVertex* v1,MVertex* v2){
   return flag;
 }
 
-void Recombinator::find(MVertex* v1,MVertex* v2,const std::vector<MVertex*>& already,std::set<MVertex*>& final){
-  std::map<MVertex*,std::set<MVertex*> >::iterator it1;
-  std::map<MVertex*,std::set<MVertex*> >::iterator it2;
-
-  it1 = vertex_to_vertices.find(v1);
-  it2 = vertex_to_vertices.find(v2);
+void Recombinator::find(MVertex* v1,MVertex* v2,const std::vector<MVertex*>& already,std::set<MVertex*>& final) const{
+  std::map<MVertex*, std::set<MVertex*> >::const_iterator it1 = vertex_to_vertices.find(v1);
+  std::map<MVertex*, std::set<MVertex*> >::const_iterator it2 = vertex_to_vertices.find(v2);
 
   intersection(it1->second,it2->second,already,final);
 }
 
-void Recombinator::find(MVertex* v1,MVertex* v2,MVertex* v3,const std::vector<MVertex*>& already,std::set<MVertex*>& final){
-  std::map<MVertex*,std::set<MVertex*> >::iterator it1;
-  std::map<MVertex*,std::set<MVertex*> >::iterator it2;
-  std::map<MVertex*,std::set<MVertex*> >::iterator it3;
-
-  it1 = vertex_to_vertices.find(v1);
-  it2 = vertex_to_vertices.find(v2);
-  it3 = vertex_to_vertices.find(v3);
+void Recombinator::find(MVertex* v1,MVertex* v2,MVertex* v3, const std::vector<MVertex*>& already,std::set<MVertex*>& final) const {   
+  std::map<MVertex*, std::set<MVertex*> >::const_iterator it1 = vertex_to_vertices.find(v1);
+  std::map<MVertex*, std::set<MVertex*> >::const_iterator it2 = vertex_to_vertices.find(v2);
+  std::map<MVertex*, std::set<MVertex*> >::const_iterator it3 = vertex_to_vertices.find(v3);
 
   intersection(it1->second,it2->second,it3->second,already,final);
 }
 
-void Recombinator::find(MVertex* v1,MVertex* v2,std::set<MElement*>& final){
-  std::map<MVertex*,std::set<MElement*> >::iterator it1;
-  std::map<MVertex*,std::set<MElement*> >::iterator it2;
-
-  it1 = vertex_to_elements.find(v1);
-  it2 = vertex_to_elements.find(v2);
+void Recombinator::find(MVertex* v1,MVertex* v2,std::set<MElement*>& final) const {
+  std::map<MVertex*, std::set<MElement*> >::const_iterator it1 = vertex_to_elements.find(v1);
+  std::map<MVertex*, std::set<MElement*> >::const_iterator it2 = vertex_to_elements.find(v2);
 
   intersection(it1->second,it2->second,final);
 }
 
-void Recombinator::find(MVertex* vertex,Hex hex,std::set<MElement*>& final){
+void Recombinator::find(MVertex* vertex,Hex hex,std::set<MElement*>& final) const {
   bool flag1,flag2,flag3,flag4;
   MVertex *a,*b,*c,*d;
-  std::map<MVertex*,std::set<MElement*> >::iterator it;
+  std::map<MVertex*,std::set<MElement*> >::const_iterator it = vertex_to_elements.find(vertex);
   std::set<MElement*>::iterator it2;
 
-  it = vertex_to_elements.find(vertex);
-
   for(it2=(it->second).begin();it2!=(it->second).end();it2++){
     a = (*it2)->getVertex(0);
     b = (*it2)->getVertex(1);
@@ -2595,27 +2206,20 @@ void Recombinator::find(MVertex* vertex,Hex hex,std::set<MElement*>& final){
   }
 }
 
-MVertex* Recombinator::find(MVertex* v1,MVertex* v2,MVertex* v3,MVertex* already,const std::set<MElement*>& bin){
-  bool flag1,flag2,flag3,flag4;
-  MElement* element;
-  MVertex *a,*b,*c,*d;
-  MVertex* pointer;
-  std::set<MElement*>::const_iterator it;
-
-  pointer = 0;
-
-  for(it=bin.begin();it!=bin.end();it++){
-    element = *it;
+MVertex* Recombinator::find(MVertex* v1,MVertex* v2,MVertex* v3,MVertex* already,const std::set<MElement*>& bin) const{
+  MVertex* pointer = NULL;
+  for(std::set<MElement*>::const_iterator it=bin.begin();it!=bin.end();it++){
+    MElement *element = *it;
 
-    a = element->getVertex(0);
-    b = element->getVertex(1);
-    c = element->getVertex(2);
-    d = element->getVertex(3);
+    MVertex *a = element->getVertex(0);
+    MVertex *b = element->getVertex(1);
+    MVertex *c = element->getVertex(2);
+    MVertex *d = element->getVertex(3);
 
-    flag1 = inclusion(v1,a,b,c,d);
-    flag2 = inclusion(v2,a,b,c,d);
-    flag3 = inclusion(v3,a,b,c,d);
-    flag4 = inclusion(already,a,b,c,d);
+    bool flag1 = inclusion(v1,a,b,c,d);
+    bool flag2 = inclusion(v2,a,b,c,d);
+    bool flag3 = inclusion(v3,a,b,c,d);
+    bool flag4 = inclusion(already,a,b,c,d);
 
     if(flag1 && flag2 && flag3 && !flag4){
       if(a!=v1 && a!=v2 && a!=v3){
@@ -2633,29 +2237,27 @@ MVertex* Recombinator::find(MVertex* v1,MVertex* v2,MVertex* v3,MVertex* already
       break;
     }
   }
-
   return pointer;
 }
 
+// Compute the intersection of bin1 and bin2
+// And add to final the elements that are not in the already vector
 void Recombinator::intersection(const std::set<MVertex*>& bin1,const std::set<MVertex*>& bin2,
-                                const std::vector<MVertex*>& already,std::set<MVertex*>& final){
-  size_t i;
-  bool ok;
+                                const std::vector<MVertex*>& already,std::set<MVertex*>& final) const{
   std::set<MVertex*> temp;
-  std::set<MVertex*>::iterator it;
 
+  // Compute the intersection of the two input sets
   std::set_intersection(bin1.begin(),bin1.end(),bin2.begin(),bin2.end(),std::inserter(temp,temp.end()));
+  
+  for(std::set<MVertex*>::iterator it=temp.begin();it!=temp.end();it++){
+    bool ok = true;
 
-  for(it=temp.begin();it!=temp.end();it++){
-    ok = 1;
-
-    for(i=0;i<already.size();i++){
+    for(int i=0;i<already.size();i++){
       if((*it)==already[i]){
         ok = 0;
         break;
       }
     }
-
     if(ok){
       final.insert(*it);
     }
@@ -2663,7 +2265,7 @@ void Recombinator::intersection(const std::set<MVertex*>& bin1,const std::set<MV
 }
 
 void Recombinator::intersection(const std::set<MVertex*>& bin1,const std::set<MVertex*>& bin2,const std::set<MVertex*>& bin3,
-                                const std::vector<MVertex*>& already,std::set<MVertex*>& final){
+                                const std::vector<MVertex*>& already,std::set<MVertex*>& final) const {
   size_t i;
   bool ok;
   std::set<MVertex*> temp;
@@ -2689,39 +2291,35 @@ void Recombinator::intersection(const std::set<MVertex*>& bin1,const std::set<MV
   }
 }
 
-void Recombinator::intersection(const std::set<MElement*>& bin1,const std::set<MElement*>& bin2,std::set<MElement*>& final){
+void Recombinator::intersection(const std::set<MElement*>& bin1,const std::set<MElement*>& bin2,std::set<MElement*>& final) const {
   std::set_intersection(bin1.begin(),bin1.end(),bin2.begin(),bin2.end(),std::inserter(final,final.end()));
 }
 
-// return true if vertex belong to hex
-bool Recombinator::inclusion(MVertex* vertex,Hex hex){
-  bool flag;
-
-  flag = 0;
+// return true if vertex belongs to hex - test on the pointer equality only
+bool Recombinator::inclusion(MVertex* vertex,Hex hex) const {
+  bool included = false;
 
-  if(vertex==hex.get_a()) flag = 1;
-  else if(vertex==hex.get_b()) flag = 1;
-  else if(vertex==hex.get_c()) flag = 1;
-  else if(vertex==hex.get_d()) flag = 1;
-  else if(vertex==hex.get_e()) flag = 1;
-  else if(vertex==hex.get_f()) flag = 1;
-  else if(vertex==hex.get_g()) flag = 1;
-  else if(vertex==hex.get_h()) flag = 1;
+  if(vertex==hex.get_a()) included = true;
+  else if(vertex==hex.get_b()) included = true;
+  else if(vertex==hex.get_c()) included = true;
+  else if(vertex==hex.get_d()) included = true;
+  else if(vertex==hex.get_e()) included = true;
+  else if(vertex==hex.get_f()) included = true;
+  else if(vertex==hex.get_g()) included = true;
+  else if(vertex==hex.get_h()) included = true;
 
-  return flag;
+  return included;
 }
 
 // pfffffff... renvoie true si vertex se trouve dans [a,b,c]
 // en gros, return (abcd.find(vertex)!=abcd.end());
-bool Recombinator::inclusion(MVertex* vertex,MVertex* a,MVertex* b,MVertex* c,MVertex* d){
-  bool flag;
+bool Recombinator::inclusion(MVertex* vertex,MVertex* a,MVertex* b,MVertex* c,MVertex* d) const {
+  bool flag = false;
 
-  flag = 0;
-
-  if(vertex==a) flag = 1;
-  else if(vertex==b) flag = 1;
-  else if(vertex==c) flag = 1;
-  else if(vertex==d) flag = 1;
+  if(vertex==a) flag = true;
+  else if(vertex==b) flag = true;
+  else if(vertex==c) flag = true;
+  else if(vertex==d) flag = true;
 
   return flag;
 }
@@ -2729,34 +2327,24 @@ bool Recombinator::inclusion(MVertex* vertex,MVertex* a,MVertex* b,MVertex* c,MV
 
 // return true if all three vertices v1,v2 and v3 belong to one tet
 // on pourrait plutot faire: est-ce que la face (v1v2v3) fait partie d'un tet, avec l'info hashée de tet to triangle ???
-bool Recombinator::inclusion(MVertex* v1,MVertex* v2,MVertex* v3,const std::set<MElement*>& bin){
-  bool ok;
-  bool flag1,flag2,flag3;
-  MVertex *a,*b,*c,*d;
-  MElement* element;
-  std::set<MElement*>::const_iterator it;
-
-  ok = 0;
-
-  for(it=bin.begin();it!=bin.end();it++){
-    element = *it;
+bool Recombinator::inclusion(MVertex* v1,MVertex* v2,MVertex* v3,const std::set<MElement*>& bin) const {
+  for(std::set<MElement*>::const_iterator it=bin.begin();it!=bin.end();it++){
+    MElement *element = *it;
 
-    a = element->getVertex(0);
-    b = element->getVertex(1);
-    c = element->getVertex(2);
-    d = element->getVertex(3);
+    MVertex *a = element->getVertex(0);
+    MVertex *b = element->getVertex(1);
+    MVertex *c = element->getVertex(2);
+    MVertex *d = element->getVertex(3);
 
-    flag1 = inclusion(v1,a,b,c,d);
-    flag2 = inclusion(v2,a,b,c,d);
-    flag3 = inclusion(v3,a,b,c,d);
+    bool flag1 = inclusion(v1,a,b,c,d);
+    bool flag2 = inclusion(v2,a,b,c,d);
+    bool flag3 = inclusion(v3,a,b,c,d);
 
     if(flag1 && flag2 && flag3){
-      ok = 1;
-      break;
+      return true;
     }
   }
-
-  return ok;
+  return false;
 }
 
 // return true si la facet existe dans la table A
@@ -3003,7 +2591,8 @@ bool Recombinator::faces_statuquo(Hex &hex){
   return c1 && c2 && c3 && c4 && c5 && c6;
 }
 
-// return false si, parmis les deux paires de facets de la face, il existe un couple de facet qui soinent toutes les deux des tuples, mais correspondant à des geometric faces différentes. Bref, une arrête géométrique confondue avec une diagonale de la face.
+// return false si, parmis les deux paires de facets de la face, il existe un couple de facet
+// qui soinent toutes les deux des tuples, mais correspondant à des geometric faces différentes. Bref, une arrête géométrique confondue avec une diagonale de la face.
 bool Recombinator::faces_statuquo(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
   bool ok;
   bool flag1,flag2;
@@ -3410,21 +2999,17 @@ void Recombinator::print_segment(SPoint3 p1,SPoint3 p2,std::ofstream& file){
        << "{10, 20};\n";
 }
 
-double Recombinator::scaled_jacobian(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
-  double val;
-  double l1,l2,l3;
-  SVector3 vec1,vec2,vec3;
+double Recombinator::scaled_jacobian(MVertex* a,MVertex* b,MVertex* c,MVertex* d){  
+  SVector3 ab(a->point(), b->point());
+  SVector3 ac(a->point(), c->point());
+  SVector3 ad(a->point(), d->point());
 
-  vec1 = SVector3(b->x()-a->x(),b->y()-a->y(),b->z()-a->z());
-  vec2 = SVector3(c->x()-a->x(),c->y()-a->y(),c->z()-a->z());
-  vec3 = SVector3(d->x()-a->x(),d->y()-a->y(),d->z()-a->z());
+  double l_ab = ab.norm();
+  double l_ac = ac.norm();
+  double l_ad = ad.norm();
 
-  l1 = vec1.norm();
-  l2 = vec2.norm();
-  l3 = vec3.norm();
-
-  val = dot(vec1,crossprod(vec2,vec3));
-  return val/(l1*l2*l3);
+  double val = dot(ab,crossprod(ac,ad));
+  return val/(l_ab*l_ac*l_ad);
 }
 
 /*double Recombinator::scaled_jacobian_face(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
@@ -3475,30 +3060,25 @@ double Recombinator::max_scaled_jacobian(MElement* element,int& index){
 
 double Recombinator::min_scaled_jacobian(Hex &hex){
   int i;
-  double min, max;
-  double j1,j2,j3,j4,j5,j6,j7,j8;
-  MVertex *a,*b,*c,*d;
-  MVertex *e,*f,*g,*h;
-  std::vector<double> jacobians;
-
-  a = hex.get_a();
-  b = hex.get_b();
-  c = hex.get_c();
-  d = hex.get_d();
-  e = hex.get_e();
-  f = hex.get_f();
-  g = hex.get_g();
-  h = hex.get_h();
-
-  j1 = scaled_jacobian(a,b,d,e);
-  j2 = scaled_jacobian(b,c,a,f);
-  j3 = scaled_jacobian(c,d,b,g);
-  j4 = scaled_jacobian(d,a,c,h);
-  j5 = scaled_jacobian(e,h,f,a);
-  j6 = scaled_jacobian(f,e,g,b);
-  j7 = scaled_jacobian(g,f,h,c);
-  j8 = scaled_jacobian(h,g,e,d);
+  MVertex *a = hex.get_a();
+  MVertex *b = hex.get_b();
+  MVertex *c = hex.get_c();
+  MVertex *d = hex.get_d();
+  MVertex *e = hex.get_e();
+  MVertex *f = hex.get_f();
+  MVertex *g = hex.get_g();
+  MVertex *h = hex.get_h();
+
+  double j1 = scaled_jacobian(a,b,d,e);
+  double j2 = scaled_jacobian(b,c,a,f);
+  double j3 = scaled_jacobian(c,d,b,g);
+  double j4 = scaled_jacobian(d,a,c,h);
+  double j5 = scaled_jacobian(e,h,f,a);
+  double j6 = scaled_jacobian(f,e,g,b);
+  double j7 = scaled_jacobian(g,f,h,c);
+  double j8 = scaled_jacobian(h,g,e,d);
 
+  std::vector<double> jacobians;
   jacobians.push_back(j1);
   jacobians.push_back(j2);
   jacobians.push_back(j3);
@@ -3508,13 +3088,13 @@ double Recombinator::min_scaled_jacobian(Hex &hex){
   jacobians.push_back(j7);
   jacobians.push_back(j8);
 
-  min = 1000000000.0;
-  max = -1000000000.0;
-  for(i=0;i<8;i++){
+  double min = DBL_MAX;
+  double max = DBL_MIN;
+  for(unsigned int i=0; i<8; i++){
     min = std::min(min, jacobians[i]);
     max = std::max(max, jacobians[i]);
   }
-  if (max < 0) min = -max;
+  if (max < 0) min = -max; // Why ? Why is there no test on min < -max ?? Jeanne 
 
   /*MHexahedron *h1 = new MHexahedron(a, b, c, d, e, f, g, h);
   MHexahedron *h2 = new MHexahedron(e, f, g, h, a, b, c, d);
@@ -8898,7 +8478,6 @@ void Recombinator_Graph::add_graph_entry(Hex* hex, Hex* other_hex)
 
 void Recombinator_Graph::compute_hex_ranks()
 {
-
   create_faces_connectivity();
 
   PETriangle* face;
@@ -8915,7 +8494,7 @@ void Recombinator_Graph::compute_hex_ranks()
     //cout << " --- hex " << hex << " has " << boundary_count << " tri faces on boundaries, " << hex_to_faces[hex].size() << " total tri faces " << endl;
     map<Hex*,vector<double> >::iterator itfind = hex_ranks.find(hex);
     if (itfind==hex_ranks.end())
-      hex_ranks.insert(make_pair(hex,vector<double>(1)));
+      hex_ranks.insert(make_pair(hex,vector<double>(2)));
     hex_ranks[hex][0] = boundary_count;
     hex_ranks[hex][1] = hex->get_quality();
   }
diff --git a/Mesh/yamakawa.h b/Mesh/yamakawa.h
index ba824672ad..8e19177f6f 100644
--- a/Mesh/yamakawa.h
+++ b/Mesh/yamakawa.h
@@ -170,68 +170,164 @@ protected:
 
 
 
-class Hex{
+class Hex {
 private:
   double quality;
   unsigned long long hash;
-  MVertex *a,*b,*c,*d,*e,*f,*g,*h;
-  void set_hash();
+  MVertex* vertices_[8];
+  //MVertex *a,*b,*c,*d,*e,*f,*g,*h;
+private:
+  void set_hash(){
+    hash = 0.;
+    for (int i = 0; i < 8; ++i) {
+      hash += vertices_[i]->getNum();
+    }    
+  }
+
 public:
-  Hex();
-  Hex(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*);
-  ~Hex();
-  double get_quality();
-  void set_quality(double);
-  MVertex* get_a();
-  MVertex* get_b();
-  MVertex* get_c();
-  MVertex* get_d();
-  MVertex* get_e();
-  MVertex* get_f();
-  MVertex* get_g();
-  MVertex* get_h();
-  MVertex* getVertex(int n);
-  bool hasVertex(const MVertex *v);
-  bool same_vertices(Hex *h);
-  void set_vertices(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*);
-  unsigned long long get_hash();
-  bool operator<( Hex&) ;
+  Hex() : quality(0.), hash(0.), vertices_{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL} {};
+
+  Hex(MVertex* a2, MVertex* b2, MVertex* c2, MVertex* d2, MVertex* e2, MVertex* f2, MVertex* g2, MVertex* h2) :
+    quality(0.), vertices_{a2,b2,c2, d2, e2, f2, g2, h2}
+  {
+    set_hash();
+  }
+  ~Hex() {};
+  double get_quality() const { return quality; }
+  void set_quality(double new_quality) { quality = new_quality; }
+  MVertex* get_a() const { return vertices_[0]; }
+  MVertex* get_b() const { return vertices_[1]; }
+  MVertex* get_c() const { return vertices_[2]; }
+  MVertex* get_d() const { return vertices_[3]; }
+  MVertex* get_e() const { return vertices_[4]; }
+  MVertex* get_f() const { return vertices_[5]; }
+  MVertex* get_g() const { return vertices_[6]; }
+  MVertex* get_h() const { return vertices_[7]; }
+  MVertex* getVertex(unsigned int n) const {
+    if (n < 8) {
+      return vertices_[n];
+    }
+    else {
+      cout << "Hex: unknown vertex number " << n << endl;
+      throw;
+      return NULL;
+    }
+  }
+
+  bool hasVertex(const MVertex *v) const {
+    for (int i = 0; i < 8; i++) {
+      if (getVertex(i) == v) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool same_vertices(Hex *h) const {
+    for (int i = 0; i < 8; i++) {
+      if (!(h->hasVertex(getVertex(i)))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void set_vertices(MVertex* a2, MVertex* b2, MVertex* c2, MVertex* d2, MVertex* e2, MVertex* f2, MVertex* g2, MVertex* h2) {
+    vertices_[0] = a2;
+    vertices_[1] = b2;
+    vertices_[2] = c2;
+    vertices_[3] = d2;
+    vertices_[4] = e2;
+    vertices_[5] = f2;
+    vertices_[6] = g2;
+    vertices_[7] = h2;
+  }
+
+  unsigned long long get_hash() {
+    if (hash == 0. && vertices_[0]!=NULL) {
+      set_hash();
+    }
+    return hash;
+  }
+  bool operator<(const Hex& hex) const {
+    return quality > hex.get_quality(); // Why > ??? Shouldn't it be < ?? Jeanne.
+  }
+
 };
 
-class Facet{
+class Facet {
 private:
-  MVertex *a,*b,*c;
+  MVertex *a, *b, *c;
   int num[3];
   unsigned long long hash;
 public:
-  Facet();
-  Facet(MVertex*,MVertex*,MVertex*);
-  ~Facet();
-  MVertex* get_a();
-  MVertex* get_b();
-  MVertex* get_c();
-  void set_vertices(MVertex*,MVertex*,MVertex*);
-  bool same_vertices(Facet);
-  void compute_hash();
-  unsigned long long get_hash() const;
-  bool operator<(const Facet&) const;
+  Facet() : a(NULL), b(NULL), c(NULL), num{ -1, -1, -1 }, hash(0.){}
+  Facet(MVertex* a2, MVertex* b2, MVertex* c2) :
+    a(a2), b(b2), c(c2), num {-1,-1,-1}, hash(0.){
+    compute_hash();
+  }
+  ~Facet() {};
+  MVertex* get_a() const { return a; }
+  MVertex* get_b() const { return b; }
+  MVertex* get_c() const { return c; }
+  void set_vertices(MVertex*a2, MVertex*b2, MVertex*c2) {
+    a = a2;
+    b = b2;
+    c = c2;
+    compute_hash();
+  }
+  bool same_vertices(const Facet& facet) const {    
+    bool c1 = (a == facet.get_a()) || (a == facet.get_b()) || (a == facet.get_c());
+    bool c2 = (b == facet.get_a()) || (b == facet.get_b()) || (b == facet.get_c());
+    bool c3 = (c == facet.get_a()) || (c == facet.get_b()) || (c == facet.get_c());
+    return c1 && c2 && c3;
+  }
+  void compute_hash() {
+    num[0] = a->getNum();
+    num[1] = b->getNum();
+    num[2] = c->getNum();
+    std::sort(num, num + 3);
+    hash = num[2] + 1e4*num[1] + 1e8*num[0];
+  }
+  unsigned long long get_hash() const { return hash; }
+  bool operator<(const Facet& rhs) const {
+    return hash<rhs.get_hash();
+  }
 };
 
 class Diagonal{
 private:
   MVertex *a,*b;
   unsigned long long hash;
+private:
+  void compute_hash() {
+    hash = a->getNum() + b->getNum();
+  }
+
 public:
-  Diagonal();
-  Diagonal(MVertex*,MVertex*);
-  ~Diagonal();
-  MVertex* get_a();
-  MVertex* get_b();
-  void set_vertices(MVertex*,MVertex*);
-  bool same_vertices(Diagonal);
-  void compute_hash();
-  unsigned long long get_hash() const;
-  bool operator<(const Diagonal&) const;
+  Diagonal() :a(NULL), b(NULL), hash() {};
+  Diagonal(MVertex*a2, MVertex*b2) :a(a2), b(b2){
+    compute_hash();
+  }
+  ~Diagonal() {};
+  MVertex* get_a() const {return a;}
+  MVertex* get_b() const {return b;}
+  void set_vertices(MVertex*a2, MVertex*b2) {
+    a = a2;
+    b = b2;
+    compute_hash();
+  }
+  bool same_vertices(Diagonal diagonal) const {
+    bool c1 = (a == diagonal.get_a()) || (a == diagonal.get_b());
+    bool c2 = (b == diagonal.get_a()) || (b == diagonal.get_b());
+    return c1 && c2;
+  }
+  unsigned long long get_hash() const {
+    return hash;
+  }
+  bool operator<(const Diagonal& rhs) const {
+    return hash<rhs.get_hash();
+  }
 };
 
 class Tuple{
@@ -241,20 +337,44 @@ private:
   GFace* gf;
   unsigned long long hash;
 public:
-  Tuple();
-  Tuple(MVertex*,MVertex*,MVertex*,MElement*,GFace*);
-  Tuple(MVertex*,MVertex*,MVertex*);
-  ~Tuple();
-  MVertex* get_v1();
-  MVertex* get_v2();
-  MVertex* get_v3();
-  MElement* get_element() const;
-  GFace* get_gf() const;
-  bool same_vertices(Tuple);
-  unsigned long long get_hash() const;
-  bool operator<(const Tuple&) const;
+  Tuple() : v1(NULL), v2(NULL), v3(NULL), element(NULL), gf(NULL), hash(0.) {}
+  Tuple(MVertex* a, MVertex* b, MVertex* c, MElement* element2, GFace* gf2)
+    : Tuple(a,b,c)
+  {    
+    element = element2;
+    gf = gf2;  
+  }
+  Tuple(MVertex* a, MVertex* b, MVertex* c)
+    :element(NULL), gf(NULL) 
+  {
+    MVertex* tmp[3] = { a,b,c };
+    std::sort(tmp, tmp + 3);
+    v1 = tmp[0];
+    v2 = tmp[1];
+    v2 = tmp[2];
+    hash = a->getNum() + b->getNum() + c->getNum();
+  }
+  ~Tuple() {};
+  MVertex* get_v1() const {return v1;}
+  MVertex* get_v2() const {return v2;}
+  MVertex* get_v3() const {return v3;}
+  MElement* get_element() const { return element; }
+  GFace* get_gf() const { return gf; }
+  bool same_vertices(const Tuple& rhs) const {
+    if (v1 == rhs.get_v1() && v2 == rhs.get_v2() && v3 == rhs.get_v3()) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+  unsigned long long get_hash() const { return hash; }
+  bool operator<(const Tuple& rhs) const {
+    return hash< rhs.get_hash();
+  }
 };
 
+
+
 //inline std::ostream& operator<<(std::ostream& s, const PETriangle& t){
 //  const MVertex *v;
 //  for (int i=0;i<3;i++){
@@ -310,26 +430,26 @@ public:
   // ce test permet probablement de virer les hex "avec des trous" (avec 8 noeuds ok, mais un tet manquant, ce qui peut occasionner un hex à 14 faces, par exemple, si l'on compte les faces à partir des tets inclus)
   bool valid(Hex&,const std::set<MElement*>&);
   // renvoie true si le "MQuadrangle::etaShapeMeasure" des 6 faces est plus grand que 0.000001
-  bool valid(Hex&);
-  double eta(MVertex*,MVertex*,MVertex*,MVertex*);
+  bool valid(Hex&) const;
+  double eta(MVertex*,MVertex*,MVertex*,MVertex*) const;
   bool linked(MVertex*,MVertex*);
 
-  void find(MVertex*,MVertex*,const std::vector<MVertex*>&,std::set<MVertex*>&);
-  void find(MVertex*,MVertex*,MVertex*,const std::vector<MVertex*>&,std::set<MVertex*>&);
-  void find(MVertex*,MVertex*,std::set<MElement*>&);
-  void find(MVertex*,Hex,std::set<MElement*>&);
-  MVertex* find(MVertex*,MVertex*,MVertex*,MVertex*,const std::set<MElement*>&);
+  void find(MVertex*,MVertex*,const std::vector<MVertex*>&,std::set<MVertex*>&) const;
+  void find(MVertex*,MVertex*,MVertex*,const std::vector<MVertex*>&,std::set<MVertex*>&) const;
+  void find(MVertex*,MVertex*,std::set<MElement*>&) const;
+  void find(MVertex*,Hex,std::set<MElement*>&) const;
+  MVertex* find(MVertex*,MVertex*,MVertex*,MVertex*,const std::set<MElement*>&) const;
 
-  void intersection(const std::set<MVertex*>&,const std::set<MVertex*>&,const std::vector<MVertex*>&,std::set<MVertex*>&);
-  void intersection(const std::set<MVertex*>&,const std::set<MVertex*>&,const std::set<MVertex*>&,const std::vector<MVertex*>&,std::set<MVertex*>&);
-  void intersection(const std::set<MElement*>&,const std::set<MElement*>&,std::set<MElement*>&);
+  void intersection(const std::set<MVertex*>&,const std::set<MVertex*>&,const std::vector<MVertex*>&,std::set<MVertex*>&) const;
+  void intersection(const std::set<MVertex*>&,const std::set<MVertex*>&,const std::set<MVertex*>&,const std::vector<MVertex*>&,std::set<MVertex*>&) const;
+  void intersection(const std::set<MElement*>&,const std::set<MElement*>&,std::set<MElement*>&) const;
 
   // return true if vertex belong to hex
-  bool inclusion(MVertex*,Hex);
+  bool inclusion(MVertex*,Hex) const;
   // renvoie true si vertex se trouve dans [a,b,c]
-  bool inclusion(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*);
+  bool inclusion(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*) const ;
   // return true if all three vertices v1,v2 and v3 belong to one tet
-  bool inclusion(MVertex*,MVertex*,MVertex*,const std::set<MElement*>&);
+  bool inclusion(MVertex*,MVertex*,MVertex*,const std::set<MElement*>&) const;
   // return true si la facet existe dans la table A
   bool inclusion(Facet);
   // return true si la diagonal existe dans la table B
-- 
GitLab