diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp
index 47cf062de496ef1963a8708d89d1f0f03a6f3df1..2d5e97f62e128260ba1dab86db23c2e6481570c6 100644
--- a/Mesh/meshGFaceOptimize.cpp
+++ b/Mesh/meshGFaceOptimize.cpp
@@ -1519,7 +1519,7 @@ void _triangleSplit (GFace *gf, MElement *t, bool swop = false) {
 }
 
 
-struct RecombineTriangle
+/*struct RecombineTriangle
 {
   MElement *t1, *t2;
   double angle;
@@ -1558,7 +1558,7 @@ struct RecombineTriangle
     //return angle < other.angle;
 	return total_cost < other.total_cost; //addition for class Temporary
   }
-};
+};*///DEV amaury
 
 static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
 {
@@ -1602,17 +1602,15 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
   e2t_cont adj;
   buildEdgeToElement(gf->triangles, adj);
 
-  std::map<MVertex*,std::pair<MElement*,MElement*> > makeGraphPeriodic;
-
   std::vector<RecombineTriangle> pairs;
-  int nbValidPairs = 0;
+  std::map<MVertex*,std::pair<MElement*,MElement*> > makeGraphPeriodic;
+  
   for(e2t_cont::iterator it = adj.begin(); it!= adj.end(); ++it){
     if(it->second.second &&
         it->second.first->getNumVertices() == 3 &&
         it->second.second->getNumVertices() == 3 &&
         (emb_edgeverts.find(it->first.getVertex(0)) == emb_edgeverts.end() ||
          emb_edgeverts.find(it->first.getVertex(1)) == emb_edgeverts.end())){
-
       pairs.push_back(RecombineTriangle(it->first,
                                      it->second.first,
                                      it->second.second));
@@ -1638,7 +1636,6 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
   std::sort(pairs.begin(),pairs.end());
   std::set<MElement*> touched;
 
-
   if(CTX::instance()->mesh.algoRecombine == 1){
 #ifdef HAVE_MATCH
     int ncount = gf->triangles.size();
@@ -1812,7 +1809,7 @@ static int _recombineIntoQuads(GFace *gf, int recur_level, bool cubicGraph = 1)
     Msg::Warning("Gmsh should be compiled with the Blossom IV code and CONCORDE in order to allow the Blossom optimization");
 #endif
   }
-
+  
   std::vector<RecombineTriangle>::iterator itp = pairs.begin();
   while(itp != pairs.end()){
     // recombine if difference between max quad angle and right
@@ -1863,6 +1860,12 @@ void recombineIntoQuads(GFace *gf,
 			bool topologicalOpti,
 			bool nodeRepositioning)
 {
+  if (false) { //|| CTX::instance()->mesh.algoRecombine == 2) {
+    Msg::Warning("New technic of recombination in development (Amaury)");
+    devRecombine_Amaury(gf,topologicalOpti,nodeRepositioning);
+    return;
+  }
+  
   double t1 = Cpu();
 
   bool haveParam = true;
@@ -1920,6 +1923,204 @@ void recombineIntoQuads(GFace *gf,
   Msg::Info("Simple recombination algorithm completed (%g s)", t2 - t1);
 }
 
+static void _makeQuad_devAmaury(GFace *gf, SetRecombTri::iterator it)
+{
+  MElement *t1 = (*it)->t1;
+  MElement *t2 = (*it)->t2;
+  int orientation = 0;
+  for(int i = 0; i < 3; i++) {
+    if(t1->getVertex(i) == (*it)->n1) {
+      if(t1->getVertex((i + 1) % 3) == (*it)->n2)
+        orientation = 1;
+      else
+        orientation = -1;
+      break;
+    }
+  }
+  MQuadrangle *q;
+  if(orientation < 0)
+    q = new MQuadrangle((*it)->n1, (*it)->n3, (*it)->n2, (*it)->n4);
+  else
+    q = new MQuadrangle((*it)->n1, (*it)->n4, (*it)->n2, (*it)->n3);
+  gf->quadrangles.push_back(q);
+}
+
+static double *_devRecombine_Amaury(GFace *gf, int depth, bool cubicGraph = 1)
+{
+  int success = 1;
+  double glob_benef = 0;
+
+  std::set<MVertex*> emb_edgeverts;
+  {
+    std::list<GEdge*> emb_edges = gf->embeddedEdges();
+    std::list<GEdge*>::iterator ite = emb_edges.begin();
+    while(ite != emb_edges.end()){
+      if(!(*ite)->isMeshDegenerated()){
+        emb_edgeverts.insert((*ite)->mesh_vertices.begin(),
+                             (*ite)->mesh_vertices.end() );
+        emb_edgeverts.insert((*ite)->getBeginVertex()->mesh_vertices.begin(),
+                             (*ite)->getBeginVertex()->mesh_vertices.end());
+        emb_edgeverts.insert((*ite)->getEndVertex()->mesh_vertices.begin(),
+                             (*ite)->getEndVertex()->mesh_vertices.end());
+      }
+      ++ite;
+    }
+  }
+
+  {
+    std::list<GEdge*> _edges = gf->edges();
+    std::list<GEdge*>::iterator ite = _edges.begin();
+    while(ite != _edges.end()){
+      if(!(*ite)->isMeshDegenerated()){
+	if ((*ite)->isSeam(gf)){
+	  emb_edgeverts.insert((*ite)->mesh_vertices.begin(),
+			       (*ite)->mesh_vertices.end() );
+	  emb_edgeverts.insert((*ite)->getBeginVertex()->mesh_vertices.begin(),
+			       (*ite)->getBeginVertex()->mesh_vertices.end());
+	  emb_edgeverts.insert((*ite)->getEndVertex()->mesh_vertices.begin(),
+			       (*ite)->getEndVertex()->mesh_vertices.end());
+	}
+      }
+      ++ite;
+    }
+  }
+
+  e2t_cont adj;
+  buildEdgeToElement(gf->triangles, adj);
+
+  SetRecombTri pairs;
+  MapElemToIncomp incomp;
+  
+  for (e2t_cont::iterator it = adj.begin(); it!= adj.end(); ++it) {
+    if (it->second.second &&
+        it->second.first->getNumVertices() == 3 &&
+        it->second.second->getNumVertices() == 3 &&
+        (emb_edgeverts.find(it->first.getVertex(0)) == emb_edgeverts.end() ||
+        emb_edgeverts.find(it->first.getVertex(1)) == emb_edgeverts.end())) {
+      RecombineTriangle *rt = new RecombineTriangle(it->first, it->second.first, it->second.second);
+      pairs.insert(rt);
+      incomp[it->second.first].push_back(rt);
+      incomp[it->second.second].push_back(rt);
+    }
+  }
+  
+  std::set<MElement*> touched;
+  SetRecombTri::iterator itp = pairs.begin();
+  while (itp != pairs.end()) {
+    RecombSeq rs(itp, pairs.end(), depth);
+    
+    if (rs.optimal() || !rs.shouldBeSkipped()) {
+      _makeQuad_devAmaury(gf, itp);
+      glob_benef += 1 - (*itp)->cost_quality;
+      
+      MElement *t1 = (*itp)->t1;
+      MElement *t2 = (*itp)->t2;
+      touched.insert(t1);
+      touched.insert(t2);
+      
+      MapElemToIncomp::iterator iti;
+      SetRecombTri::iterator itmp;
+      
+      iti = incomp.find(t1);
+      for (int i = 0; i < iti->second.size(); i++)
+        if ((itmp = pairs.find(iti->second[i])) != pairs.end())
+          pairs.erase(itmp);
+      incomp.erase(iti);
+      
+      iti = incomp.find(t2);
+      for (int i = 0; i < iti->second.size(); i++)
+        if ((itmp = pairs.find(iti->second[i])) != pairs.end())
+          pairs.erase(itmp);
+      incomp.erase(iti);
+    }
+    else {
+      pairs.erase(itp);
+    }
+    itp = pairs.begin();
+  }
+
+  std::vector<MTriangle*> triangles2;
+  for(unsigned int i = 0; i < gf->triangles.size(); i++){
+    if(touched.find(gf->triangles[i]) == touched.end()){
+      triangles2.push_back(gf->triangles[i]);
+    }
+    else {
+      delete gf->triangles[i];
+    }
+  }
+  gf->triangles = triangles2;
+  
+  double *b = new double[2];
+  *b = glob_benef;
+  b[1] = touched.size()/2;
+  return b;
+}
+
+void devRecombine_Amaury(GFace *gf, bool topologicalOpti, bool nodeRepositioning)
+{ 
+  double t1 = Cpu();
+
+  bool haveParam = true;
+  if(gf->geomType() == GEntity::DiscreteSurface && !gf->getCompound())
+    haveParam = false;
+
+  if(haveParam && topologicalOpti)
+    removeFourTrianglesNodes(gf, false);
+
+  gf->model()->writeMSH("before.msh");
+  Msg::Info("Nombre de triangles : %d", gf->triangles.size());
+  double tt1 = Cpu();
+  int d = 700;
+  double max = 0, maxQuad = 0;
+  while (Cpu() - tt1 < 30) {
+    double tt2 = Cpu();
+    double *b = _devRecombine_Amaury(gf, d);
+    if (*b > max) max = *b;
+    if (b[1] > maxQuad) maxQuad = b[1];
+    Msg::Info("depth %d in (%g s) : benef = %lf / numQuad = %f", d++, Cpu() - tt2, *b, b[1]);
+    if (d > 200 && d < 100) d = 620;
+    break;
+  }
+  Msg::Info("Benef max = %lf", max);
+  Msg::Info("Max quad = %f sur %d", maxQuad, gf->triangles.size()/2);
+
+  gf->model()->writeMSH("raw.msh");
+  /*if(haveParam && nodeRepositioning)
+    laplaceSmoothing(gf, CTX::instance()->mesh.nbSmoothing);
+
+  // blossom-quad algo
+  if(success){
+    if(topologicalOpti){
+      if(haveParam){
+        gf->model()->writeMSH("smoothed.msh");
+        int COUNT = 0;
+        char NAME[256];
+        while(1){
+          int x = removeTwoQuadsNodes(gf);
+          if(x){ sprintf(NAME,"iter%dTQ.msh",COUNT++); gf->model()->writeMSH(NAME);}
+          int y = removeDiamonds(gf);
+          if(y){ sprintf(NAME,"iter%dD.msh",COUNT++); gf->model()->writeMSH(NAME); }
+          laplaceSmoothing(gf);
+          int z = 0; //edgeSwapQuadsForBetterQuality(gf);
+          if(z){ sprintf(NAME,"iter%dS.msh",COUNT++); gf->model()->writeMSH(NAME); }
+          if (!(x+y+z)) break;
+        }
+      }
+      edgeSwapQuadsForBetterQuality(gf);
+      //if(z){ sprintf(NAME,"iter%dS.msh",COUNT++); gf->model()->writeMSH(NAME); }
+      if(haveParam) laplaceSmoothing(gf,CTX::instance()->mesh.nbSmoothing);
+    }
+    double t2 = Cpu();
+    Msg::Info("Tree recombination algorithm completed (%g s)", t2 - t1);
+    return;
+  }
+
+  gf->model()->writeMSH("after.msh");*/
+
+  double t2 = Cpu();
+  Msg::Info("Simple recombination algorithm completed (%g s)", t2 - t1);
+}
+
 void quadsToTriangles(GFace *gf, double minqual = -10000.)
 {
   std::vector<MQuadrangle*> qds;
@@ -2130,3 +2331,137 @@ void Temporary::quadrilaterize(std::string file_name,double _w1,double _w2,doubl
   }
 }
 
+
+bool RecombineTriangle::operator < (const RecombineTriangle &other) const
+{
+  //return angle < other.angle;
+      //return total_cost < other.total_cost; //addition for class Temporary
+    return cost_quality < other.cost_quality; // DEV AMAURY !!!!!!!!!!
+}
+bool RecombSeq::parcours(int d, int countdown)
+{
+  if (d < 1 || countdown < 1) return true;
+  
+  if (_toBeSkipped.find(*_it2) != _toBeSkipped.end() ||
+      _toBeKept.find(*_it2) != _toBeKept.end()   ) {
+    if (++_it2 == _ite) return true;
+    return parcours(d, countdown); 
+  }
+  
+  MElement *t1 = (*_it2)->t1;
+  MElement *t2 = (*_it2)->t2;
+  
+  bool a, b;
+  std::map< MElement*, std::pair<RecombineTriangle*, bool> >::iterator m1, m2;
+  a = (m1 = _touched.find(t1)) != _touched.end();
+  b = (m2 = _touched.find(t2)) != _touched.end();
+  
+  if (a || b) {
+    MElement *t3;
+    if (a) {
+      (*m1).second.second = true;
+      if((*m1).second.first->t1 == t1)
+        t3 = (*m1).second.first->t2;
+      else
+        t3 = (*m1).second.first->t1;
+      if (_touched[t3].second == true) _canBeSkipped.insert((*m1).second.first);
+    }
+    if (b) {
+      (*m2).second.second = true;
+      if((*m2).second.first->t1 == t2)
+        t3 = (*m2).second.first->t2;
+      else
+        t3 = (*m2).second.first->t1;
+      if (_touched[t3].second == true) _canBeSkipped.insert((*m2).second.first);
+    }
+    if (++_it2 == _ite) return true;
+    return parcours(d, --countdown);
+  }
+  
+  _touched[t1] = std::make_pair(*_it2,false);
+  _touched[t2] = std::make_pair(*_it2,false);
+  _benef += 1 - (*_it2)->cost_quality;
+  if (++_it2 == _ite) return true;
+  d--;
+  //_perspect = (1 - (*(_it2))->cost_quality) * d;
+  //if (_benef+_perspect < best) return false;
+  
+  return parcours(d);
+}
+
+bool RecombSeq::shouldBeSkipped()
+{
+  //if (_canBeSkipped.find(*_it1) == _canBeSkipped.end())
+  //  return false;
+  SetRecombTri::iterator itmp = _it1;
+  itmp++;
+  RecombSeq rs(itmp, _ite, _depth);
+  if(rs.getBenef() > getBenef())
+    return true;
+  return false;
+  if (rs.getOptimalBenef(true) > getOptimalBenef(false))
+    return true;
+  return false;
+}
+
+RecombSeq::RecombSeq(SetRecombTri::iterator it,
+                     SetRecombTri::iterator itend,
+                     int depth,
+                     SetRecombTri toBeSkipped,
+                     SetRecombTri toBeKept)
+                : _it1(it), _ite(itend), _depth(depth),
+                  _toBeSkipped(toBeSkipped), _toBeKept(toBeKept)
+{
+  _benef = 0;
+  _it2 = it;
+  
+  if (depth < _toBeKept.size()) return;
+  
+  SetRecombTri::iterator itmp = _toBeKept.begin();
+  while (itmp != _toBeKept.end()) {
+    MElement *t1 = (*itmp)->t1;
+    MElement *t2 = (*itmp)->t2;
+    _touched[t1] = std::make_pair(*itmp,false);
+    _touched[t2] = std::make_pair(*itmp,false);
+    _benef += 1 - (*itmp++)->cost_quality;
+  }
+  
+  parcours(depth - _toBeKept.size());
+}
+
+double RecombSeq::getOptimalBenef(bool firstSkipable)
+{
+  if (!firstSkipable)
+    if (_canBeSkipped.find(*_it1) != _canBeSkipped.end())
+      _canBeSkipped.erase(*_it1);
+  
+  if (_canBeSkipped.empty())
+    return getBenef();
+  
+  double maxBenef = getBenef();
+  SetRecombTri toBeKept(_toBeKept);
+  SetRecombTri toBeSkipped(_toBeSkipped);
+  SetRecombTri::iterator it = _canBeSkipped.begin();
+  
+  if (_toBeKept.find(*it) == _toBeKept.end()) {
+    toBeSkipped.insert(*it);
+    RecombSeq rs(_it1, _it2, _depth, toBeSkipped, toBeKept);
+    double b;
+    if ((b = rs.getOptimalBenef(firstSkipable)) > maxBenef)
+      maxBenef = b;
+  }
+  
+  while(it != --_canBeSkipped.end()) {
+    toBeSkipped.erase(*it);
+    toBeKept.insert(*it++);
+    if (_toBeKept.find(*it) == _toBeKept.end()) {
+      toBeSkipped.insert(*it);
+      RecombSeq rs(_it1, _it2, _depth, toBeSkipped, toBeKept);
+      double b;
+      if ((b = rs.getOptimalBenef(firstSkipable)) > maxBenef)
+        maxBenef = b;
+    }
+  }
+  
+  return maxBenef;
+}
diff --git a/Mesh/meshGFaceOptimize.h b/Mesh/meshGFaceOptimize.h
index 55b2d34e371aef4b2dcfe9d4c7a66723f4a8af78..93bcf5c92429a01a6e14a26212e67dff787f39bd 100644
--- a/Mesh/meshGFaceOptimize.h
+++ b/Mesh/meshGFaceOptimize.h
@@ -147,4 +147,111 @@ class Temporary{
 	static double compute_alignment(const MEdge&,MElement*,MElement*);
 };
 
+
+//DEV Amaury
+void devRecombine_Amaury(GFace *gf, 
+			bool topologicalOpti   = true, 
+			bool nodeRepositioning = true);
+struct RecombineTriangle
+{
+  MElement *t1, *t2;
+  double angle;
+  double cost_quality; //addition for class Temporary
+  double cost_alignment; //addition for class Temporary
+  double total_cost; //addition for class Temporary
+  MVertex *n1, *n2, *n3, *n4;
+  RecombineTriangle(const MEdge &me, MElement *_t1, MElement *_t2)
+    : t1(_t1), t2(_t2)
+  {
+    n1 = me.getVertex(0);
+    n2 = me.getVertex(1);
+
+    if(t1->getVertex(0) != n1 && t1->getVertex(0) != n2) n3 = t1->getVertex(0);
+    else if(t1->getVertex(1) != n1 && t1->getVertex(1) != n2) n3 = t1->getVertex(1);
+    else if(t1->getVertex(2) != n1 && t1->getVertex(2) != n2) n3 = t1->getVertex(2);
+    if(t2->getVertex(0) != n1 && t2->getVertex(0) != n2) n4 = t2->getVertex(0);
+    else if(t2->getVertex(1) != n1 && t2->getVertex(1) != n2) n4 = t2->getVertex(1);
+    else if(t2->getVertex(2) != n1 && t2->getVertex(2) != n2) n4 = t2->getVertex(2);
+
+    double a1 = 180 * angle3Vertices(n1, n4, n2) / M_PI;
+    double a2 = 180 * angle3Vertices(n4, n2, n3) / M_PI;
+    double a3 = 180 * angle3Vertices(n2, n3, n1) / M_PI;
+    double a4 = 180 * angle3Vertices(n3, n1, n4) / M_PI;
+    angle = fabs(90. - a1);
+    angle = std::max(fabs(90. - a2),angle);
+    angle = std::max(fabs(90. - a3),angle);
+    angle = std::max(fabs(90. - a4),angle);
+	cost_quality = 1.0 - std::max(1.0 - angle/90.0,0.0); //addition for class Temporary
+	cost_alignment = Temporary::compute_alignment(me,_t1,_t2); //addition for class Temporary
+	total_cost = Temporary::compute_total_cost(cost_quality,cost_alignment); //addition for class Temporary
+	total_cost = 100.0*cost_quality; //addition for class Temporary
+  }
+  bool operator < (const RecombineTriangle &other) const;
+  /*{
+    //return angle < other.angle;
+	//return total_cost < other.total_cost; //addition for class Temporary
+  }*/
+};
+struct lessRecombTri
+{
+  bool operator()(RecombineTriangle *rt1, RecombineTriangle *rt2)
+  {
+    return *rt1 < *rt2;
+  }
+};
+typedef std::set<RecombineTriangle*,lessRecombTri> SetRecombTri;
+typedef std::map< MElement*, std::vector<RecombineTriangle*> > MapElemToIncomp;
+class RecombSeq {
+  private:
+    //std::vector<int> _skipped;
+    //std::vector<int> _toBeSkipped;
+    //std::map<RecombineTriangle*, int> _numSkip;
+    SetRecombTri _canBeSkipped, _toBeSkipped, _toBeKept;
+    SetRecombTri::iterator _it1, _it2, _ite;
+    //std::set<MElement*> _touched;
+    //std::map< MElement*, std::pair<MElement*, bool> > _touched;
+    std::map< MElement*, std::pair<RecombineTriangle*, bool> > _touched;
+    double _benef, _perspect;
+    int _depth;
+    
+  public:
+    RecombSeq(SetRecombTri::iterator it,
+	      SetRecombTri::iterator itend,
+	      int depth) : _it1(it), _ite(itend), _depth(depth)
+    {
+      _benef = 0;
+      _it2 = it;
+      parcours(depth);
+    }
+    
+    RecombSeq(SetRecombTri::iterator it,
+	      SetRecombTri::iterator itend,
+	      int depth,
+	      SetRecombTri toBeSkipped,
+	      SetRecombTri toBeKept);
+    bool parcours(int d, int a = 10);
+    double getOptimalBenef(bool firstSkipable);
+    
+    bool optimal() const {return _canBeSkipped.empty();}
+    bool shouldBeSkipped();
+    /*void getOptimal(SetRecombTri::iterator &it)
+    {
+      SetRecombTri::iterator itmp = _it1;
+      itmp++;
+      MElement *t1 = (*_it2)->t1;
+      MElement *t2 = (*_it2)->t2;
+      while (_touched.find(t1) != _touched.end() ||
+	     _touched.find(t2) != _touched.end()) {
+	if (++itmp == _ite) return;
+	t1 = (*_it2)->t1;
+	t2 = (*_it2)->t2;
+      }
+      
+      RecombSeq rs(itmp, _ite, _depth);
+      
+    }*/
+    
+    double getBenef() const {return _benef;}
+    //std::vector<int> getSkipped() const {return _skipped;}
+};
 #endif