diff --git a/Mesh/yamakawa.cpp b/Mesh/yamakawa.cpp
index bc569f76426799f2b0ca534d7db16110cb763638..ef8ea15a2d9ad93a150b256b110f6768a8140a7d 100755
--- a/Mesh/yamakawa.cpp
+++ b/Mesh/yamakawa.cpp
@@ -13,8 +13,12 @@
 #include <fstream>
 #include "MHexahedron.h"
 #include "MQuadrangle.h"
+#include "MPyramid.h"
+#include "MPrism.h"
 
+/*****************************************/
 /****************class Hex****************/
+/*****************************************/
 
 Hex::Hex(){}
 
@@ -86,7 +90,9 @@ bool Hex::operator<(const Hex& hex) const{
   return quality>hex.get_quality();
 }
 
+/*******************************************/
 /****************class Facet****************/
+/*******************************************/
 
 Facet::Facet(){}
 
@@ -140,7 +146,9 @@ bool Facet::operator<(const Facet& facet) const{
   return hash<facet.get_hash();
 }
 
+/**********************************************/
 /****************class Diagonal****************/
+/**********************************************/
 
 Diagonal::Diagonal(){}
 
@@ -187,7 +195,9 @@ bool Diagonal::operator<(const Diagonal& diagonal) const{
   return hash<diagonal.get_hash();
 }
 
+/**************************************************/
 /****************class Recombinator****************/
+/**************************************************/
 
 Recombinator::Recombinator(){}
 
@@ -208,6 +218,7 @@ void Recombinator::execute(){
 }
 
 void Recombinator::execute(GRegion* gr){
+  printf("................HEXAHEDRA................\n");
   init_markings(gr);
 
   build_vertex_to_vertices(gr);
@@ -226,6 +237,7 @@ void Recombinator::execute(GRegion* gr){
 
   hash_tableA.clear();
   hash_tableB.clear();
+  hash_tableC.clear();
   merge(gr);
 
   rearrange(gr);
@@ -557,6 +569,10 @@ void Recombinator::merge(GRegion* gr){
 	  flag = 0;
 	}  
 
+	if(!conformityC(hex)){
+	  flag = 0;
+	}  
+	  
 	if(flag){
 	  printf("%d - %d/%d - %f\n",count,i,(int)potential.size(),hex.get_quality());
 	  quality = quality + hex.get_quality();
@@ -568,6 +584,7 @@ void Recombinator::merge(GRegion* gr){
 	  gr->addHexahedron(new MHexahedron(a,b,c,d,e,f,g,h));
 	  build_hash_tableA(hex);
 	  build_hash_tableB(hex);
+	  build_hash_tableC(hex);
 	  idle = 0;
 	  count++;
 	}
@@ -593,7 +610,7 @@ void Recombinator::merge(GRegion* gr){
 	}
   }
 
-  printf("hex average quality (0->1) : %f\n",quality/count);
+  printf("hexahedra average quality (0->1) : %f\n",quality/count);
 }
 
 void Recombinator::rearrange(GRegion* gr){
@@ -630,8 +647,8 @@ void Recombinator::statistics(GRegion* gr){
 	all_volume = all_volume + volume;
   }
 
-  printf("percentage of hex (number) : %.2f\n",hex_nbr*100.0/all_nbr);
-  printf("percentage of hex (volume) : %.2f\n",hex_volume*100.0/all_volume);
+  printf("percentage of hexahedra (number) : %.2f\n",hex_nbr*100.0/all_nbr);
+  printf("percentage of hexahedra (volume) : %.2f\n",hex_volume*100.0/all_volume);
 }
 
 bool Recombinator::sliver(MElement* element,Hex hex){
@@ -1180,6 +1197,29 @@ bool Recombinator::inclusion(Diagonal diagonal){
   return flag;
 }
 
+bool Recombinator::duplicate(Diagonal diagonal){
+  bool flag;
+  std::multiset<Diagonal>::iterator it;
+	
+  it = hash_tableC.find(diagonal);
+  flag = 0;
+	
+  while(it!=hash_tableC.end()){
+    if(diagonal.get_hash()!=it->get_hash()){
+	  break;
+	}
+		
+	if(diagonal.same_vertices(*it)){
+	  flag = 1;
+	  break;
+	}
+		
+	it++;
+  }
+	
+  return flag;
+}
+
 bool Recombinator::conformityA(Hex hex){
   bool c1,c2,c3,c4,c5,c6;
   MVertex *a,*b,*c,*d;
@@ -1216,7 +1256,64 @@ bool Recombinator::conformityA(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
 }
 
 bool Recombinator::conformityB(Hex hex){
-  int count;
+  bool flag1;
+  bool flag2;
+  bool c1,c2,c3,c4;
+  bool c5,c6,c7,c8;
+  bool c9,c10,c11,c12;
+  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();
+	
+  flag1 = inclusion(Diagonal(a,b));
+  flag1 = flag1 || inclusion(Diagonal(b,f));
+  flag1 = flag1 || inclusion(Diagonal(f,e));
+  flag1 = flag1 || inclusion(Diagonal(e,a));
+  flag1 = flag1 || inclusion(Diagonal(d,c));
+  flag1 = flag1 || inclusion(Diagonal(c,g));
+  flag1 = flag1 || inclusion(Diagonal(g,h));
+  flag1 = flag1 || inclusion(Diagonal(h,d));
+  flag1 = flag1 || inclusion(Diagonal(b,c));
+  flag1 = flag1 || inclusion(Diagonal(f,g));
+  flag1 = flag1 || inclusion(Diagonal(e,h));
+  flag1 = flag1 || inclusion(Diagonal(a,d));
+	
+  c1 = inclusion(Diagonal(a,f));
+  c2 = inclusion(Diagonal(b,e));
+  flag2 = (c1 && !c2) || (!c1 && c2);
+  c3 = inclusion(Diagonal(d,g));
+  c4 = inclusion(Diagonal(c,h));
+  flag2 = flag2 || (c3 && !c4) || (!c3 && c4);
+  c5 = inclusion(Diagonal(b,g));
+  c6 = inclusion(Diagonal(c,f));
+  flag2 = flag2 || (c5 && !c6) || (!c5 && c6);
+  c7 = inclusion(Diagonal(e,g));
+  c8 = inclusion(Diagonal(f,h));
+  flag2 = flag2 || (c7 && !c8) || (!c7 && c8);
+  c9 = inclusion(Diagonal(a,h));
+  c10 = inclusion(Diagonal(d,e));
+  flag2 = flag2 || (c9 && !c10) || (!c9 && c10);
+  c11 = inclusion(Diagonal(a,c));
+  c12 = inclusion(Diagonal(b,d));
+  flag2 = flag2 || (c11 && !c12) || (!c11 && c12);
+	
+  if(flag1 || flag2){
+    return 0;
+  }
+  else{
+    return 1;
+  }
+}
+
+bool Recombinator::conformityC(Hex hex){
   bool flag;
   MVertex *a,*b,*c,*d;
   MVertex *e,*f,*g,*h;
@@ -1230,34 +1327,20 @@ bool Recombinator::conformityB(Hex hex){
   g = hex.get_g();
   h = hex.get_h();
 	
-  flag = inclusion(Diagonal(a,b));
-  flag = flag || inclusion(Diagonal(b,f));
-  flag = flag || inclusion(Diagonal(f,e));
-  flag = flag || inclusion(Diagonal(e,a));
-  flag = flag || inclusion(Diagonal(d,c));
-  flag = flag || inclusion(Diagonal(c,g));
-  flag = flag || inclusion(Diagonal(g,h));
-  flag = flag || inclusion(Diagonal(h,d));
-  flag = flag || inclusion(Diagonal(b,c));
-  flag = flag || inclusion(Diagonal(f,g));
-  flag = flag || inclusion(Diagonal(e,h));
-  flag = flag || inclusion(Diagonal(a,d));
-	
-  count = 0;
-  count = count + (int)inclusion(Diagonal(a,f));
-  count = count + (int)inclusion(Diagonal(b,e));
-  count = count + (int)inclusion(Diagonal(d,g));
-  count = count + (int)inclusion(Diagonal(c,h));
-  count = count + (int)inclusion(Diagonal(b,g));
-  count = count + (int)inclusion(Diagonal(c,f));
-  count = count + (int)inclusion(Diagonal(e,g));
-  count = count + (int)inclusion(Diagonal(f,h));
-  count = count + (int)inclusion(Diagonal(a,h));
-  count = count + (int)inclusion(Diagonal(d,e));
-  count = count + (int)inclusion(Diagonal(a,c));
-  count = count + (int)inclusion(Diagonal(b,d));
-	
-  if(flag || count%2==1){
+  flag = duplicate(Diagonal(a,f));
+  flag = flag || duplicate(Diagonal(b,e));
+  flag = flag || duplicate(Diagonal(d,g));
+  flag = flag || duplicate(Diagonal(c,h));
+  flag = flag || duplicate(Diagonal(b,g));
+  flag = flag || duplicate(Diagonal(c,f));
+  flag = flag || duplicate(Diagonal(e,g));
+  flag = flag || duplicate(Diagonal(f,h));
+  flag = flag || duplicate(Diagonal(a,h));
+  flag = flag || duplicate(Diagonal(d,e));
+  flag = flag || duplicate(Diagonal(a,c));
+  flag = flag || duplicate(Diagonal(b,d));
+	
+  if(flag){
     return 0;
   }
   else{
@@ -1432,6 +1515,58 @@ void Recombinator::build_hash_tableB(Diagonal diagonal){
   }	
 }
 
+void Recombinator::build_hash_tableC(Hex hex){
+  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();
+	
+  build_hash_tableC(Diagonal(a,b));
+  build_hash_tableC(Diagonal(b,c));
+  build_hash_tableC(Diagonal(c,d));
+  build_hash_tableC(Diagonal(d,a));
+  build_hash_tableC(Diagonal(e,f));
+  build_hash_tableC(Diagonal(f,g));
+  build_hash_tableC(Diagonal(g,h));
+  build_hash_tableC(Diagonal(h,e));
+  build_hash_tableC(Diagonal(a,e));
+  build_hash_tableC(Diagonal(b,f));
+  build_hash_tableC(Diagonal(c,g));
+  build_hash_tableC(Diagonal(d,h));
+}
+
+void Recombinator::build_hash_tableC(Diagonal diagonal){
+  bool flag;
+  std::multiset<Diagonal>::iterator it;
+	
+  it = hash_tableC.find(diagonal);
+  flag = 1;
+	
+  while(it!=hash_tableC.end()){
+    if(diagonal.get_hash()!=it->get_hash()){
+	  break;
+	}
+		
+	if(diagonal.same_vertices(*it)){
+	  flag = 0;
+	  break;
+	}
+		
+	it++;
+  }
+	
+  if(flag){
+    hash_tableC.insert(diagonal);
+  }	
+}
+
 void Recombinator::print_vertex_to_vertices(GRegion* gr){
   size_t i;
   int j;
@@ -1589,3 +1724,1387 @@ double Recombinator::min_scaled_jacobian(Hex hex){
 
   return min;
 }
+
+/*******************************************/
+/****************class Prism****************/
+/*******************************************/
+
+Prism::Prism(){}
+
+Prism::Prism(MVertex* a2,MVertex* b2,MVertex* c2,MVertex* d2,MVertex* e2,MVertex* f2){
+  a = a2;
+  b = b2;
+  c = c2;
+  d = d2;
+  e = e2;
+  f = f2;
+}
+
+Prism::~Prism(){}
+
+double Prism::get_quality() const{
+  return quality;
+}
+
+void Prism::set_quality(double new_quality){
+  quality = new_quality;
+}
+
+MVertex* Prism::get_a(){
+  return a;
+}
+
+MVertex* Prism::get_b(){
+  return b;
+}
+
+MVertex* Prism::get_c(){
+  return c;
+}
+
+MVertex* Prism::get_d(){
+  return d;
+}
+
+MVertex* Prism::get_e(){
+  return e;
+}
+
+MVertex* Prism::get_f(){
+  return f;
+}
+
+void Prism::set_vertices(MVertex* a2,MVertex* b2,MVertex* c2,MVertex* d2,MVertex* e2,MVertex* f2){
+  a = a2;
+  b = b2;
+  c = c2;
+  d = d2;
+  e = e2;
+  f = f2;
+}
+
+bool Prism::operator<(const Prism& prism) const{
+  return quality>prism.get_quality();
+}
+
+/***************************************************/
+/****************class Supplementary****************/
+/***************************************************/
+
+Supplementary::Supplementary(){}
+
+Supplementary::~Supplementary(){}
+
+void Supplementary::execute(){
+  GRegion* gr;
+  GModel* model = GModel::current();
+  GModel::riter it;
+	
+  for(it=model->firstRegion();it!=model->lastRegion();it++)
+  {
+    gr = *it;
+	if(gr->getNumMeshElements()>0){
+	  execute(gr);
+	}
+  }
+}
+
+void Supplementary::execute(GRegion* gr){
+  unsigned int i;
+  MElement* element;
+  MVertex *a,*b,*c,*d;
+  MVertex *e,*f,*g,*h;
+	
+  printf("................PRISMS................\n");
+  init_markings(gr);
+ 
+  build_vertex_to_vertices(gr);
+  build_vertex_to_tetrahedra(gr);
+  printf("connectivity\n");
+	
+  potential.clear();
+  patern(gr);
+  printf("patern\n");
+	
+  hash_tableA.clear();
+  hash_tableB.clear();
+  hash_tableC.clear();
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(eight(element)){
+	  a = element->getVertex(0);
+	  b = element->getVertex(1);
+	  c = element->getVertex(2);
+	  d = element->getVertex(3);
+	  e = element->getVertex(4);
+	  f = element->getVertex(5);
+	  g = element->getVertex(6);
+	  h = element->getVertex(7);
+		
+	  build_hash_tableA(a,b,c,d);
+	  build_hash_tableA(e,f,g,h);
+	  build_hash_tableA(a,b,f,e);
+	  build_hash_tableA(b,c,g,f);
+	  build_hash_tableA(d,c,g,h);
+	  build_hash_tableA(d,a,e,h);
+		
+	  build_hash_tableB(a,b,c,d);
+	  build_hash_tableB(e,f,g,h);
+	  build_hash_tableB(a,b,f,e);
+	  build_hash_tableB(b,c,g,f);
+	  build_hash_tableB(d,c,g,h);
+	  build_hash_tableB(d,a,e,h);
+		
+	  build_hash_tableC(Diagonal(a,b));
+	  build_hash_tableC(Diagonal(b,c));
+	  build_hash_tableC(Diagonal(c,d));
+	  build_hash_tableC(Diagonal(d,a));
+	  build_hash_tableC(Diagonal(e,f));
+	  build_hash_tableC(Diagonal(f,g));
+	  build_hash_tableC(Diagonal(g,h));
+	  build_hash_tableC(Diagonal(h,e));
+	  build_hash_tableC(Diagonal(a,e));
+	  build_hash_tableC(Diagonal(b,f));
+	  build_hash_tableC(Diagonal(c,g));
+	  build_hash_tableC(Diagonal(d,h));
+	}
+  }
+	
+  std::sort(potential.begin(),potential.end());
+	
+  merge(gr);	
+	
+  rearrange(gr);
+	
+  statistics(gr);
+}
+
+void Supplementary::init_markings(GRegion* gr){
+  unsigned int i;
+  MElement* element;
+	
+  markings.clear();
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(four(element)){
+	  markings.insert(std::pair<MElement*,bool>(element,0));
+	}
+  }
+}
+
+void Supplementary::patern(GRegion* gr){
+  size_t i;
+  int j,k;
+  double quality;
+  MElement* element;
+  MVertex *a,*b,*c,*d;
+  MVertex *p,*q;
+  std::vector<MVertex*> vertices;
+  std::vector<MVertex*> already;
+  std::set<MVertex*> bin1;
+  std::set<MVertex*> bin2;
+  std::set<MVertex*>::iterator it1;
+  std::set<MVertex*>::iterator it2;
+  Prism prism;
+	
+  vertices.resize(3);
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(four(element)){
+	  for(j=0;j<4;j++){ 
+	    a = element->getVertex(j);
+		vertices[0] = element->getVertex((j+1)%4);
+		vertices[1] = element->getVertex((j+2)%4);
+		vertices[2] = element->getVertex((j+3)%4);
+		for(k=0;k<3;k++){
+		  b = vertices[k%3];
+		  c = vertices[(k+1)%3];
+		  d = vertices[(k+2)%3];
+		  already.clear();
+		  already.push_back(a);
+		  already.push_back(b);
+		  already.push_back(c);
+		  already.push_back(d);
+		  bin1.clear();
+		  bin2.clear();
+		  find(b,d,already,bin1);
+		  find(c,d,already,bin2);
+		  for(it1=bin1.begin();it1!=bin1.end();it1++){
+			p = *it1;
+			for(it2=bin2.begin();it2!=bin2.end();it2++){
+			  q = *it2;
+			  if(p!=q && linked(p,q)){
+			    prism = Prism(a,b,c,d,p,q);
+				quality = min_scaled_jacobian(prism);
+				prism.set_quality(quality);
+				if(valid(prism)){
+				  potential.push_back(prism);
+				}
+			  }
+			}
+		  }
+		}
+	  }
+	}
+  }
+}
+
+void Supplementary::merge(GRegion* gr){
+  unsigned int i;
+  int count;
+  bool flag;
+  double threshold;
+  double quality;
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+  MElement* element;
+  std::set<MElement*> parts;
+  std::set<MElement*>::iterator it;
+  std::map<MElement*,bool>::iterator it2;
+  std::vector<MTetrahedron*>::iterator it3;
+  Prism prism;
+	
+  count = 1;
+  quality = 0.0;
+	
+  for(i=0;i<potential.size();i++){
+    prism = potential[i];
+		
+	a = prism.get_a();
+	b = prism.get_b();
+	c = prism.get_c();
+	d = prism.get_d();
+	e = prism.get_e();
+	f = prism.get_f();
+		
+	parts.clear();
+	find(a,prism,parts);
+	find(b,prism,parts);
+	find(c,prism,parts);
+	find(d,prism,parts);
+	find(e,prism,parts);
+	find(f,prism,parts);
+		
+	flag = 1;
+		
+	for(it=parts.begin();it!=parts.end();it++){
+	  element = *it;
+	  it2 = markings.find(element);
+	  if(it2->second==1 && !sliver(element,prism)){
+	    flag = 0;
+		break;
+	  }
+	}
+		
+	threshold = 0.15;
+	if(prism.get_quality()<threshold){
+      flag = 0;
+	}
+		
+	if(!valid(prism,parts)){
+      flag = 0;
+	}
+		
+	if(!conformityA(prism)){
+	  flag = 0;
+	}
+	  
+	if(!conformityB(prism)){
+	  flag = 0;
+	}  
+	  
+	if(!conformityC(prism)){
+	  flag = 0;
+	}  
+	  
+	if(flag){
+	  printf("%d - %d/%d - %f\n",count,i,(int)potential.size(),prism.get_quality());
+	  quality = quality + prism.get_quality();
+	  for(it=parts.begin();it!=parts.end();it++){
+	    element = *it;
+		it2 = markings.find(element);
+		it2->second = 1;
+	  }
+	  gr->addPrism(new MPrism(a,b,c,d,e,f));
+	  build_hash_tableA(prism);
+	  build_hash_tableB(prism);
+	  build_hash_tableC(prism);
+	  count++;
+	}
+  }
+	
+  it3 = gr->tetrahedra.begin();
+  while(it3!=gr->tetrahedra.end()){
+    element = (MElement*)(*it3);
+	it2 = markings.find(element);
+	if(it2->second==1){
+	  it3 = gr->tetrahedra.erase(it3);
+	}
+	else{
+      it3++;
+	}
+  }
+	
+  printf("prisms average quality (0->1) : %f\n",quality/count);
+}
+
+void Supplementary::rearrange(GRegion* gr){
+  size_t i;
+  MElement* element;
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	element->setVolumePositive();
+  }
+}
+
+void Supplementary::statistics(GRegion* gr){
+  size_t i;
+  int all_nbr,prism_nbr;
+  double all_volume,prism_volume,volume;
+  MElement* element;
+	
+  all_nbr = 0;
+  prism_nbr = 0;
+  all_volume = 0.0;
+  prism_volume = 0.0;
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	volume = element->getVolume();
+		
+	if(six(element)){
+	  prism_nbr = prism_nbr + 1;
+	  prism_volume = prism_volume + volume;
+	}
+		
+	all_nbr = all_nbr + 1;
+	all_volume = all_volume + volume;
+  }
+	
+  printf("percentage of prisms (number) : %.2f\n",prism_nbr*100.0/all_nbr);
+  printf("percentage of prisms (volume) : %.2f\n",prism_volume*100.0/all_volume);
+}
+
+bool Supplementary::four(MElement* element){
+  if(element->getNumVertices()==4) return 1;
+  else return 0;
+}
+
+bool Supplementary::five(MElement* element){
+  if(element->getNumVertices()==5) return 1;
+  else return 0;
+}
+
+bool Supplementary::six(MElement* element){
+  if(element->getNumVertices()==6) return 1;
+  else return 0;
+}
+
+bool Supplementary::eight(MElement* element){
+  if(element->getNumVertices()==8) return 1;
+  else return 0;
+}
+
+bool Supplementary::sliver(MElement* element,Prism prism){
+  bool val;
+  bool flag1,flag2,flag3,flag4;
+  MVertex *a,*b,*c,*d;
+	
+  val = 0;
+  a = element->getVertex(0);
+  b = element->getVertex(1);
+  c = element->getVertex(2);
+  d = element->getVertex(3);
+	
+  flag1 = inclusion(a,prism.get_a(),prism.get_d(),prism.get_f(),prism.get_c());
+  flag2 = inclusion(b,prism.get_a(),prism.get_d(),prism.get_f(),prism.get_c());
+  flag3 = inclusion(c,prism.get_a(),prism.get_d(),prism.get_f(),prism.get_c());
+  flag4 = inclusion(d,prism.get_a(),prism.get_d(),prism.get_f(),prism.get_c());
+  if(flag1 && flag2 && flag3 && flag4) val = 1;
+	
+  flag1 = inclusion(a,prism.get_a(),prism.get_b(),prism.get_e(),prism.get_d());
+  flag2 = inclusion(b,prism.get_a(),prism.get_b(),prism.get_e(),prism.get_d());
+  flag3 = inclusion(c,prism.get_a(),prism.get_b(),prism.get_e(),prism.get_d());
+  flag4 = inclusion(d,prism.get_a(),prism.get_b(),prism.get_e(),prism.get_d());
+  if(flag1 && flag2 && flag3 && flag4) val = 1;
+	
+  flag1 = inclusion(a,prism.get_b(),prism.get_c(),prism.get_f(),prism.get_e());
+  flag2 = inclusion(b,prism.get_b(),prism.get_c(),prism.get_f(),prism.get_e());
+  flag3 = inclusion(c,prism.get_b(),prism.get_c(),prism.get_f(),prism.get_e());
+  flag4 = inclusion(d,prism.get_b(),prism.get_c(),prism.get_f(),prism.get_e());
+  if(flag1 && flag2 && flag3 && flag4) val = 1;
+	
+  return val;
+}
+
+bool Supplementary::valid(Prism prism,const std::set<MElement*>& parts){
+  bool ok1,ok2,ok3,ok4;
+  bool flag1A,flag1B,flag1C,flag1D;
+  bool flag2A,flag2B,flag2C,flag2D;
+  bool flag3A,flag3B,flag3C,flag3D;
+  bool flag4,flag5;
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  flag1A = inclusion(a,d,f,parts);
+  flag1B = inclusion(a,f,c,parts);
+  flag1C = inclusion(a,c,d,parts);
+  flag1D = inclusion(c,d,f,parts);
+  ok1 = (flag1A && flag1B) || (flag1C && flag1D);
+	
+  flag2A = inclusion(a,b,d,parts);
+  flag2B = inclusion(b,d,e,parts);
+  flag2C = inclusion(a,d,e,parts);
+  flag2D = inclusion(a,b,e,parts);
+  ok2 = (flag2A && flag2B) || (flag2C && flag2D);
+	
+  flag3A = inclusion(b,c,f,parts);
+  flag3B = inclusion(b,e,f,parts);
+  flag3C = inclusion(b,c,e,parts);
+  flag3D = inclusion(c,e,f,parts);
+  ok3 = (flag3A && flag3B) || (flag3C && flag3D);
+	
+  flag4 = inclusion(a,b,c,parts);
+  flag5 = inclusion(d,e,f,parts);
+  ok4 = flag4 && flag5;
+	
+  if(ok1 && ok2 && ok3 && ok4){
+    return 1;
+  }
+  else{
+    return 0;
+  }
+}
+
+bool Supplementary::valid(Prism prism){
+  double k;
+  double eta1,eta2,eta3;
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+	
+  k = 0.000001;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  eta1 = eta(a,d,f,c);
+  eta2 = eta(a,b,e,d);
+  eta3 = eta(b,c,f,e);
+	
+  if(eta1>k && eta2>k && eta3>k){
+    return 1;
+  }
+  else{
+    return 0;
+  }
+}
+
+double Supplementary::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;
+}
+
+bool Supplementary::linked(MVertex* v1,MVertex* v2){
+  bool flag;
+  std::map<MVertex*,std::set<MVertex*> >::iterator it;
+  std::set<MVertex*>::iterator it2;
+	
+  it = vertex_to_vertices.find(v1);
+  flag = 0;
+	
+  if(it!=vertex_to_vertices.end()){
+    for(it2=(it->second).begin();it2!=(it->second).end();it2++){
+      if(*it2==v2){
+	    flag = 1;
+	    break;
+	  }
+    }
+  }
+	
+  return flag;
+}
+
+void Supplementary::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);
+	
+  if(it1!=vertex_to_vertices.end() && it2!=vertex_to_vertices.end()){
+    intersection(it1->second,it2->second,already,final);
+  }
+}
+
+void Supplementary::find(MVertex* vertex,Prism prism,std::set<MElement*>& final){
+  bool flag1,flag2,flag3,flag4;
+  MVertex *a,*b,*c,*d;
+  std::map<MVertex*,std::set<MElement*> >::iterator it;
+  std::set<MElement*>::iterator it2;
+	
+  it = vertex_to_tetrahedra.find(vertex);
+	
+  if(it!=vertex_to_tetrahedra.end()){
+    for(it2=(it->second).begin();it2!=(it->second).end();it2++){
+      a = (*it2)->getVertex(0);
+	  b = (*it2)->getVertex(1);
+	  c = (*it2)->getVertex(2);
+	  d = (*it2)->getVertex(3);
+		
+	  flag1 = inclusion(a,prism);
+	  flag2 = inclusion(b,prism);
+	  flag3 = inclusion(c,prism);
+	  flag4 = inclusion(d,prism);
+		
+	  if(flag1 && flag2 && flag3 && flag4){
+	    final.insert(*it2);
+	  }
+    }
+  }
+}
+
+void Supplementary::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;
+  std::set<MVertex*> temp;
+  std::set<MVertex*>::iterator it;
+	
+  std::set_intersection(bin1.begin(),bin1.end(),bin2.begin(),bin2.end(),std::inserter(temp,temp.end()));
+	
+  for(it=temp.begin();it!=temp.end();it++){
+    ok = 1;
+		
+	for(i=0;i<already.size();i++){
+	  if((*it)==already[i]){
+	    ok = 0;
+		break;
+	  }
+	}
+		
+	if(ok){
+	  final.insert(*it);
+	}
+  }
+}
+
+bool Supplementary::inclusion(MVertex* vertex,Prism prism){
+  bool flag;
+	
+  flag = 0;
+	
+  if(vertex==prism.get_a()) flag = 1;
+  else if(vertex==prism.get_b()) flag = 1;
+  else if(vertex==prism.get_c()) flag = 1;
+  else if(vertex==prism.get_d()) flag = 1;
+  else if(vertex==prism.get_e()) flag = 1;
+  else if(vertex==prism.get_f()) flag = 1;
+	
+  return flag;
+}
+
+bool Supplementary::inclusion(MVertex* vertex,MVertex* a,MVertex* b,MVertex* c,MVertex* d){
+  bool flag;
+	
+  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;
+	
+  return flag;
+}
+
+bool Supplementary::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*>::iterator it;
+	
+  ok = 0;
+	
+  for(it=bin.begin();it!=bin.end();it++){
+    element = *it;
+		
+	a = element->getVertex(0);
+	b = element->getVertex(1);
+	c = element->getVertex(2);
+	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);
+		
+	if(flag1 && flag2 && flag3){
+	  ok = 1;
+	  break;
+	}
+  }
+	
+  return ok;
+}
+
+bool Supplementary::inclusion(Facet facet){
+  bool flag;
+  std::multiset<Facet>::iterator it;
+	
+  it = hash_tableA.find(facet);
+  flag = 0;
+	
+  while(it!=hash_tableA.end()){
+    if(facet.get_hash()!=it->get_hash()){
+	  break;
+	}
+		
+	if(facet.same_vertices(*it)){
+	  flag = 1;
+	  break;
+	}
+		
+	it++;
+  }
+	
+  return flag;
+}
+
+bool Supplementary::inclusion(Diagonal diagonal){
+  bool flag;
+  std::multiset<Diagonal>::iterator it;
+	
+  it = hash_tableB.find(diagonal);
+  flag = 0;
+	
+  while(it!=hash_tableB.end()){
+    if(diagonal.get_hash()!=it->get_hash()){
+	  break;
+	}
+		
+	if(diagonal.same_vertices(*it)){
+	  flag = 1;
+	  break;
+	}
+		
+	it++;
+  }
+	
+  return flag;
+}
+
+bool Supplementary::duplicate(Diagonal diagonal){
+  bool flag;
+  std::multiset<Diagonal>::iterator it;
+	
+  it = hash_tableC.find(diagonal);
+  flag = 0;
+	
+  while(it!=hash_tableC.end()){
+    if(diagonal.get_hash()!=it->get_hash()){
+	  break;
+	}
+		
+	if(diagonal.same_vertices(*it)){
+	  flag = 1;
+	  break;
+	}
+		
+	it++;
+  }
+	
+  return flag;
+}
+
+bool Supplementary::conformityA(Prism prism){
+  bool c1,c2,c3;
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  c1 = conformityA(a,d,f,c);
+  c2 = conformityA(a,d,e,b);
+  c3 = conformityA(b,c,f,e);
+	
+  return c1 && c2 && c3;
+}
+
+bool Supplementary::conformityA(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
+  bool c1,c2,c3,c4;
+	
+  c1 = inclusion(Facet(a,b,c));
+  c2 = inclusion(Facet(a,c,d));
+  c3 = inclusion(Facet(a,b,d));
+  c4 = inclusion(Facet(b,c,d));
+	
+  return (c1 && c2 && c3 && c4) || (!c1 && !c2 && !c3 && !c4);
+}
+
+bool Supplementary::conformityB(Prism prism){
+  bool flag1;
+  bool flag2;
+  bool c1,c2,c3;
+  bool c4,c5,c6;
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  flag1 = inclusion(Diagonal(a,c));
+  flag1 = flag1 || inclusion(Diagonal(d,f));
+  flag1 = flag1 || inclusion(Diagonal(d,a));
+  flag1 = flag1 || inclusion(Diagonal(f,c));
+  flag1 = flag1 || inclusion(Diagonal(e,b));
+  flag1 = flag1 || inclusion(Diagonal(d,e));
+  flag1 = flag1 || inclusion(Diagonal(e,f));
+  flag1 = flag1 || inclusion(Diagonal(a,b));
+  flag1 = flag1 || inclusion(Diagonal(b,c));
+	
+  c1 = inclusion(Diagonal(a,f));
+  c2 = inclusion(Diagonal(d,c));
+  flag2 = (c1 && !c2) || (!c1 && c2);
+  c3 = inclusion(Diagonal(a,e));
+  c4 = inclusion(Diagonal(b,d));
+  flag2 = flag2 || (c3 && !c4) || (!c3 && c4);
+  c5 = inclusion(Diagonal(b,f));
+  c6 = inclusion(Diagonal(c,e));
+  flag2 = flag2 || (c5 && !c6) || (!c5 && c6);
+	
+  if(flag1 || flag2){
+    return 0;
+  }
+  else{
+    return 1;
+  }
+}
+
+bool Supplementary::conformityC(Prism prism){
+  bool flag;
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  flag = duplicate(Diagonal(a,f));
+  flag = flag || duplicate(Diagonal(d,c));
+  flag = flag || duplicate(Diagonal(a,e));
+  flag = flag || duplicate(Diagonal(b,d));
+  flag = flag || duplicate(Diagonal(b,f));
+  flag = flag || duplicate(Diagonal(c,e));
+	
+  if(flag){
+    return 0;
+  }
+  else{
+    return 1;
+  }
+}
+
+void Supplementary::build_vertex_to_vertices(GRegion* gr){
+  size_t i;
+  int j;
+  MElement* element;
+  MVertex *a,*b,*c,*d;
+  std::set<MVertex*> bin;
+  std::map<MVertex*,std::set<MVertex*> >::iterator it;
+	
+  vertex_to_vertices.clear();
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(four(element)){
+	  for(j=0;j<element->getNumVertices();j++){
+	    a = element->getVertex(j);
+	    b = element->getVertex((j+1)%4);
+	    c = element->getVertex((j+2)%4);
+	    d = element->getVertex((j+3)%4);
+			
+	    it = vertex_to_vertices.find(a);
+	    if(it!=vertex_to_vertices.end()){
+	      it->second.insert(b);
+		  it->second.insert(c);
+		  it->second.insert(d);
+	    }
+	    else{
+	      bin.clear();
+		  bin.insert(b);
+		  bin.insert(c);
+		  bin.insert(d);
+		  vertex_to_vertices.insert(std::pair<MVertex*,std::set<MVertex*> >(a,bin));
+	    }
+	  }
+    }
+  }
+}
+
+void Supplementary::build_vertex_to_tetrahedra(GRegion* gr){
+  unsigned int i;
+  int j;
+  MElement* element;
+  MVertex* vertex;
+  std::set<MElement*> bin;
+  std::map<MVertex*,std::set<MElement*> >::iterator it;
+	
+  vertex_to_tetrahedra.clear();
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(four(element)){
+	  for(j=0;j<element->getNumVertices();j++){
+	    vertex = element->getVertex(j);
+				
+		it = vertex_to_tetrahedra.find(vertex);
+		if(it!=vertex_to_tetrahedra.end()){
+		  it->second.insert(element);
+		}
+		else{
+		  bin.clear();
+		  bin.insert(element);
+		  vertex_to_tetrahedra.insert(std::pair<MVertex*,std::set<MElement*> >(vertex,bin));
+		}
+	  }
+	}
+  }
+}
+
+void Supplementary::build_hash_tableA(Prism prism){
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  build_hash_tableA(a,d,f,c);
+  build_hash_tableA(a,d,e,b);
+  build_hash_tableA(b,c,f,e);
+}
+
+void Supplementary::build_hash_tableA(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
+  build_hash_tableA(Facet(a,b,c));
+  build_hash_tableA(Facet(a,c,d));
+  build_hash_tableA(Facet(a,b,d));
+  build_hash_tableA(Facet(b,d,c));
+}
+
+void Supplementary::build_hash_tableA(Facet facet){
+  bool flag;
+  std::multiset<Facet>::iterator it;
+	
+  it = hash_tableA.find(facet);
+  flag = 1;
+	
+  while(it!=hash_tableA.end()){
+    if(facet.get_hash()!=it->get_hash()){
+	  break;
+	}
+		
+	if(facet.same_vertices(*it)){
+	  flag = 0;
+	  break;
+	}
+		
+	it++;
+  }
+	
+  if(flag){
+    hash_tableA.insert(facet);
+  }	
+}
+
+void Supplementary::build_hash_tableB(Prism prism){
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  build_hash_tableB(a,d,f,c);
+  build_hash_tableB(a,d,e,b);
+  build_hash_tableB(b,e,f,c);
+}
+
+void Supplementary::build_hash_tableB(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
+  build_hash_tableB(Diagonal(a,c));
+  build_hash_tableB(Diagonal(b,d));
+}
+
+void Supplementary::build_hash_tableB(Diagonal diagonal){
+  bool flag;
+  std::multiset<Diagonal>::iterator it;
+	
+  it = hash_tableB.find(diagonal);
+  flag = 1;
+	
+  while(it!=hash_tableB.end()){
+    if(diagonal.get_hash()!=it->get_hash()){
+	  break;
+	}
+		
+	if(diagonal.same_vertices(*it)){
+	  flag = 0;
+	  break;
+	}
+		
+	it++;
+  }
+	
+  if(flag){
+    hash_tableB.insert(diagonal);
+  }	
+}
+
+void Supplementary::build_hash_tableC(Prism prism){
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  build_hash_tableC(Diagonal(a,d));
+  build_hash_tableC(Diagonal(d,f));
+  build_hash_tableC(Diagonal(f,c));
+  build_hash_tableC(Diagonal(a,c));
+  build_hash_tableC(Diagonal(e,b));
+  build_hash_tableC(Diagonal(d,e));
+  build_hash_tableC(Diagonal(f,e));
+  build_hash_tableC(Diagonal(a,b));
+  build_hash_tableC(Diagonal(b,c));
+}
+
+void Supplementary::build_hash_tableC(Diagonal diagonal){
+  bool flag;
+  std::multiset<Diagonal>::iterator it;
+	
+  it = hash_tableC.find(diagonal);
+  flag = 1;
+	
+  while(it!=hash_tableC.end()){
+    if(diagonal.get_hash()!=it->get_hash()){
+	  break;
+	}
+		
+	if(diagonal.same_vertices(*it)){
+	  flag = 0;
+	  break;
+	}
+		
+	it++;
+  }
+	
+  if(flag){
+    hash_tableC.insert(diagonal);
+  }	
+}
+
+double Supplementary::scaled_jacobian(MVertex* a,MVertex* b,MVertex* c,MVertex* d){
+  double val;
+  double l1,l2,l3;
+  SVector3 vec1,vec2,vec3;
+	
+  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());
+	
+  l1 = vec1.norm();
+  l2 = vec2.norm();
+  l3 = vec3.norm();
+	
+  val = dot(vec1,crossprod(vec2,vec3));
+  return fabs(val)/(l1*l2*l3);
+}
+
+double Supplementary::min_scaled_jacobian(Prism prism){
+  int i;
+  double min;
+  double j1,j2,j3,j4,j5,j6;
+  MVertex *a,*b,*c;
+  MVertex *d,*e,*f;
+  std::vector<double> jacobians;
+	
+  a = prism.get_a();
+  b = prism.get_b();
+  c = prism.get_c();
+  d = prism.get_d();
+  e = prism.get_e();
+  f = prism.get_f();
+	
+  j1 = scaled_jacobian(a,b,c,d);
+  j2 = scaled_jacobian(b,a,c,e);
+  j3 = scaled_jacobian(c,a,b,f);
+  j4 = scaled_jacobian(d,a,e,f);
+  j5 = scaled_jacobian(e,b,d,f);
+  j6 = scaled_jacobian(f,c,d,e);
+	
+  jacobians.push_back(j1);
+  jacobians.push_back(j2);
+  jacobians.push_back(j3);
+  jacobians.push_back(j4);
+  jacobians.push_back(j5);
+  jacobians.push_back(j6);
+	
+  min = 1000000000.0;
+  for(i=0;i<6;i++){
+    if(jacobians[i]<=min){
+	  min = jacobians[i];
+	}
+  }
+	
+  return min;
+}
+
+/********************************************/
+/****************class PostOp****************/
+/********************************************/
+
+PostOp::PostOp(){}
+
+PostOp::~PostOp(){}
+
+void PostOp::execute(){
+  GRegion* gr;
+  GModel* model = GModel::current();
+  GModel::riter it;
+	
+  for(it=model->firstRegion();it!=model->lastRegion();it++)
+  {
+    gr = *it;
+	if(gr->getNumMeshElements()>0){
+	  execute(gr);
+	}
+  }
+}
+
+void PostOp::execute(GRegion* gr){
+  printf("................PYRAMIDS................\n");
+  init_markings(gr);
+  build_vertex_to_tetrahedra(gr);
+  pyramids(gr);
+  rearrange(gr);
+  statistics(gr);
+}
+
+void PostOp::init_markings(GRegion* gr){
+  unsigned int i;
+  MElement* element;
+	
+  markings.clear();
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(four(element)){
+	  markings.insert(std::pair<MElement*,bool>(element,0));
+	}
+  }
+}
+
+void PostOp::pyramids(GRegion* gr){
+  unsigned int i;
+  MVertex *a,*b,*c,*d;
+  MVertex *e,*f,*g,*h;
+  MElement* element;
+  std::vector<MElement*> hexahedra;
+  std::vector<MElement*> prisms;
+  std::vector<MTetrahedron*>::iterator it;
+  std::map<MElement*,bool>::iterator it2;
+	
+  hexahedra.clear();
+  prisms.clear();
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(eight(element)){
+	  hexahedra.push_back(element);
+	}
+  }
+
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(six(element)){
+	  prisms.push_back(element);
+	}
+  }	
+
+  for(i=0;i<hexahedra.size();i++){
+    element = hexahedra[i];
+		
+	a = element->getVertex(0);
+	b = element->getVertex(1);
+	c = element->getVertex(2);
+	d = element->getVertex(3);
+	e = element->getVertex(4);
+	f = element->getVertex(5);
+	g = element->getVertex(6);
+	h = element->getVertex(7);
+		
+	pyramids(a,b,c,d,gr);
+	pyramids(e,f,g,h,gr);
+	pyramids(a,b,f,e,gr);
+	pyramids(b,c,g,f,gr);
+	pyramids(d,c,g,h,gr);
+	pyramids(d,a,e,h,gr);
+  }
+	
+  for(i=0;i<prisms.size();i++){
+    element = prisms[i];
+		
+	a = element->getVertex(0);
+	b = element->getVertex(1);
+	c = element->getVertex(2);
+	d = element->getVertex(3);
+	e = element->getVertex(4);
+	f = element->getVertex(5);
+		
+	pyramids(a,d,f,c,gr);
+	pyramids(a,b,e,d,gr);
+	pyramids(b,c,f,e,gr);
+  }	
+	
+  it = gr->tetrahedra.begin();
+  while(it!=gr->tetrahedra.end()){
+    element = (MElement*)(*it);
+	it2 = markings.find(element);
+	if(it2->second==1){
+	  it = gr->tetrahedra.erase(it);
+	}
+	else{
+	  it++;
+	}
+  }
+}
+
+void PostOp::pyramids(MVertex* a,MVertex* b,MVertex* c,MVertex* d,GRegion* gr){
+  MVertex* vertex;
+  std::set<MElement*> bin;
+  std::set<MElement*> bin1;
+  std::set<MElement*> bin2;
+  std::set<MElement*>::iterator it;
+  std::map<MElement*,bool>::iterator it1;
+  std::map<MElement*,bool>::iterator it2;
+	
+  bin1.clear();
+  bin2.clear();
+  find(a,c,bin1);
+  find(b,d,bin2);
+	
+  bin.clear();
+  for(it=bin1.begin();it!=bin1.end();it++){
+    bin.insert(*it);
+  }
+  for(it=bin2.begin();it!=bin2.end();it++){
+    bin.insert(*it);
+  }
+	
+  if(bin.size()==2){
+    it = bin.begin();
+	it1 = markings.find(*it);
+	it++;
+	it2 = markings.find(*it);
+		
+	if(it1->second==0 && it2->second==0){
+	  vertex = find(a,b,c,d,*it);
+			
+	  if(vertex!=0){
+	    it1->second = 1;
+		it2->second = 1;
+		gr->addPyramid(new MPyramid(a,b,c,d,vertex));
+	  }
+	}
+  }
+}
+
+void PostOp::rearrange(GRegion* gr){
+  unsigned int i;
+  MElement* element;
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	element->setVolumePositive();
+  }
+}
+
+void PostOp::statistics(GRegion* gr){
+  unsigned int i;
+  int nbr,nbr8,nbr6,nbr5,nbr4;
+  double vol,vol8,vol6,vol5,vol4;
+  MElement* element;
+	
+  nbr = 0;
+  nbr8 = 0;
+  nbr6 = 0;
+  nbr5 = 0;
+  nbr4 = 0;
+  vol = 0.0;
+  vol8 = 0.0;
+  vol6 = 0.0;
+  vol5 = 0.0;
+  vol4 = 0.0;
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+		
+	if(eight(element)){
+	  nbr8 = nbr8 + 1;
+	  vol8 = vol8 + element->getVolume();
+	}
+		
+	if(six(element)){
+	  nbr6 = nbr6 + 1;
+	  vol6 = vol6 + element->getVolume();
+	}  
+	  
+    if(five(element)){
+	  nbr5 = nbr5 + 1;
+	  vol5 = vol5 + element->getVolume();
+	}
+		
+	if(four(element)){
+	  nbr4 = nbr4 + 1;
+	  vol4 = vol4 + element->getVolume();
+	}
+		
+	nbr = nbr + 1;
+	vol = vol + element->getVolume();
+  }
+	
+  printf("Number :\n");
+  printf("  percentage of hexahedra : %.2f\n",nbr8*100.0/nbr);
+  printf("  percentage of prisms : %.2f\n",nbr6*100.0/nbr);
+  printf("  percentage of pyramids : %.2f\n",nbr5*100.0/nbr);
+  printf("  percentage of tetrahedra : %.2f\n",nbr4*100.0/nbr);
+  printf("Volume :\n");
+  printf("  percentage of hexahedra : %.2f\n",vol8*100.0/vol);
+  printf("  percentage of prisms : %.2f\n",vol6*100.0/vol);
+  printf("  percentage of pyramids : %.2f\n",vol5*100.0/vol);
+  printf("  percentage of tetrahedra : %.2f\n",vol4*100.0/vol);
+  printf("Total number of elements : %d\n",gr->getNumMeshElements());
+}
+
+bool PostOp::four(MElement* element){
+  if(element->getNumVertices()==4) return 1;
+  else return 0;
+}
+
+bool PostOp::five(MElement* element){
+  if(element->getNumVertices()==5) return 1;
+  else return 0;
+}
+
+bool PostOp::six(MElement* element){
+  if(element->getNumVertices()==6) return 1;
+  else return 0;
+}
+
+bool PostOp::eight(MElement* element){
+  if(element->getNumVertices()==8) return 1;
+  else return 0;
+}
+
+MVertex* PostOp::find(MVertex* v1,MVertex* v2,MVertex* v3,MVertex* v4,MElement* element){
+  int i;
+  MVertex* vertex;
+  MVertex* pointer;
+	
+  pointer = 0;	
+	
+  for(i=0;i<element->getNumVertices();i++){
+    vertex = element->getVertex(i);
+	if(vertex!=v1 && vertex!=v2 && vertex!=v3 && vertex!=v4){
+	  pointer = vertex;
+	  break;
+	}
+  }
+	
+  return pointer;
+}
+
+void PostOp::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_tetrahedra.find(v1);
+  it2 = vertex_to_tetrahedra.find(v2);
+	
+  if(it1!=vertex_to_tetrahedra.end() && it2!=vertex_to_tetrahedra.end()){
+    intersection(it1->second,it2->second,final);
+  }
+}
+
+void PostOp::intersection(const std::set<MElement*>& bin1,const std::set<MElement*>& bin2,std::set<MElement*>& final){
+  std::set_intersection(bin1.begin(),bin1.end(),bin2.begin(),bin2.end(),std::inserter(final,final.end()));
+}
+
+void PostOp::build_vertex_to_tetrahedra(GRegion* gr){
+  unsigned int i;
+  int j;
+  MElement* element;
+  MVertex* vertex;
+  std::set<MElement*> bin;
+  std::map<MVertex*,std::set<MElement*> >::iterator it;
+	
+  vertex_to_tetrahedra.clear();	
+	
+  for(i=0;i<gr->getNumMeshElements();i++){
+    element = gr->getMeshElement(i);
+	if(four(element)){
+	  for(j=0;j<element->getNumVertices();j++){
+	    vertex = element->getVertex(j);
+				
+		it = vertex_to_tetrahedra.find(vertex);
+		if(it!=vertex_to_tetrahedra.end()){
+		  it->second.insert(element);
+		}
+		else{
+		  bin.clear();
+		  bin.insert(element);
+		  vertex_to_tetrahedra.insert(std::pair<MVertex*,std::set<MElement*> >(vertex,bin));
+		}
+	  }
+	}
+  }
+}
\ No newline at end of file
diff --git a/Mesh/yamakawa.h b/Mesh/yamakawa.h
index 81f5c3316da8abf11996dbca5ecfafd10a638e3a..93ed85a65dc708ccbe1318422a17f02c17848464 100755
--- a/Mesh/yamakawa.h
+++ b/Mesh/yamakawa.h
@@ -74,6 +74,7 @@ class Recombinator{
   std::map<MVertex*,std::set<MElement*> > vertex_to_elements;
   std::multiset<Facet> hash_tableA;
   std::multiset<Diagonal> hash_tableB;
+  std::multiset<Diagonal> hash_tableC;
  public:
   Recombinator();
   ~Recombinator();
@@ -115,10 +116,12 @@ class Recombinator{
   bool inclusion(MVertex*,MVertex*,MVertex*,const std::set<MElement*>&);
   bool inclusion(Facet);
   bool inclusion(Diagonal);
+  bool duplicate(Diagonal);
   
   bool conformityA(Hex);
   bool conformityA(MVertex*,MVertex*,MVertex*,MVertex*);
   bool conformityB(Hex);
+  bool conformityC(Hex);
 	
   void build_vertex_to_vertices(GRegion*);
   void build_vertex_to_elements(GRegion*);
@@ -128,6 +131,8 @@ class Recombinator{
   void build_hash_tableB(Hex);
   void build_hash_tableB(MVertex*,MVertex*,MVertex*,MVertex*);
   void build_hash_tableB(Diagonal);
+  void build_hash_tableC(Hex);
+  void build_hash_tableC(Diagonal);
   
   void print_vertex_to_vertices(GRegion*);
   void print_vertex_to_elements(GRegion*);
@@ -137,4 +142,119 @@ class Recombinator{
   double scaled_jacobian(MVertex*,MVertex*,MVertex*,MVertex*);
   double max_scaled_jacobian(MElement*,int&);
   double min_scaled_jacobian(Hex);	
+};
+
+class Prism{
+ private:
+  double quality;
+  MVertex *a,*b,*c,*d,*e,*f;
+ public:
+  Prism();
+  Prism(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*);
+  ~Prism();
+  double get_quality() const;
+  void set_quality(double);
+  MVertex* get_a();
+  MVertex* get_b();
+  MVertex* get_c();
+  MVertex* get_d();
+  MVertex* get_e();
+  MVertex* get_f();
+  void set_vertices(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*,MVertex*);
+  bool operator<(const Prism&) const;
+};
+
+class Supplementary{
+ private:
+  std::vector<Prism> potential;
+  std::map<MElement*,bool> markings;
+  std::map<MVertex*,std::set<MVertex*> > vertex_to_vertices;
+  std::map<MVertex*,std::set<MElement*> > vertex_to_tetrahedra;
+  std::multiset<Facet> hash_tableA;
+  std::multiset<Diagonal> hash_tableB;
+  std::multiset<Diagonal> hash_tableC;
+ public:
+  Supplementary();
+  ~Supplementary();
+	
+  void execute();
+  void execute(GRegion*);	
+	
+  void init_markings(GRegion*);
+  void patern(GRegion*);
+  void merge(GRegion*);
+  void rearrange(GRegion*);
+  void statistics(GRegion*);
+	
+  bool four(MElement*);
+  bool five(MElement*);
+  bool six(MElement*);
+  bool eight(MElement*);	
+	
+  bool sliver(MElement*,Prism);
+  bool valid(Prism,const std::set<MElement*>&);
+  bool valid(Prism);
+  double eta(MVertex*,MVertex*,MVertex*,MVertex*);
+  bool linked(MVertex*,MVertex*);	
+	
+  void find(MVertex*,MVertex*,const std::vector<MVertex*>&,std::set<MVertex*>&);	
+  void find(MVertex*,Prism,std::set<MElement*>&);
+	
+  void intersection(const std::set<MVertex*>&,const std::set<MVertex*>&,const std::vector<MVertex*>&,std::set<MVertex*>&);	
+	
+  bool inclusion(MVertex*,Prism);
+  bool inclusion(MVertex*,MVertex*,MVertex*,MVertex*,MVertex*);
+  bool inclusion(MVertex*,MVertex*,MVertex*,const std::set<MElement*>&);
+  bool inclusion(Facet);
+  bool inclusion(Diagonal);
+  bool duplicate(Diagonal);
+	
+  bool conformityA(Prism);
+  bool conformityA(MVertex*,MVertex*,MVertex*,MVertex*);
+  bool conformityB(Prism);
+  bool conformityC(Prism);
+	
+  void build_vertex_to_vertices(GRegion*);
+  void build_vertex_to_tetrahedra(GRegion*);
+  void build_hash_tableA(Prism);
+  void build_hash_tableA(MVertex*,MVertex*,MVertex*,MVertex*);
+  void build_hash_tableA(Facet);
+  void build_hash_tableB(Prism);
+  void build_hash_tableB(MVertex*,MVertex*,MVertex*,MVertex*);
+  void build_hash_tableB(Diagonal);
+  void build_hash_tableC(Prism);
+  void build_hash_tableC(Diagonal);
+	
+  double scaled_jacobian(MVertex*,MVertex*,MVertex*,MVertex*);
+  double min_scaled_jacobian(Prism);
+};
+
+class PostOp{
+ private:
+  std::map<MElement*,bool> markings;
+  std::map<MVertex*,std::set<MElement*> > vertex_to_tetrahedra;
+ public:
+  PostOp();
+  ~PostOp();
+	
+  void execute();
+  void execute(GRegion*);
+	
+  void init_markings(GRegion*);
+  void pyramids(GRegion*);
+  void pyramids(MVertex*,MVertex*,MVertex*,MVertex*,GRegion*);
+  void rearrange(GRegion*);
+  void statistics(GRegion*);
+	
+  bool four(MElement*);
+  bool five(MElement*);
+  bool six(MElement*);
+  bool eight(MElement*);
+	
+  MVertex* find(MVertex*,MVertex*,MVertex*,MVertex*,MElement*);
+  void find(MVertex*,MVertex*,std::set<MElement*>&);
+	
+  void intersection(const std::set<MElement*>&,const std::set<MElement*>&,std::set<MElement*>&);
+	
+  void build_vertex_to_tetrahedra(GRegion*);
 };
\ No newline at end of file