diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp
index 448766489261a5f6641d747dfe608746050431d2..e63b430dda9f0f10d4401ef575d6331690b2dc0e 100644
--- a/Geo/MVertex.cpp
+++ b/Geo/MVertex.cpp
@@ -1,4 +1,4 @@
-// $Id: MVertex.cpp,v 1.13 2007-04-21 19:40:00 geuzaine Exp $
+// $Id: MVertex.cpp,v 1.14 2007-07-31 22:09:11 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -25,6 +25,16 @@
 int MVertex::_globalNum = 0;
 double MVertexLessThanLexicographic::tolerance = 1.e-6;
 
+bool MVertexLessThanLexicographic::operator()(const MVertex *v1, const MVertex *v2) const
+{
+  if(v1->x() - v2->x() >  tolerance) return true;
+  if(v1->x() - v2->x() < -tolerance) return false;
+  if(v1->y() - v2->y() >  tolerance) return true;
+  if(v1->y() - v2->y() < -tolerance) return false;
+  if(v1->z() - v2->z() >  tolerance) return true;
+  return false;
+}
+
 void MVertex::writeMSH(FILE *fp, bool binary, double scalingFactor)
 {
   if(_num < 0) return; // negative vertices are never saved
@@ -133,3 +143,14 @@ void MVertex::writeBDF(FILE *fp, int format, double scalingFactor)
     fprintf(fp, "*N%-6d%-16.9G\n", _num, z1);
   }
 }
+
+std::set<MVertex*, MVertexLessThanLexicographic>::iterator 
+MVertex::linearSearch(std::set<MVertex*, MVertexLessThanLexicographic> &pos)
+{
+  double tol = MVertexLessThanLexicographic::tolerance;
+  for(std::set<MVertex*, MVertexLessThanLexicographic>::iterator it = pos.begin();
+      it != pos.end(); ++it){
+    if(distance(*it) < tol) return it;
+  }
+  return pos.end();
+}
diff --git a/Geo/MVertex.h b/Geo/MVertex.h
index 157a84195a0d11a21727277893b8a59ab23cebd0..895e1d12f2e8a73e6e3010eccb8ce514ad039c8c 100644
--- a/Geo/MVertex.h
+++ b/Geo/MVertex.h
@@ -21,10 +21,17 @@
 // Please report all bugs and problems to <gmsh@geuz.org>.
 
 #include <stdio.h>
-#include <algorithm>
+#include <set>
 #include "SPoint3.h"
 
 class GEntity;
+class MVertex;
+
+class MVertexLessThanLexicographic{
+ public:
+  static double tolerance;
+  bool operator()(const MVertex *v1, const MVertex *v2) const;
+};
 
 // A mesh vertex.
 class MVertex{
@@ -90,6 +97,10 @@ class MVertex{
     return sqrt(dx * dx + dy * dy + dz * dz);
   }
 
+  // linear coordinate search for the vertex in a set
+  std::set<MVertex*, MVertexLessThanLexicographic>::iterator 
+  linearSearch(std::set<MVertex*, MVertexLessThanLexicographic> &pos);
+
   // Get the data associated with this vertex
   virtual void *getData(){ return 0; }
 
@@ -143,18 +154,4 @@ class MDataFaceVertex : public MFaceVertex{
   virtual void *getData(){ return (void*)&_data; }
 };
 
-class MVertexLessThanLexicographic{
- public:
-  static double tolerance;
-  bool operator()(const MVertex *v1, const MVertex *v2) const
-  {
-    if(v1->x() - v2->x() >  tolerance) return true;
-    if(v1->x() - v2->x() < -tolerance) return false;
-    if(v1->y() - v2->y() >  tolerance) return true;
-    if(v1->y() - v2->y() < -tolerance) return false;
-    if(v1->z() - v2->z() >  tolerance) return true;
-    return false;
-  }
-};
-
 #endif
diff --git a/Geo/Makefile b/Geo/Makefile
index 32b798047dff8480fa4e911f9e9ad8e8a2d05939..627a7815f44731177e0026948984b34026118766 100644
--- a/Geo/Makefile
+++ b/Geo/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.153 2007-07-31 20:07:38 geuzaine Exp $
+# $Id: Makefile,v 1.154 2007-07-31 22:09:11 geuzaine Exp $
 #
 # Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 #
@@ -223,8 +223,7 @@ GModelIO_F.o: GModelIO_F.cpp GModel.h GVertex.h GEntity.h Range.h \
   ExtrudeParams.h ../Common/SmoothData.h GFace.h GEdgeLoop.h Pair.h \
   GRegion.h ../Common/Message.h ../Post/Views.h ../Post/ColorTable.h \
   ../Common/VertexArray.h ../Post/AdaptiveViews.h ../Common/GmshMatrix.h \
-  FFace.h FEdge.h FVertex.h ../Mesh/meshGFace.h ../Geo/MVertex.h \
-  GModelIO_F.h
+  FFace.h FEdge.h FVertex.h ../Mesh/meshGFace.h GModelIO_F.h
 GModelIO_CGNS.o: GModelIO_CGNS.cpp GModel.h GVertex.h GEntity.h Range.h \
   SPoint3.h SBoundingBox3d.h ../Common/GmshDefines.h MVertex.h GPoint.h \
   SPoint2.h GEdge.h SVector3.h MElement.h MEdge.h ../Common/Hash.h \
diff --git a/Mesh/Makefile b/Mesh/Makefile
index 836d395680b669c2f98ad07712e29480b968410a..ae455eb57f295b0a2c29552caba097ec0fdf5a03 100644
--- a/Mesh/Makefile
+++ b/Mesh/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.177 2007-07-31 20:07:38 geuzaine Exp $
+# $Id: Makefile,v 1.178 2007-07-31 22:09:11 geuzaine Exp $
 #
 # Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 #
@@ -42,6 +42,7 @@ SRC = Generator.cpp \
         meshGRegionDelaunayInsertion.cpp \
         meshGRegionTransfinite.cpp \
         meshGRegionExtruded.cpp \
+        meshGRegionCarveHole.cpp \
         DivideAndConquer.cpp \
         BackgroundMesh.cpp \
         BoundaryLayer.cpp \
@@ -150,9 +151,9 @@ meshGEdgeExtruded.o: meshGEdgeExtruded.cpp ../Geo/ExtrudeParams.h \
   ../Geo/Pair.h ../Geo/ExtrudeParams.h ../Geo/GRegion.h ../Geo/GEntity.h \
   ../Geo/MElement.h ../Geo/ExtrudeParams.h ../Geo/SBoundingBox3d.h \
   ../Common/Message.h
-meshGFace.o: meshGFace.cpp meshGFace.h ../Geo/MVertex.h ../Geo/SPoint3.h \
-  meshGFaceDelaunayInsertion.h ../Geo/MElement.h ../Common/GmshDefines.h \
-  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+meshGFace.o: meshGFace.cpp meshGFace.h meshGFaceDelaunayInsertion.h \
+  ../Geo/MElement.h ../Common/GmshDefines.h ../Geo/MVertex.h \
+  ../Geo/SPoint3.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
   ../Geo/SPoint3.h ../Common/Hash.h ../Geo/MFace.h ../Geo/MVertex.h \
   ../Geo/SVector3.h ../Numeric/Numeric.h ../Common/Context.h \
   ../DataStr/List.h DivideAndConquer.h BackgroundMesh.h ../Geo/GVertex.h \
@@ -170,19 +171,18 @@ meshGFace.o: meshGFace.cpp meshGFace.h ../Geo/MVertex.h ../Geo/SPoint3.h \
   ../Common/OS.h BDS.h ../Post/Views.h ../Post/ColorTable.h \
   ../Post/AdaptiveViews.h ../Common/GmshMatrix.h
 meshGFaceTransfinite.o: meshGFaceTransfinite.cpp meshGFace.h \
-  ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GVertex.h ../Geo/GEntity.h \
-  ../Geo/Range.h ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h \
-  ../Geo/SPoint3.h ../Common/GmshDefines.h ../Geo/MVertex.h \
-  ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/GEdge.h ../Geo/GEntity.h \
-  ../Geo/GVertex.h ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h \
-  ../Geo/SPoint2.h ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Common/Hash.h ../Geo/MFace.h \
-  ../Geo/MVertex.h ../Geo/SVector3.h ../Numeric/Numeric.h \
-  ../Common/Context.h ../DataStr/List.h ../Geo/ExtrudeParams.h \
-  ../Common/SmoothData.h ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h \
-  ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/MElement.h ../Geo/SPoint2.h \
-  ../Geo/SVector3.h ../Geo/Pair.h ../Geo/ExtrudeParams.h \
-  ../Common/Message.h
+  ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Common/GmshDefines.h \
+  ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/SPoint2.h \
+  ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h \
+  ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h \
+  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/Hash.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \
+  ../Geo/ExtrudeParams.h ../Common/SmoothData.h ../Geo/GFace.h \
+  ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h \
+  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/ExtrudeParams.h ../Common/Message.h
 meshGFaceExtruded.o: meshGFaceExtruded.cpp ../Geo/ExtrudeParams.h \
   ../Common/SmoothData.h ../Numeric/Numeric.h ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
@@ -254,19 +254,19 @@ meshGRegionDelaunayInsertion.o: meshGRegionDelaunayInsertion.cpp \
   ../Geo/GEntity.h ../Geo/MElement.h ../Geo/ExtrudeParams.h \
   ../Geo/SBoundingBox3d.h ../Common/Message.h
 meshGRegionTransfinite.o: meshGRegionTransfinite.cpp meshGFace.h \
-  ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GFace.h ../Geo/GPoint.h \
-  ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
-  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Common/GmshDefines.h \
-  ../Geo/GEdgeLoop.h ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h \
-  ../Geo/GEntity.h ../Geo/MVertex.h ../Geo/GPoint.h ../Geo/SPoint2.h \
-  ../Geo/SVector3.h ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h \
-  ../Geo/MElement.h ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Common/Hash.h ../Geo/MFace.h ../Geo/MVertex.h \
-  ../Geo/SVector3.h ../Numeric/Numeric.h ../Common/Context.h \
-  ../DataStr/List.h ../Geo/ExtrudeParams.h ../Common/SmoothData.h \
-  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
-  ../Geo/ExtrudeParams.h ../Geo/GRegion.h ../Geo/GEntity.h \
-  ../Geo/MElement.h ../Geo/ExtrudeParams.h ../Common/Message.h
+  ../Geo/GFace.h ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/Range.h \
+  ../Geo/SPoint3.h ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h \
+  ../Common/GmshDefines.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h \
+  ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/MVertex.h \
+  ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/SPoint2.h ../Geo/SVector3.h \
+  ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h \
+  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/Hash.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \
+  ../Geo/ExtrudeParams.h ../Common/SmoothData.h ../Geo/MElement.h \
+  ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h ../Geo/ExtrudeParams.h \
+  ../Geo/GRegion.h ../Geo/GEntity.h ../Geo/MElement.h \
+  ../Geo/ExtrudeParams.h ../Common/Message.h
 meshGRegionExtruded.o: meshGRegionExtruded.cpp ../Geo/ExtrudeParams.h \
   ../Common/SmoothData.h ../Numeric/Numeric.h ../Geo/GModel.h \
   ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
@@ -282,6 +282,21 @@ meshGRegionExtruded.o: meshGRegionExtruded.cpp ../Geo/ExtrudeParams.h \
   ../Geo/Pair.h ../Geo/ExtrudeParams.h ../Geo/GRegion.h ../Geo/GEntity.h \
   ../Geo/MElement.h ../Geo/ExtrudeParams.h ../Geo/SBoundingBox3d.h \
   meshGFace.h meshGRegion.h ../Common/Message.h
+meshGRegionCarveHole.o: meshGRegionCarveHole.cpp ../Geo/GModel.h \
+  ../Geo/GVertex.h ../Geo/GEntity.h ../Geo/Range.h ../Geo/SPoint3.h \
+  ../Geo/SBoundingBox3d.h ../Geo/SPoint3.h ../Common/GmshDefines.h \
+  ../Geo/MVertex.h ../Geo/SPoint3.h ../Geo/GPoint.h ../Geo/SPoint2.h \
+  ../Geo/GEdge.h ../Geo/GEntity.h ../Geo/GVertex.h ../Geo/SVector3.h \
+  ../Geo/SPoint3.h ../Geo/SPoint3.h ../Geo/SPoint2.h ../Geo/MElement.h \
+  ../Geo/MVertex.h ../Geo/MEdge.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Common/Hash.h ../Geo/MFace.h ../Geo/MVertex.h ../Geo/SVector3.h \
+  ../Numeric/Numeric.h ../Common/Context.h ../DataStr/List.h \
+  ../Geo/ExtrudeParams.h ../Common/SmoothData.h ../Geo/GFace.h \
+  ../Geo/GPoint.h ../Geo/GEntity.h ../Geo/GEdgeLoop.h ../Geo/GEdge.h \
+  ../Geo/MElement.h ../Geo/SPoint2.h ../Geo/SVector3.h ../Geo/Pair.h \
+  ../Geo/ExtrudeParams.h ../Geo/GRegion.h ../Geo/GEntity.h \
+  ../Geo/MElement.h ../Geo/ExtrudeParams.h ../Geo/SBoundingBox3d.h \
+  ../Common/Message.h
 DivideAndConquer.o: DivideAndConquer.cpp ../Common/Gmsh.h \
   ../Common/Message.h ../DataStr/Malloc.h ../DataStr/List.h \
   ../DataStr/Tree.h ../DataStr/avl.h ../DataStr/Tools.h ../DataStr/List.h \
diff --git a/Mesh/meshGFace.h b/Mesh/meshGFace.h
index da58bf00ef66fca4e6b9d0ed72537bd20c17c062..df7171e49c0baa15f48cf8eee24c89ac014a1296 100644
--- a/Mesh/meshGFace.h
+++ b/Mesh/meshGFace.h
@@ -22,9 +22,9 @@
 
 #include <vector>
 #include <set>
-#include "MVertex.h"
 
 class GFace;
+class MVertex;
 
 // Create the mesh of the face
 class meshGFace {
@@ -59,7 +59,4 @@ int MeshTransfiniteSurface(GFace *gf);
 int MeshExtrudedSurface(GFace *gf, 
 			std::set<std::pair<MVertex*, MVertex*> > *constrainedEdges=0);
 
-std::set<MVertex*, MVertexLessThanLexicographic>::iterator 
-linearFind(std::set<MVertex*, MVertexLessThanLexicographic> &pos, MVertex *p);
-
 #endif
diff --git a/Mesh/meshGFaceExtruded.cpp b/Mesh/meshGFaceExtruded.cpp
index 759f50b8b7d14c4ec3163adbc4b81eeebd651c4c..b29c958b154e3cd9d69633b04209ed1caec75614 100644
--- a/Mesh/meshGFaceExtruded.cpp
+++ b/Mesh/meshGFaceExtruded.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFaceExtruded.cpp,v 1.20 2007-07-31 20:07:38 geuzaine Exp $
+// $Id: meshGFaceExtruded.cpp,v 1.21 2007-07-31 22:09:11 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -60,26 +60,6 @@ void createQuaTri(std::vector<MVertex*> &v, GFace *to,
   }
 }
 
-// FIXME: this is a temporary hack to try to circumvent problems
-// experienced with pos.find(). We need to find a better solution.
-std::set<MVertex*, MVertexLessThanLexicographic>::iterator 
-linearFind(std::set<MVertex*, MVertexLessThanLexicographic> &pos, MVertex *p)
-{
-  double eps = MVertexLessThanLexicographic::tolerance;
-  Msg(INFO, "Trying linear find for point %.16g %.16g %.16g (eps = %.16g)",
-      p->x(), p->y(), p->z(), eps);
-  for(std::set<MVertex*, MVertexLessThanLexicographic>::iterator it = pos.begin();
-      it != pos.end(); ++it){
-    MVertex *v = *it;
-    double dx = v->x() - p->x();
-    double dy = v->y() - p->y();
-    double dz = v->z() - p->z();
-    if(sqrt(dx * dx + dy * dy + dz * dz) < eps) return it;
-  }
-  return pos.end();
-}
-	   
-
 void extrudeMesh(GEdge *from, GFace *to,
 		 std::set<MVertex*, MVertexLessThanLexicographic> &pos,
 		 std::set<std::pair<MVertex*, MVertex*> > *constrainedEdges)
@@ -124,7 +104,10 @@ void extrudeMesh(GEdge *from, GFace *to,
 	for(int p = 0; p < 4; p++){
 	  MVertex tmp(x[p], y[p], z[p], 0, -1);
 	  itp = pos.find(&tmp);
-	  if(itp == pos.end()) itp = linearFind(pos, &tmp);
+	  if(itp == pos.end()){ // FIXME: workaround
+	    Msg(INFO, "Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z());
+	    itp = tmp.linearSearch(pos);
+	  }
 	  if(itp == pos.end()){
 	    Msg(GERROR, "Could not find extruded vertex (%.16g, %.16g, %.16g) in surface %d",
 		tmp.x(), tmp.y(), tmp.z(), to->tag());
@@ -164,7 +147,10 @@ void copyMesh(GFace *from, GFace *to,
       ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
 		  tmp.x(), tmp.y(), tmp.z());
       itp = pos.find(&tmp);
-      if(itp == pos.end()) itp = linearFind(pos, &tmp);
+      if(itp == pos.end()){ // FIXME: workaround
+	Msg(INFO, "Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z());
+	itp = tmp.linearSearch(pos);
+      }
       if(itp == pos.end()) {
 	Msg(GERROR, "Could not find extruded vertex (%.16g, %.16g, %.16g) in surface %d",
 	    tmp.x(), tmp.y(), tmp.z(), to->tag());
@@ -182,7 +168,10 @@ void copyMesh(GFace *from, GFace *to,
       ep->Extrude(ep->mesh.NbLayer - 1, ep->mesh.NbElmLayer[ep->mesh.NbLayer - 1],
 		  tmp.x(), tmp.y(), tmp.z());
       itp = pos.find(&tmp);
-      if(itp == pos.end()) itp = linearFind(pos, &tmp);
+      if(itp == pos.end()){ // FIXME: workaround
+	Msg(INFO, "Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z());
+	itp = tmp.linearSearch(pos);
+      }
       if(itp == pos.end()) {
 	Msg(GERROR, "Could not find extruded vertex (%.16g, %.16g, %.16g) in surface %d", 
 	    tmp.x(), tmp.y(), tmp.z(), to->tag());
diff --git a/Mesh/meshGRegion.h b/Mesh/meshGRegion.h
index b59fbb4320cc31fd836bf2c1f1466a0c58dcc2c5..cc9081fb479777035708fbbf115a2bd3eb332d92 100644
--- a/Mesh/meshGRegion.h
+++ b/Mesh/meshGRegion.h
@@ -53,5 +53,6 @@ class deMeshGRegion {
 void MeshDelaunayVolume(std::vector<GRegion*> &delaunay);
 int MeshTransfiniteVolume(GRegion *gr);
 int SubdivideExtrudedMesh(GModel *m);
+void carveHole(GRegion *gr, int num, double distance, std::vector<int> &surfaces);
 
 #endif
diff --git a/Mesh/meshGRegionCarveHole.cpp b/Mesh/meshGRegionCarveHole.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5d66438cc5117dce6004e9837413616c074e63cc
--- /dev/null
+++ b/Mesh/meshGRegionCarveHole.cpp
@@ -0,0 +1,152 @@
+// $Id: meshGRegionCarveHole.cpp,v 1.1 2007-07-31 22:09:11 geuzaine Exp $
+//
+// Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+// USA.
+// 
+// Please report all bugs and problems to <gmsh@geuz.org>.
+
+#include <set>
+#include "GModel.h"
+#include "Message.h"
+
+#if !defined(HAVE_ANN_)
+
+void carveHole(GRegion *gr, int num, double distance, std::vector<int> &surfaces)
+{
+  Msg(GERROR, "Gmsh must be compiled with ANN support to carve holes in meshes");
+}
+
+#else
+
+#include "ANN/ANN.h"
+
+template <class T>
+void carveHole(std::vector<T*> &elements, double distance, ANNkd_tree *kdtree)
+{
+  // delete all elements that have at least one vertex closer than
+  // 'distance' from the carving surface vertices
+  ANNidxArray index = new ANNidx[1];
+  ANNdistArray dist = new ANNdist[1];
+  std::vector<T*> temp;
+  for(unsigned int i = 0; i < elements.size(); i++){
+    for(int j = 0; j < elements[i]->getNumVertices(); j++){
+      MVertex *v = elements[i]->getVertex(j);
+      double xyz[3] = {v->x(), v->y(), v->z()};
+      kdtree->annkSearch(xyz, 1, index, dist);
+      double d = sqrt(dist[0]);
+      if(d < distance){
+	delete elements[i];
+	break;
+      }
+      else if(j == elements[i]->getNumVertices() - 1){
+        temp.push_back(elements[i]);
+      }
+    }
+  }
+  elements = temp;
+  delete [] index;
+  delete [] dist;
+}
+
+template <class T>
+void addFaces(std::vector<T*> &elements, std::set<MFace, Less_Face> &faces)
+{
+  for(unsigned int i = 0; i < elements.size(); i++){
+    for(int j = 0; j < elements[i]->getNumFaces(); j++){
+      MFace f = elements[i]->getFace(j);
+      std::set<MFace, Less_Face>::iterator it = faces.find(f);
+      if(it == faces.end())
+	faces.insert(f);
+      else
+	faces.erase(it);
+    }
+  }
+}
+
+void carveHole(GRegion *gr, int num, double distance, std::vector<int> &surfaces)
+{
+  Msg(INFO, "Carving hole %d from surface %d at distance %g", num, surfaces[0], distance);
+  GModel *m = gr->model();
+
+  // add all points from carving surfaces into kdtree
+  int numnodes = 0;
+  for(unsigned int i = 0; i < surfaces.size(); i++){
+    GFace *gf = m->faceByTag(surfaces[i]);
+    if(!gf){
+      Msg(GERROR, "Unknown carving surface %d", surfaces[i]);
+      return;
+    }
+    numnodes += gf->mesh_vertices.size();
+  }
+
+  ANNpointArray kdnodes = annAllocPts(numnodes, 4);
+  int k = 0;
+  for(unsigned int i = 0; i < surfaces.size(); i++){
+    GFace *gf = m->faceByTag(surfaces[i]);
+    for(unsigned int j = 0; j < gf->mesh_vertices.size(); j++){
+      kdnodes[k][0] = gf->mesh_vertices[j]->x();
+      kdnodes[k][1] = gf->mesh_vertices[j]->y();
+      kdnodes[k][2] = gf->mesh_vertices[j]->z();
+      k++;
+    }
+  }
+  ANNkd_tree *kdtree = new ANNkd_tree(kdnodes, numnodes, 3);
+
+  // remove the volume elements that are within 'distance' of the
+  // carved surface
+  carveHole(gr->tetrahedra, distance, kdtree);
+  carveHole(gr->hexahedra, distance, kdtree);
+  carveHole(gr->prisms, distance, kdtree);
+  carveHole(gr->pyramids, distance, kdtree);
+
+  delete kdtree;
+  annDeallocPts(kdnodes);
+
+  // TODO: remove any interior elements left inside the carved surface
+  // (could shoot a line from each element's barycenter and count
+  // intersections o see who's inside)
+
+  // generate discrete boundary mesh of the carved hole
+  GFace *gf = m->faceByTag(num);
+  if(!gf) return;
+  std::set<MFace, Less_Face> faces;
+  std::list<GFace*> f = gr->faces();
+  for(std::list<GFace*>::iterator it = f.begin(); it != f.end(); it++){
+    addFaces((*it)->triangles, faces);
+    addFaces((*it)->quadrangles, faces);
+  }
+  addFaces(gr->tetrahedra, faces);
+  addFaces(gr->hexahedra, faces);
+  addFaces(gr->prisms, faces);
+  addFaces(gr->pyramids, faces);
+
+  std::set<MVertex*> verts;
+  for(std::set<MFace, Less_Face>::iterator it = faces.begin(); it != faces.end(); it++){
+    for(int i = 0; i < it->getNumVertices(); i++){
+      it->getVertex(i)->setEntity(gf);
+      verts.insert(it->getVertex(i));
+    }
+    if(it->getNumVertices() == 3)
+      gf->triangles.push_back(new MTriangle(it->getVertex(0), it->getVertex(1),
+					    it->getVertex(2)));
+    else if(it->getNumVertices() == 4)
+      gf->quadrangles.push_back(new MQuadrangle(it->getVertex(0), it->getVertex(1),
+						it->getVertex(2), it->getVertex(3)));
+  }
+}
+
+#endif
diff --git a/Mesh/meshGRegionExtruded.cpp b/Mesh/meshGRegionExtruded.cpp
index 27ee65851d49fdb3c2c1615f6f2a424afad8f0f5..b2e0933c9030819b68f25ea69dad1ad793f94fca 100644
--- a/Mesh/meshGRegionExtruded.cpp
+++ b/Mesh/meshGRegionExtruded.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGRegionExtruded.cpp,v 1.18 2007-07-31 20:07:38 geuzaine Exp $
+// $Id: meshGRegionExtruded.cpp,v 1.19 2007-07-31 22:09:11 geuzaine Exp $
 //
 // Copyright (C) 1997-2007 C. Geuzaine, J.-F. Remacle
 //
@@ -111,7 +111,10 @@ int getExtrudedVertices(MElement *ele, ExtrudeParams *ep, int j, int k,
   for(int p = 0; p < 2 * n; p++){
     MVertex tmp(x[p], y[p], z[p], 0, -1);
     itp = pos.find(&tmp);
-    if(itp == pos.end()) itp = linearFind(pos, &tmp);
+    if(itp == pos.end()){ // FIXME: workaround
+      Msg(INFO, "Linear search for (%.16g, %.16g, %.16g)", tmp.x(), tmp.y(), tmp.z());
+      itp = tmp.linearSearch(pos);
+    }
     if(itp == pos.end())
       Msg(GERROR, "Could not find extruded vertex (%.16g, %.16g, %.16g)",
 	  tmp.x(), tmp.y(), tmp.z());
@@ -187,131 +190,6 @@ void insertAllVertices(GRegion *gr,
   }
 }
 
-#if defined(HAVE_ANN_)
-
-#include "ANN/ANN.h"
-
-template <class T>
-void carveHole(std::vector<T*> &elements, double distance, ANNkd_tree *kdtree)
-{
-  // delete all elements that have at least one vertex closer than
-  // 'distance' from the carving surface vertices
-  ANNidxArray index = new ANNidx[1];
-  ANNdistArray dist = new ANNdist[1];
-  std::vector<T*> temp;
-  for(unsigned int i = 0; i < elements.size(); i++){
-    for(int j = 0; j < elements[i]->getNumVertices(); j++){
-      MVertex *v = elements[i]->getVertex(j);
-      double xyz[3] = {v->x(), v->y(), v->z()};
-      kdtree->annkSearch(xyz, 1, index, dist);
-      double d = sqrt(dist[0]);
-      if(d < distance){
-	delete elements[i];
-	break;
-      }
-      else if(j == elements[i]->getNumVertices() - 1){
-        temp.push_back(elements[i]);
-      }
-    }
-  }
-  elements = temp;
-  delete [] index;
-  delete [] dist;
-}
-
-#endif
-
-template <class T>
-void addFaces(std::vector<T*> &elements, std::set<MFace, Less_Face> &faces)
-{
-  for(unsigned int i = 0; i < elements.size(); i++){
-    for(int j = 0; j < elements[i]->getNumFaces(); j++){
-      MFace f = elements[i]->getFace(j);
-      std::set<MFace, Less_Face>::iterator it = faces.find(f);
-      if(it == faces.end())
-	faces.insert(f);
-      else
-	faces.erase(it);
-    }
-  }
-}
-
-void carveHole(GRegion *gr, int num, double distance, std::vector<int> &surfaces)
-{
-#if !defined(HAVE_ANN_)
-  Msg(GERROR, "Gmsh must be compiled with ANN support to carve holes in extruded meshes");
-#else
-  Msg(INFO, "Carving hole %d from surface %d at distance %g", num, surfaces[0], distance);
-  GModel *m = gr->model();
-
-  // add all points from carving surfaces into kdtree
-  int numnodes = 0;
-  for(unsigned int i = 0; i < surfaces.size(); i++){
-    GFace *gf = m->faceByTag(surfaces[i]);
-    if(!gf){
-      Msg(GERROR, "Unknown carving surface %d", surfaces[i]);
-      return;
-    }
-    numnodes += gf->mesh_vertices.size();
-  }
-
-  ANNpointArray kdnodes = annAllocPts(numnodes, 4);
-  int k = 0;
-  for(unsigned int i = 0; i < surfaces.size(); i++){
-    GFace *gf = m->faceByTag(surfaces[i]);
-    for(unsigned int j = 0; j < gf->mesh_vertices.size(); j++){
-      kdnodes[k][0] = gf->mesh_vertices[j]->x();
-      kdnodes[k][1] = gf->mesh_vertices[j]->y();
-      kdnodes[k][2] = gf->mesh_vertices[j]->z();
-      k++;
-    }
-  }
-  ANNkd_tree *kdtree = new ANNkd_tree(kdnodes, numnodes, 3);
-
-  // remove the volume elements that are within 'distance' of the
-  // carved surface
-  carveHole(gr->tetrahedra, distance, kdtree);
-  carveHole(gr->hexahedra, distance, kdtree);
-  carveHole(gr->prisms, distance, kdtree);
-  carveHole(gr->pyramids, distance, kdtree);
-
-  delete kdtree;
-  annDeallocPts(kdnodes);
-
-  // TODO: remove any interior elements left inside the carved surface
-  // (could shoot a line from each element's barycenter and count
-  // intersections o see who's inside)
-
-  // generate discrete boundary mesh of the carved hole
-  GFace *gf = m->faceByTag(num);
-  if(!gf) return;
-  std::set<MFace, Less_Face> faces;
-  std::list<GFace*> f = gr->faces();
-  for(std::list<GFace*>::iterator it = f.begin(); it != f.end(); it++){
-    addFaces((*it)->triangles, faces);
-    addFaces((*it)->quadrangles, faces);
-  }
-  addFaces(gr->tetrahedra, faces);
-  addFaces(gr->hexahedra, faces);
-  addFaces(gr->prisms, faces);
-  addFaces(gr->pyramids, faces);
-
-  std::set<MVertex*> verts;
-  for(std::set<MFace, Less_Face>::iterator it = faces.begin(); it != faces.end(); it++){
-    for(int i = 0; i < it->getNumVertices(); i++){
-      it->getVertex(i)->setEntity(gf);
-      verts.insert(it->getVertex(i));
-    }
-    if(it->getNumVertices() == 3)
-      gf->triangles.push_back(new MTriangle(it->getVertex(0), it->getVertex(1),
-					    it->getVertex(2)));
-    else if(it->getNumVertices() == 4)
-      gf->quadrangles.push_back(new MQuadrangle(it->getVertex(0), it->getVertex(1),
-						it->getVertex(2), it->getVertex(3)));
-  }
-#endif
-}
-
 void meshGRegionExtruded::operator() (GRegion *gr) 
 {  
   if(gr->geomType() == GEntity::DiscreteVolume) return;
@@ -320,7 +198,6 @@ void meshGRegionExtruded::operator() (GRegion *gr)
 
   if(!ep || !ep->mesh.ExtrudeMesh || ep->geo.Mode != EXTRUDED_ENTITY) return;
 
-  // Send a messsage to the GMSH environment
   Msg(STATUS2, "Meshing volume %d (extruded)", gr->tag());
 
   // destroy the mesh if it exists