diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index 248f98f1895baee7386309bc969a6dab7251a759..adcf36203dcafa8f518a080cadbb026cb0e88fcb 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -1,4 +1,4 @@
-// $Id: MElement.cpp,v 1.59 2008-03-18 19:30:14 geuzaine Exp $
+// $Id: MElement.cpp,v 1.60 2008-03-19 21:22:36 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -133,27 +133,20 @@ double MTetrahedron::etaShapeMeasure()
 }
 
 double MTetrahedron::getVolume()
-{ 
+{
   double mat[3][3];
   getMat(mat);
   return det3x3(mat) / 6.;
 }
 
-bool MTetrahedron::invertmapping(double *p, double *uvw, double tol)
+void MTetrahedron::xyz2uvw(double xyz[3], double uvw[3])
 {
-  double mat[3][3];
-  double b[3], dum;
+  double mat[3][3], b[3], det;
   getMat(mat);
-  b[0] = p[0] - getVertex(0)->x();
-  b[1] = p[1] - getVertex(0)->y();
-  b[2] = p[2] - getVertex(0)->z();
-  sys3x3(mat, b, uvw, &dum);
-  if(uvw[0] >= -tol && uvw[1] >= -tol && uvw[2] >= -tol &&
-     uvw[0] <= 1. + tol && uvw[1] <= 1. + tol && uvw[2] <= 1. + tol &&
-     1. - uvw[0] - uvw[1] - uvw[2] > -tol) {
-    return true;
-  }
-  return false;
+  b[0] = xyz[0] - getVertex(0)->x();
+  b[1] = xyz[1] - getVertex(0)->y();
+  b[2] = xyz[2] - getVertex(0)->z();
+  sys3x3(mat, b, uvw, &det);
 }
 
 int MHexahedron::getVolumeSign()
@@ -224,6 +217,172 @@ std::string MElement::getInfoString()
   return std::string(tmp);
 }
 
+double MElement::getJacobian(double u, double v, double w, double jac[3][3])
+{
+  jac[0][0] = jac[0][1] = jac[0][2] = 0.;
+  jac[1][0] = jac[1][1] = jac[1][2] = 0.;
+  jac[2][0] = jac[2][1] = jac[2][2] = 0.;
+  double s[3];
+  switch(getDim()){
+  case 3 :
+    for(int i = 0; i < getNumVertices(); i++) {
+      getGradShapeFunction(i, u, v, w, s);
+      MVertex *p = getVertex(i);
+      jac[0][0] += p->x() * s[0]; jac[0][1] += p->y() * s[0]; jac[0][2] += p->z() * s[0];
+      jac[1][0] += p->x() * s[1]; jac[1][1] += p->y() * s[1]; jac[1][2] += p->z() * s[1];
+      jac[2][0] += p->x() * s[2]; jac[2][1] += p->y() * s[2]; jac[2][2] += p->z() * s[2];
+    }
+    return fabs(jac[0][0] * jac[1][1] * jac[2][2] + jac[0][2] * jac[1][0] * jac[2][1] +
+		jac[0][1] * jac[1][2] * jac[2][0] - jac[0][2] * jac[1][1] * jac[2][0] -
+		jac[0][0] * jac[1][2] * jac[2][1] - jac[0][1] * jac[1][0] * jac[2][2]);
+  case 2 :
+    for(int i = 0; i < getNumVertices(); i++) {
+      getGradShapeFunction(i, u, v, w, s);
+      MVertex *p = getVertex(i);
+      jac[0][0] += p->x() * s[0]; jac[0][1] += p->y() * s[0]; jac[0][2] += p->z() * s[0];
+      jac[1][0] += p->x() * s[1]; jac[1][1] += p->y() * s[1]; jac[1][2] += p->z() * s[1];
+    }
+    {
+      double a[3], b[3], c[3];
+      a[0]= getVertex(1)->x() - getVertex(0)->x(); 
+      a[1]= getVertex(1)->y() - getVertex(0)->y();
+      a[2]= getVertex(1)->z() - getVertex(0)->z();	
+      b[0]= getVertex(2)->x() - getVertex(0)->x(); 
+      b[1]= getVertex(2)->y() - getVertex(0)->y();
+      b[2]= getVertex(2)->z() - getVertex(0)->z();	
+      prodve(a, b, c);
+      jac[2][0] = c[0]; jac[2][1] = c[1]; jac[2][2] = c[2]; 
+    }
+    return sqrt(SQR(jac[0][0] * jac[1][1] - jac[0][1] * jac[1][0]) +
+		SQR(jac[0][2] * jac[1][0] - jac[0][0] * jac[1][2]) +
+		SQR(jac[0][1] * jac[1][2] - jac[0][2] * jac[1][1]));
+  case 1:
+    for(int i = 0; i < getNumVertices(); i++) {
+      getGradShapeFunction(i, u, v, w, s);
+      MVertex *p = getVertex(i);
+      jac[0][0] += p->x() * s[0]; jac[0][1] += p->y() * s[0]; jac[0][2] += p->z() * s[0];
+    }
+    {
+      double a[3], b[3], c[3];
+      a[0]= getVertex(1)->x() - getVertex(0)->x(); 
+      a[1]= getVertex(1)->y() - getVertex(0)->y();
+      a[2]= getVertex(1)->z() - getVertex(0)->z();	
+      if((fabs(a[0]) >= fabs(a[1]) && fabs(a[0]) >= fabs(a[2])) ||
+	 (fabs(a[1]) >= fabs(a[0]) && fabs(a[1]) >= fabs(a[2]))) {
+	b[0] = a[1]; b[1] = -a[0]; b[2] = 0.;
+      }
+      else {
+	b[0] = 0.; b[1] = a[2]; b[2] = -a[1];
+      }
+      prodve(a, b, c);
+      jac[1][0] = b[0]; jac[1][1] = b[1]; jac[1][2] = b[2]; 
+      jac[2][0] = c[0]; jac[2][1] = c[1]; jac[2][2] = c[2]; 
+    }
+    return sqrt(SQR(jac[0][0]) + SQR(jac[0][1]) + SQR(jac[0][2]));
+  default:
+    return 1.;
+  }
+}
+
+void MElement::xyz2uvw(double xyz[3], double uvw[3])
+{
+  // general Newton routine for the nonlinear case (more efficient
+  // routines are implemented for simplices, where the basis functions
+  // are linear)
+  uvw[0] = uvw[1] = uvw[2] = 0.;
+  int iter = 1, maxiter = 20;
+  double error = 1., tol = 1.e-6;
+
+  while (error > tol && iter < maxiter){
+    double jac[3][3];
+    if(!getJacobian(uvw[0], uvw[1], uvw[2], jac)) break;
+    double xn = 0., yn = 0., zn = 0.;
+    for (int i = 0; i < getNumVertices(); i++) {
+      double s;
+      getShapeFunction(i, uvw[0], uvw[1], uvw[2], s);
+      MVertex *v = getVertex(i);
+      xn += v->x() * s;
+      yn += v->y() * s;
+      zn += v->z() * s;
+    }
+    double inv[3][3];
+    inv3x3(jac, inv);
+    double un = uvw[0] +
+      inv[0][0] * (xyz[0] - xn) + inv[1][0] * (xyz[1] - yn) + inv[2][0] * (xyz[2] - zn);
+    double vn = uvw[1] +
+      inv[0][1] * (xyz[0] - xn) + inv[1][1] * (xyz[1] - yn) + inv[2][1] * (xyz[2] - zn) ;
+    double wn = uvw[2] +
+      inv[0][2] * (xyz[0] - xn) + inv[1][2] * (xyz[1] - yn) + inv[2][2] * (xyz[2] - zn) ;
+    error = sqrt(SQR(un - uvw[0]) + SQR(vn - uvw[1]) + SQR(wn - uvw[2]));
+    uvw[0] = un;
+    uvw[1] = vn;
+    uvw[2] = wn;
+    iter++ ;
+  }
+}
+
+double MElement::interpolate(double val[], double u, double v, double w, int stride)
+{
+  double sum = 0;
+  int j = 0;
+  for(int i = 0; i < getNumVertices(); i++){
+    double s;
+    getShapeFunction(i, u, v, w, s);
+    sum += val[j] * s;
+    j += stride;
+  }
+  return sum;
+}
+
+void MElement::interpolateGrad(double val[], double u, double v, double w, double f[3],
+			       int stride, double invjac[3][3])
+{
+  double dfdu[3] = {0., 0., 0.};
+  int j = 0;
+  for(int i = 0; i < getNumVertices(); i++){
+    double s[3];
+    getGradShapeFunction(i, u, v, w, s);
+    dfdu[0] += val[j] * s[0];
+    dfdu[1] += val[j] * s[1];
+    dfdu[2] += val[j] * s[2];
+    j += stride;
+  }
+  if(invjac){
+    matvec(invjac, dfdu, f);
+  }
+  else{
+    double jac[3][3], inv[3][3];
+    getJacobian(u, v, w, jac);
+    inv3x3(jac, inv);
+    matvec(inv, dfdu, f);
+  }
+}
+
+void MElement::interpolateCurl(double val[], double u, double v, double w, double f[3],
+			       int stride)
+{
+  double fx[3], fy[3], fz[3], jac[3][3], inv[3][3];
+  getJacobian(u, v, w, jac);
+  inv3x3(jac, inv);
+  interpolateGrad(&val[0], u, v, w, fx, stride, inv);
+  interpolateGrad(&val[1], u, v, w, fy, stride, inv);
+  interpolateGrad(&val[2], u, v, w, fz, stride, inv);
+  f[0] = fz[1] - fy[2];
+  f[1] = -(fz[0] - fx[2]);
+  f[2] = fy[0] - fx[1];
+}
+
+double MElement::interpolateDiv(double val[], double u, double v, double w, int stride)
+{
+  double fx[3], fy[3], fz[3], jac[3][3], inv[3][3];
+  getJacobian(u, v, w, jac);
+  inv3x3(jac, inv);
+  interpolateGrad(&val[0], u, v, w, fx, stride, inv);
+  interpolateGrad(&val[1], u, v, w, fy, stride, inv);
+  interpolateGrad(&val[2], u, v, w, fz, stride, inv);
+  return fx[0] + fy[1] + fz[2];
+}
+
 void MElement::writeMSH(FILE *fp, double version, bool binary, int num, 
 			int elementary, int physical)
 {
@@ -534,35 +693,6 @@ void MTriangle::pnt(int ord, MVertex *vs[], double uu, double vv, SPoint3 &p)
 #endif
 }
 
-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)
-{
-  MTriangle::pnt(_order, &(*(_vs.begin())), uu, vv, p);
-}
-
-void MTriangle6::jac(double uu, double vv , double j[2][3])  
-{
-  MTriangle::jac(2, _vs, uu, vv, j);
-}
-
-void MTriangle6::pnt(double uu, double vv, SPoint3 &p){
-  MTriangle::pnt(2, _vs, uu, vv, p);
-}
-
-void MTriangle::jac(double uu, double vv, double j[2][3])
-{
-  jac(1, 0, uu, vv, j);
-}
-
-void MTriangle::pnt(double uu, double vv, SPoint3 &p)
-{
-  MTriangle::pnt(1, 0, uu, vv, p);
-}
-
 int MTriangle6::getNumEdgesRep(){ return 3 * 6; }
 
 void MTriangle6::getEdgeRep(int num, double *x, double *y, double *z, SVector3 *n)
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 27de345dcf0c027b00902857d33d7a3505f2f354..222070a36b2d4f7f3982e716c77a7af7b7be0e0a 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -142,6 +142,37 @@ class MElement
   // Returns an information string for the element
   virtual std::string getInfoString();
 
+  // Returns the interpolating nodal shape function associated with
+  // node num, evaluated at point (u,v,w) in parametric coordinates
+  virtual void getShapeFunction(int num, double u, double v, double w,
+				double &s) = 0;
+
+  // Returns the gradient of of the nodal shape function associated
+  // with node num, evaluated at point (u,v,w) in parametric
+  // coordinates
+  virtual void getGradShapeFunction(int num, double u, double v, double w,
+				    double s[3]) = 0;
+
+  // Returns the Jacobian of the element evaluated at point (u,v,w) in
+  // parametric coordinates
+  double getJacobian(double u, double v, double w, double jac[3][3]);
+
+  // Inverts the parametrisation
+  virtual void xyz2uvw(double xyz[3], double uvw[3]);
+
+  // Tests if a point, given in parametric coordinates, belongs to the
+  // element
+  virtual bool isInside(double u, double v, double w, double tol=1.e-8) = 0;
+
+  // Interpolate the given nodal data (resp. its gradient, curl and
+  // divergence) at point (u,v,w) in parametric coordinates
+  double interpolate(double val[], double u, double v, double w, int stride=1);
+  void interpolateGrad(double val[], double u, double v, double w, double f[3],
+		       int stride=1, double invjac[3][3]=0);
+  void interpolateCurl(double val[], double u, double v, double w, double f[3],
+		       int stride=3);
+  double interpolateDiv(double val[], double u, double v, double w, int stride=3);
+
   // IO routines
   virtual void writeMSH(FILE *fp, double version=1.0, bool binary=false, 
 			int num=0, int elementary=1, int physical=1);
@@ -217,6 +248,28 @@ class MLine : public MElement {
   {
     MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
   }
+  virtual void getShapeFunction(int num, double u, double v, double w, double &s) 
+  {
+    switch(num) {
+    case 0  : s = 0.5 * (1. - u); break;
+    case 1  : s = 0.5 * (1. + u); break;
+    default : s = 0.; break;
+    }
+  }
+  virtual void getGradShapeFunction(int num, double u, double v, double w, double s[3]) 
+  {
+    switch(num) {
+    case 0  : s[0] = -0.5; s[1] = 0.; s[2] = 0.; break;
+    case 1  : s[0] =  0.5; s[1] = 0.; s[2] = 0.; break;
+    default : s[0] = s[1] = s[2] = 0.; break;
+    }
+  }
+  virtual bool isInside(double u, double v, double w, double tol=1.e-8)
+  {
+    if(u < -(1. + tol) || u > (1. + tol))
+      return false;
+    return true;
+  }
 };
 
 class MLine3 : public MLine {
@@ -274,7 +327,7 @@ class MLineN : public MLine {
   {
     for(unsigned int i = 2; i < v.size(); i++)
       _vs.push_back(v[i]);
-    for(unsigned int i = 0 ; i < _vs.size(); i++)
+    for(unsigned int i = 0; i < _vs.size(); i++)
       _vs[i]->setPolynomialOrder(_vs.size() + 1);
   }
   ~MLineN(){}
@@ -304,8 +357,6 @@ class MTriangle : public MElement {
  protected:
   MVertex *_v[3];
  public :
-  virtual void jac(int order, MVertex *verts[], double u, double v, double jac[2][3]);
-  virtual void pnt(int order, MVertex *verts[], double u, double v, SPoint3 &);
   MTriangle(MVertex *v0, MVertex *v1, MVertex *v2, int num=0, int part=0) 
     : MElement(num, part)
   {
@@ -318,13 +369,6 @@ class MTriangle : public MElement {
   }
   ~MTriangle(){}
   virtual int getDim(){ return 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();
-  }
   virtual double gammaShapeMeasure();
   virtual int getNumVertices(){ return 3; }
   virtual MVertex *getVertex(int num){ return _v[num]; }
@@ -369,8 +413,40 @@ class MTriangle : public MElement {
   {
     MVertex *tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
   }
-  virtual void jac(double u, double v, double j[2][3]);
-  virtual void pnt(double u, double v, SPoint3&);
+  virtual void jac(int order, MVertex *verts[], double u, double v, double jac[2][3]);
+  virtual void jac(double u, double v, double j[2][3])
+  {
+    jac(1, 0, u, v, j);
+  }
+  virtual void pnt(int order, MVertex *verts[], double u, double v, SPoint3 &);
+  virtual void pnt(double u, double v, SPoint3 &p)
+  {
+    pnt(1, 0, u, v, p);
+  }
+  virtual void getShapeFunction(int num, double u, double v, double w, double &s) 
+  {
+    switch(num){
+    case 0  : s = 1. - u - v; break;
+    case 1  : s =      u    ; break;
+    case 2  : s =          v; break;
+    default : s = 0.; break;
+    }
+  }
+  virtual void getGradShapeFunction(int num, double u, double v, double w, double s[3]) 
+  {
+    switch(num) {
+    case 0  : s[0] = -1.; s[1] = -1.; s[2] =  0.; break;
+    case 1  : s[0] =  1.; s[1] =  0.; s[2] =  0.; break;
+    case 2  : s[0] =  0.; s[1] =  1.; s[2] =  0.; break;
+    default : s[0] = s[1] = s[2] = 0.; break;
+    }
+  }
+  virtual bool isInside(double u, double v, double w, double tol=1.e-8)
+  {
+    if(u < (-tol) || v < (-tol) || u > ((1. + tol) - v))
+      return false; 
+    return true;
+  }
 };
 
 class MTriangle6 : public MTriangle {
@@ -429,8 +505,14 @@ class MTriangle6 : public MTriangle {
     tmp = _v[1]; _v[1] = _v[2]; _v[2] = tmp;
     tmp = _vs[0]; _vs[0] = _vs[2]; _vs[2] = tmp;
   }
-  virtual void jac ( double u, double v , double j[2][3]) ;
-  virtual void pnt(double u, double v, SPoint3&);
+  virtual void jac(double u, double v, double j[2][3])
+  {
+    MTriangle::jac(2, _vs, u, v, j);
+  }
+  virtual void pnt(double u, double v, SPoint3 &p)
+  {
+    MTriangle::pnt(2, _vs, u, v, p);
+  }
 };
 
 class MTriangleN : public MTriangle {
@@ -461,7 +543,7 @@ class MTriangleN : public MTriangle {
   }
   ~MTriangleN(){}
   virtual int getPolynomialOrder(){ return _order; }
-  virtual int getNumVertices(){ return 3 + _vs.size() ; }
+  virtual int getNumVertices(){ return 3 + _vs.size(); }
   virtual MVertex *getVertex(int num){ return num < 3 ? _v[num] : _vs[num - 3]; }
   virtual int getNumFaceVertices()
   {
@@ -502,8 +584,14 @@ class MTriangleN : public MTriangle {
     inv.insert(inv.begin(), _vs.rbegin(), _vs.rend());
     _vs = inv;
   }
-  virtual void jac(double u, double v, double jac[2][3]);
-  virtual void pnt(double u, double v, SPoint3&);
+  virtual void jac(double u, double v, double j[2][3])
+  {
+    MTriangle::jac(_order, &(*(_vs.begin())), u, v, j);
+  }
+  virtual void pnt(double u, double v, SPoint3 &p)
+  {
+    MTriangle::pnt(_order, &(*(_vs.begin())), u, v, p);
+  }
 };
 
 class MQuadrangle : public MElement {
@@ -560,6 +648,32 @@ class MQuadrangle : public MElement {
   {
     MVertex *tmp = _v[1]; _v[1] = _v[3]; _v[3] = tmp;
   }
+  virtual void getShapeFunction(int num, double u, double v, double w, double &s) 
+  {
+    switch(num) {
+    case 0  : s = 0.25 * (1. - u) * (1. - v); break;
+    case 1  : s = 0.25 * (1. + u) * (1. - v); break;
+    case 2  : s = 0.25 * (1. + u) * (1. + v); break;
+    case 3  : s = 0.25 * (1. - u) * (1. + v); break;
+    default : s = 0.; break;
+    }
+  }
+  virtual void getGradShapeFunction(int num, double u, double v, double w, double s[3]) 
+  {
+    switch(num) {
+    case 0  : s[0] = -0.25 * (1. - v); s[1] = -0.25 * (1. - u); s[2] = 0.; break;
+    case 1  : s[0] =  0.25 * (1. - v); s[1] = -0.25 * (1. + u); s[2] = 0.; break;
+    case 2  : s[0] =  0.25 * (1. + v); s[1] =  0.25 * (1. + u); s[2] = 0.; break;
+    case 3  : s[0] = -0.25 * (1. + v); s[1] =  0.25 * (1. - u); s[2] = 0.; break;
+    default : s[0] = s[1] = s[2] = 0.; break;
+    }
+  }
+  virtual bool isInside(double u, double v, double w, double tol=1.e-8)
+  {
+    if(u < -(1. + tol) || v < -(1. + tol) || u > (1. + tol) || v > (1. + tol))
+      return false;
+    return true;
+  }
 };
 
 class MQuadrangle8 : public MQuadrangle {
@@ -744,7 +858,7 @@ class MTetrahedron : public MElement {
   {
     MVertex *tmp = _v[0]; _v[0] = _v[1]; _v[1] = tmp;
   }
-  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();
@@ -760,8 +874,33 @@ class MTetrahedron : public MElement {
   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);
+  void xyz2uvw(double xyz[3], double uvw[3]);
+  virtual void getShapeFunction(int num, double u, double v, double w, double &s) 
+  {
+    switch(num) {
+    case 0  : s = 1. - u - v - w; break;
+    case 1  : s =      u        ; break;
+    case 2  : s =          v    ; break;
+    case 3  : s =              w; break;
+    default : s = 0.; break;
+    }
+  }
+  virtual void getGradShapeFunction(int num, double u, double v, double w, double s[3]) 
+  {
+    switch(num) {
+    case 0  : s[0] = -1.; s[1] = -1.; s[2] = -1.; break;
+    case 1  : s[0] =  1.; s[1] =  0.; s[2] =  0.; break;
+    case 2  : s[0] =  0.; s[1] =  1.; s[2] =  0.; break;
+    case 3  : s[0] =  0.; s[1] =  0.; s[2] =  1.; break;
+    default : s[0] = s[1] = s[2] = 0.; break;
+    }
+  }
+  virtual bool isInside(double u, double v, double w, double tol=1.e-8)
+  {
+    if(u < (-tol) || v < (-tol) || w < (-tol) || u > ((1. + tol) - v - w))
+      return false;
+    return true;
+  }
 };
 
 class MTetrahedron10 : public MTetrahedron {
@@ -923,6 +1062,57 @@ class MHexahedron : public MElement {
     tmp = _v[4]; _v[4] = _v[6]; _v[6] = tmp;
   }
   virtual int getVolumeSign();
+  virtual void getShapeFunction(int num, double u, double v, double w, double &s) 
+  {
+    switch(num) {
+    case 0  : s = (1. - u) * (1. - v) * (1. - w) * 0.125; break;
+    case 1  : s = (1. + u) * (1. - v) * (1. - w) * 0.125; break;
+    case 2  : s = (1. + u) * (1. + v) * (1. - w) * 0.125; break;
+    case 3  : s = (1. - u) * (1. + v) * (1. - w) * 0.125; break;
+    case 4  : s = (1. - u) * (1. - v) * (1. + w) * 0.125; break;
+    case 5  : s = (1. + u) * (1. - v) * (1. + w) * 0.125; break;
+    case 6  : s = (1. + u) * (1. + v) * (1. + w) * 0.125; break;
+    case 7  : s = (1. - u) * (1. + v) * (1. + w) * 0.125; break;
+    default : s = 0.; break;
+    }
+  }
+  virtual void getGradShapeFunction(int num, double u, double v, double w, double s[3]) 
+  {
+    switch(num) {
+    case 0  : s[0] = -0.125 * (1. - v) * (1. - w);
+              s[1] = -0.125 * (1. - u) * (1. - w);
+              s[2] = -0.125 * (1. - u) * (1. - v); break;
+    case 1  : s[0] =  0.125 * (1. - v) * (1. - w);
+              s[1] = -0.125 * (1. + u) * (1. - w);
+              s[2] = -0.125 * (1. + u) * (1. - v); break;
+    case 2  : s[0] =  0.125 * (1. + v) * (1. - w);
+              s[1] =  0.125 * (1. + u) * (1. - w);
+              s[2] = -0.125 * (1. + u) * (1. + v); break;
+    case 3  : s[0] = -0.125 * (1. + v) * (1. - w);
+              s[1] =  0.125 * (1. - u) * (1. - w);
+              s[2] = -0.125 * (1. - u) * (1. + v); break;
+    case 4  : s[0] = -0.125 * (1. - v) * (1. + w);
+              s[1] = -0.125 * (1. - u) * (1. + w);
+              s[2] =  0.125 * (1. - u) * (1. - v); break;
+    case 5  : s[0] =  0.125 * (1. - v) * (1. + w);
+              s[1] = -0.125 * (1. + u) * (1. + w);
+              s[2] =  0.125 * (1. + u) * (1. - v); break;
+    case 6  : s[0] =  0.125 * (1. + v) * (1. + w);
+              s[1] =  0.125 * (1. + u) * (1. + w);
+              s[2] =  0.125 * (1. + u) * (1. + v); break;
+    case 7  : s[0] = -0.125 * (1. + v) * (1. + w);
+              s[1] =  0.125 * (1. - u) * (1. + w);
+              s[2] =  0.125 * (1. - u) * (1. + v); break;
+    default : s[0] = s[1] = s[2] = 0.; break;
+    }
+  }
+  virtual bool isInside(double u, double v, double w, double tol=1.e-8)
+  {
+    if(u < -(1. + tol) || v < -(1. + tol) || w < -(1. + tol) || 
+       u > (1. + tol) || v > (1. + tol) || w > (1. + tol))
+      return false;
+    return true;
+  }
 };
 
 class MHexahedron20 : public MHexahedron {
@@ -1200,6 +1390,49 @@ class MPrism : public MElement {
     tmp = _v[3]; _v[3] = _v[4]; _v[4] = tmp;
   }
   virtual int getVolumeSign();
+  virtual void getShapeFunction(int num, double u, double v, double w, double &s) 
+  {
+    switch(num) {
+    case 0  : s = (1. - u - v) * (1. - w) * 0.5; break;
+    case 1  : s =       u      * (1. - w) * 0.5; break;
+    case 2  : s =           v  * (1. - w) * 0.5; break;
+    case 3  : s = (1. - u - v) * (1. + w) * 0.5; break;
+    case 4  : s =       u      * (1. + w) * 0.5; break;
+    case 5  : s =           v  * (1. + w) * 0.5; break;
+    default : s = 0.; break;
+    }
+  }
+  virtual void getGradShapeFunction(int num, double u, double v, double w, double s[3]) 
+  {
+    switch(num) {
+    case 0  : s[0] = -0.5 * (1. - w)    ; 
+              s[1] = -0.5 * (1. - w)    ;
+              s[2] = -0.5 * (1. - u - v); break;
+    case 1  : s[0] =  0.5 * (1. - w)    ; 
+              s[1] =  0.                ;
+              s[2] = -0.5 * u           ; break;
+    case 2  : s[0] =  0.                ; 
+              s[1] =  0.5 * (1. - w)    ;
+              s[2] = -0.5 * v           ; break;
+    case 3  : s[0] = -0.5 * (1. + w)    ; 
+              s[1] = -0.5 * (1. + w)    ;
+              s[2] =  0.5 * (1. - u - v); break;
+    case 4  : s[0] =  0.5 * (1. + w)    ; 
+              s[1] =  0.                ;
+              s[2] =  0.5 * u           ; break;
+    case 5  : s[0] =  0.                ; 
+              s[1] =  0.5 * (1. + w)    ;
+              s[2] =  0.5 * v           ; break;
+    default : s[0] = s[1] = s[2] = 0.; break;
+    }
+  }
+  virtual bool isInside(double u, double v, double w, double tol=1.e-8)
+  {
+    if(w > (1. + tol) || w < -(1. + tol) || u < (1. + tol)
+       || v < (1. + tol) || u > ((1. + tol) - v))
+      return false;
+    return true;
+  }
 };
 
 class MPrism15 : public MPrism {
@@ -1439,6 +1672,55 @@ class MPyramid : public MElement {
     MVertex *tmp = _v[0]; _v[0] = _v[2]; _v[2] = tmp;
   }
   virtual int getVolumeSign();
+  virtual void getShapeFunction(int num, double u, double v, double w, double &s) 
+  {
+    double r;
+    if(w != 1. && num != 4) r = u * v * w / (1. - w);
+    else                    r = 0.;
+    switch(num) {
+    case 0  : s = 0.25 * ((1. - u) * (1. - v) - w + r); break;
+    case 1  : s = 0.25 * ((1. + u) * (1. - v) - w - r); break;
+    case 2  : s = 0.25 * ((1. + u) * (1. + v) - w + r); break;
+    case 3  : s = 0.25 * ((1. - u) * (1. + v) - w - r); break;
+    case 4  : s = w; break;
+    default : s = 0.; break;
+    }
+  }
+  virtual void getGradShapeFunction(int num, double u, double v, double w, double s[3]) 
+  {
+    if(w == 1. && num != 4) {
+      s[0] =  0.25; 
+      s[1] =  0.25;
+      s[2] = -0.25; 
+    }
+    else{
+      switch(num) {
+      case 0  : s[0] = 0.25 * (-(1. - v) + v * w / (1. - w));
+	        s[1] = 0.25 * (-(1. - u) + u * w / (1. - w));
+      	        s[2] = 0.25 * (-1.       + u * v / (1. - w) / (1. - w)); break;
+      case 1  : s[0] = 0.25 * ( (1. - v) + v * w / (1. - w));
+	        s[1] = 0.25 * (-(1. + u) + u * w / (1. - w));
+	        s[2] = 0.25 * (-1.       + u * v / (1. - w) / (1. - w)); break;
+      case 2  : s[0] = 0.25 * ( (1. + v) + v * w / (1. - w));
+                s[1] = 0.25 * ( (1. + u) + u * w / (1. - w));
+                s[2] = 0.25 * (-1.       + u * v / (1. - w) / (1. - w)); break;
+      case 3  : s[0] = 0.25 * (-(1. + v) + v * w / (1. - w));
+                s[1] = 0.25 * ( (1. - u) + u * w / (1. - w));
+                s[2] = 0.25 * (-1.       + u * v / (1. - w) / (1. - w)); break;
+      case 4  : s[0] = 0.; 
+                s[1] = 0.;
+                s[2] = 1.; break;
+      default : s[0] = s[1] = s[2] = 0.; break;
+      }
+    }
+  }
+  virtual bool isInside(double u, double v, double w, double tol=1.e-8)
+  {
+    if(u < (w - (1. + tol)) || u > ((1. + tol) - w) || v < (w - (1. + tol)) ||
+       v > ((1. + tol) - w) || w < (-tol) || w > (1. + tol))
+      return false;
+    return true;
+  }
 };
 
 class MPyramid13 : public MPyramid {
diff --git a/Mesh/meshGRegionDelaunayInsertion.cpp b/Mesh/meshGRegionDelaunayInsertion.cpp
index 82df613ff9003101164d1df4a0d8925d4e53d89a..f903157c0237451014e0e20ead27493ac1e867b8 100644
--- a/Mesh/meshGRegionDelaunayInsertion.cpp
+++ b/Mesh/meshGRegionDelaunayInsertion.cpp
@@ -1,4 +1,4 @@
-// $Id: meshGRegionDelaunayInsertion.cpp,v 1.41 2008-03-18 19:30:14 geuzaine Exp $
+// $Id: meshGRegionDelaunayInsertion.cpp,v 1.42 2008-03-19 21:22:36 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -811,8 +811,8 @@ void insertVerticesInRegion (GRegion *gr)
       double center[3];
       worst->circumcenter(center);
       double uvw[3];
-      bool inside = worst->tet()->invertmapping(center, uvw);
-      if(inside){
+      worst->tet()->xyz2uvw(center, uvw);
+      if(worst->tet()->isInside(uvw[0], uvw[1], uvw[2])){
 	MVertex *v = new MVertex(center[0], center[1], center[2], worst->onWhat());
 	v->setNum(NUM++);
 	double lc1 = 
@@ -820,8 +820,8 @@ void insertVerticesInRegion (GRegion *gr)
 	  uvw[0] * vSizes[worst->tet()->getVertex(1)->getNum()] +
 	  uvw[1] * vSizes[worst->tet()->getVertex(2)->getNum()] +
 	  uvw[2] * vSizes[worst->tet()->getVertex(3)->getNum()];
-	double lc =  BGM_MeshSize(gr, 0, 0, center[0], center[1], center[2]);
-	//	double lc = std::min(lc1, BGM_MeshSize(gr, 0, 0, center[0], center[1], center[2]));
+	double lc = BGM_MeshSize(gr, 0, 0, center[0], center[1], center[2]);
+	// double lc = std::min(lc1, BGM_MeshSize(gr, 0, 0, center[0], center[1], center[2]));
 	vSizes.push_back(lc1);
 	vSizesBGM.push_back(lc);
 	// compute mesh spacing there