diff --git a/Geo/GModel.cpp b/Geo/GModel.cpp
index e693d950565e0f672c1b1538a266b825e01ad344..01f8e88eb86a5a198a3ebbddf1fc0e1f6df8a371 100644
--- a/Geo/GModel.cpp
+++ b/Geo/GModel.cpp
@@ -622,7 +622,7 @@ void GModel::getMeshVerticesForPhysicalGroup(int dim, int num, std::vector<MVert
 
 MElement *GModel::getMeshElementByTag(int num)
 {
-  int n = (*_newElemNumbers)(num);
+  int n = (_newElemNumbers) ? (*_newElemNumbers)(num) : num;
   if(_elementVectorCache.empty() && _elementMapCache.empty()){
     Msg::Debug("Rebuilding mesh element cache");
     _elementVectorCache.clear();
@@ -637,14 +637,16 @@ MElement *GModel::getMeshElementByTag(int num)
       for(unsigned int i = 0; i < entities.size(); i++)
         for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
           MElement *e = entities[i]->getMeshElement(j);
-          _elementVectorCache[(*_newElemNumbers)(e->getNum())] = e;
+          int ni = (_newElemNumbers) ? (*_newElemNumbers)(e->getNum()) : e->getNum();
+          _elementVectorCache[ni] = e;
         }
     }
     else{
       for(unsigned int i = 0; i < entities.size(); i++)
         for(unsigned int j = 0; j < entities[i]->getNumMeshElements(); j++){
           MElement *e = entities[i]->getMeshElement(j);
-          _elementMapCache[(*_newElemNumbers)(e->getNum())] = e;
+          int ni = (_newElemNumbers) ? (*_newElemNumbers)(e->getNum()) : e->getNum();
+          _elementMapCache[ni] = e;
         }
     }
   }
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index e1d8f5d555034c1908b018edf5440dd1848976bb..47946a3669e81177108edeb0158883393d92ddf8 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -364,6 +364,29 @@ void MElement::xyz2uvw(double xyz[3], double uvw[3])
   }
 }
 
+void MElement::movePointFromParentSpaceToElementSpace(double &u, double &v, double &w)
+{
+  if(!getParent()) return;
+  SPoint3 p;
+  getParent()->pnt(u, v, w, p);
+  double xyz[3] = {p.x(), p.y(), p.z()};
+  double uvwE[3];
+  xyz2uvw(xyz, uvwE);
+  u = uvwE[0]; v = uvwE[1]; w = uvwE[2];
+}
+
+void MElement::movePointFromElementSpaceToParentSpace(double &u, double &v, double &w)
+{
+  if(!getParent()) return;
+  SPoint3 p;
+  double uvwE[3] = {u, v, w};
+  pnt(u, v, w, p);
+  double xyz[3] = {p.x(), p.y(), p.z()};
+  double uvwP[3];
+  getParent()->xyz2uvw(xyz, uvwP);
+  u = uvwP[0]; v = uvwP[1]; w = uvwP[2];
+}
+
 double MElement::interpolate(double val[], double u, double v, double w, int stride,
                              int order)
 {
@@ -883,12 +906,12 @@ MElement *MElement::copy(int &num, std::map<int, MVertex*> &vertexMap,
     }
   }
   MElementFactory factory;
-  MElement *newEl = factory.create(eType, vmv, ++num, _partition);
+  MElement *newEl = factory.create(eType, vmv, getNum(), _partition);
   if(eParent && !getDomain(0) && !getDomain(1)) {
     std::map<MElement*, MElement*>::iterator it = newParents.find(eParent);
     MElement *newParent;
     if(it == newParents.end()) {
-      newParent = eParent->copy(num, vertexMap, newParents, newDomains);
+      newParent = eParent->copy(++num, vertexMap, newParents, newDomains);
       newParents[eParent] = newParent;
     }
     else
@@ -901,7 +924,7 @@ MElement *MElement::copy(int &num, std::map<int, MVertex*> &vertexMap,
     std::map<MElement*, MElement*>::iterator it = newDomains.find(dom);
     MElement *newDom;
     if(it == newDomains.end()) {
-      newDom = dom->copy(num, vertexMap, newParents, newDomains);
+      newDom = dom->copy(++num, vertexMap, newParents, newDomains);
       newDomains[dom] = newDom;
     }
     else
diff --git a/Geo/MElement.h b/Geo/MElement.h
index d13f59b206792236ad22b9535bf44cf95cc79568..ff1165a37cb9199054514bdc5ad5ecba675dfd7f 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -229,6 +229,10 @@ class MElement
   // invert the parametrisation
   virtual void xyz2uvw(double xyz[3], double uvw[3]);
 
+  // move point between parent and element parametric spaces
+  virtual void movePointFromParentSpaceToElementSpace(double &u, double &v, double &w);
+  virtual void movePointFromElementSpaceToParentSpace(double &u, double &v, double &w);
+
   // test if a point, given in parametric coordinates, belongs to the
   // element
   virtual bool isInside(double u, double v, double w) = 0;
diff --git a/Geo/MElementCut.cpp b/Geo/MElementCut.cpp
index eb4267ecf0c6eb7cb4127d40dfb8b83008714893..e38e0ad9f99babaaf73ad09eaab17cbbc69c2d25 100644
--- a/Geo/MElementCut.cpp
+++ b/Geo/MElementCut.cpp
@@ -341,6 +341,12 @@ void MLineChild::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 
 void MTriangleBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 {
+  *npts = 0;
+  if(_intpt) delete [] _intpt;
+  _intpt = new IntPt[getNGQTPts(pOrder)];
+  int nptsi;
+  IntPt *ptsi;
+
   double uvw[3][3];
   for(int j = 0; j < 3; j++) {
     double xyz[3] = {_v[j]->x(), _v[j]->y(), _v[j]->z()};
@@ -350,26 +356,34 @@ void MTriangleBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
   MVertex v1(uvw[1][0], uvw[1][1], uvw[1][2]);
   MVertex v2(uvw[2][0], uvw[2][1], uvw[2][2]);
   MTriangle tt(&v0, &v1, &v2);
-  tt.getIntegrationPoints(pOrder, npts, pts);
+  tt.getIntegrationPoints(pOrder, &nptsi, &ptsi);
   double jac[3][3];
-  for(int ip = 0; ip < (*npts); ip++){
-    const double u = pts[ip]->pt[0];
-    const double v = pts[ip]->pt[1];
-    const double w = pts[ip]->pt[2];
-    const double weight = pts[ip]->weight;
+  for(int ip = 0; ip < nptsi; ip++){
+    const double u = ptsi[ip].pt[0];
+    const double v = ptsi[ip].pt[1];
+    const double w = ptsi[ip].pt[2];
+    const double weight = ptsi[ip].weight;
     const double detJ = tt.getJacobian(u, v, w, jac);
     SPoint3 p; tt.pnt(u, v, w, p);
-    (*pts[ip]).pt[0] = p.x();
-    (*pts[ip]).pt[1] = p.y();
-    (*pts[ip]).pt[2] = p.z();
-    (*pts[ip]).weight = detJ * weight;
+    _intpt[ip].pt[0] = p.x();
+    _intpt[ip].pt[1] = p.y();
+    _intpt[ip].pt[2] = p.z();
+    _intpt[ip].weight = weight;//detJ * weight;
   }
+  *npts = nptsi;
+  *pts = _intpt;
 }
 
 //----------------------------------- MPolygonBorder ------------------------------
 
 void MPolygonBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 {
+  *npts = 0;
+  if(_intpt) delete [] _intpt;
+  _intpt = new IntPt[getNGQTPts(pOrder) * _parts.size()];
+  int nptsi;
+  IntPt *ptsi;
+
   std::vector<MVertex*> verts;
   for(unsigned int i = 0; i < _parts.size(); i++) {
     double uvw[3][3];
@@ -383,20 +397,22 @@ void MPolygonBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
     verts.push_back(new MVertex(uvw[2][0], uvw[2][1], uvw[2][2]));
   }
   MPolygon pp(verts);
-  pp.getIntegrationPoints(pOrder, npts, pts);
+  pp.getIntegrationPoints(pOrder, &nptsi, &ptsi);
   double jac[3][3];
-  for(int ip = 0; ip < (*npts); ip++){
-    const double u = pts[ip]->pt[0];
-    const double v = pts[ip]->pt[1];
-    const double w = pts[ip]->pt[2];
-    const double weight = pts[ip]->weight;
+  for(int ip = 0; ip < nptsi; ip++){
+    const double u = ptsi[ip].pt[0];
+    const double v = ptsi[ip].pt[1];
+    const double w = ptsi[ip].pt[2];
+    const double weight = ptsi[ip].weight;
     const double detJ = pp.getJacobian(u, v, w, jac);
     SPoint3 p; pp.pnt(u, v, w, p);
-    (*pts[ip]).pt[0] = p.x();
-    (*pts[ip]).pt[1] = p.y();
-    (*pts[ip]).pt[2] = p.z();
-    (*pts[ip]).weight = detJ * weight;
+    _intpt[ip].pt[0] = p.x();
+    _intpt[ip].pt[1] = p.y();
+    _intpt[ip].pt[2] = p.z();
+    _intpt[ip].weight = weight;//detJ * weight;
   }
+  *npts = nptsi;
+  *pts = _intpt;
   for(unsigned int i = 0; i < verts.size(); i++)
     delete verts[i];
 }
@@ -405,6 +421,12 @@ void MPolygonBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 
 void MLineBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 {
+  *npts = 0;
+  if(_intpt) delete [] _intpt;
+  _intpt = new IntPt[getNGQLPts(pOrder)];
+  int nptsi;
+  IntPt *ptsi;
+
   double uvw[2][3];
   for(int j = 0; j < 2; j++) {
     double xyz[3] = {_v[j]->x(), _v[j]->y(), _v[j]->z()};
@@ -413,20 +435,22 @@ void MLineBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
   MVertex v0(uvw[0][0], uvw[0][1], uvw[0][2]);
   MVertex v1(uvw[1][0], uvw[1][1], uvw[1][2]);
   MLine ll(&v0, &v1);
-  ll.getIntegrationPoints(pOrder, npts, pts);
+  ll.getIntegrationPoints(pOrder, &nptsi, &ptsi);
   double jac[3][3];
-  for(int ip = 0; ip < (*npts); ip++){
-    const double u = pts[ip]->pt[0];
-    const double v = pts[ip]->pt[1];
-    const double w = pts[ip]->pt[2];
-    const double weight = pts[ip]->weight;
+  for(int ip = 0; ip < nptsi; ip++){
+    const double u = ptsi[ip].pt[0];
+    const double v = ptsi[ip].pt[1];
+    const double w = ptsi[ip].pt[2];
+    const double weight = ptsi[ip].weight;
     const double detJ = ll.getJacobian(u, v, w, jac);
     SPoint3 p; ll.pnt(u, v, w, p);
-    (*pts[ip]).pt[0] = p.x();
-    (*pts[ip]).pt[1] = p.y();
-    (*pts[ip]).pt[2] = p.z();
-    (*pts[ip]).weight = detJ * weight;
+    _intpt[ip].pt[0] = p.x();
+    _intpt[ip].pt[1] = p.y();
+    _intpt[ip].pt[2] = p.z();
+    _intpt[ip].weight = weight;//detJ * weight;
   }
+  *npts = nptsi;
+  *pts = _intpt;
 }
 
 //---------------------------------------- CutMesh ----------------------------
@@ -1120,7 +1144,7 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
     newPhysTags[d][0] = gm->getMaxPhysicalNumber(d); //max value at [dim][0]
   }
 
-  int numEle = 0; //element number increment
+  int numEle = gm->getNumMeshElements(); //element number increment
   std::map<MElement*, MElement*> newParents; //map<oldParent, newParent>
   std::map<MElement*, MElement*> newDomains; //map<oldDomain, newDomain>
 
diff --git a/Geo/MElementCut.h b/Geo/MElementCut.h
index 40c0529c1003bd938b5265268864d7b98c8357c2..359fb2aabfab3d064b5ce997ef6c893e81363f3c 100644
--- a/Geo/MElementCut.h
+++ b/Geo/MElementCut.h
@@ -320,16 +320,17 @@ class MLineChild : public MLine {
 class MTriangleBorder : public MTriangle {
  protected:
   MElement* _domains[2];
+  IntPt *_intpt;
  public:
   MTriangleBorder(MVertex *v0, MVertex *v1, MVertex *v2, int num = 0, int part = 0,
                   MElement* d1 = NULL, MElement* d2 = NULL)
-    : MTriangle(v0, v1, v2, num, part)
+    : MTriangle(v0, v1, v2, num, part), _intpt(0)
   {
     _domains[0] = d1; _domains[1] = d2;
   }
   MTriangleBorder(std::vector<MVertex*> v, int num = 0, int part = 0,
                   MElement* d1 = NULL, MElement* d2 = NULL)
-    : MTriangle(v, num, part)
+    : MTriangle(v, num, part), _intpt(0)
   {
     _domains[0] = d1; _domains[1] = d2;
   }
@@ -342,38 +343,24 @@ class MTriangleBorder : public MTriangle {
     return NULL;
   }
   virtual int getTypeForMSH() const { return MSH_TRI_B; }
-  virtual const polynomialBasis* getFunctionSpace(int order=-1) const
-  {
-    return getParent()->getFunctionSpace(order);
-  }
-  virtual void getShapeFunctions(double u, double v, double w, double s[], int o)
-  {
-    getParent()->getShapeFunctions(u, v, w, s, o);
-  }
-  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o)
-  {
-    getParent()->getGradShapeFunctions(u, v, w, s, o);
-  }
-  virtual void xyz2uvw(double xyz[3], double uvw[3])
-  {
-    getParent()->xyz2uvw(xyz,uvw);
-  }
+  // the integration points of the MTriangleBorder are in the parent element space
   virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts);
 };
 
 class MPolygonBorder : public MPolygon {
  protected:
   MElement* _domains[2];
+  IntPt *_intpt;
  public:
   MPolygonBorder(std::vector<MTriangle*> v, int num = 0, int part = 0,
                   MElement* d1 = NULL, MElement* d2 = NULL)
-    : MPolygon(v, num, part)
+    : MPolygon(v, num, part), _intpt(0)
   {
     _domains[0] = d1; _domains[1] = d2;
   }
   MPolygonBorder(std::vector<MVertex*> v, int num = 0, int part = 0,
                   MElement* d1 = NULL, MElement* d2 = NULL)
-    : MPolygon(v, num, part)
+    : MPolygon(v, num, part), _intpt(0)
   {
     _domains[0] = d1; _domains[1] = d2;
   }
@@ -386,38 +373,24 @@ class MPolygonBorder : public MPolygon {
     return NULL;
   }
   virtual int getTypeForMSH() const { return MSH_POLYG_B; }
-  virtual const polynomialBasis* getFunctionSpace(int order=-1) const
-  {
-    return getParent()->getFunctionSpace(order);
-  }
-  virtual void getShapeFunctions(double u, double v, double w, double s[], int o)
-  {
-    getParent()->getShapeFunctions(u, v, w, s, o);
-  }
-  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o)
-  {
-    getParent()->getGradShapeFunctions(u, v, w, s, o);
-  }
-  virtual void xyz2uvw(double xyz[3], double uvw[3])
-  {
-    getParent()->xyz2uvw(xyz,uvw);
-  }
+  // the integration points of the MPolygonBorder are in the parent element space
   virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts);
 };
 
 class MLineBorder : public MLine {
  protected:
   MElement* _domains[2];
+  IntPt *_intpt;
  public:
   MLineBorder(MVertex *v0, MVertex *v1, int num = 0, int part = 0,
               MElement* d1 = NULL, MElement* d2 = NULL)
-    : MLine(v0, v1, num, part)
+    : MLine(v0, v1, num, part), _intpt(0)
   {
     _domains[0] = d1; _domains[1] = d2;
   }
   MLineBorder(std::vector<MVertex*> v, int num = 0, int part = 0,
               MElement* d1 = NULL, MElement* d2 = NULL)
-    : MLine(v, num, part)
+    : MLine(v, num, part), _intpt(0)
   {
     _domains[0] = d1; _domains[1] = d2;
   }
@@ -430,23 +403,7 @@ class MLineBorder : public MLine {
     return NULL;
   }
   virtual int getTypeForMSH() const { return MSH_LIN_B; }
-  virtual const polynomialBasis* getFunctionSpace(int order=-1) const
-  {
-    if (this->getParent()) return getParent()->getFunctionSpace(order);
-    else return NULL;
-  }
-  virtual void getShapeFunctions(double u, double v, double w, double s[], int o)
-  {
-    getParent()->getShapeFunctions(u, v, w, s, o);
-  }
-  virtual void getGradShapeFunctions(double u, double v, double w, double s[][3], int o)
-  {
-    getParent()->getGradShapeFunctions(u, v, w, s, o);
-  }
-  virtual void xyz2uvw(double xyz[3], double uvw[3])
-  {
-    getParent()->xyz2uvw(xyz,uvw);
-  }
+  // the integration points of the MLineBorder are in the parent element space
   virtual void getIntegrationPoints(int pOrder, int *npts, IntPt **pts);
 };