diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp
index 90e588a0921b5253150a75cd0f6f47fa45c6dd4c..02154eab05a8eda39828a6ebf02e754d45e19ab9 100644
--- a/Fltk/GUI.cpp
+++ b/Fltk/GUI.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI.cpp,v 1.662 2008-03-18 08:41:21 remacle Exp $
+// $Id: GUI.cpp,v 1.663 2008-03-18 19:30:13 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -72,7 +72,6 @@ Fl_Menu_Item m_menubar_table[] = {
   {"&Tools", 0, 0, 0, FL_SUBMENU},
     {"&Options...",      FL_CTRL+FL_SHIFT+'n', (Fl_Callback *)options_cb, 0},
     {"Pl&ugins...",      FL_CTRL+FL_SHIFT+'u', (Fl_Callback *)view_plugin_cb, (void*)(-1)},
-    {"&Fields...",      FL_CTRL+FL_SHIFT+'f', (Fl_Callback *)view_field_cb, (void*)(-1)},
     {"&Visibility",      FL_CTRL+FL_SHIFT+'v', (Fl_Callback *)visibility_cb, 0},
     {"&Clipping Planes", FL_CTRL+FL_SHIFT+'c', (Fl_Callback *)clip_cb, 0},
     {"&Manipulator",     FL_CTRL+FL_SHIFT+'m', (Fl_Callback *)manip_cb, 0, FL_MENU_DIVIDER},
@@ -114,7 +113,6 @@ Fl_Menu_Item m_sys_menubar_table[] = {
   {"Tools", 0, 0, 0, FL_SUBMENU},
     {"Options...",      FL_META+FL_SHIFT+'n', (Fl_Callback *)options_cb, 0},
     {"Plugins...",      FL_META+FL_SHIFT+'u', (Fl_Callback *)view_plugin_cb, (void*)(-1)},
-    {"Fields...",      FL_META+FL_SHIFT+'f', (Fl_Callback *)view_field_cb, (void*)(-1)},
     {"Visibility",      FL_META+FL_SHIFT+'v', (Fl_Callback *)visibility_cb, 0},
     {"Clipping Planes", FL_META+FL_SHIFT+'c', (Fl_Callback *)clip_cb, 0},
     {"Manipulator",     FL_META+FL_SHIFT+'m', (Fl_Callback *)manip_cb, 0, FL_MENU_DIVIDER},
@@ -312,6 +310,7 @@ Context_Item menu_mesh[] = {
 };  
     Context_Item menu_mesh_define[] = {
       {"1Mesh>Define", NULL} ,
+      {"Fields",  (Fl_Callback *)view_field_cb, (void*)(-1) },
       {"Characteristic length", (Fl_Callback *)mesh_define_length_cb  } ,
       {"Recombine",   (Fl_Callback *)mesh_define_recombine_cb  } ,
       {"Transfinite", (Fl_Callback *)mesh_define_transfinite_cb  } , 
diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index 0ce655c6ab09d631abf3ea247ea3c0f79ccc6833..a3c97196422267afb7a69cbd8e8dbce8e36aed26 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -1,4 +1,4 @@
-// $Id: GModel.cpp,v 1.71 2008-03-18 08:41:21 remacle Exp $
+// $Id: GModel.cpp,v 1.72 2008-03-18 19:30:13 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -99,8 +99,8 @@ void GModel::destroy()
 
   MVertex::resetGlobalNumber();
   MElement::resetGlobalNumber();
-  fields.reset();
 #if !defined(HAVE_GMSH_EMBEDDED)
+  fields.reset();
   gmshSurface::reset();
   BGMReset();
 #endif
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 022a4e36342b3fc9fb6ecdb7ea479dbb7ec5cb29..9958c592725913e7b0936823d75c9d2d336faf88 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -28,7 +28,9 @@
 #include "GFace.h"
 #include "GRegion.h"
 #include "SBoundingBox3d.h"
+#if !defined(HAVE_GMSH_EMBEDDED)
 #include "Field.h"
+#endif
 
 class GEO_Internals;
 class OCC_Internals;
@@ -38,7 +40,6 @@ class smooth_normals;
 class GModel
 {
  private:
-	std::set<Field*>mesh_size_fields;
   // Vertex cache to speed-up direct access by vertex number (used for
   // post-processing I/O)
   std::vector<MVertex*> _vertexVectorCache;
@@ -248,8 +249,10 @@ class GModel
   // Med interface ("Modele d'Echange de Donnees")
   int writeMED(const std::string &name);
 
-	// Characteristic Lengths fields
-	FieldManager fields;
+#if !defined(HAVE_GMSH_EMBEDDED)
+  // Characteristic Lengths fields
+  FieldManager fields;
+#endif
 };
 
 #endif
diff --git a/Geo/GModelIO_Mesh.cpp b/Geo/GModelIO_Mesh.cpp
index 5bedf5f37e173f16ded63f1548432edea5a79e5b..f6db22a9fbdae7f70d9a8c6babd05069be1a2503 100644
--- a/Geo/GModelIO_Mesh.cpp
+++ b/Geo/GModelIO_Mesh.cpp
@@ -1,4 +1,4 @@
-// $Id: GModelIO_Mesh.cpp,v 1.42 2008-03-11 22:51:08 geuzaine Exp $
+// $Id: GModelIO_Mesh.cpp,v 1.43 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -261,7 +261,7 @@ int GModel::readMSH(const std::string &name)
 
   double version = 1.0;
   bool binary = false, swap = false;
-  char str[256];
+  char str[256] = "XXX";
   std::map<int, std::vector<MVertex*> > points;
   std::map<int, std::vector<MElement*> > elements[7];
   std::map<int, std::map<int, std::string> > physicals[4];
@@ -273,11 +273,11 @@ int GModel::readMSH(const std::string &name)
  
   while(1) {
 
-    do {
+    while(str[0] != '$'){
       if(!fgets(str, sizeof(str), fp) || feof(fp))
         break;
-    } while(str[0] != '$');
-
+    }
+    
     if(feof(fp))
       break;
 
@@ -467,7 +467,6 @@ int GModel::readMSH(const std::string &name)
       if(!fgets(str, sizeof(str), fp) || feof(fp))
 	Msg(GERROR, "Prematured end of mesh file");
     } while(str[0] != '$');
-
   }
 
   // store the elements in their associated elementary entity. If the
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index ce7f8fecb952b8d5ca205a57ff97a4b05fdb47b7..248f98f1895baee7386309bc969a6dab7251a759 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -1,4 +1,4 @@
-// $Id: MElement.cpp,v 1.58 2008-02-22 07:19:07 geuzaine Exp $
+// $Id: MElement.cpp,v 1.59 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -132,19 +132,6 @@ double MTetrahedron::etaShapeMeasure()
 #endif
 }
 
-void MTetrahedron::getMat(double mat[3][3])
-{
-  mat[0][0] = _v[1]->x() - _v[0]->x();
-  mat[0][1] = _v[2]->x() - _v[0]->x();
-  mat[0][2] = _v[3]->x() - _v[0]->x();
-  mat[1][0] = _v[1]->y() - _v[0]->y();
-  mat[1][1] = _v[2]->y() - _v[0]->y();
-  mat[1][2] = _v[3]->y() - _v[0]->y();
-  mat[2][0] = _v[1]->z() - _v[0]->z();
-  mat[2][1] = _v[2]->z() - _v[0]->z();
-  mat[2][2] = _v[3]->z() - _v[0]->z();
-}
-
 double MTetrahedron::getVolume()
 { 
   double mat[3][3];
@@ -169,31 +156,6 @@ bool MTetrahedron::invertmapping(double *p, double *uvw, double tol)
   return false;
 }
 
-void MTetrahedron::circumcenter(double X[4], double Y[4], double Z[4], double *res)
-{
-  double mat[3][3], b[3], dum;    
-  b[0] = X[1] * X[1] - X[0] * X[0] +
-    Y[1] * Y[1] - Y[0] * Y[0] + Z[1] * Z[1] - Z[0] * Z[0];
-  b[1] = X[2] * X[2] - X[1] * X[1] +
-    Y[2] * Y[2] - Y[1] * Y[1] + Z[2] * Z[2] - Z[1] * Z[1];
-  b[2] = X[3] * X[3] - X[2] * X[2] +
-    Y[3] * Y[3] - Y[2] * Y[2] + Z[3] * Z[3] - Z[2] * Z[2];
-  for(int i = 0; i < 3; i++)
-    b[i] *= 0.5;
-  mat[0][0] = X[1] - X[0];
-  mat[0][1] = Y[1] - Y[0];
-  mat[0][2] = Z[1] - Z[0];
-  mat[1][0] = X[2] - X[1];
-  mat[1][1] = Y[2] - Y[1];
-  mat[1][2] = Z[2] - Z[1];
-  mat[2][0] = X[3] - X[2];
-  mat[2][1] = Y[3] - Y[2];
-  mat[2][2] = Z[3] - Z[2];
-  if(!sys3x3(mat, b, res, &dum)) {
-    res[0] = res[1] = res[2] = 10.0e10;
-  }
-}
-
 int MHexahedron::getVolumeSign()
 { 
   double mat[3][3];
@@ -487,161 +449,6 @@ void MElement::writeBDF(FILE *fp, int format, int elementary)
   }
 }
 
-bool MTriangle::invertmappingXY(double *p, double *uv, double tol)
-{
-  double mat[2][2];
-  double b[2];
-  getMat(mat);
-  b[0] = p[0] - getVertex(0)->x();
-  b[1] = p[1] - getVertex(0)->y();
-  sys2x2(mat, b, uv);
-
-  if(uv[0] >= -tol && 
-     uv[1] >= -tol && 
-     uv[0] <= 1. + tol && 
-     uv[1] <= 1. + tol && 
-     1. - uv[0] - uv[1] > -tol) {
-    return true;
-  }
-  return false; 
-}
-
-bool MTriangle::invertmappingUV(GFace* gf, double *p, double *uv, double tol)
-{
-  double mat[2][2];
-  double b[2];
-  double u0, v0, u1, v1, u2, v2;
-
-  parametricCoordinates(getVertex(0), gf, u0, v0);
-  parametricCoordinates(getVertex(1), gf, u1, v1);
-  parametricCoordinates(getVertex(2), gf, u2, v2);
-  
-  mat[0][0] = u1 - u0;
-  mat[0][1] = u2 - u0;
-  mat[1][0] = v1 - v0;
-  mat[1][1] = v2 - v0;
-
-  b[0] = p[0] - u0;
-  b[1] = p[1] - v0;
-  sys2x2(mat, b, uv);
-
-  if(uv[0] >= -tol && 
-     uv[1] >= -tol && 
-     uv[0] <= 1. + tol && 
-     uv[1] <= 1. + tol && 
-     1. - uv[0] - uv[1] > -tol) {
-    return true;
-  }
-  return false; 
-}
-
-double MTriangle::getSurfaceUV(GFace *gf)
-{
-  double u3, v3, u1, v1, u2, v2;
-
-  parametricCoordinates(getVertex(0), gf, u1, v1);
-  parametricCoordinates(getVertex(1), gf, u2, v2);
-  parametricCoordinates(getVertex(2), gf, u3, v3);
-
-  const double vv1 [2] = {u2 - u1, v2 - v1};
-  const double vv2 [2] = {u3 - u1, v3 - v1};
-
-  double s = vv1[0] * vv2[1] - vv1[1] * vv2[0]; 
-  return s * 0.5;
-}
-
-double MTriangle::getSurfaceXY() const
-{
-  const double x1 = _v[0]->x();
-  const double x2 = _v[1]->x();
-  const double x3 = _v[2]->x();
-  const double y1 = _v[0]->y();
-  const double y2 = _v[1]->y();
-  const double y3 = _v[2]->y();
-
-  const double v1 [2] = {x2 - x1, y2 - y1};
-  const double v2 [2] = {x3 - x1, y3 - y1};
-
-  double s = v1[0] * v2[1] - v1[1] * v2[0]; 
-  return s * 0.5;
-}
-
-void MTriangle::circumcenterXYZ(double *p1, double *p2, double *p3, 
-				double *res, double *uv)
-{
-  double v1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
-  double v2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
-  double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
-  double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
-  double vz[3]; prodve(vx, vy, vz); prodve(vz, vx, vy);
-  norme(vx); norme(vy); norme(vz);
-  double p1P[2] = {0.0, 0.0};
-  double p2P[2]; prosca(v1, vx, &p2P[0]); prosca(v1, vy, &p2P[1]);
-  double p3P[2]; prosca(v2, vx, &p3P[0]); prosca(v2, vy, &p3P[1]);
-  double resP[2];
-
-  circumcenterXY(p1P, p2P, p3P,resP);
-
-  if(uv){
-    double mat[2][2] = {{p2P[0] - p1P[0], p3P[0] - p1P[0]},
-			{p2P[1] - p1P[1], p3P[1] - p1P[1]}};
-    double rhs[2] = {resP[0] - p1P[0], resP[1] - p1P[1]};
-    sys2x2(mat, rhs, uv);
-  }
-  
-  res[0] = p1[0] + resP[0] * vx[0] + resP[1] * vy[0];
-  res[1] = p1[1] + resP[0] * vx[1] + resP[1] * vy[1];
-  res[2] = p1[2] + resP[0] * vx[2] + resP[1] * vy[2];
-}
-
-void MTriangle::circumcenterXY(double *p1, double *p2, double *p3, double *res)
-{
-  double d, a1, a2, a3;
-
-  const double x1 = p1[0];
-  const double x2 = p2[0];
-  const double x3 = p3[0];
-  const double y1 = p1[1];
-  const double y2 = p2[1];
-  const double y3 = p3[1];
-
-  d = 2. * (double)(y1 * (x2 - x3) + y2 * (x3 - x1) + y3 * (x1 - x2));
-  if(d == 0.0) {
-    Msg(WARNING, "Colinear points in circum circle computation");
-    res[0] = res[1] = -99999.;
-    return ;
-  }
-
-  a1 = x1 * x1 + y1 * y1;
-  a2 = x2 * x2 + y2 * y2;
-  a3 = x3 * x3 + y3 * y3;
-  res[0] = (double)((a1 * (y3 - y2) + a2 * (y1 - y3) + a3 * (y2 - y1)) / d);
-  res[1] = (double)((a1 * (x2 - x3) + a2 * (x3 - x1) + a3 * (x1 - x2)) / d);
-}
-
-void MTriangle::circumcenterUV(GFace *gf, double *res)
-{
-  double u3, v3, u1, v1, u2, v2;
-
-  parametricCoordinates(getVertex(0), gf, u1, v1);
-  parametricCoordinates(getVertex(1), gf, u2, v2);
-  parametricCoordinates(getVertex(2), gf, u3, v3);
-
-  double p1[2] = {u1, v1};
-  double p2[2] = {u2, v2};
-  double p3[2] = {u3, v3};
-
-  circumcenterXY(p1, p2, p3, res);
-}
-
-void MTriangle::circumcenterXY(double *res) const
-{
-  double p1[2] = {_v[0]->x(), _v[0]->y()};
-  double p2[2] = {_v[1]->x(), _v[1]->y()};
-  double p3[2] = {_v[2]->x(), _v[2]->y()};
-  circumcenterXY(p1, p2, p3, res);
-}
-
 void MTriangle::jac(int ord, MVertex *vs[], double uu, double vv, double j[2][3])
 {
 #if defined(HAVE_GMSH_EMBEDDED)
@@ -732,7 +539,8 @@ void MTriangleN::jac(double uu, double vv , double j[2][3])
   MTriangle::jac(_order, &(*(_vs.begin())), uu, vv, j);
 }
 
-void MTriangleN::pnt(double uu, double vv, SPoint3 &p){
+void MTriangleN::pnt(double uu, double vv, SPoint3 &p)
+{
   MTriangle::pnt(_order, &(*(_vs.begin())), uu, vv, p);
 }
 
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 04a55d28bc5ce946960d4d71e3c2df8755430dfb..27de345dcf0c027b00902857d33d7a3505f2f354 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -318,23 +318,14 @@ class MTriangle : public MElement {
   }
   ~MTriangle(){}
   virtual int getDim(){ return 2; }
-  virtual void getMat(double mat[2][2])
+  void getMat(double mat[2][2])
   {
     mat[0][0] = _v[1]->x() - _v[0]->x();
     mat[0][1] = _v[2]->x() - _v[0]->x();
     mat[1][0] = _v[1]->y() - _v[0]->y();
     mat[1][1] = _v[2]->y() - _v[0]->y();
   }
-  void circumcenterXY(double *res) const; 
   virtual double gammaShapeMeasure();
-  void circumcenterUV(GFace*,double *res); 
-  static void circumcenterXYZ(double *p1, double *p2, double *p3, double *res,
-			      double *uv = 0);
-  static void circumcenterXY(double *p1, double *p2, double *p3, double *res);
-  double getSurfaceXY() const;
-  double getSurfaceUV(GFace*);
-  bool invertmappingXY(double *p, double *uv, double tol = 1.e-8);
-  bool invertmappingUV(GFace*,double *p, double *uv, double tol = 1.e-8);
   virtual int getNumVertices(){ return 3; }
   virtual MVertex *getVertex(int num){ return _v[num]; }
   virtual MVertex *getOtherVertex(MVertex *v1, MVertex *v2)
@@ -753,21 +744,24 @@ class MTetrahedron : public MElement {
   {
     MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
   }
-  virtual void  getMat(double mat[3][3]);
+  void  getMat(double mat[3][3])
+  {
+    mat[0][0] = _v[1]->x() - _v[0]->x();
+    mat[0][1] = _v[2]->x() - _v[0]->x();
+    mat[0][2] = _v[3]->x() - _v[0]->x();
+    mat[1][0] = _v[1]->y() - _v[0]->y();
+    mat[1][1] = _v[2]->y() - _v[0]->y();
+    mat[1][2] = _v[3]->y() - _v[0]->y();
+    mat[2][0] = _v[1]->z() - _v[0]->z();
+    mat[2][1] = _v[2]->z() - _v[0]->z();
+    mat[2][2] = _v[3]->z() - _v[0]->z();
+  }
   virtual double getVolume();
   virtual int getVolumeSign(){ return (getVolume() >= 0) ? 1 : -1; }
   virtual double gammaShapeMeasure();
   virtual double etaShapeMeasure();
   // returns true if the point lies inside the tet
   bool invertmapping(double *p, double *uvw, double tol = 1.e-8);
-  static void circumcenter(double X[4],double Y[4],double Z[4],double *res);
-  void circumcenter(double *res)
-  {
-    double X[4] = {_v[0]->x(), _v[1]->x(), _v[2]->x(), _v[3]->x()};
-    double Y[4] = {_v[0]->y(), _v[1]->y(), _v[2]->y(), _v[3]->y()};
-    double Z[4] = {_v[0]->z(), _v[1]->z(), _v[2]->z(), _v[3]->z()};
-    MTetrahedron::circumcenter(X, Y, Z, res); 
-  }
 };
 
 class MTetrahedron10 : public MTetrahedron {
diff --git a/Mesh/meshGFace.cpp b/Mesh/meshGFace.cpp
index 30bdabc60dacd32b7955e1e25e233eb5dd04e0e7..9edb7e115fcac014a5f1e30af9502ef7770ae446 100644
--- a/Mesh/meshGFace.cpp
+++ b/Mesh/meshGFace.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFace.cpp,v 1.125 2008-03-12 14:52:58 geuzaine Exp $
+// $Id: meshGFace.cpp,v 1.126 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -41,10 +41,10 @@
 
 extern Context_T CTX;
 
-void fourthPoint (double *p1, double *p2, double *p3, double *p4)
+void fourthPoint(double *p1, double *p2, double *p3, double *p4)
 {
   double c[3];
-  MTriangle::circumcenterXYZ(p1, p2, p3, c);
+  circumCenterXYZ(p1, p2, p3, c);
   double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
   double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
   double vz[3]; prodve(vx, vy, vz);
diff --git a/Mesh/meshGFaceDelaunayInsertion.cpp b/Mesh/meshGFaceDelaunayInsertion.cpp
index ae7b68ebe57cc5e401215ea1d98edc4ae50c6863..a9297656cbfdb79bc241b7e3f3089ecc5a1528f6 100644
--- a/Mesh/meshGFaceDelaunayInsertion.cpp
+++ b/Mesh/meshGFaceDelaunayInsertion.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGFaceDelaunayInsertion.cpp,v 1.13 2008-03-12 14:52:58 geuzaine Exp $
+// $Id: meshGFaceDelaunayInsertion.cpp,v 1.14 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -31,6 +31,58 @@
 #include <map>
 #include <algorithm>
 
+void circumCenterXY(double *p1, double *p2, double *p3, double *res)
+{
+  double d, a1, a2, a3;
+
+  const double x1 = p1[0];
+  const double x2 = p2[0];
+  const double x3 = p3[0];
+  const double y1 = p1[1];
+  const double y2 = p2[1];
+  const double y3 = p3[1];
+
+  d = 2. * (double)(y1 * (x2 - x3) + y2 * (x3 - x1) + y3 * (x1 - x2));
+  if(d == 0.0) {
+    Msg(WARNING, "Colinear points in circum circle computation");
+    res[0] = res[1] = -99999.;
+    return ;
+  }
+
+  a1 = x1 * x1 + y1 * y1;
+  a2 = x2 * x2 + y2 * y2;
+  a3 = x3 * x3 + y3 * y3;
+  res[0] = (double)((a1 * (y3 - y2) + a2 * (y1 - y3) + a3 * (y2 - y1)) / d);
+  res[1] = (double)((a1 * (x2 - x3) + a2 * (x3 - x1) + a3 * (x1 - x2)) / d);
+}
+
+void circumCenterXYZ(double *p1, double *p2, double *p3, double *res, double *uv)
+{
+  double v1[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
+  double v2[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
+  double vx[3] = {p2[0] - p1[0], p2[1] - p1[1], p2[2] - p1[2]};
+  double vy[3] = {p3[0] - p1[0], p3[1] - p1[1], p3[2] - p1[2]};
+  double vz[3]; prodve(vx, vy, vz); prodve(vz, vx, vy);
+  norme(vx); norme(vy); norme(vz);
+  double p1P[2] = {0.0, 0.0};
+  double p2P[2]; prosca(v1, vx, &p2P[0]); prosca(v1, vy, &p2P[1]);
+  double p3P[2]; prosca(v2, vx, &p3P[0]); prosca(v2, vy, &p3P[1]);
+  double resP[2];
+
+  circumCenterXY(p1P, p2P, p3P,resP);
+
+  if(uv){
+    double mat[2][2] = {{p2P[0] - p1P[0], p3P[0] - p1P[0]},
+			{p2P[1] - p1P[1], p3P[1] - p1P[1]}};
+    double rhs[2] = {resP[0] - p1P[0], resP[1] - p1P[1]};
+    sys2x2(mat, rhs, uv);
+  }
+  
+  res[0] = p1[0] + resP[0] * vx[0] + resP[1] * vy[0];
+  res[1] = p1[1] + resP[0] * vx[1] + resP[1] * vy[1];
+  res[2] = p1[2] + resP[0] * vx[2] + resP[1] * vy[2];
+}
+
 bool circumCenterMetricInTriangle(MTriangle *base, 
 				  const double *metric,
 				  const std::vector<double> &Us,
@@ -147,7 +199,7 @@ MTri3::MTri3(MTriangle *t, double lc) : deleted(false), base(t)
   double pb[3] = {base->getVertex(1)->x(), base->getVertex(1)->y(), base->getVertex(1)->z()};
   double pc[3] = {base->getVertex(2)->x(), base->getVertex(2)->y(), base->getVertex(2)->z()};
   double center[3];
-  base->circumcenterXYZ(pa, pb, pc, center);
+  circumCenterXYZ(pa, pb, pc, center);
   const double dx = base->getVertex(0)->x() - center[0];
   const double dy = base->getVertex(0)->y() - center[1];
   const double dz = base->getVertex(0)->z() - center[2];
@@ -273,13 +325,13 @@ bool circUV(MTriangle *t, std::vector<double> & Us, std::vector<double> &Vs,
   double u1 [3] = {Us[t->getVertex(0)->getNum()], Vs[t->getVertex(0)->getNum()], 0};
   double u2 [3] = {Us[t->getVertex(1)->getNum()], Vs[t->getVertex(1)->getNum()], 0};
   double u3 [3] = {Us[t->getVertex(2)->getNum()], Vs[t->getVertex(2)->getNum()], 0};
-  t->circumcenterXY(u1, u2, u3, res);
+  circumCenterXY(u1, u2, u3, res);
   return true;
   double p1 [3] = {t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z()};
   double p2 [3] = {t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z()};
   double p3 [3] = {t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z()};
   double resxy[3], uv[2];
-  t->circumcenterXYZ(p1, p2, p3, resxy,uv);
+  circumCenterXYZ(p1, p2, p3, resxy,uv);
   return true;
 }
 
diff --git a/Mesh/meshGFaceDelaunayInsertion.h b/Mesh/meshGFaceDelaunayInsertion.h
index 377e0a08e96f312f64f0ad3e4324a7c49ba49ad5..ab9160c99682f6b279ee4c11d9c6561329e17eb8 100644
--- a/Mesh/meshGFaceDelaunayInsertion.h
+++ b/Mesh/meshGFaceDelaunayInsertion.h
@@ -35,6 +35,7 @@ int inCircumCircleAniso(GFace *gf, double *p1, double *p2, double *p3, double *p
 			double *metric);
 int inCircumCircleAniso(GFace *gf, MTriangle *base, const double *uv, const double *metric,
 			const std::vector<double> &Us, const std::vector<double> &Vs); 
+void circumCenterXYZ(double *p1, double *p2, double *p3, double *res, double *uv=0);
 void circumCenterMetric(MTriangle *base, 
 			const double *metric,
 			const std::vector<double> &Us,
@@ -74,8 +75,6 @@ class MTri3
   {
     return inCircumCircle(v->x(), v->y());
   }
-  double getSurfaceXY () const { return base -> getSurfaceXY(); }
-  double getSurfaceUV (GFace* gf) const { return base -> getSurfaceUV(gf); }
   inline void setDeleted (bool d){ deleted = d; }
   inline bool assertNeigh() const 
   {
diff --git a/Mesh/meshGRegionDelaunayInsertion.cpp b/Mesh/meshGRegionDelaunayInsertion.cpp
index a6f8af177a4c1f936b3adff5787abe632fdc7ba3..82df613ff9003101164d1df4a0d8925d4e53d89a 100644
--- a/Mesh/meshGRegionDelaunayInsertion.cpp
+++ b/Mesh/meshGRegionDelaunayInsertion.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGRegionDelaunayInsertion.cpp,v 1.40 2008-03-12 08:36:49 remacle Exp $
+// $Id: meshGRegionDelaunayInsertion.cpp,v 1.41 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -809,7 +809,7 @@ void insertVerticesInRegion (GRegion *gr)
 	    vSizes.size(), worst->getRadius());
       if(worst->getRadius() < 1) break;
       double center[3];
-      worst->tet()->circumcenter(center);
+      worst->circumcenter(center);
       double uvw[3];
       bool inside = worst->tet()->invertmapping(center, uvw);
       if(inside){
diff --git a/Mesh/meshGRegionDelaunayInsertion.h b/Mesh/meshGRegionDelaunayInsertion.h
index c4971ec0249ec8c69c5d27944586bf1114c701f4..ff09da3593f4c0c4eaa4ad31f8c99592fe518349 100644
--- a/Mesh/meshGRegionDelaunayInsertion.h
+++ b/Mesh/meshGRegionDelaunayInsertion.h
@@ -25,6 +25,7 @@
 #include <map>
 #include <stack>
 #include "MElement.h"
+#include "Numeric.h"
 #include "BackgroundMesh.h"
 #include "qualityMeasures.h"
 
@@ -86,18 +87,47 @@ class MTet4
     double vol;
     circum_radius = qmTet(t, qm, &vol);
   }
-
+  void circumcenter(double *res)
+  {
+    MVertex *v0 = base->getVertex(0);
+    MVertex *v1 = base->getVertex(1);
+    MVertex *v2 = base->getVertex(2);
+    MVertex *v3 = base->getVertex(3);
+    double X[4] = {v0->x(), v1->x(), v2->x(), v3->x()};
+    double Y[4] = {v0->y(), v1->y(), v2->y(), v3->y()};
+    double Z[4] = {v0->z(), v1->z(), v2->z(), v3->z()};
+    double b[3], mat[3][3], dum;    
+    b[0] = X[1] * X[1] - X[0] * X[0] +
+      Y[1] * Y[1] - Y[0] * Y[0] + Z[1] * Z[1] - Z[0] * Z[0];
+    b[1] = X[2] * X[2] - X[1] * X[1] +
+      Y[2] * Y[2] - Y[1] * Y[1] + Z[2] * Z[2] - Z[1] * Z[1];
+    b[2] = X[3] * X[3] - X[2] * X[2] +
+      Y[3] * Y[3] - Y[2] * Y[2] + Z[3] * Z[3] - Z[2] * Z[2];
+    for(int i = 0; i < 3; i++)
+      b[i] *= 0.5;
+    mat[0][0] = X[1] - X[0];
+    mat[0][1] = Y[1] - Y[0];
+    mat[0][2] = Z[1] - Z[0];
+    mat[1][0] = X[2] - X[1];
+    mat[1][1] = Y[2] - Y[1];
+    mat[1][2] = Z[2] - Z[1];
+    mat[2][0] = X[3] - X[2];
+    mat[2][1] = Y[3] - Y[2];
+    mat[2][2] = Z[3] - Z[2];
+    if(!sys3x3(mat, b, res, &dum)) {
+      res[0] = res[1] = res[2] = 10.0e10;
+    }
+  }
   void setup(MTetrahedron *t, std::vector<double> &sizes, std::vector<double> &sizesBGM)
   {
     base = t;
     neigh[0] = neigh[1] = neigh[2] = neigh[3] = 0;
     double center[3];
-    base->circumcenter(center);
+    circumcenter(center);
     const double dx = base->getVertex(0)->x() - center[0];
     const double dy = base->getVertex(0)->y() - center[1];
     const double dz = base->getVertex(0)->z() - center[2];
-    circum_radius = sqrt ( dx*dx + dy*dy + dz*dz);
-
+    circum_radius = sqrt(dx * dx + dy * dy + dz * dz);
     double lc1 = 0.25*(sizes[base->getVertex(0)->getNum()]+
 		      sizes[base->getVertex(1)->getNum()]+
 		       sizes[base->getVertex(2)->getNum()]+
@@ -107,17 +137,16 @@ class MTet4
 			 sizesBGM[base->getVertex(2)->getNum()]+
 			 sizesBGM[base->getVertex(3)->getNum()]);
     double lc = Extend2dMeshIn3dVolumes() ? std::min(lc1, lcBGM) : lcBGM;
-    
     circum_radius /= lc;
     deleted = false;
   } 
-  inline GRegion *onWhat () const { return gr; }
-  inline void setOnWhat (GRegion *g) { gr = g; }
-  inline bool isDeleted () const { return deleted; }
-  inline void forceRadius (double r){ circum_radius = r; }
-  inline double getRadius () const { return circum_radius; }
-  inline double getQuality () const { return circum_radius; } 
-  inline void setQuality (const double &q){ circum_radius = q; } 
+  inline GRegion *onWhat() const { return gr; }
+  inline void setOnWhat(GRegion *g) { gr = g; }
+  inline bool isDeleted() const { return deleted; }
+  inline void forceRadius(double r){ circum_radius = r; }
+  inline double getRadius() const { return circum_radius; }
+  inline double getQuality() const { return circum_radius; } 
+  inline void setQuality(const double &q){ circum_radius = q; } 
   inline MTetrahedron *tet() const { return base; }
   inline MTetrahedron *&tet() { return base; }
   inline void setNeigh(int iN, MTet4 *n) { neigh[iN] = n; }
@@ -203,14 +232,14 @@ class MTet4Factory
     allSlots = new MTet4[s_alloc];
 #endif
   }
-  ~MTet4Factory () 
+  ~MTet4Factory() 
   {
 #ifdef _GMSH_PRE_ALLOCATE_STRATEGY_
     delete [] allSlots;
 #endif
   }
-  MTet4 * Create (MTetrahedron * t, std::vector<double> &sizes, 
-		  std::vector<double> &sizesBGM)
+  MTet4 *Create(MTetrahedron * t, std::vector<double> &sizes, 
+		std::vector<double> &sizesBGM)
   {
 #ifdef _GMSH_PRE_ALLOCATE_STRATEGY_
     MTet4 *t4 = getAnEmptySlot();
diff --git a/Plugin/Levelset.cpp b/Plugin/Levelset.cpp
index c4f9d726e5c6eb54d19a19cd6c2229acbf01bd6e..4640b95353d9e07fec74e47bf399dcbea4f0dba0 100644
--- a/Plugin/Levelset.cpp
+++ b/Plugin/Levelset.cpp
@@ -1,4 +1,4 @@
-// $Id: Levelset.cpp,v 1.39 2008-02-17 08:48:07 geuzaine Exp $
+// $Id: Levelset.cpp,v 1.40 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -24,40 +24,81 @@
 #include "List.h"
 #include "Numeric.h"
 
-GMSH_LevelsetPlugin::GMSH_LevelsetPlugin()
+static const int exn[13][12][2] = {
+  {{0,0}}, // point
+  {{0,1}}, // line
+  {{}}, // -
+  {{0,1}, {0,2}, {1,2}}, // triangle
+  {{0,1}, {0,3}, {1,2}, {2,3}}, // quad
+  {{}}, // -
+  {{0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3}}, // tetra
+  {{}}, // -
+  {{0,1}, {0,3}, {0,4}, {1,2}, {1,4}, {2,3}, {2,4}, {3,4}}, // pyramid
+  {{0,1}, {0,2}, {0,3}, {1,2}, {1,4}, {2,5}, {3,4}, {3,5}, {4,5}}, // prism
+  {{}}, {{}}, // -
+  {{0,1}, {0,3}, {0,4}, {1,2}, {1,5}, {2,3}, 
+   {2,6}, {3,7}, {4,5}, {4,7}, {5,6}, {6,7}} // hexa
+};
+
+static int numSimplexDec(int numEdges)
 {
-  _invert = 0.;
-  _ref[0] = _ref[1] = _ref[2] = 0.;
-  _valueIndependent = 0; // "moving" levelset
-  _valueView = -1; // use same view for levelset and field data
-  _valueTimeStep = -1; // use same time step in levelset and field data views
-  _recurLevel = 4;
-  _targetError = 0.;
-  _extractVolume = 0; // to create isovolumes (keep all elements < or > levelset)
-  _orientation = GMSH_LevelsetPlugin::NONE;
+  switch(numEdges){
+  case 4: return 2;
+  case 12: return 6;
+  case 9: return 3;
+  case 8: return 2;
+  default: return 1;
+  }
 }
 
-static void affect(double *xpi, double *ypi, double *zpi, double valpi[12][9], int epi[12],
-		   int i,
-		   double *xp, double *yp, double *zp, double valp[12][9], int ep[12],
-		   int j, int nb)
+static void getSimplexDec(int numNodes, int numEdges, int i, 
+			  int &n0, int &n1, int &n2, int &n3,
+			  int &nn, int &ne)
+{
+  static const int qua[2][3] = {{0,1,2}, {0,2,3}};
+  static const int hex[6][4] = {{0,1,3,7}, {0,4,1,7}, {1,4,5,7}, 
+				{1,2,3,7}, {1,6,2,7}, {1,5,6,7}};
+  static const int pri[3][4] = {{0,1,2,4}, {0,2,4,5}, {0,3,4,5}};
+  static const int pyr[2][4] = {{0,1,3,4}, {1,2,3,4}};
+  switch(numEdges){
+  case 4: 
+    n0 = qua[i][0]; n1 = qua[i][1]; n2 = qua[i][2]; nn = 3; ne = 3; 
+    break;
+  case 12:
+    n0 = hex[i][0]; n1 = hex[i][1]; n2 = hex[i][2]; n3 = hex[i][3]; nn = 4; ne = 6;
+    break;
+  case 9:
+    n0 = pri[i][0]; n1 = pri[i][1]; n2 = pri[i][2]; n3 = pri[i][3]; nn = 4; ne = 6;
+    break;
+  case 8:
+    n0 = pri[i][0]; n1 = pri[i][1]; n2 = pri[i][2]; n3 = pri[i][3]; nn = 4; ne = 6;
+    break;
+  default:
+    n0 = 0; n1 = 1; n2 = 2; n3 = 3; nn = numNodes; ne = numEdges;
+    break;
+  }
+}
+
+static void affect(double *xpi, double *ypi, double *zpi,
+		   double valpi[12][9], int epi[12], int i,
+		   double *xp, double *yp, double *zp,
+		   double valp[12][9], int ep[12], int j, int nb)
 {
   xpi[i] = xp[j];
   ypi[i] = yp[j];
   zpi[i] = zp[j];
-  for(int k = 0; k < nb; k++)
-    valpi[i][k] = valp[j][k];
+  for(int k = 0; k < nb; k++) valpi[i][k] = valp[j][k];
   epi[i] = ep[j];
 }
 
-static void removeIdenticalNodes(int *np, int nbComp, 
-				 double xp[12], double yp[12], double zp[12], 
+static void removeIdenticalNodes(int *np, int numComp,
+				 double xp[12], double yp[12], double zp[12],
 				 double valp[12][9], int ep[12])
 {
   double xpi[12], ypi[12], zpi[12], valpi[12][9];
   int epi[12];
 
-  affect(xpi, ypi, zpi, valpi, epi, 0, xp, yp, zp, valp, ep, 0, nbComp);
+  affect(xpi, ypi, zpi, valpi, epi, 0, xp, yp, zp, valp, ep, 0, numComp);
   int npi = 1;
   for(int j = 1; j < *np; j++) {
     for(int i = 0; i < npi; i++) {
@@ -67,32 +108,29 @@ static void removeIdenticalNodes(int *np, int nbComp,
 	break;
       }
       if(i == npi-1) {
-	affect(xpi, ypi, zpi, valpi, epi, npi, xp, yp, zp, valp, ep, j, nbComp);
+	affect(xpi, ypi, zpi, valpi, epi, npi, xp, yp, zp, valp, ep, j, numComp);
 	npi++;
 	break;
       }
     }
   }
   for(int i = 0; i < npi; i++)
-    affect(xp, yp, zp, valp, ep, i, xpi, ypi, zpi, valpi, epi, i, nbComp);
+    affect(xp, yp, zp, valp, ep, i, xpi, ypi, zpi, valpi, epi, i, numComp);
   *np = npi;
 }
 
-static void reorderQuad(int nbComp, 
-			double xp[12], double yp[12], double zp[12], 
+static void reorderQuad(int numComp, double xp[12], double yp[12], double zp[12], 
 			double valp[12][9], int ep[12])
 {
   double xpi[1], ypi[1], zpi[1], valpi[1][9];
   int epi[12];
-  affect(xpi, ypi, zpi, valpi, epi, 0, xp, yp, zp, valp, ep, 3, nbComp);
-  affect(xp, yp, zp, valp, ep, 3, xp, yp, zp, valp, ep, 2, nbComp);
-  affect(xp, yp, zp, valp, ep, 2, xpi, ypi, zpi, valpi, epi, 0, nbComp);
+  affect(xpi, ypi, zpi, valpi, epi, 0, xp, yp, zp, valp, ep, 3, numComp);
+  affect(xp, yp, zp, valp, ep, 3, xp, yp, zp, valp, ep, 2, numComp);
+  affect(xp, yp, zp, valp, ep, 2, xpi, ypi, zpi, valpi, epi, 0, numComp);
 }
 
-static void reorderPrism(int nbComp, 
-			 double xp[12], double yp[12], double zp[12], 
-			 double valp[12][9], int ep[12],
-			 int nbCut, int exn[12][2])
+static void reorderPrism(int numComp, double xp[12], double yp[12], double zp[12], 
+			 double valp[12][9], int ep[12], int nbCut)
 {
   double xpi[6], ypi[6], zpi[6], valpi[6][9];
   int epi[12];
@@ -100,135 +138,120 @@ static void reorderPrism(int nbComp,
   if(nbCut == 3){
     // 3 first nodes come from zero levelset intersection, next 3 are
     // endpoints of relative edges
-    affect(xpi, ypi, zpi, valpi, epi, 0, xp, yp, zp, valp, ep, 3, nbComp);
-    affect(xpi, ypi, zpi, valpi, epi, 1, xp, yp, zp, valp, ep, 4, nbComp);
-    affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 5, nbComp);
+    affect(xpi, ypi, zpi, valpi, epi, 0, xp, yp, zp, valp, ep, 3, numComp);
+    affect(xpi, ypi, zpi, valpi, epi, 1, xp, yp, zp, valp, ep, 4, numComp);
+    affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 5, numComp);
     for(int i = 0; i < 3; i++){
       int edgecut = ep[i]-1;
       for(int j = 0; j < 3; j++){
 	int p = -epi[j]-1;
-	if(exn[edgecut][0] == p || exn[edgecut][1] == p)
-	  affect(xp, yp, zp, valp, ep, 3+i, xpi, ypi, zpi, valpi, epi, j, nbComp);	  
+	if(exn[9][edgecut][0] == p || exn[9][edgecut][1] == p)
+	  affect(xp, yp, zp, valp, ep, 3+i, xpi, ypi, zpi, valpi, epi, j, numComp);	  
       }
     }
   }
   else if(nbCut == 4){
     // 4 first nodes come from zero levelset intersection
-    affect(xpi, ypi, zpi, valpi, epi, 0, xp, yp, zp, valp, ep, 0, nbComp);
+    affect(xpi, ypi, zpi, valpi, epi, 0, xp, yp, zp, valp, ep, 0, numComp);
     int edgecut = ep[0]-1;
     int p0 = -ep[4]-1;
 
-    if(exn[edgecut][0] == p0 || exn[edgecut][1] == p0){
-      affect(xpi, ypi, zpi, valpi, epi, 1, xp, yp, zp, valp, ep, 4, nbComp);
-      if(exn[ep[1]-1][0] == p0 || exn[ep[1]-1][1] == p0){
-	affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 1, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 3, xp, yp, zp, valp, ep, 3, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 4, xp, yp, zp, valp, ep, 5, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 5, xp, yp, zp, valp, ep, 2, nbComp);
+    if(exn[9][edgecut][0] == p0 || exn[9][edgecut][1] == p0){
+      affect(xpi, ypi, zpi, valpi, epi, 1, xp, yp, zp, valp, ep, 4, numComp);
+      if(exn[9][ep[1]-1][0] == p0 || exn[9][ep[1]-1][1] == p0){
+	affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 1, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 3, xp, yp, zp, valp, ep, 3, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 4, xp, yp, zp, valp, ep, 5, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 5, xp, yp, zp, valp, ep, 2, numComp);
       }
       else{
-	affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 3, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 3, xp, yp, zp, valp, ep, 1, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 4, xp, yp, zp, valp, ep, 5, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 5, xp, yp, zp, valp, ep, 2, nbComp);
+	affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 3, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 3, xp, yp, zp, valp, ep, 1, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 4, xp, yp, zp, valp, ep, 5, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 5, xp, yp, zp, valp, ep, 2, numComp);
       }
     }
     else{
-      affect(xpi, ypi, zpi, valpi, epi, 1, xp, yp, zp, valp, ep, 5, nbComp);
-      if(exn[ep[1]-1][0] == p0 || exn[ep[1]-1][1] == p0){
-	affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 1, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 3, xp, yp, zp, valp, ep, 3, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 4, xp, yp, zp, valp, ep, 4, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 5, xp, yp, zp, valp, ep, 2, nbComp);
+      affect(xpi, ypi, zpi, valpi, epi, 1, xp, yp, zp, valp, ep, 5, numComp);
+      if(exn[9][ep[1]-1][0] == p0 || exn[9][ep[1]-1][1] == p0){
+	affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 1, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 3, xp, yp, zp, valp, ep, 3, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 4, xp, yp, zp, valp, ep, 4, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 5, xp, yp, zp, valp, ep, 2, numComp);
       }
       else{
-	affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 3, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 3, xp, yp, zp, valp, ep, 1, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 4, xp, yp, zp, valp, ep, 4, nbComp);
-	affect(xpi, ypi, zpi, valpi, epi, 5, xp, yp, zp, valp, ep, 2, nbComp);
+	affect(xpi, ypi, zpi, valpi, epi, 2, xp, yp, zp, valp, ep, 3, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 3, xp, yp, zp, valp, ep, 1, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 4, xp, yp, zp, valp, ep, 4, numComp);
+	affect(xpi, ypi, zpi, valpi, epi, 5, xp, yp, zp, valp, ep, 2, numComp);
       }
     }
     for(int i = 0; i < 6; i++)
-      affect(xp, yp, zp, valp, ep, i, xpi, ypi, zpi, valpi, epi, i, nbComp);
+      affect(xp, yp, zp, valp, ep, i, xpi, ypi, zpi, valpi, epi, i, numComp);
   }
 }
  
-void GMSH_LevelsetPlugin::evalLevelset(int nbNod, int nbComp,
-				       double *x, double *y, double *z, double *val,
-				       double *levels, double *scalarVal)
+GMSH_LevelsetPlugin::GMSH_LevelsetPlugin()
 {
-  if(_valueIndependent) {
-    for(int k = 0; k < nbNod; k++)
-      levels[k] = levelset(x[k], y[k], z[k], 0.0);
-  }
-  else{
-    for(int k = 0; k < nbNod; k++) {
-      double *vals = &val[nbComp * k];
-      switch(nbComp) {
-      case 1: // scalar
-	scalarVal[k] = vals[0];
-	break;
-      case 3 : // vector
-	scalarVal[k] = sqrt(DSQR(vals[0]) + DSQR(vals[1]) + DSQR(vals[2]));
-	break;
-      case 9 : // tensor
-	scalarVal[k] = ComputeVonMises(vals);
-	break;
-      }
-      levels[k] = levelset(x[k], y[k], z[k], scalarVal[k]);
-    }
-  }
+  _invert = 0.;
+  _ref[0] = _ref[1] = _ref[2] = 0.;
+  _valueIndependent = 0; // "moving" levelset
+  _valueView = -1; // use same view for levelset and field data
+  _valueTimeStep = -1; // use same time step in levelset and field data views
+  _recurLevel = 4;
+  _targetError = 0.;
+  _extractVolume = 0; // to create isovolumes (keep all elements < or > levelset)
+  _orientation = GMSH_LevelsetPlugin::NONE;
 }
 
-void GMSH_LevelsetPlugin::addElement(int timeStep, int np, int nbEdg, int dNbComp,
-				     double xp[12], double yp[12], double zp[12],
-				     double valp[12][9], std::vector<PViewDataList *> &out)
+void GMSH_LevelsetPlugin::_addElement(int step, int np, int numEdges, int numComp,
+				      double xp[12], double yp[12], double zp[12],
+				      double valp[12][9], std::vector<PViewDataList*> &out)
 {
-  // select the output data
-  PViewDataList *data = _valueIndependent ? out[0] : out[timeStep];
+  PViewDataList *data = _valueIndependent ? out[0] : out[step];
   List_T *list;
   int *nbPtr;
   switch(np){
   case 1:
-    if(dNbComp == 1)      { list = data->SP; nbPtr = &data->NbSP; }
-    else if(dNbComp == 3) { list = data->VP; nbPtr = &data->NbVP; }
+    if(numComp == 1)      { list = data->SP; nbPtr = &data->NbSP; }
+    else if(numComp == 3) { list = data->VP; nbPtr = &data->NbVP; }
     else                  { list = data->TP; nbPtr = &data->NbTP; }
     break;
   case 2:
-    if(dNbComp == 1)      { list = data->SL; nbPtr = &data->NbSL; }
-    else if(dNbComp == 3) { list = data->VL; nbPtr = &data->NbVL; }
+    if(numComp == 1)      { list = data->SL; nbPtr = &data->NbSL; }
+    else if(numComp == 3) { list = data->VL; nbPtr = &data->NbVL; }
     else                  { list = data->TL; nbPtr = &data->NbTL; }
     break;
   case 3:
-    if(dNbComp == 1)      { list = data->ST; nbPtr = &data->NbST; }
-    else if(dNbComp == 3) { list = data->VT; nbPtr = &data->NbVT; }
+    if(numComp == 1)      { list = data->ST; nbPtr = &data->NbST; }
+    else if(numComp == 3) { list = data->VT; nbPtr = &data->NbVT; }
     else                  { list = data->TT; nbPtr = &data->NbTT; }
     break;
   case 4:
-    if(!_extractVolume || nbEdg <= 4){
-      if(dNbComp == 1)      { list = data->SQ; nbPtr = &data->NbSQ; }
-      else if(dNbComp == 3) { list = data->VQ; nbPtr = &data->NbVQ; }
+    if(!_extractVolume || numEdges <= 4){
+      if(numComp == 1)      { list = data->SQ; nbPtr = &data->NbSQ; }
+      else if(numComp == 3) { list = data->VQ; nbPtr = &data->NbVQ; }
       else                  { list = data->TQ; nbPtr = &data->NbTQ; }
     }
     else{
-      if(dNbComp == 1)      { list = data->SS; nbPtr = &data->NbSS; }
-      else if(dNbComp == 3) { list = data->VS; nbPtr = &data->NbVS; }
+      if(numComp == 1)      { list = data->SS; nbPtr = &data->NbSS; }
+      else if(numComp == 3) { list = data->VS; nbPtr = &data->NbVS; }
       else                  { list = data->TS; nbPtr = &data->NbTS; }
     }
     break;
   case 5:
-    if(dNbComp == 1)      { list = data->SY; nbPtr = &data->NbSY; }
-    else if(dNbComp == 3) { list = data->VY; nbPtr = &data->NbVY; }
+    if(numComp == 1)      { list = data->SY; nbPtr = &data->NbSY; }
+    else if(numComp == 3) { list = data->VY; nbPtr = &data->NbVY; }
     else                  { list = data->TY; nbPtr = &data->NbTY; }
     break;
   case 6:
-    if(dNbComp == 1)      { list = data->SI; nbPtr = &data->NbSI; }
-    else if(dNbComp == 3) { list = data->VI; nbPtr = &data->NbVI; }
+    if(numComp == 1)      { list = data->SI; nbPtr = &data->NbSI; }
+    else if(numComp == 3) { list = data->VI; nbPtr = &data->NbVI; }
     else                  { list = data->TI; nbPtr = &data->NbTI; }
     break;
-  case 8: // should never happen
-    if(dNbComp == 1)      { list = data->SH; nbPtr = &data->NbSH; }
-    else if(dNbComp == 3) { list = data->VH; nbPtr = &data->NbVH; }
+  case 8:
+    if(numComp == 1)      { list = data->SH; nbPtr = &data->NbSH; }
+    else if(numComp == 3) { list = data->VH; nbPtr = &data->NbVH; }
     else                  { list = data->TH; nbPtr = &data->NbTH; }
     break;
   default:
@@ -236,7 +259,7 @@ void GMSH_LevelsetPlugin::addElement(int timeStep, int np, int nbEdg, int dNbCom
   }
 
   // copy the elements in the output data
-  if(!timeStep || !_valueIndependent) {
+  if(!step || !_valueIndependent) {
     for(int k = 0; k < np; k++) 
       List_Add(list, &xp[k]);
     for(int k = 0; k < np; k++)
@@ -246,525 +269,217 @@ void GMSH_LevelsetPlugin::addElement(int timeStep, int np, int nbEdg, int dNbCom
     (*nbPtr)++;
   }
   for(int k = 0; k < np; k++)
-    for(int l = 0; l < dNbComp; l++)
+    for(int l = 0; l < numComp; l++)
       List_Add(list, &valp[k][l]);
 }
 
-void GMSH_LevelsetPlugin::nonZeroLevelset(int timeStep, 
-					  int nbNod, int nbEdg, int exn[12][2],
-					  double *x, double *y, double *z, 
-					  double *iVal, int iNbComp,
-					  double *dVal, int dNbComp,
-					  std::vector<PViewDataList*> &out)
+void GMSH_LevelsetPlugin::_cutAndAddElements(PViewData *vdata, PViewData *wdata,
+					     int ent, int ele, int step, int wstep, 
+					     double x[8], double y[8], double z[8],
+					     double levels[8], double scalarValues[8],
+					     std::vector<PViewDataList*> &out)
 {
-  double levels[8], scalarVal[8];
-  
-  evalLevelset(nbNod, iNbComp, x, y, z, iVal, levels, scalarVal);
-  
-  int add = 1;
-  for(int k = 0; k < nbNod; k++){
-    if((_extractVolume < 0. && levels[k] > 0.) ||
-       (_extractVolume > 0. && levels[k] < 0.)){
-      add = 0;
-      break;
-    }
-  }
-  
-  if(add){
-    double xp[12], yp[12], zp[12], valp[12][9];
-    for(int k = 0; k < nbNod; k++){
-      xp[k] = x[k];
-      yp[k] = y[k];
-      zp[k] = z[k];
-      for(int l = 0; l < dNbComp; l++)
-	valp[k][l] = dVal[dNbComp * k + l];
-    }
-    addElement(timeStep, nbNod, nbEdg, dNbComp, xp, yp, zp, valp, out);
-  }
-}
+  int numNodes = vdata->getNumNodes(ent, ele);
+  int numEdges = vdata->getNumEdges(ent, ele);
+  int numComp = wdata->getNumComponents(ent, ele, wstep);
 
-int GMSH_LevelsetPlugin::zeroLevelset(int timeStep, 
-				      int nbNod, int nbEdg, int exn[12][2],
-				      double *x, double *y, double *z, 
-				      double *iVal, int iNbComp,
-				      double *dVal, int dNbComp,
-				      std::vector<PViewDataList*> &out)
-{
-  double levels[8], scalarVal[8];
-
-  evalLevelset(nbNod, iNbComp, x, y, z, iVal, levels, scalarVal);
-
-  // interpolate the zero levelset and the field to plot on it
-  double xp[12], yp[12], zp[12], valp[12][9];
-  int np = 0, ep[12];
-  for(int k = 0; k < nbEdg; k++) {
-    if(levels[exn[k][0]] * levels[exn[k][1]] <= 0.0) {
-      if(iVal && dVal) {
-	double coef = InterpolateIso(x, y, z, levels, 0.0, exn[k][0], exn[k][1],
-				     &xp[np], &yp[np], &zp[np]);
-	double *val1 = &dVal[dNbComp * exn[k][0]];
-	double *val2 = &dVal[dNbComp * exn[k][1]];
-	for(int l = 0; l < dNbComp; l++)
-	  valp[np][l] = coef * (val2[l] - val1[l]) + val1[l];
+  for(int simplex = 0; simplex < numSimplexDec(numEdges); simplex++){
+    double xp[12], yp[12], zp[12], valp[12][9];
+    int n[4], np = 0, ep[12], nsn, nse;
+    getSimplexDec(numNodes, numEdges, simplex, n[0], n[1], n[2], n[3], nsn, nse);
+
+    for(int i = 0; i < nse; i++){
+      int n0 = exn[nse][i][0], n1 = exn[nse][i][1];
+      if(levels[n[n0]] * levels[n[n1]] <= 0.) {
+	double c = InterpolateIso(x, y, z, levels, 0., n[n0], n[n1], 
+				  &xp[np], &yp[np], &zp[np]);
+	for(int comp = 0; comp < numComp; comp++){
+	  double v0, v1;
+	  wdata->getValue(ent, ele, n[n0], comp, wstep, v0);
+	  wdata->getValue(ent, ele, n[n1], comp, wstep, v1);
+	  valp[np][comp] = v0 + c * (v1 - v0);
+	}
+	ep[np++] = i + 1;
       }
-      ep[np] = k+1;
-      np++;
     }
-  }
 
-  if(!iVal || !dVal)
-    return np;
-
-  // Remove identical nodes (this can happen if an edge actually
-  // belongs to the zero levelset, i.e., if levels[] * levels[] == 0)
-  if(np > 1)
-    removeIdenticalNodes(&np, dNbComp, xp, yp, zp, valp, ep);
-
-  if(nbEdg > 4 && np < 3) // 3D input should only lead to 2D output
-    return 0;
-  else if(nbEdg > 1 && np < 2) // 2D input should only lead to 1D output
-    return 0;
-  else if(np < 1 || np > 4) // can't deal with this
-    return 0;
-
-  // avoid "butterflies"
-  if(np == 4)
-    reorderQuad(dNbComp, xp, yp, zp, valp, ep);
-      
-  // orient the triangles and the quads to get the normals right
-  if(!_extractVolume && (np == 3 || np == 4)) {
-    if(!timeStep || !_valueIndependent) {
-      // test this only once for spatially-fixed views
-      double v1[3] = { xp[2] - xp[0], yp[2] - yp[0], zp[2] - zp[0] };
-      double v2[3] = { xp[1] - xp[0], yp[1] - yp[0], zp[1] - zp[0] };
-      double gr[3], n[3];
-      prodve(v1, v2, n);
-      switch (_orientation) {
-      case MAP:
-	gradSimplex(x, y, z, scalarVal, gr);
-	prosca(gr, n, &_invert);
-	break;
-      case PLANE:
-	prosca(n, _ref, &_invert);
-	break;
-      case SPHERE:
-	gr[0] = xp[0] - _ref[0];
-	gr[1] = yp[0] - _ref[1];
-	gr[2] = zp[0] - _ref[2];
-	prosca(gr, n, &_invert);
-      case NONE:
-      default:
-	break;
+    // Remove identical nodes (this can happen if an edge actually
+    // belongs to the zero levelset, i.e., if levels[] * levels[] == 0)
+    if(np > 1) removeIdenticalNodes(&np, numComp, xp, yp, zp, valp, ep);
+    if(numEdges > 4 && np < 3) // 3D input should only lead to 2D output
+      continue;
+    else if(numEdges > 1 && np < 2) // 2D input should only lead to 1D output
+      continue;
+    else if(np < 1 || np > 4) // can't deal with this
+      continue;
+
+    // avoid "butterflies"
+    if(np == 4) reorderQuad(numComp, xp, yp, zp, valp, ep);
+
+    // orient the triangles and the quads to get the normals right
+    if(!_extractVolume && (np == 3 || np == 4)) {
+      if(!step || !_valueIndependent) {
+	// test this only once for spatially-fixed views
+	double v1[3] = {xp[2] - xp[0], yp[2] - yp[0], zp[2] - zp[0]};
+	double v2[3] = {xp[1] - xp[0], yp[1] - yp[0], zp[1] - zp[0]};
+	double gr[3], normal[3];
+	prodve(v1, v2, normal);
+	switch (_orientation) {
+	case MAP:
+	  gradSimplex(x, y, z, scalarValues, gr);
+	  prosca(gr, normal, &_invert);
+	  break;
+	case PLANE:
+	  prosca(normal, _ref, &_invert);
+	  break;
+	case SPHERE:
+	  gr[0] = xp[0] - _ref[0];
+	  gr[1] = yp[0] - _ref[1];
+	  gr[2] = zp[0] - _ref[2];
+	  prosca(gr, normal, &_invert);
+	case NONE:
+	default:
+	  break;
+	}
+      }
+      if(_invert > 0.) {
+	double xpi[12], ypi[12], zpi[12], valpi[12][9];
+	int epi[12];
+	for(int k = 0; k < np; k++)
+	  affect(xpi, ypi, zpi, valpi, epi, k, xp, yp, zp, valp, ep, k, numComp);
+	for(int k = 0; k < np; k++)
+	  affect(xp, yp, zp, valp, ep, k, xpi, ypi, zpi, valpi, epi, np - k - 1, numComp);
       }
     }
-    if(_invert > 0.) {
-      double xpi[12], ypi[12], zpi[12], valpi[12][9];
-      int epi[12];
-      for(int k = 0; k < np; k++)
-	affect(xpi, ypi, zpi, valpi, epi, k, xp, yp, zp, valp, ep, k, dNbComp);
-      for(int k = 0; k < np; k++)
-	affect(xp, yp, zp, valp, ep, k, xpi, ypi, zpi, valpi, epi, np-k-1, dNbComp);
-    }
-  }
 
-  // if we compute isovolumes, add the nodes on the chosen side 
-  if(_extractVolume){
-    // FIXME: when cutting 2D views, the elts we get can have the wrong
-    // orientation
-    int nbCut = np;
-    for(int k = 0; k < nbNod; k++){
-      if((_extractVolume < 0. && levels[k] < 0.0) ||
-	 (_extractVolume > 0. && levels[k] > 0.0)){
-	xp[np] = x[k];
-	yp[np] = y[k];
-	zp[np] = z[k];
-	for(int l = 0; l < dNbComp; l++)
-	  valp[np][l] = dVal[dNbComp * k + l];
-	ep[np] = -(k+1); // node num!
-	np++;
+    // if we compute isovolumes, add the nodes on the chosen side
+    // (FIXME: when cutting 2D views, the elts can have the wrong
+    // orientation)
+    if(_extractVolume){
+      int nbCut = np;
+      for(int nod = 0; nod < nsn; nod++){
+	if((_extractVolume < 0. && levels[n[nod]] < 0.) ||
+	   (_extractVolume > 0. && levels[n[nod]] > 0.)){
+	  xp[np] = x[n[nod]];
+	  yp[np] = y[n[nod]];
+	  zp[np] = z[n[nod]];
+	  for(int comp = 0; comp < numComp; comp++)
+	    wdata->getValue(ent, ele, n[nod], comp, wstep, valp[np][comp]);
+	  ep[np] = -(nod + 1); // store node num!
+	  np++;
+	}
       }
+      removeIdenticalNodes(&np, numComp, xp, yp, zp, valp, ep);
+      if(np == 4 && numEdges <= 4)
+	reorderQuad(numComp, xp, yp, zp, valp, ep);
+      if(np == 6)
+	reorderPrism(numComp, xp, yp, zp, valp, ep, nbCut);
+      if(np > 8) // can't deal with this
+	continue;
     }
-    removeIdenticalNodes(&np, dNbComp, xp, yp, zp, valp, ep);
-    if(np == 4 && nbEdg <= 4)
-      reorderQuad(dNbComp, xp, yp, zp, valp, ep);
-    if(np == 6)
-      reorderPrism(dNbComp, xp, yp, zp, valp, ep, nbCut, exn);
-    if(np > 8) // can't deal with this
-      return 0;
-  }
 
-  addElement(timeStep, np, nbEdg, dNbComp, xp, yp, zp, valp, out);
-  
-  return 0;
-}
-
-void GMSH_LevelsetPlugin::executeList(PViewDataList *iData, List_T *iList,
-				      int iNbElm, int iNbComp,
-				      PViewDataList *dData, List_T *dList,
-				      int dNbElm, int dNbComp,
-				      int nbNod, int nbEdg, int exn[12][2], 
-				      std::vector<PViewDataList*> &out)
-{
-  if(!iNbElm || !dNbElm) 
-    return;
-  
-  if(iNbElm != dNbElm) {
-    Msg(GERROR, "Views have a different number of elements (%d != %d)", iNbElm, dNbElm);
-    return;
+    _addElement(step, np, numEdges, numComp, xp, yp, zp, valp, out);
   }
 
-  int dTimeStep = _valueTimeStep;
-  if(dTimeStep >= dData->getNumTimeSteps()) {
-    Msg(GERROR, "Wrong time step %d in view", dTimeStep);
-    return;
-  }
-
-  int iNb = List_Nbr(iList) / iNbElm;
-  int dNb = List_Nbr(dList) / dNbElm;
-  for(int i = 0, j = 0; i < List_Nbr(iList); i += iNb, j += dNb) {
-    double *x = (double *)List_Pointer_Fast(iList, i);
-    double *y = (double *)List_Pointer_Fast(iList, i + nbNod);
-    double *z = (double *)List_Pointer_Fast(iList, i + 2 * nbNod);
-
-    if(nbNod == 1 || nbNod == 2 || nbNod == 3 || (nbNod == 4 && nbEdg == 6)) {
-      // easy for simplices: at most one element is created per time step 
-      for(int iTS = 0; iTS < iData->getNumTimeSteps(); iTS++) {
-	int dTS = (dTimeStep < 0) ? iTS : dTimeStep;
-	// don't compute the zero levelset of the value view
-	if(dTimeStep < 0 || iData != dData || dTS != iTS) {
-	  double *iVal = (double *)List_Pointer_Fast(iList, i + 3 * nbNod + 
-						     iNbComp * nbNod * iTS); 
-	  double *dVal = (double *)List_Pointer_Fast(dList, j + 3 * nbNod + 
-						     dNbComp * nbNod * dTS);
-	  zeroLevelset(iTS, nbNod, nbEdg, exn, x, y, z, 
-		       iVal, iNbComp, dVal, dNbComp, out);
-	  if(_extractVolume)
-	    nonZeroLevelset(iTS, nbNod, nbEdg, exn, x, y, z, 
-			    iVal, iNbComp, dVal, dNbComp, out);
-	}
+  if(_extractVolume){
+    // if we compute isovolumes, add full elements that are completely
+    // on one side
+    bool add = true;
+    for(int nod = 0; nod < numNodes; nod++){
+      if((_extractVolume < 0. && levels[nod] > 0.) ||
+	 (_extractVolume > 0. && levels[nod] < 0.)){
+	add = false;
+	break;
       }
     }
-    else{
-      // we decompose the element into simplices
-      MakeSimplex iDec(nbNod, iNbComp);
-      MakeSimplex dDec(nbNod, dNbComp);
-      
-      int nbNodNew = iDec.numSimplexNodes();
-      int nbEdgNew = (nbNodNew == 4) ? 6 : 3;
-      int exnTri[12][2] = {{0,1},{0,2},{1,2}};
-      int exnTet[12][2] = {{0,1},{0,2},{0,3},{1,2},{1,3},{2,3}};
-      double xNew[4], yNew[4], zNew[4];
-      double *iValNew = new double[4 * iNbComp];
-      double *dValNew = new double[4 * dNbComp];
-
-      if(_valueIndependent) {
-	// since the intersection is value-independent, we can loop on
-	// the time steps so that only one element gets created per
-	// time step. This allows us to still easily generate a
-	// *single* multi-timestep view.
-	if(zeroLevelset(0, nbNod, nbEdg, exn, x, y, z, NULL, 0, 
-			NULL, 0, out)) {
-	  for(int k = 0; k < iDec.numSimplices(); k++) {
-	    for(int iTS = 0; iTS < iData->getNumTimeSteps(); iTS++) {
-	      int dTS = (dTimeStep < 0) ? iTS : dTimeStep;
-	      // don't compute the zero levelset of the value view
-	      if(dTimeStep < 0 || iData != dData || dTS != iTS) {
-		double *iVal = (double *)List_Pointer_Fast(iList, i + 3 * nbNod + 
-							   iNbComp * nbNod * iTS); 
-		double *dVal = (double *)List_Pointer_Fast(dList, j + 3 * nbNod + 
-							   dNbComp * nbNod * dTS);
-		iDec.decompose(k, x, y, z, iVal, xNew, yNew, zNew, iValNew);
-		dDec.decompose(k, x, y, z, dVal, xNew, yNew, zNew, dValNew);
-		zeroLevelset(iTS, nbNodNew, nbEdgNew, (nbNodNew == 4) ? exnTet : exnTri, 
-			     xNew, yNew, zNew, iValNew, iNbComp, dValNew, dNbComp, out);
-		if(_extractVolume)
-		  nonZeroLevelset(iTS, nbNodNew, nbEdgNew, (nbNodNew == 4) ? exnTet : exnTri, 
-				  xNew, yNew, zNew, iValNew, iNbComp, dValNew, dNbComp, out);
-	      }
-	    }
-	  }
-	}
-	else if(_extractVolume){
-	  for(int iTS = 0; iTS < iData->getNumTimeSteps(); iTS++) {
-	    int dTS = (dTimeStep < 0) ? iTS : dTimeStep;
-	    // don't compute the zero levelset of the value view
-	    if(dTimeStep < 0 || iData != dData || dTS != iTS) {
-	      double *iVal = (double *)List_Pointer_Fast(iList, i + 3 * nbNod + 
-							 iNbComp * nbNod * iTS); 
-	      double *dVal = (double *)List_Pointer_Fast(dList, j + 3 * nbNod + 
-							 dNbComp * nbNod * dTS);
-	      nonZeroLevelset(iTS, nbNod, nbEdg, exn, x, y, z, 
-			      iVal, iNbComp, dVal, dNbComp, out);
-	    }
-	  }
-	}
+    if(add){
+      double xp[12], yp[12], zp[12], valp[12][9];
+      for(int nod = 0; nod < numNodes; nod++){
+	xp[nod] = x[nod];
+	yp[nod] = y[nod];
+	zp[nod] = z[nod];
+	for(int comp = 0; comp < numComp; comp++)
+	  wdata->getValue(ent, ele, nod, comp, wstep, valp[nod][comp]);
       }
-      else{
-	// since we generate one view for each time step, we can
-	// generate multiple elements per time step without problem.
-	for(int iTS = 0; iTS < iData->getNumTimeSteps(); iTS++) {
-	  int dTS = (dTimeStep < 0) ? iTS : dTimeStep;
-	  // don't compute the zero levelset of the value view
-	  if(dTimeStep < 0 || iData != dData || dTS != iTS) {
-	    double *iVal = (double *)List_Pointer_Fast(iList, i + 3 * nbNod +
-						       iNbComp * nbNod * iTS); 
-	    double *dVal = (double *)List_Pointer_Fast(dList, j + 3 * nbNod +
-						       dNbComp * nbNod * dTS);
-	    if(zeroLevelset(iTS, nbNod, nbEdg, exn, x, y, z, iVal, iNbComp, 
-			    NULL, 0, out)) {
-	      for(int k = 0; k < iDec.numSimplices(); k++) {
-		iDec.decompose(k, x, y, z, iVal, xNew, yNew, zNew, iValNew);
-		dDec.decompose(k, x, y, z, dVal, xNew, yNew, zNew, dValNew);
-		zeroLevelset(iTS, nbNodNew, nbEdgNew, (nbNodNew == 4) ? exnTet : exnTri, 
-			     xNew, yNew, zNew, iValNew, iNbComp, dValNew, dNbComp, out);
-		if(_extractVolume)
-		  nonZeroLevelset(iTS, nbNodNew, nbEdgNew, (nbNodNew == 4) ? exnTet : exnTri, 
-				  xNew, yNew, zNew, iValNew, iNbComp, dValNew, dNbComp, out);
-	      }
-	    }
-	    else if(_extractVolume)
-	      nonZeroLevelset(iTS, nbNod, nbEdg, exn, x, y, z, 
-			      iVal, iNbComp, dVal, dNbComp, out);
-	  }
-	}
-      }
-      
-      delete [] iValNew;
-      delete [] dValNew;
+      _addElement(step, numNodes, numEdges, numComp, xp, yp, zp, valp, out);
     }
-
   }
 }
-  
+
 PView *GMSH_LevelsetPlugin::execute(PView *v)
 {
-  PView *w;
-  std::vector<PViewDataList*> out;
-
-  PViewDataList *dv = getDataList(v);
-  if(!dv) return v;
-
-  if(dv->isAdaptive()){
-    dv->adaptive->setTolerance(_targetError);
-    if(dv->NbST || dv->NbSS || dv->NbSQ || dv->NbSH){
-      dv->adaptive->setAdaptiveResolutionLevel(dv, _recurLevel, this);
-      v->setChanged(true);
+  if(v->getData()->isAdaptive()){
+    PViewDataList *dv = getDataList(v);
+    if(dv){
+      dv->adaptive->setTolerance(_targetError);
+      if(dv->NbST || dv->NbSS || dv->NbSQ || dv->NbSH){
+	dv->adaptive->setAdaptiveResolutionLevel(dv, _recurLevel, this);
+	v->setChanged(true);
+      }
     }
   }
 
+  PViewData *vdata = v->getData(), *wdata;
   if(_valueView < 0) {
-    w = v;
+    wdata = vdata;
   }
   else if(_valueView > (int)PView::list.size() - 1){
     Msg(GERROR, "View[%d] does not exist: reverting to View[%d]", 
 	_valueView, v->getIndex());
-    w = v;
+    wdata = vdata;
   }
   else{
-    w = PView::list[_valueView];
+    wdata = PView::list[_valueView]->getData();
   }
 
-  PViewDataList *dw = getDataList(w);
-  if(!dw) return v;
+  // sanity checks
+  if(vdata->getNumEntities() != wdata->getNumEntities() ||
+     vdata->getNumElements() != wdata->getNumElements()) return v;
+  if(_valueTimeStep >= wdata->getNumTimeSteps()) {
+    Msg(GERROR, "Wrong time step %d in view", _valueTimeStep);
+    return v;
+  }
 
+  // create output dataset(s), in the list format
+  std::vector<PViewDataList*> out;
   if(_valueIndependent) {
     out.push_back(getDataList(new PView(true)));
   }
   else{
-    for(int ts = 0; ts < dv->getNumTimeSteps(); ts++)
+    for(int ts = 0; ts < vdata->getNumTimeSteps(); ts++)
       out.push_back(getDataList(new PView(true)));
   }
-
-  // We should definitely recode the View interface in C++ (and define
-  // iterators on the different kinds of elements...)
-
-  // To avoid surprising results, we don't try to plot values of
-  // different types on the levelset if the value view (w) is the same
-  // as the levelset view (v).
-
-  // points
-  executeList(dv, dv->SP, dv->NbSP, 1, dw, dw->SP, dw->NbSP, 1, 1, 0, 0, out);
-  if(dv != dw) {
-    executeList(dv, dv->SP, dv->NbSP, 1, dw, dw->VP, dw->NbVP, 3, 1, 0, 0, out);
-    executeList(dv, dv->SP, dv->NbSP, 1, dw, dw->TP, dw->NbTP, 9, 1, 0, 0, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->VP, dv->NbVP, 3, dw, dw->SP, dw->NbSP, 1, 1, 0, 0, out);
-  }
-  executeList(dv, dv->VP, dv->NbVP, 3, dw, dw->VP, dw->NbVP, 3, 1, 0, 0, out);
-  if(dv != dw) {
-    executeList(dv, dv->VP, dv->NbVP, 3, dw, dw->TP, dw->NbTP, 9, 1, 0, 0, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->TP, dv->NbTP, 9, dw, dw->SP, dw->NbSP, 1, 1, 0, 0, out);
-    executeList(dv, dv->TP, dv->NbTP, 9, dw, dw->VP, dw->NbVP, 3, 1, 0, 0, out);
-  }
-  executeList(dv, dv->TP, dv->NbTP, 9, dw, dw->TP, dw->NbTP, 9, 1, 0, 0, out);
-
-  // lines
-  int exnLin[12][2] = {{0,1}};
-  executeList(dv, dv->SL, dv->NbSL, 1, dw, dw->SL, dw->NbSL, 1, 2, 1, exnLin, out);
-  if(dv != dw) {
-    executeList(dv, dv->SL, dv->NbSL, 1, dw, dw->VL, dw->NbVL, 3, 2, 1, exnLin, out);
-    executeList(dv, dv->SL, dv->NbSL, 1, dw, dw->TL, dw->NbTL, 9, 2, 1, exnLin, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->VL, dv->NbVL, 3, dw, dw->SL, dw->NbSL, 1, 2, 1, exnLin, out);
-  }
-  executeList(dv, dv->VL, dv->NbVL, 3, dw, dw->VL, dw->NbVL, 3, 2, 1, exnLin, out);
-  if(dv != dw) {
-    executeList(dv, dv->VL, dv->NbVL, 3, dw, dw->TL, dw->NbTL, 9, 2, 1, exnLin, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->TL, dv->NbTL, 9, dw, dw->SL, dw->NbSL, 1, 2, 1, exnLin, out);
-    executeList(dv, dv->TL, dv->NbTL, 9, dw, dw->VL, dw->NbVL, 3, 2, 1, exnLin, out);
-  }
-  executeList(dv, dv->TL, dv->NbTL, 9, dw, dw->TL, dw->NbTL, 9, 2, 1, exnLin, out);
-
-  // triangles
-  int exnTri[12][2] = {{0,1}, {0,2}, {1,2}};
-  executeList(dv, dv->ST, dv->NbST, 1, dw, dw->ST, dw->NbST, 1, 3, 3, exnTri, out);
-  if(dv != dw) {
-    executeList(dv, dv->ST, dv->NbST, 1, dw, dw->VT, dw->NbVT, 3, 3, 3, exnTri, out);
-    executeList(dv, dv->ST, dv->NbST, 1, dw, dw->TT, dw->NbTT, 9, 3, 3, exnTri, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->VT, dv->NbVT, 3, dw, dw->ST, dw->NbST, 1, 3, 3, exnTri, out);
-  }
-  executeList(dv, dv->VT, dv->NbVT, 3, dw, dw->VT, dw->NbVT, 3, 3, 3, exnTri, out);
-  if(dv != dw) {
-    executeList(dv, dv->VT, dv->NbVT, 3, dw, dw->TT, dw->NbTT, 9, 3, 3, exnTri, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->TT, dv->NbTT, 9, dw, dw->ST, dw->NbST, 1, 3, 3, exnTri, out);
-    executeList(dv, dv->TT, dv->NbTT, 9, dw, dw->VT, dw->NbVT, 3, 3, 3, exnTri, out);
-  }
-  executeList(dv, dv->TT, dv->NbTT, 9, dw, dw->TT, dw->NbTT, 9, 3, 3, exnTri, out);
-
-  // tets
-  int exnTet[12][2] = {{0,1},{0,2},{0,3},{1,2},{1,3},{2,3}};
-  executeList(dv, dv->SS, dv->NbSS, 1, dw, dw->SS, dw->NbSS, 1, 4, 6, exnTet, out);
-  if(dv != dw) {
-    executeList(dv, dv->SS, dv->NbSS, 1, dw, dw->VS, dw->NbVS, 3, 4, 6, exnTet, out);
-    executeList(dv, dv->SS, dv->NbSS, 1, dw, dw->TS, dw->NbTS, 9, 4, 6, exnTet, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->VS, dv->NbVS, 3, dw, dw->SS, dw->NbSS, 1, 4, 6, exnTet, out);
-  }
-  executeList(dv, dv->VS, dv->NbVS, 3, dw, dw->VS, dw->NbVS, 3, 4, 6, exnTet, out);
-  if(dv != dw) {
-    executeList(dv, dv->VS, dv->NbVS, 3, dw, dw->TS, dw->NbTS, 9, 4, 6, exnTet, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->TS, dv->NbTS, 9, dw, dw->SS, dw->NbSS, 1, 4, 6, exnTet, out);
-    executeList(dv, dv->TS, dv->NbTS, 9, dw, dw->VS, dw->NbVS, 3, 4, 6, exnTet, out);
-  }
-  executeList(dv, dv->TS, dv->NbTS, 9, dw, dw->TS, dw->NbTS, 9, 4, 6, exnTet, out);
-
-  // quads
-  int exnQua[12][2] = {{0,1}, {0,3}, {1,2}, {2,3}};
-  executeList(dv, dv->SQ, dv->NbSQ, 1, dw, dw->SQ, dw->NbSQ, 1, 4, 4, exnQua, out);
-  if(dv != dw) {
-    executeList(dv, dv->SQ, dv->NbSQ, 1, dw, dw->VQ, dw->NbVQ, 3, 4, 4, exnQua, out);
-    executeList(dv, dv->SQ, dv->NbSQ, 1, dw, dw->TQ, dw->NbTQ, 9, 4, 4, exnQua, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->VQ, dv->NbVQ, 3, dw, dw->SQ, dw->NbSQ, 1, 4, 4, exnQua, out);
-  }
-  executeList(dv, dv->VQ, dv->NbVQ, 3, dw, dw->VQ, dw->NbVQ, 3, 4, 4, exnQua, out);
-  if(dv != dw) {
-    executeList(dv, dv->VQ, dv->NbVQ, 3, dw, dw->TQ, dw->NbTQ, 9, 4, 4, exnQua, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->TQ, dv->NbTQ, 9, dw, dw->SQ, dw->NbSQ, 1, 4, 4, exnQua, out);
-    executeList(dv, dv->TQ, dv->NbTQ, 9, dw, dw->VQ, dw->NbVQ, 3, 4, 4, exnQua, out);
-  }
-  executeList(dv, dv->TQ, dv->NbTQ, 9, dw, dw->TQ, dw->NbTQ, 9, 4, 4, exnQua, out);
-
-  // hexes
-  int exnHex[12][2] = {{0,1}, {0,3}, {0,4}, {1,2}, {1,5}, {2,3},
-		       {2,6}, {3,7}, {4,5}, {4,7}, {5,6}, {6,7}};
-  executeList(dv, dv->SH, dv->NbSH, 1, dw, dw->SH, dw->NbSH, 1, 8, 12, exnHex, out);
-  if(dv != dw) {
-    executeList(dv, dv->SH, dv->NbSH, 1, dw, dw->VH, dw->NbVH, 3, 8, 12, exnHex, out);
-    executeList(dv, dv->SH, dv->NbSH, 1, dw, dw->TH, dw->NbTH, 9, 8, 12, exnHex, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->VH, dv->NbVH, 3, dw, dw->SH, dw->NbSH, 1, 8, 12, exnHex, out);
-  }
-  executeList(dv, dv->VH, dv->NbVH, 3, dw, dw->VH, dw->NbVH, 3, 8, 12, exnHex, out);
-  if(dv != dw) {
-    executeList(dv, dv->VH, dv->NbVH, 3, dw, dw->TH, dw->NbTH, 9, 8, 12, exnHex, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->TH, dv->NbTH, 9, dw, dw->SH, dw->NbSH, 1, 8, 12, exnHex, out);
-    executeList(dv, dv->TH, dv->NbTH, 9, dw, dw->VH, dw->NbVH, 3, 8, 12, exnHex, out);
-  }
-  executeList(dv, dv->TH, dv->NbTH, 9, dw, dw->TH, dw->NbTH, 9, 8, 12, exnHex, out);
-
-  // prisms
-  int exnPri[12][2] = {{0,1}, {0,2}, {0,3}, {1,2}, {1,4}, {2,5},
-		       {3,4}, {3,5}, {4,5}};
-  executeList(dv, dv->SI, dv->NbSI, 1, dw, dw->SI, dw->NbSI, 1, 6, 9, exnPri, out);
-  if(dv != dw) {
-    executeList(dv, dv->SI, dv->NbSI, 1, dw, dw->VI, dw->NbVI, 3, 6, 9, exnPri, out);
-    executeList(dv, dv->SI, dv->NbSI, 1, dw, dw->TI, dw->NbTI, 9, 6, 9, exnPri, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->VI, dv->NbVI, 3, dw, dw->SI, dw->NbSI, 1, 6, 9, exnPri, out);
-  }
-  executeList(dv, dv->VI, dv->NbVI, 3, dw, dw->VI, dw->NbVI, 3, 6, 9, exnPri, out);
-  if(dv != dw) {
-    executeList(dv, dv->VI, dv->NbVI, 3, dw, dw->TI, dw->NbTI, 9, 6, 9, exnPri, out);
-  }
- 
-  if(dv != dw) {
-    executeList(dv, dv->TI, dv->NbTI, 9, dw, dw->SI, dw->NbSI, 1, 6, 9, exnPri, out);
-    executeList(dv, dv->TI, dv->NbTI, 9, dw, dw->VI, dw->NbVI, 3, 6, 9, exnPri, out);
-  }
-  executeList(dv, dv->TI, dv->NbTI, 9, dw, dw->TI, dw->NbTI, 9, 6, 9, exnPri, out);
-
-  // pyramids
-  int exnPyr[12][2] = {{0,1}, {0,3}, {0,4}, {1,2}, {1,4}, {2,3}, {2,4}, {3,4}};
-  executeList(dv, dv->SY, dv->NbSY, 1, dw, dw->SY, dw->NbSY, 1, 5, 8, exnPyr, out);
-  if(dv != dw) {
-    executeList(dv, dv->SY, dv->NbSY, 1, dw, dw->VY, dw->NbVY, 3, 5, 8, exnPyr, out);
-    executeList(dv, dv->SY, dv->NbSY, 1, dw, dw->TY, dw->NbTY, 9, 5, 8, exnPyr, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->VY, dv->NbVY, 3, dw, dw->SY, dw->NbSY, 1, 5, 8, exnPyr, out);
-  }
-  executeList(dv, dv->VY, dv->NbVY, 3, dw, dw->VY, dw->NbVY, 3, 5, 8, exnPyr, out);
-  if(dv != dw) {
-    executeList(dv, dv->VY, dv->NbVY, 3, dw, dw->TY, dw->NbTY, 9, 5, 8, exnPyr, out);
-  }
-
-  if(dv != dw) {
-    executeList(dv, dv->TY, dv->NbTY, 9, dw, dw->SY, dw->NbSY, 1, 5, 8, exnPyr, out);
-    executeList(dv, dv->TY, dv->NbTY, 9, dw, dw->VY, dw->NbVY, 3, 5, 8, exnPyr, out);
+  
+  for(int ent = 0; ent < vdata->getNumEntities(); ent++){
+    for(int ele = 0; ele < vdata->getNumElements(ent); ele++){
+      int numNodes = vdata->getNumNodes(ent, ele);
+      int numEdges = vdata->getNumEdges(ent, ele);
+      double x[8], y[8], z[8], levels[8];
+      double scalarValues[8] = {0., 0., 0., 0., 0., 0., 0., 0.};
+      for(int nod = 0; nod < numNodes; nod++){
+	vdata->getNode(ent, ele, nod, x[nod], y[nod], z[nod]);
+	if(_valueIndependent) 
+	  levels[nod] = levelset(x[nod], y[nod], z[nod], 0.);
+      }
+      for(int step = 0; step < vdata->getNumTimeSteps(); step++){
+	if(!_valueIndependent){
+	  for(int nod = 0; nod < numNodes; nod++){
+	    vdata->getScalarValue(ent, ele, nod, step, scalarValues[nod]);
+	    levels[nod] = levelset(x[nod], y[nod], z[nod], scalarValues[nod]);
+	  }
+	}
+	int wstep = (_valueTimeStep < 0) ? step : _valueTimeStep;
+	_cutAndAddElements(vdata, wdata, ent, ele, step, wstep, x, y, z,
+			   levels, scalarValues, out);
+      }
+    }
   }
-  executeList(dv, dv->TY, dv->NbTY, 9, dw, dw->TY, dw->NbTY, 9, 5, 8, exnPyr, out);
-
+  
   for(unsigned int i = 0; i < out.size(); i++) {
-    // FIXME: create time data
     char tmp[246];
     sprintf(tmp, "_Levelset_%d", i);
-    out[i]->setName(dv->getName() + tmp);
-    out[i]->setFileName(dv->getFileName() + tmp + ".pos");
+    out[i]->setName(vdata->getName() + tmp);
+    out[i]->setFileName(vdata->getFileName() + tmp + ".pos");
     out[i]->finalize();
   }
 
@@ -846,7 +561,7 @@ static bool recur_sign_change(adapt_tet *t, double val,
 static bool recur_sign_change(adapt_hex *t, double val,
 			      const GMSH_LevelsetPlugin *plug)
 {
-  if (!t->e[0]|| t->visible){
+  if (!t->e[0] || t->visible){
     double v1 = plug->levelset(t->p[0]->X, t->p[0]->Y, t->p[0]->Z, t->p[0]->val);
     double v2 = plug->levelset(t->p[1]->X, t->p[1]->Y, t->p[1]->Z, t->p[1]->val);
     double v3 = plug->levelset(t->p[2]->X, t->p[2]->Y, t->p[2]->Z, t->p[2]->val);
@@ -887,8 +602,8 @@ static bool recur_sign_change(adapt_hex *t, double val,
   }      
 }
 
-static bool recur_sign_change (adapt_quad *q, double val,
-			       const GMSH_LevelsetPlugin *plug)
+static bool recur_sign_change(adapt_quad *q, double val,
+			      const GMSH_LevelsetPlugin *plug)
 {
   if(!q->e[0]|| q->visible){
     double v1 = plug->levelset(q->p[0]->X, q->p[0]->Y, q->p[0]->Z, q->p[0]->val);
diff --git a/Plugin/Levelset.h b/Plugin/Levelset.h
index 7fa6257e14f39b185772f19db5762d05c07737e1..1575e9b149e71c6ae79fca7858308d5caababb3c 100644
--- a/Plugin/Levelset.h
+++ b/Plugin/Levelset.h
@@ -26,39 +26,26 @@
 
 class GMSH_LevelsetPlugin : public GMSH_Post_Plugin
 {
-public:
-  typedef enum {NONE, PLANE, SPHERE, MAP} ORIENTATION ;
-  virtual double levelset(double x, double y, double z, double val) const = 0;
-protected:
+ private:
+  double _invert;
+  void _addElement(int step, int np, int numEdges, int numComp,
+		   double xp[12], double yp[12], double zp[12],
+		   double valp[12][9], std::vector<PViewDataList*> &out);
+  void _cutAndAddElements(PViewData *vdata, PViewData *wdata,
+			  int ent, int ele, int step, int wstep,
+			  double x[8], double y[8], double z[8],
+			  double levels[8], double scalarValues[8],
+			  std::vector<PViewDataList*> &out);
+ protected:
   double _ref[3], _targetError;
   int _valueTimeStep, _valueView, _valueIndependent, _recurLevel, _extractVolume;  
+  typedef enum {NONE, PLANE, SPHERE, MAP} ORIENTATION;
   ORIENTATION _orientation;
-private:
-  double _invert;
-  void addElement(int timeStep, int np, int nbEdg, int dNbComp,
-		  double xp[12], double yp[12], double zp[12],
-		  double valp[12][9], std::vector<PViewDataList*> &out);
-  void evalLevelset(int nbNod, int nbComp,
-		    double *x, double *y, double *z, double *val,
-		    double *levels, double *scalarVal);
-  void nonZeroLevelset(int timeStep, int nbVert, int nbEdg, int exn[12][2],
-		       double *x, double *y, double *z, 
-		       double *iVal, int iNbComp, double *dVal, int dNbComp,
-		       std::vector<PViewDataList*> &out);
-  int zeroLevelset(int timeStep, int nbVert, int nbEdg, int exn[12][2],
-		   double *x, double *y, double *z, 
-		   double *iVal, int iNbComp, double *dVal, int dNbComp,
-		   std::vector<PViewDataList*> &out);
-  void executeList(PViewDataList *iData, List_T *iList, 
-		   int iNbElm, int iNbComp,
-		   PViewDataList *dData, List_T *dList, 
-		   int dNbElm, int dNbComp,
-		   int nbVert, int nbEdg, int exn[12][2], 
-		   std::vector<PViewDataList*> &out);
-  virtual void assignSpecificVisibility () const;
 public:
   GMSH_LevelsetPlugin();
+  virtual double levelset(double x, double y, double z, double val) const = 0;
   virtual PView *execute(PView *);
+  void assignSpecificVisibility() const;
 };
 
 #endif
diff --git a/Plugin/MakeSimplex.cpp b/Plugin/MakeSimplex.cpp
index a00c4576ecb2efdf79c79078bb08dc15142c0994..7831612b97e214ac4d2fa83014acff063e50afde 100644
--- a/Plugin/MakeSimplex.cpp
+++ b/Plugin/MakeSimplex.cpp
@@ -1,4 +1,4 @@
-// $Id: MakeSimplex.cpp,v 1.6 2008-02-17 08:48:07 geuzaine Exp $
+// $Id: MakeSimplex.cpp,v 1.7 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -184,26 +184,6 @@ void MakeSimplex::reorder(int map[4], int n,
   }
 
   int map2[4] = {map[0], map[1], map[2], map[3]};
-#if 0
-  // make sure to create tets with positive volume?
-  if(n == 4){ // tets
-    double mat[3][3];
-    mat[0][0] = xn[1] - xn[0]; mat[0][1] = xn[2] - xn[0]; mat[0][2] = xn[3] - xn[0];
-    mat[1][0] = yn[1] - yn[0]; mat[1][1] = yn[2] - yn[0]; mat[1][2] = yn[3] - yn[0];
-    mat[2][0] = zn[1] - zn[0]; mat[2][1] = zn[2] - zn[0]; mat[2][2] = zn[3] - zn[0];
-    if(det3x3(mat) < 0.){
-      map2[0] = map[1];
-      map2[1] = map[0];
-      xn[0] = x[map2[0]];
-      yn[0] = y[map2[0]];
-      zn[0] = z[map2[0]];
-      xn[1] = x[map2[1]];
-      yn[1] = y[map2[1]];
-      zn[1] = z[map2[1]];
-    }
-  }
-#endif
-
   for(int ts = 0; ts < _numTimeSteps; ts++)
     for(int i = 0; i < n; i++) {
       for(int j = 0; j < _numComponents; j++)
diff --git a/Post/OctreePost.cpp b/Post/OctreePost.cpp
index 97f913d9129bf319727161c61082ddd584ce18e0..1b8e745a64acb87efd3a3d301216cb4a2d9a4371 100644
--- a/Post/OctreePost.cpp
+++ b/Post/OctreePost.cpp
@@ -1,4 +1,4 @@
-// $Id: OctreePost.cpp,v 1.3 2008-02-17 08:48:08 geuzaine Exp $
+// $Id: OctreePost.cpp,v 1.4 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -24,6 +24,7 @@
 #include "List.h"
 #include "PView.h"
 #include "PViewDataList.h"
+#include "PViewDataGModel.h"
 #include "Numeric.h"
 #include "Message.h"
 #include "ShapeFunctions.h"
@@ -216,107 +217,120 @@ static void addListOfStuff(Octree *o, List_T *l, int nbelm)
 
 OctreePost::~OctreePost() 
 {
-  Octree_Delete(ST); Octree_Delete(VT); Octree_Delete(TT);
-  Octree_Delete(SQ); Octree_Delete(VQ); Octree_Delete(TQ);
-  Octree_Delete(SS); Octree_Delete(VS); Octree_Delete(TS);
-  Octree_Delete(SH); Octree_Delete(VH); Octree_Delete(TH);
-  Octree_Delete(SI); Octree_Delete(VI); Octree_Delete(TI);
-  Octree_Delete(SY); Octree_Delete(VY); Octree_Delete(TY);
+  if(_ST) Octree_Delete(_ST); if(_VT) Octree_Delete(_VT); if(_TT) Octree_Delete(_TT);
+  if(_SQ) Octree_Delete(_SQ); if(_VQ) Octree_Delete(_VQ); if(_TQ) Octree_Delete(_TQ);
+  if(_SS) Octree_Delete(_SS); if(_VS) Octree_Delete(_VS); if(_TS) Octree_Delete(_TS);
+  if(_SH) Octree_Delete(_SH); if(_VH) Octree_Delete(_VH); if(_TH) Octree_Delete(_TH);
+  if(_SI) Octree_Delete(_SI); if(_VI) Octree_Delete(_VI); if(_TI) Octree_Delete(_TI);
+  if(_SY) Octree_Delete(_SY); if(_VY) Octree_Delete(_VY); if(_TY) Octree_Delete(_TY);
+  if(_GModel) Octree_Delete(_GModel);
 }
 
 OctreePost::OctreePost(PView *v) 
-  : theView(v)
+  : _ST(0), _VT(0), _TT(0), _SQ(0), _VQ(0), _TQ(0), _SS(0), _VS(0), _TS(0),
+    _SH(0), _VH(0), _TH(0), _SI(0), _VI(0), _TI(0), _SY(0), _VY(0), _TY(0),
+    _GModel(0), _theView(v), _viewType(-1)
 {
-  PViewDataList *l = dynamic_cast<PViewDataList*>(theView->getData());
-
-  if(!l){
-    Msg(GERROR, "OctreePost only accepts list-based view data for now");
-    return;
-  }
-
-  SBoundingBox3d bb = l->getBoundingBox();
+  SBoundingBox3d bb = v->getData()->getBoundingBox();
 
   double min[3] = {bb.min().x(), bb.min().y(), bb.min().z()};
 
   double size[3] = {bb.max().x() - bb.min().x(),
 		    bb.max().y() - bb.min().y(),
 		    bb.max().z() - bb.min().z()};		    
-  
+
   const int maxElePerBucket = 100; // memory vs. speed trade-off
 
-  SL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle);
-  addListOfStuff(SL, l->SL, 6 + 2 * l->getNumTimeSteps());
-  Octree_Arrange(SL);
-  VL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle);
-  addListOfStuff(VL, l->VL, 6 + 6 * l->getNumTimeSteps());
-  Octree_Arrange(VL);
-  TL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle);
-  addListOfStuff(TL, l->TL, 6 + 18 * l->getNumTimeSteps());
-  Octree_Arrange(TL);
-
-  ST = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle);
-  addListOfStuff(ST, l->ST, 9 + 3 * l->getNumTimeSteps());
-  Octree_Arrange(ST);
-  VT = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle);
-  addListOfStuff(VT, l->VT, 9 + 9 * l->getNumTimeSteps());
-  Octree_Arrange(VT);
-  TT = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle);
-  addListOfStuff(TT, l->TT, 9 + 27 * l->getNumTimeSteps());
-  Octree_Arrange(TT);
-
-  SQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle);
-  addListOfStuff(SQ, l->SQ, 12 + 4 * l->getNumTimeSteps());
-  Octree_Arrange(SQ);
-  VQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle);
-  addListOfStuff(VQ, l->VQ, 12 + 12 * l->getNumTimeSteps());
-  Octree_Arrange(VQ);
-  TQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle);
-  addListOfStuff(TQ, l->TQ, 12 + 36 * l->getNumTimeSteps());
-  Octree_Arrange(TQ);
-
-  SS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle);
-  addListOfStuff(SS, l->SS, 12 + 4 * l->getNumTimeSteps());
-  Octree_Arrange(SS);
-  VS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle);
-  addListOfStuff(VS, l->VS, 12 + 12 * l->getNumTimeSteps());
-  Octree_Arrange(VS);
-  TS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle);
-  addListOfStuff(TS, l->TS, 12 + 36 * l->getNumTimeSteps());
-  Octree_Arrange(TS);
-
-  SH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle);
-  addListOfStuff(SH, l->SH, 24 + 8 * l->getNumTimeSteps());
-  Octree_Arrange(SH);
-  VH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle);
-  addListOfStuff(VH, l->VH, 24 + 24 * l->getNumTimeSteps());
-  Octree_Arrange(VH);
-  TH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle);
-  addListOfStuff(TH, l->TH, 24 + 72 * l->getNumTimeSteps());
-  Octree_Arrange(TH);
-
-  SI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle);
-  addListOfStuff(SI, l->SI, 18 + 6 * l->getNumTimeSteps());
-  Octree_Arrange(SI);
-  VI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle);
-  addListOfStuff(VI, l->VI, 18 + 18 * l->getNumTimeSteps());
-  Octree_Arrange(VI);
-  TI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle);
-  addListOfStuff(TI, l->TI, 18 + 54 * l->getNumTimeSteps());
-  Octree_Arrange(TI);
-
-  SY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle);
-  addListOfStuff(SY, l->SY, 15 + 5 * l->getNumTimeSteps());
-  Octree_Arrange(SY);
-  VY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle);
-  addListOfStuff(VY, l->VY, 15 + 15 * l->getNumTimeSteps());
-  Octree_Arrange(VY);
-  TY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle);
-  addListOfStuff(TY, l->TY, 15 + 45 * l->getNumTimeSteps());
-  Octree_Arrange(TY);
+  PViewDataList *l = dynamic_cast<PViewDataList*>(_theView->getData());
+  if(l){
+    _viewType = 0;
+
+    _SL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle);
+    addListOfStuff(_SL, l->SL, 6 + 2 * l->getNumTimeSteps());
+    Octree_Arrange(_SL);
+    _VL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle);
+    addListOfStuff(_VL, l->VL, 6 + 6 * l->getNumTimeSteps());
+    Octree_Arrange(_VL);
+    _TL = Octree_Create(maxElePerBucket, min, size, linBB, linCentroid, linInEle);
+    addListOfStuff(_TL, l->TL, 6 + 18 * l->getNumTimeSteps());
+    Octree_Arrange(_TL);
+
+    _ST = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle);
+    addListOfStuff(_ST, l->ST, 9 + 3 * l->getNumTimeSteps());
+    Octree_Arrange(_ST);
+    _VT = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle);
+    addListOfStuff(_VT, l->VT, 9 + 9 * l->getNumTimeSteps());
+    Octree_Arrange(_VT);
+    _TT = Octree_Create(maxElePerBucket, min, size, triBB, triCentroid, triInEle);
+    addListOfStuff(_TT, l->TT, 9 + 27 * l->getNumTimeSteps());
+    Octree_Arrange(_TT);
+
+    _SQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle);
+    addListOfStuff(_SQ, l->SQ, 12 + 4 * l->getNumTimeSteps());
+    Octree_Arrange(_SQ);
+    _VQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle);
+    addListOfStuff(_VQ, l->VQ, 12 + 12 * l->getNumTimeSteps());
+    Octree_Arrange(_VQ);
+    _TQ = Octree_Create(maxElePerBucket, min, size, quaBB, quaCentroid, quaInEle);
+    addListOfStuff(_TQ, l->TQ, 12 + 36 * l->getNumTimeSteps());
+    Octree_Arrange(_TQ);
+
+    _SS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle);
+    addListOfStuff(_SS, l->SS, 12 + 4 * l->getNumTimeSteps());
+    Octree_Arrange(_SS);
+    _VS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle);
+    addListOfStuff(_VS, l->VS, 12 + 12 * l->getNumTimeSteps());
+    Octree_Arrange(_VS);
+    _TS = Octree_Create(maxElePerBucket, min, size, tetBB, tetCentroid, tetInEle);
+    addListOfStuff(_TS, l->TS, 12 + 36 * l->getNumTimeSteps());
+    Octree_Arrange(_TS);
+
+    _SH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle);
+    addListOfStuff(_SH, l->SH, 24 + 8 * l->getNumTimeSteps());
+    Octree_Arrange(_SH);
+    _VH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle);
+    addListOfStuff(_VH, l->VH, 24 + 24 * l->getNumTimeSteps());
+    Octree_Arrange(_VH);
+    _TH = Octree_Create(maxElePerBucket, min, size, hexBB, hexCentroid, hexInEle);
+    addListOfStuff(_TH, l->TH, 24 + 72 * l->getNumTimeSteps());
+    Octree_Arrange(_TH);
+    
+    _SI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle);
+    addListOfStuff(_SI, l->SI, 18 + 6 * l->getNumTimeSteps());
+    Octree_Arrange(_SI);
+    _VI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle);
+    addListOfStuff(_VI, l->VI, 18 + 18 * l->getNumTimeSteps());
+    Octree_Arrange(_VI);
+    _TI = Octree_Create(maxElePerBucket, min, size, priBB, priCentroid, priInEle);
+    addListOfStuff(_TI, l->TI, 18 + 54 * l->getNumTimeSteps());
+    Octree_Arrange(_TI);
+
+    _SY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle);
+    addListOfStuff(_SY, l->SY, 15 + 5 * l->getNumTimeSteps());
+    Octree_Arrange(_SY);
+    _VY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle);
+    addListOfStuff(_VY, l->VY, 15 + 15 * l->getNumTimeSteps());
+    Octree_Arrange(_VY);
+    _TY = Octree_Create(maxElePerBucket, min, size, pyrBB, pyrCentroid, pyrInEle);
+    addListOfStuff(_TY, l->TY, 15 + 45 * l->getNumTimeSteps());
+    Octree_Arrange(_TY);
+  }
+
+  PViewDataGModel *g = dynamic_cast<PViewDataGModel*>(_theView->getData());
+  if(g){
+    _viewType = 1;
+
+    //_GModel = Octree_Create(maxElePerBucket, min, size, 
+    //		    MElementBB, MElementCentroid, MElementInEle);
+    // add MElement pointers in
+    //Octree_Arrange(_GModel);
+  }
+
 }
 
-bool OctreePost::getValue(void *in, int dim, int nbNod, int nbComp, 
-			  double P[3], int timestep, double *values, double *size_elem)
+bool OctreePost::_getValue(void *in, int dim, int nbNod, int nbComp, 
+			   double P[3], int step, double *values,
+			   double *elementSize)
 {
   if(!in) return false;
 
@@ -327,89 +341,106 @@ bool OctreePost::getValue(void *in, int dim, int nbNod, int nbComp,
   if(!e) return false;
 
   e->xyz2uvw(P, U);
-  if(timestep < 0){
-    for(int i = 0; i < theView->getData()->getNumTimeSteps(); i++)
+  if(step < 0){
+    for(int i = 0; i < _theView->getData()->getNumTimeSteps(); i++)
       for(int j = 0; j < nbComp; j++)
 	values[nbComp * i + j] = e->interpolate(&V[nbNod * nbComp * i + j], 
 						U[0], U[1], U[2], nbComp);
   }
   else{
     for(int j = 0; j < nbComp; j++)
-      values[j] = e->interpolate(&V[nbNod * nbComp * timestep + j], 
+      values[j] = e->interpolate(&V[nbNod * nbComp * step + j], 
 				 U[0], U[1], U[2], nbComp);
   }
 
-  if(size_elem)
-    *size_elem = e->maxEdgeLength();
+  if(elementSize) *elementSize = e->maxEdgeLength();
 
   delete e;
   return true;
 } 
 
 bool OctreePost::searchScalar(double x, double y, double z, double *values, 
-			      int timestep, double *size_elem)
+			      int step, double *size)
 {
   double P[3] = {x, y, z};
 
-  if(timestep < 0)
-    for(int i = 0; i < theView->getData()->getNumTimeSteps(); i++)
+  if(step < 0)
+    for(int i = 0; i < _theView->getData()->getNumTimeSteps(); i++)
       values[i] = 0.0; 
   else
     values[0] = 0.0;
 
-  if(getValue(Octree_Search(P, SS), 3, 4, 1, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, SH), 3, 8, 1, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, SI), 3, 6, 1, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, SY), 3, 5, 1, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, ST), 2, 3, 1, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, SQ), 2, 4, 1, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, SL), 1, 2, 1, P, timestep, values, size_elem)) return true;
+  if(_viewType == 0){
+    if(_getValue(Octree_Search(P, _SS), 3, 4, 1, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _SH), 3, 8, 1, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _SI), 3, 6, 1, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _SY), 3, 5, 1, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _ST), 2, 3, 1, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _SQ), 2, 4, 1, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _SL), 1, 2, 1, P, step, values, size)) return true;
+  }
+
+  if(_viewType == 1){
+    
+  }
 
   return false;
 }
 
 bool OctreePost::searchVector(double x, double y, double z, double *values, 
-			      int timestep, double *size_elem)
+			      int step, double *size)
 {
   double P[3] = {x, y, z};
 
-  if(timestep < 0)
-    for(int i = 0; i < 3 * theView->getData()->getNumTimeSteps(); i++)
+  if(step < 0)
+    for(int i = 0; i < 3 * _theView->getData()->getNumTimeSteps(); i++)
       values[i] = 0.0; 
   else
     for(int i = 0; i < 3; i++)
       values[i] = 0.0;
 
-  if(getValue(Octree_Search(P, VS), 3, 4, 3, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, VH), 3, 8, 3, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, VI), 3, 6, 3, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, VY), 3, 5, 3, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, VT), 2, 3, 3, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, VQ), 2, 4, 3, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, VL), 1, 2, 3, P, timestep, values, size_elem)) return true;
+  if(_viewType == 0){
+    if(_getValue(Octree_Search(P, _VS), 3, 4, 3, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _VH), 3, 8, 3, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _VI), 3, 6, 3, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _VY), 3, 5, 3, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _VT), 2, 3, 3, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _VQ), 2, 4, 3, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _VL), 1, 2, 3, P, step, values, size)) return true;
+  }
+
+  if(_viewType == 1){
+    
+  }
 
   return false;
 }
 
 bool OctreePost::searchTensor(double x, double y, double z, double *values, 
-			      int timestep, double *size_elem)
+			      int step, double *size)
 {
   double P[3] = {x, y, z};
 
-  if(timestep < 0)
-    for(int i = 0; i < 9 * theView->getData()->getNumTimeSteps(); i++)
+  if(step < 0)
+    for(int i = 0; i < 9 * _theView->getData()->getNumTimeSteps(); i++)
       values[i] = 0.0; 
   else
     for(int i = 0; i < 9; i++)
       values[i] = 0.0;
 
-  if(getValue(Octree_Search(P, TS), 3, 4, 9, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, TH), 3, 8, 9, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, TI), 3, 6, 9, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, TY), 3, 5, 9, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, TT), 2, 3, 9, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, TQ), 2, 4, 9, P, timestep, values, size_elem)) return true;
-  if(getValue(Octree_Search(P, TL), 1, 2, 9, P, timestep, values, size_elem)) return true;
+  if(_viewType == 0){
+    if(_getValue(Octree_Search(P, _TS), 3, 4, 9, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _TH), 3, 8, 9, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _TI), 3, 6, 9, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _TY), 3, 5, 9, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _TT), 2, 3, 9, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _TQ), 2, 4, 9, P, step, values, size)) return true;
+    if(_getValue(Octree_Search(P, _TL), 1, 2, 9, P, step, values, size)) return true;
+  }
+
+  if(_viewType == 1){
+    
+  }
 
   return false;
 }
diff --git a/Post/OctreePost.h b/Post/OctreePost.h
index ec7301751f6afd83c351b6f63821acc947fccca5..b1e0911d245097f863c22fa41af0f44a898bccab 100644
--- a/Post/OctreePost.h
+++ b/Post/OctreePost.h
@@ -26,16 +26,20 @@ class PView;
 
 class OctreePost 
 {
-  Octree *SL, *VL, *TL;
-  Octree *ST, *VT, *TT;
-  Octree *SQ, *VQ, *TQ;
-  Octree *SS, *VS, *TS;
-  Octree *SH, *VH, *TH;
-  Octree *SI, *VI, *TI;
-  Octree *SY, *VY, *TY;
-  PView *theView;
-  bool getValue(void *in, int dim, int nbNod, int nbComp, 
-		double P[3], int timestep, double *values, double *size_elem);
+ private:
+  Octree *_SL, *_VL, *_TL;
+  Octree *_ST, *_VT, *_TT;
+  Octree *_SQ, *_VQ, *_TQ;
+  Octree *_SS, *_VS, *_TS;
+  Octree *_SH, *_VH, *_TH;
+  Octree *_SI, *_VI, *_TI;
+  Octree *_SY, *_VY, *_TY;
+  Octree *_GModel;
+  PView *_theView;
+  int _viewType; // internal view type (0=list, 1=GModel) 
+  bool _getValue(void *in, int dim, int nbNod, int nbComp, 
+		 double P[3], int step, double *values,
+		 double *elementSize);
  public :
   OctreePost(PView *);
   ~OctreePost();
@@ -45,11 +49,11 @@ class OctreePost
   // interpolated unless time step is set to a different value than
   // -1.
   bool searchScalar(double x, double y, double z, double *values, 
-		    int timestep = -1, double *size_elem = 0);
+		    int step = -1, double *size = 0);
   bool searchVector(double x, double y, double z, double *values, 
-		    int timestep = -1, double *size_elem = 0);
+		    int step = -1, double *size = 0);
   bool searchTensor(double x, double y, double z, double *values, 
-		    int timestep = -1, double *size_elem = 0);
+		    int step = -1, double *size = 0);
 };
 
 #endif
diff --git a/Post/PView.cpp b/Post/PView.cpp
index 626cb03631c8305f7a95c1fa979869ab4d403faa..5100c4b73c2054b9766d1acfc20338d9ba5a9a5d 100644
--- a/Post/PView.cpp
+++ b/Post/PView.cpp
@@ -1,4 +1,4 @@
-// $Id: PView.cpp,v 1.22 2008-03-12 21:28:53 geuzaine Exp $
+// $Id: PView.cpp,v 1.23 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -231,16 +231,16 @@ bool PView::readPOS(std::string fileName, int fileIndex)
     return false;
   }
 
-  char str[256];
+  char str[256] = "XXX";
   double version;
   int format, size, index = -1;
 
   while(1) {
 
-    do {
-      if(!fgets(str, 256, fp) || feof(fp))
+    while(str[0] != '$'){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
         break;
-    } while(str[0] != '$');
+    } 
     
     if(feof(fp))
       break;
@@ -291,7 +291,7 @@ bool PView::readPOS(std::string fileName, int fileIndex)
     }
 
     do {
-      if(!fgets(str, 256, fp) || feof(fp))
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
 	break;
     } while(str[0] != '$');
 
@@ -310,16 +310,16 @@ bool PView::readMSH(std::string fileName, int fileIndex)
     return false;
   }
 
-  char str[256];
+  char str[256] = "XXX";
   int index = -1;
   bool binary = false, swap = false;
 
   while(1) {
 
-    do {
-      if(!fgets(str, 256, fp) || feof(fp))
-        break;
-    } while(str[0] != '$');
+    while(str[0] != '$'){
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
+	break;
+    }
     
     if(feof(fp))
       break;
@@ -345,7 +345,7 @@ bool PView::readMSH(std::string fileName, int fileIndex)
       if(fileIndex < 0 || fileIndex == index){
 	// read data info
 	if(!fgets(str, sizeof(str), fp)) return false;
-	std::string name = extractDoubleQuotedString(str, 256);
+	std::string name = extractDoubleQuotedString(str, sizeof(str));
 	int timeStep, partition, interpolationScheme, numComp, numNodes;
 	double time;
 	if(!fgets(str, sizeof(str), fp)) return false;
@@ -373,10 +373,9 @@ bool PView::readMSH(std::string fileName, int fileIndex)
     }
     
     do {
-      if(!fgets(str, 256, fp) || feof(fp))
+      if(!fgets(str, sizeof(str), fp) || feof(fp))
 	break;
     } while(str[0] != '$');
-    
   }
 
   fclose(fp);
diff --git a/Post/PViewData.cpp b/Post/PViewData.cpp
index c153ca4c240e6f9966e9559b67d1346b5a0ecd4a..0956aeabec3c50daf7115717e1f344712f256f86 100644
--- a/Post/PViewData.cpp
+++ b/Post/PViewData.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewData.cpp,v 1.12 2008-03-12 21:28:53 geuzaine Exp $
+// $Id: PViewData.cpp,v 1.13 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -23,6 +23,7 @@
 // 
 
 #include "PViewData.h"
+#include "Numeric.h"
 
 PViewData::PViewData()
   : _dirty(true), _fileIndex(0)
@@ -31,7 +32,15 @@ PViewData::PViewData()
 
 bool PViewData::empty()
 {
-  return (!getNumElements() && 
-	  !getNumStrings2D() &&
-	  !getNumStrings3D());
+  return (!getNumElements() && !getNumStrings2D() && !getNumStrings3D());
 }
+
+void PViewData::getScalarValue(int ent, int ele, int nod, int step, double &val)
+{
+  int numComp = getNumComponents(ent, ele, step);
+  double d[9];
+  for(int comp = 0; comp < numComp; comp++)
+    getValue(ent, ele, nod, comp, step, d[comp]);
+  val = ComputeScalarRep(numComp, d);
+}
+
diff --git a/Post/PViewData.h b/Post/PViewData.h
index 53ba037c6d626b1f93d239bd737d29a57d4facd7..9172f4e0d0ae6af333aad111114c854c87193fd8 100644
--- a/Post/PViewData.h
+++ b/Post/PViewData.h
@@ -88,6 +88,10 @@ class PViewData {
   // associated with the node-th node from the ele-th element in the
   // ent-th entity
   virtual void getValue(int ent, int ele, int nod, int comp, int step, double &val) = 0;
+  // Returns a scalar value (same as value for scalars, norm for
+  // vectors, etc.) associated with the node-th node from the ele-th
+  // element in the ent-th entity
+  virtual void getScalarValue(int ent, int ele, int nod, int step, double &val);
   // Returns the number of edges of the ele-th element in the ent-th
   // entity
   virtual int getNumEdges(int ent, int ele) = 0;
@@ -122,12 +126,4 @@ class nameData{
   std::vector<PViewData*> data;
 };
 
-class nameDataLessThan{
- public:
-  bool operator()(const nameData &n1, const nameData &n2) const
-  {
-    return n1.name < n2.name;
-  }
-};
-
 #endif
diff --git a/Post/PViewDataGModel.cpp b/Post/PViewDataGModel.cpp
index f75eb1c4712b8a264d15c9e5013993e7b222e04a..e947442c777b1f629c3ab2e135e00d34f3ef5dfe 100644
--- a/Post/PViewDataGModel.cpp
+++ b/Post/PViewDataGModel.cpp
@@ -1,4 +1,4 @@
-// $Id: PViewDataGModel.cpp,v 1.27 2008-03-13 22:02:08 geuzaine Exp $
+// $Id: PViewDataGModel.cpp,v 1.28 2008-03-18 19:30:14 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -27,7 +27,6 @@
 
 PViewDataGModel::PViewDataGModel(GModel *model) 
   : _model(model), _min(VAL_INF), _max(-VAL_INF)
-
 {
   // store vector of GEntities so we can index them efficiently
   for(GModel::eiter it = _model->firstEdge(); it != _model->lastEdge(); ++it)
@@ -53,6 +52,10 @@ bool PViewDataGModel::finalize()
     _min = std::min(_min, _nodeData[i]->getMin());
     _max = std::max(_max, _nodeData[i]->getMax());
   }
+  for(unsigned int i = 0; i < _elementData.size(); i++){
+    _min = std::min(_min, _elementData[i]->getMin());
+    _max = std::max(_max, _elementData[i]->getMax());
+  }
   setDirty(false);
   return true;
 }
@@ -66,20 +69,28 @@ double PViewDataGModel::getTime(int step)
 {
   if(step < (int)_nodeData.size())
     return _nodeData[step]->getTime();
+  else if(step < (int)_elementData.size())
+    return _elementData[step]->getTime();
   return 0.;
 }
 
 double PViewDataGModel::getMin(int step)
 {
   if(step < 0) return _min;
-  if(step < (int)_nodeData.size()) return _nodeData[step]->getMin();
+  if(step < (int)_nodeData.size()) 
+    return _nodeData[step]->getMin();
+  else if(step < (int)_elementData.size())
+    return _elementData[step]->getMin();
   return 0.;
 }
 
 double PViewDataGModel::getMax(int step)
 {
   if(step < 0) return _max;
-  if(step < (int)_nodeData.size()) return _nodeData[step]->getMax();
+  if(step < (int)_nodeData.size())
+    return _nodeData[step]->getMax();
+  else if(step < (int)_elementData.size())
+    return _elementData[step]->getMax();
   return 0.;
 }
 
@@ -114,16 +125,21 @@ void PViewDataGModel::getNode(int ent, int ele, int nod, double &x, double &y, d
 
 int PViewDataGModel::getNumComponents(int ent, int ele, int step)
 {
-  // no range check here: we assume this is guarded by skipElement()
-  return _nodeData[step]->getNumComp();
+  if(step < (int)_nodeData.size())
+    return _nodeData[step]->getNumComp();
+  else if(step < (int)_elementData.size())
+    return _elementData[step]->getNumComp();
+  return 1;
 }
 
 void PViewDataGModel::getValue(int ent, int ele, int nod, int comp, int step, double &val)
 {
   MVertex *v = _entities[ent]->getMeshElement(ele)->getVertex(nod);
   int index = v->getDataIndex();
-  // no range check here: we assume this is guarded by skipElement()
-  val = _nodeData[step]->getData(index)[comp];
+  if(step < (int)_nodeData.size())
+    val = _nodeData[step]->getData(index)[comp];
+  //else if(step < (int)_elementData.size())
+  //  val = _elementData[step]->getData(index)[nod * numComp + comp];
 }
 
 int PViewDataGModel::getNumEdges(int ent, int ele)
diff --git a/Post/PViewDataGModel.h b/Post/PViewDataGModel.h
index af4d2067719d676b26f6745b7b8106718aa8a302..e81fb2732ce30dbd53154626d2aea9be1126f28f 100644
--- a/Post/PViewDataGModel.h
+++ b/Post/PViewDataGModel.h
@@ -28,9 +28,9 @@
 template<class real>
 class stepData{
  private:
-  // the file the data was read from
+  // the file the data was read from (if empty, refer to PViewData)
   std::string _fileName;
-  // the index in the file
+  // the index in the file (if negative, refer to PViewData)
   int _fileIndex;
   // the value of the time step and value min/max
   double _time, _min, _max;
@@ -80,8 +80,8 @@ class stepData{
       for(unsigned int i = 0; i < _data->size(); i++)
 	if((*_data)[i]) delete [] (*_data)[i];
       delete _data;
+      _data = 0;
     }
-    _data = 0;
   }
 };
 
diff --git a/benchmarks/3d/hexaprism.geo b/benchmarks/3d/hexaprism.geo
index eaf12fe1e2d153812ccb24c3658a2a624f92c6aa..807bbd5b1d0a391582e652615760a02723f5d743 100644
--- a/benchmarks/3d/hexaprism.geo
+++ b/benchmarks/3d/hexaprism.geo
@@ -8,11 +8,12 @@ Line(3) = {3,4};
 Line(4) = {4,1};
 Line Loop(5) = {2,3,4,1};
 Plane Surface(6) = {5};
-Recombine Surface {6};
-Extrude Surface {6, {0.0,0.0,1.0}}{Layers{1,1,1};Recombine;};
+Transfinite Surface{6} = {1,2,3,4};
+Recombine Surface{6};
+Extrude Surface {6, {0.0,0.0,1.0}}{Layers{1};Recombine;};
 Point(15) = {2,0.0,0.0,1.0};
 Line(29) = {15,2};
 Line(30) = {3,15};
 Line Loop(31) = {30,29,2};
 Plane Surface(32) = {31};
-Extrude Surface {32, {0.0,0.0,1.0}}{Layers{1,1,1};Recombine;};
+Extrude Surface {32, {0.0,0.0,1.0}}{Layers{1};Recombine;};
diff --git a/utils/misc/driver.cpp b/utils/misc/driver.cpp
index 5e6b766210db434b9fac5fa6919fb91fe17af2f0..bd8b2b1c1aa8ceb41eae8fd02e99f3f35270f298 100644
--- a/utils/misc/driver.cpp
+++ b/utils/misc/driver.cpp
@@ -17,9 +17,10 @@ int main(int argc, char **argv)
   m->readGEO("../../tutorial/t5.geo");
   m->mesh(3);
   for(GModel::riter it = m->firstRegion(); it != m->lastRegion(); ++it){
-    printf("volume %d contains %d elements:\n", (*it)->tag(), (*it)->getNumMeshElements());
-    for(unsigned int i = 0; i < (*it)->getNumMeshElements(); i++)
-      printf(" %d", (*it)->getMeshElement(i)->getNum());
+    GRegion *r = *it;
+    printf("volume %d contains %d elements:\n", r->tag(), r->getNumMeshElements());
+    for(unsigned int i = 0; i < r->getNumMeshElements(); i++)
+      printf(" %d", r->getMeshElement(i)->getNum());
     printf("\n");
   }
   m->writeMSH("test.msh");