diff --git a/Geo/discreteDiskFace.cpp b/Geo/discreteDiskFace.cpp
index 6a639cde7068a731d86ea33d4bf93a42cd0ca420..591228d545322973170a92c1e5ee1b62e39210ad 100644
--- a/Geo/discreteDiskFace.cpp
+++ b/Geo/discreteDiskFace.cpp
@@ -1,3 +1,4 @@
+
 // Gmsh - Copyright (C) 1997-2015 C. Geuzaine, J.-F. Remacle
 //
 // See the LICENSE.txt file for license information. Please report all
@@ -26,6 +27,118 @@
 #include "convexCombinationTerm.h"  // #
 #include "BasisFactory.h"
 
+static inline void functionShapes(int p, double Xi[2], double* phi)
+{
+
+  switch(p){
+
+  case 1:
+    phi[0] = 1. - Xi[0] - Xi[1];
+    phi[1] = Xi[0];
+    phi[2] = Xi[1];
+    break;
+
+  case 2:
+    phi[0] = 1. - 3.*(Xi[0]+Xi[1]) + 2.*(Xi[0]+Xi[1])*(Xi[0]+Xi[1]);
+    phi[1] = Xi[0]*(2.*Xi[0]-1);
+    phi[2] = Xi[1]*(2.*Xi[1]-1);
+    phi[3] = 4.*Xi[0]*(1.-Xi[0]-Xi[1]);
+    phi[4] = 4.*Xi[0]*Xi[1];
+    phi[5] = 4.*Xi[1]*(1.-Xi[0]-Xi[1]);
+    break;
+
+  default:
+    Msg::Error("(discreteDiskFace) static inline functionShapes, only first and second order available; order %d requested.",p);
+    break;
+  }
+
+}
+
+
+static inline void derivativeShapes(int p, double Xi[2], double phi[6][2])
+{
+
+  switch(p){
+
+  case 1:
+    phi[0][0] = -1. ; phi[0][1] = -1.;
+    phi[1][0] = 1.  ; phi[1][1] = 0.;
+    phi[2][0] = 0.  ; phi[2][1] = 1.;
+
+    break;
+
+  case 2:
+    phi[0][0] = -3. + 4.*(Xi[0]+Xi[1])   ; phi[0][1] = -3. + 4.*(Xi[0]+Xi[1]);
+    phi[1][0] = 4.*Xi[0] - 1.            ; phi[1][1] = 0.;
+    phi[2][0] = 0.                       ; phi[2][1] = 4.*Xi[1] - 1.;
+    phi[3][0] = 4. - 8.*Xi[0] - 4.*Xi[1] ; phi[3][1] = -4.*Xi[0];
+    phi[4][0] = 4.*Xi[1]                 ; phi[4][1] = 4.*Xi[0];
+    phi[5][0] = -4.*Xi[1]                ; phi[5][1] = 4. - 4.*Xi[0] - 8.*Xi[1];
+    break;
+
+  default:
+    Msg::Error("(discreteDiskFace) static inline derivativeShapes, only first and second order available; order %d requested.",p);
+    break;
+  }
+
+}
+
+static inline void uv2xi(discreteDiskFaceTriangle* my_ddft, double U[2], double Xi[2]){
+
+  double M[2][2], R[2];    
+  const SPoint3 p0 = my_ddft->p[0];
+  const SPoint3 p1 = my_ddft->p[1];
+  const SPoint3 p2 = my_ddft->p[2];
+  M[0][0] = p1.x() - p0.x();
+  M[0][1] = p2.x() - p0.x();
+  M[1][0] = p1.y() - p0.y();
+  M[1][1] = p2.y() - p0.y();
+  R[0] = (U[0] - p0.x());
+  R[1] = (U[1] - p0.y());
+  sys2x2(M, R, Xi);
+
+  if (my_ddft->tri->getPolynomialOrder() == 2){
+
+    int iter = 1, maxiter = 20;
+    double error = 1., tol = 1.e-6;
+    while (error > tol && iter < maxiter){// Newton-Raphson
+
+      double fs[6];// phi_i
+      functionShapes(2,Xi,fs);
+      double ds[6][2];// dPhi_i/dXi_j
+      derivativeShapes(2,Xi,ds);
+
+      double un[2] = {0.,0.};
+      double jac[2][2] = {{0.,0.},{0.,0.}}; // d(u,v)/d(xi,eta)
+      for (int i=0; i<6; i++){
+	double ui[2] = {my_ddft->p[i].x(),my_ddft->p[i].y()};
+	for(int k=0; k<2; k++){
+	  un[k] += ui[k] * fs[i];
+	  for (int j=0; j<2; j++)
+	    jac[k][j] += ui[k] * ds[i][j];
+	}
+      }
+
+      double inv[2][2];
+      inv2x2(jac,inv);
+      double xin[2] = {Xi[0],Xi[1]};
+      error = 0.;
+      for (int i=0; i<2; i++){
+	for (int j=0; j<2; j++)
+	  xin[i] += inv[i][j] * (U[j] - un[j]);
+	error += (xin[i] - Xi[i])*(xin[i] - Xi[i]);
+      }
+
+      error = sqrt(error);
+      Xi[0] = xin[0];
+      Xi[1] = xin[1];
+      iter++;
+
+    } // end Newton-Raphson
+  }// end order 2
+}
+
+
 // The three things that are mandatory to manipulate octrees (octree in (u;v)).
 static void discreteDiskFaceBB(void *a, double*mmin, double*mmax)
 { // called once  by buildOct()
@@ -63,9 +176,11 @@ static int discreteDiskFaceInEle(void *a, double*c)// # mark
 { // called once  by buildOct()
 
   discreteDiskFaceTriangle *t = (discreteDiskFaceTriangle *)a;
-
-  double X[2];
-  const double eps = 1.e-8;
+  double Xi[2];
+  double U[2] = {c[0],c[1]};
+  uv2xi(t,U,Xi);
+  double eps = 1e-8;
+  /*
   
   if (t->tri->getPolynomialOrder() == 1){
 
@@ -95,8 +210,8 @@ static int discreteDiskFaceInEle(void *a, double*c)// # mark
     t6.xyz2uvw(xyz,X); 
     
   }
-  
-  if(X[0] > -eps && X[1] > -eps && 1. - X[0] - X[1] > -eps)
+  */
+  if(Xi[0] > -eps && Xi[1] > -eps && 1. - Xi[0] - Xi[1] > -eps)
     return 1;
 
   return 0;
@@ -146,7 +261,7 @@ discreteDiskFace::discreteDiskFace(GFace *gf, std::vector<MTriangle*> &mesh, int
     tagElementOrder = -1;
     Msg::Error("discreteDiskFace:: only p=1 or p=2 allowed");
   }
-  mynodalbasis = BasisFactory::getNodalBasis(tagElementOrder);
+  //mynodalbasis = BasisFactory::getNodalBasis(tagElementOrder);
 
   std::map<MVertex*,MVertex*> v2v;// mesh vertex |-> face vertex 
   std::map<MEdge,MVertex*,Less_Edge> ed2nodes; // edge to interior node(s) 
@@ -477,11 +592,18 @@ bool discreteDiskFace::parametrize() const
 
 void discreteDiskFace::getTriangleUV(const double u,const double v,
 				     discreteDiskFaceTriangle **mt,
-				     double &_u, double &_v)const{
+				     double &_xi, double &_eta)const{
   double uv[3] = {u,v,0.};
   *mt = (discreteDiskFaceTriangle*) Octree_Search(uv,oct);
   if (!(*mt)) return;
+  
+  double Xi[2];
+  double U[2] = {u,v};
+  uv2xi(*mt,U,Xi);
+  _xi = Xi[0];
+  _eta = Xi[1];
 
+  /*
   if (_order == 1){
     double M[2][2],X[2],R[2];
     const SPoint3 p0 = (*mt)->p[0];
@@ -518,7 +640,8 @@ void discreteDiskFace::getTriangleUV(const double u,const double v,
     _u = uv[0];// xi
     _v = uv[1];// eta    
 
-  }  
+  } 
+  */ 
 }
 
 void discreteDiskFace::checkOrientationUV(){
@@ -549,19 +672,21 @@ void discreteDiskFace::checkOrientationUV(){
 // (u;v) |-> < (x;y;z); GFace; (u;v) >
 GPoint discreteDiskFace::point(const double par1, const double par2) const
 {
-  double U,V;
+  double xi,eta;
   double par[2] = {par1,par2};
   discreteDiskFaceTriangle* dt;
-  getTriangleUV(par1,par2,&dt,U,V);// return Xi,Eta
+  getTriangleUV(par1,par2,&dt,xi,eta);// return Xi,Eta
+  double Xi[2] = {xi,eta};
   if (!dt) {
     GPoint gp = GPoint(1.e22,1.e22,1.e22,_parent,par);
     gp.setNoSuccess();
     return gp;
   }
-
+  
   //polynomialBasis myPolynomial = polynomialBasis(dt->tri->getTypeForMSH());
   double eval[_N]; 
-  mynodalbasis->f(U,V,0.,eval);//#mark
+  //mynodalbasis->f(U,V,0.,eval);//#mark
+  functionShapes(_order,Xi,eval);
   double X=0,Y=0,Z=0;
   for(int io=0; io<_N; io++){
     X += dt->tri->getVertex(io)->x()*eval[io];
@@ -626,9 +751,9 @@ double discreteDiskFace::curvatures(const SPoint2 &param, SVector3 *dirMax, SVec
 
 Pair<SVector3, SVector3> discreteDiskFace::firstDer(const SPoint2 &param) const
 {
-  double U,V;
+  double xi,eta;
   discreteDiskFaceTriangle* ddft;
-  getTriangleUV(param.x(),param.y(),&ddft,U,V);
+  getTriangleUV(param.x(),param.y(),&ddft,xi,eta);
 
   MTriangle* tri = NULL;
   if (ddft) tri = ddft->tri;
@@ -637,10 +762,10 @@ Pair<SVector3, SVector3> discreteDiskFace::firstDer(const SPoint2 &param) const
     return Pair<SVector3, SVector3>(SVector3(1,0,0), SVector3(0,1,0));
   }
   
-
-  double df[_N][3]; 
-  mynodalbasis->df(U,V,0.,df); 
- 
+  double Xi[2] = {xi,eta};
+  double df[_N][2]; 
+  //mynodalbasis->df(U,V,0.,df); 
+  derivativeShapes(_order,Xi,df);
   double dxdxi[3][2] = {{0.,0.},{0.,0.},{0.,0.}};
 
   double dudxi[2][2] = {{0.,0.},{0.,0.}};
@@ -885,6 +1010,4 @@ GPoint discreteDiskFace::intersectionWithCircle(const SVector3 &n1, const SVecto
 }
 
 
-
-
 #endif
diff --git a/Geo/discreteDiskFace.h b/Geo/discreteDiskFace.h
index 499dcf875c3b77360ab56a7d08bde15db771e8a0..61a845d61d923a3ab636274e20ada61a9588b8dc 100644
--- a/Geo/discreteDiskFace.h
+++ b/Geo/discreteDiskFace.h
@@ -96,7 +96,7 @@ class discreteDiskFace : public GFace {
   mutable discreteDiskFaceTriangle *_ddft;
   mutable Octree *oct;
   mutable std::vector<double> _coords;
-  const nodalBasis* mynodalbasis;
+  //  const nodalBasis* mynodalbasis;
 };
 
 #endif