From c8200a8f66f193e0ec0d983ff7a4ac1a61ab88bc Mon Sep 17 00:00:00 2001
From: Gaetan Bricteux <gaetan.bricteux@uclouvain.be>
Date: Mon, 7 Dec 2009 13:03:33 +0000
Subject: [PATCH] - setting pointers as arguments to limit copying - use
 fullmatrix to store levelset values at nodes - fix compile + clean up

---
 Geo/MElementCut.cpp                           |  250 ++-
 Solver/multiscaleLaplace.cpp                  |    2 +-
 contrib/DiscreteIntegration/Integration3D.cpp | 1649 +++++++++--------
 contrib/DiscreteIntegration/Integration3D.h   |  316 ++--
 contrib/DiscreteIntegration/recurCut.cpp      |  530 ++----
 contrib/DiscreteIntegration/recurCut.h        |   12 +-
 6 files changed, 1295 insertions(+), 1464 deletions(-)

diff --git a/Geo/MElementCut.cpp b/Geo/MElementCut.cpp
index ac50ddb52e..667d49dae2 100644
--- a/Geo/MElementCut.cpp
+++ b/Geo/MElementCut.cpp
@@ -21,7 +21,7 @@ void MPolyhedron::_init()
   if(_parts.size() == 0) return;
 
   for(unsigned int i = 0; i < _parts.size(); i++) {
-    if(_parts[i]->getVolume() * _parts[0]->getVolume() < 0)
+    if(_parts[i]->getVolume() * _parts[0]->getVolume() < 0.)
       _parts[i]->revert();
     for(int j = 0; j < 4; j++) {
       int k;
@@ -217,47 +217,6 @@ void MPolygon::_initVertices()
     }
   }
 
-  /*std::vector<MEdge>::iterator ite = edges.begin();
-  MVertex *vINIT = ite->getVertex(0);
-  _vertices.push_back(ite->getVertex(0));
-  _vertices.push_back(ite->getVertex(1));
-  edges.erase(ite);
-
-  while(edges.size() > 1) {
-    for(ite = edges.begin(); ite != edges.end(); ite++) {
-      if(ite->getVertex(0) == _vertices.back()) {
-        if(ite->getVertex(1) != vINIT) {
-          _vertices.push_back(ite->getVertex(1));
-          edges.erase(ite);
-        }
-        else {
-          edges.erase(ite);
-          ite = edges.begin();
-          vINIT = ite->getVertex(0);
-          _vertices.push_back(ite->getVertex(0));
-          _vertices.push_back(ite->getVertex(1));
-          edges.erase(ite);
-        }
-        break;
-      }
-      else if(ite->getVertex(1) == _vertices.back()) {
-        if(ite->getVertex(0) != vINIT) {
-          _vertices.push_back(ite->getVertex(0));
-          edges.erase(ite);
-        }
-        else {
-          edges.erase(ite);
-          ite = edges.begin();
-          vINIT = ite->getVertex(0);
-          _vertices.push_back(ite->getVertex(0));
-          _vertices.push_back(ite->getVertex(1));
-          edges.erase(ite);
-        }
-        break;
-      }
-    }
-  }*/
-
   // innerVertices
   for(unsigned int i = 0; i < _parts.size(); i++) {
     for(int j = 0; j < 3; j++) {
@@ -427,14 +386,14 @@ void MLineBorder::getIntegrationPoints(int pOrder, int *npts, IntPt **pts)
 
 #if defined(HAVE_DINTEGRATION)
 
-static bool equalV(MVertex *v, const DI_Point &p)
+static bool equalV(MVertex *v, const DI_Point *p)
 {
-  return (fabs(v->x() - p.x()) < 1.e-15 &&
-          fabs(v->y() - p.y()) < 1.e-15 &&
-          fabs(v->z() - p.z()) < 1.e-15);
+  return (fabs(v->x() - p->x()) < 1.e-15 &&
+          fabs(v->y() - p->y()) < 1.e-15 &&
+          fabs(v->z() - p->z()) < 1.e-15);
 }
 
-static int getElementVertexNum(DI_Point &p, MElement *e)
+static int getElementVertexNum(DI_Point *p, MElement *e)
 {
   for(int i = 0; i < e->getNumVertices(); i++)
     if(equalV(e->getVertex(i), p))
@@ -442,7 +401,7 @@ static int getElementVertexNum(DI_Point &p, MElement *e)
   return -1;
 }
 
-static void assignPhysicals(GModel *GM, std::vector<int> gePhysicals, int reg, int dim,
+static void assignPhysicals(GModel *GM, std::vector<int> &gePhysicals, int reg, int dim,
                             std::map<int, std::map<int, std::string> > physicals[4])
 {
   for(unsigned int i = 0; i < gePhysicals.size(); i++){
@@ -495,8 +454,8 @@ static int getBorderTag(int lsTag, int count, int &maxTag, std::map<int, int> &b
 
 typedef std::set<MVertex*,MVertexLessThanLexicographic> newVerticesContainer ;
 
-static void elementCutMesh(MElement *e, gLevelset *ls,
-                           std::map<int, std::map<int, double> > &verticesLs,
+static void elementCutMesh(MElement *e, std::vector<const gLevelset *> &RPN,
+                           fullMatrix<double> &verticesLs,
                            GEntity *ge, GModel *GM, int &numEle, std::map<int, MVertex*> &vertexMap,
 			   newVerticesContainer &newVertices,
                            std::map<int, std::vector<MElement*> > elements[10],
@@ -505,12 +464,12 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
                            std::map<int, int> newPhysTags[4],
                            std::map<int, int> borderElemTags[2],
                            std::map<int, int> borderPhysTags[2],
-                           std::vector<DI_CuttingPoint> &cp,
-                           std::vector<DI_Line> &lines,
-                           std::vector<DI_Triangle> &triangles,
-                           std::vector<DI_Quad> &quads,
-                           std::vector<DI_Tetra> &tetras,
-                           std::vector<DI_Hexa> &hexas)
+                           DI_Point::Container &cp,
+                           std::vector<DI_Line *> &lines,
+                           std::vector<DI_Triangle *> &triangles,
+                           std::vector<DI_Quad *> &quads,
+                           std::vector<DI_Tetra *> &tetras,
+                           std::vector<DI_Hexa *> &hexas)
 {
   int elementary = ge->tag();
   int eType = e->getTypeForMSH();
@@ -518,8 +477,8 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
   std::vector<int> gePhysicals = ge->physicals;
 
   int integOrder = 1;
-  std::vector<DI_IntegrationPoint> ipV;
-  std::vector<DI_IntegrationPoint> ipS;
+  std::vector<DI_IntegrationPoint *> ipV;
+  std::vector<DI_IntegrationPoint *> ipS;
   bool isCut = false;
   unsigned int nbL = lines.size();
   unsigned int nbTr = triangles.size();
@@ -560,6 +519,9 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
   MElementFactory factory;
   MElement *copy = factory.create(eType, vmv, ++numEle, ePart);
 
+  double **nodeLs = new double*[e->getNumPrimaryVertices()];
+  for(int i = 0; i < e->getNumPrimaryVertices(); i++) nodeLs[i] = new double[verticesLs.size2()];
+
   switch (eType) {
   case MSH_TET_4 :
   case MSH_HEX_8 :
@@ -572,9 +534,8 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
                    e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z(),
                    e->getVertex(2)->x(), e->getVertex(2)->y(), e->getVertex(2)->z(),
                    e->getVertex(3)->x(), e->getVertex(3)->y(), e->getVertex(3)->z());
-        std::map<int, double> nodeLs[4];
-        for(int i = 0; i < 4; i++) nodeLs[i] = verticesLs[e->getVertex(i)->getNum()];
-        isCut = T.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+        for(int i = 0; i < 4; i++) nodeLs[i] = &verticesLs(e->getVertex(i)->getIndex(),0);
+        isCut = T.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                       tetras, quads, triangles, 0, nodeLs);
       }
       else if(eType == MSH_HEX_8){
@@ -586,9 +547,8 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
                   e->getVertex(5)->x(), e->getVertex(5)->y(), e->getVertex(5)->z(),
                   e->getVertex(6)->x(), e->getVertex(6)->y(), e->getVertex(6)->z(),
                   e->getVertex(7)->x(), e->getVertex(7)->y(), e->getVertex(7)->z());
-        std::map<int, double> nodeLs[8];
-        for(int i = 0; i < 8; i++) nodeLs[i] = verticesLs[e->getVertex(i)->getNum()];
-        isCut = H.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder, integOrder,
+        for(int i = 0; i < 8; i++) nodeLs[i] = &verticesLs(e->getVertex(i)->getIndex(),0);
+        isCut = H.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder, integOrder,
                       hexas, tetras, quads, triangles, lines, 0, nodeLs);
       }
       else if(eType == MSH_PRI_6){
@@ -596,28 +556,26 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
                     e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z(),
                     e->getVertex(2)->x(), e->getVertex(2)->y(), e->getVertex(2)->z(),
                     e->getVertex(5)->x(), e->getVertex(5)->y(), e->getVertex(5)->z());
-        std::map<int, double> nodeLs[4];
-        for(int i = 0; i < 3; i++) nodeLs[i] = verticesLs[e->getVertex(i)->getNum()];
-        nodeLs[3] = verticesLs[e->getVertex(5)->getNum()];
-        bool iC1 = T1.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+        for(int i = 0; i < 3; i++) nodeLs[i] = &verticesLs(e->getVertex(i)->getIndex(),0);
+        nodeLs[3] = &verticesLs(e->getVertex(5)->getIndex(),0);
+        bool iC1 = T1.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                           tetras, quads, triangles, 0, nodeLs);
         DI_Tetra T2(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z(),
                     e->getVertex(4)->x(), e->getVertex(4)->y(), e->getVertex(4)->z(),
                     e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z(),
                     e->getVertex(5)->x(), e->getVertex(5)->y(), e->getVertex(5)->z());
-        nodeLs[0] = verticesLs[e->getVertex(0)->getNum()];
-        nodeLs[1] = verticesLs[e->getVertex(4)->getNum()];
-        nodeLs[2] = verticesLs[e->getVertex(1)->getNum()];
-        nodeLs[3] = verticesLs[e->getVertex(5)->getNum()];
-        bool iC2 = T2.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+        nodeLs[0] = &verticesLs(e->getVertex(0)->getIndex(),0);
+        nodeLs[1] = &verticesLs(e->getVertex(4)->getIndex(),0);
+        nodeLs[2] = &verticesLs(e->getVertex(1)->getIndex(),0);
+        nodeLs[3] = &verticesLs(e->getVertex(5)->getIndex(),0);
+        bool iC2 = T2.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                           tetras, quads, triangles, 0, nodeLs);
         DI_Tetra T3(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z(),
                     e->getVertex(3)->x(), e->getVertex(3)->y(), e->getVertex(3)->z(),
                     e->getVertex(4)->x(), e->getVertex(4)->y(), e->getVertex(4)->z(),
                     e->getVertex(5)->x(), e->getVertex(5)->y(), e->getVertex(5)->z());
-        nodeLs[0] = verticesLs[e->getVertex(0)->getNum()];
-        for(int i = 1; i < 4; i++) nodeLs[i] = verticesLs[e->getVertex(i+2)->getNum()];
-        bool iC3 = T3.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+        for(int i = 1; i < 4; i++) nodeLs[i] = &verticesLs(e->getVertex(i+2)->getIndex(),0);
+        bool iC3 = T3.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                           tetras, quads, triangles, 0, nodeLs);
         isCut = iC1 || iC2 || iC3;
       }
@@ -626,31 +584,29 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
                     e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z(),
                     e->getVertex(2)->x(), e->getVertex(2)->y(), e->getVertex(2)->z(),
                     e->getVertex(4)->x(), e->getVertex(4)->y(), e->getVertex(4)->z());
-        std::map<int, double> nodeLs[4];
-        for(int i = 0; i < 3; i++) nodeLs[i] = verticesLs[e->getVertex(i)->getNum()];
-        nodeLs[3] = verticesLs[e->getVertex(4)->getNum()];
-        bool iC1 = T1.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+        for(int i = 0; i < 3; i++) nodeLs[i] = &verticesLs(e->getVertex(i)->getIndex(),0);
+        nodeLs[3] = &verticesLs(e->getVertex(4)->getIndex(),0);
+        bool iC1 = T1.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                           tetras, quads, triangles, 0, nodeLs);
         DI_Tetra T2(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z(),
                     e->getVertex(2)->x(), e->getVertex(2)->y(), e->getVertex(2)->z(),
                     e->getVertex(3)->x(), e->getVertex(3)->y(), e->getVertex(3)->z(),
                     e->getVertex(4)->x(), e->getVertex(4)->y(), e->getVertex(4)->z());
-        nodeLs[0] = verticesLs[e->getVertex(0)->getNum()];
-        for(int i = 1; i < 4; i++) nodeLs[i] = verticesLs[e->getVertex(i+1)->getNum()];
-        bool iC2 = T2.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+        nodeLs[0] = &verticesLs(e->getVertex(0)->getIndex(),0);
+        for(int i = 1; i < 4; i++) nodeLs[i] = &verticesLs(e->getVertex(i+1)->getIndex(),0);
+        bool iC2 = T2.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                           tetras, quads, triangles, 0, nodeLs);
         isCut = iC1 || iC2;
       }
       else if(eType == MSH_POLYH_){
-        std::map<int, double> nodeLs[4];
         for(int i = 0; i < e->getNumChildren(); i++) {
           MTetrahedron *t = (MTetrahedron*) e->getChild(i);
           DI_Tetra Tet(t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z(),
                        t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z(),
                        t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z(),
                        t->getVertex(3)->x(), t->getVertex(3)->y(), t->getVertex(3)->z());
-          for(int i = 0; i < 4; i++) nodeLs[i] = verticesLs[t->getVertex(i)->getNum()];
-          bool iC = Tet.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+          for(int i = 0; i < 4; i++) nodeLs[i] = &verticesLs(t->getVertex(i)->getIndex(),0);
+          bool iC = Tet.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                             tetras, quads, triangles, 0, nodeLs);
           isCut = (isCut || iC);
         }
@@ -663,9 +619,9 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
         for (unsigned int i = nbTe; i < tetras.size(); i++){
           MVertex *mv[4] = {NULL, NULL, NULL, NULL};
           for(int j = 0; j < 4; j++){
-            int numV = getElementVertexNum(tetras[i].pt(j), e);
+            int numV = getElementVertexNum(tetras[i]->pt(j), e);
 	    if (numV == -1){
-	      MVertex *newv = new MVertex(tetras[i].x(j), tetras[i].y(j), tetras[i].z(j), 0);
+	      MVertex *newv = new MVertex(tetras[i]->x(j), tetras[i]->y(j), tetras[i]->z(j), 0);
 	      std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
 	      mv[j] = *(it.first);
 	      if (!it.second) delete newv;
@@ -673,15 +629,15 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
 	    else {
               std::map<int, MVertex*>::iterator it = vertexMap.find(numV);
               if(it == vertexMap.end()) {
-                mv[j] = new MVertex(tetras[i].x(j), tetras[i].y(j),
-                                    tetras[i].z(j), 0, numV);
+                mv[j] = new MVertex(tetras[i]->x(j), tetras[i]->y(j),
+                                    tetras[i]->z(j), 0, numV);
                 vertexMap[numV] = mv[j];
               }
               else mv[j] = it->second;
             }
           }
           MTetrahedron *mt = new MTetrahedron(mv[0], mv[1], mv[2], mv[3], ++numEle, ePart);
-          if(tetras[i].lsTag() < 0)
+          if(tetras[i]->lsTag() < 0)
             poly[0].push_back(mt);
           else
             poly[1].push_back(mt);
@@ -701,9 +657,9 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
         }
       }
       else { // no cut
-        int reg = getElementaryTag(tetras[nbTe].lsTag(), elementary, newElemTags[3]);
+        int reg = getElementaryTag(tetras[nbTe]->lsTag(), elementary, newElemTags[3]);
         std::vector<int> phys;
-        getPhysicalTag(tetras[nbTe].lsTag(), gePhysicals, phys, newPhysTags[3]);
+        getPhysicalTag(tetras[nbTe]->lsTag(), gePhysicals, phys, newPhysTags[3]);
         if(eType == MSH_TET_4)
           elements[4][reg].push_back(copy);
         else if(eType == MSH_HEX_8)
@@ -720,9 +676,9 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
       for (unsigned int i = nbTr; i < triangles.size(); i++){
         MVertex *mv[3] = {NULL, NULL, NULL};
         for(int j = 0; j < 3; j++){
-          int numV = getElementVertexNum(triangles[i].pt(j), e);
+          int numV = getElementVertexNum(triangles[i]->pt(j), e);
           if(numV == -1) {
-	    MVertex *newv = new MVertex(triangles[i].x(j), triangles[i].y(j), triangles[i].z(j), 0);
+	    MVertex *newv = new MVertex(triangles[i]->x(j), triangles[i]->y(j), triangles[i]->z(j), 0);
 	    std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
 	    mv[j] = *(it.first);
 	    if (!it.second) delete newv;
@@ -730,8 +686,8 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
           else {
             std::map<int, MVertex*>::iterator it = vertexMap.find(numV);
             if(it == vertexMap.end()) {
-              mv[j] = new MVertex(triangles[i].x(j), triangles[i].y(j),
-                                  triangles[i].z(j), 0, numV);
+              mv[j] = new MVertex(triangles[i]->x(j), triangles[i]->y(j),
+                                  triangles[i]->z(j), 0, numV);
               vertexMap[numV] = mv[j];
             }
             else mv[j] = it->second;
@@ -740,7 +696,7 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
         MTriangle *tri;
         if(p1 || p2) tri = new MTriangleBorder(mv[0], mv[1], mv[2], p1, p2, ++numEle, ePart);
         else tri = new MTriangle(mv[0], mv[1], mv[2], ++numEle, ePart);
-        int lsT = triangles[i].lsTag();
+        int lsT = triangles[i]->lsTag();
         int c = elements[2].count(lsT) + elements[3].count(lsT);
         // suppose that the surfaces have been cut before the volumes!
         int reg = getBorderTag(lsT, c, newElemTags[2][0], borderElemTags[1]);
@@ -759,9 +715,8 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
         DI_Triangle T(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z(),
                       e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z(),
                       e->getVertex(2)->x(), e->getVertex(2)->y(), e->getVertex(2)->z());
-        std::map<int, double> nodeLs[3];
-        for(int i = 0; i < 3; i++) nodeLs[i] = verticesLs[e->getVertex(i)->getNum()];
-        isCut = T.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+        for(int i = 0; i < 3; i++) nodeLs[i] = &verticesLs(e->getVertex(i)->getIndex(),0);
+        isCut = T.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                       quads, triangles, lines, 0, nodeLs);
       }
       else if(eType == MSH_QUA_4){
@@ -769,20 +724,18 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
                   e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z(),
                   e->getVertex(2)->x(), e->getVertex(2)->y(), e->getVertex(2)->z(),
                   e->getVertex(3)->x(), e->getVertex(3)->y(), e->getVertex(3)->z());
-        std::map<int, double> nodeLs[4];
-        for(int i = 0; i < 4; i++) nodeLs[i] = verticesLs[e->getVertex(i)->getNum()];
-        isCut = Q.cut(*ls, ipV, ipS, cp, integOrder,integOrder,integOrder,
+        for(int i = 0; i < 4; i++) nodeLs[i] = &verticesLs(e->getVertex(i)->getIndex(),0);
+        isCut = Q.cut(RPN, ipV, ipS, cp, integOrder,integOrder,integOrder,
                       quads, triangles, lines, 0, nodeLs);
       }
       else if(eType == MSH_POLYG_){
-        std::map<int, double> nodeLs[3];
         for(int i = 0; i < e->getNumChildren(); i++) {
           MTriangle *t = (MTriangle*) e->getChild(i);
           DI_Triangle Tri(t->getVertex(0)->x(), t->getVertex(0)->y(), t->getVertex(0)->z(),
                           t->getVertex(1)->x(), t->getVertex(1)->y(), t->getVertex(1)->z(),
                           t->getVertex(2)->x(), t->getVertex(2)->y(), t->getVertex(2)->z());
-          for(int i = 0; i < 3; i++) nodeLs[i] = verticesLs[t->getVertex(i)->getNum()];
-          bool iC = Tri.cut(*ls, ipV, ipS, cp, integOrder, integOrder, integOrder,
+          for(int i = 0; i < 3; i++) nodeLs[i] = &verticesLs(t->getVertex(i)->getIndex(),0);
+          bool iC = Tri.cut(RPN, ipV, ipS, cp, integOrder, integOrder, integOrder,
                             quads, triangles, lines, 0, nodeLs);
           isCut = (isCut || iC);
         }
@@ -795,9 +748,9 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
         for (unsigned int i = nbTr; i < triangles.size(); i++){
           MVertex *mv[3] = {NULL, NULL, NULL};
           for(int j = 0; j < 3; j++){
-            int numV = getElementVertexNum(triangles[i].pt(j), e);
+            int numV = getElementVertexNum(triangles[i]->pt(j), e);
             if(numV == -1) {
-	      MVertex *newv = new MVertex(triangles[i].x(j), triangles[i].y(j), triangles[i].z(j), 0);
+	      MVertex *newv = new MVertex(triangles[i]->x(j), triangles[i]->y(j), triangles[i]->z(j), 0);
 	      std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
 	      mv[j] = *(it.first);
 	      if (!it.second) delete newv;
@@ -805,15 +758,15 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
             else {
               std::map<int, MVertex*>::iterator it = vertexMap.find(numV);
               if(it == vertexMap.end()) {
-                mv[j] = new MVertex(triangles[i].x(j), triangles[i].y(j),
-                                    triangles[i].z(j), 0, numV);
+                mv[j] = new MVertex(triangles[i]->x(j), triangles[i]->y(j),
+                                    triangles[i]->z(j), 0, numV);
                 vertexMap[numV] = mv[j];
               }
               else mv[j] = it->second;
             }
           }
           MTriangle *mt = new MTriangle(mv[0], mv[1], mv[2], ++numEle, ePart);
-          if(triangles[i].lsTag() < 0)
+          if(triangles[i]->lsTag() < 0)
             poly[0].push_back(mt);
           else
             poly[1].push_back(mt);
@@ -833,9 +786,9 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
         }
       }
       else { // no cut
-        int reg = getElementaryTag(triangles[nbTr].lsTag(), elementary, newElemTags[2]);
+        int reg = getElementaryTag(triangles[nbTr]->lsTag(), elementary, newElemTags[2]);
         std::vector<int> phys;
-        getPhysicalTag(triangles[nbTr].lsTag(), gePhysicals, phys, newPhysTags[2]);
+        getPhysicalTag(triangles[nbTr]->lsTag(), gePhysicals, phys, newPhysTags[2]);
         if(eType == MSH_TRI_3)
           elements[2][reg].push_back(copy);
         else if(eType == MSH_QUA_4)
@@ -848,9 +801,9 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
       for (unsigned int i = nbL; i < lines.size(); i++){
         MVertex *mv[2] = {NULL, NULL};
         for(int j = 0; j < 2; j++){
-          int numV = getElementVertexNum(lines[i].pt(j), e);
+          int numV = getElementVertexNum(lines[i]->pt(j), e);
           if(numV == -1) {
-	    MVertex *newv = new MVertex(lines[i].x(j), lines[i].y(j), lines[i].z(j), 0);
+	    MVertex *newv = new MVertex(lines[i]->x(j), lines[i]->y(j), lines[i]->z(j), 0);
 	    std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
 	    mv[j] = *(it.first);
 	    if (!it.second) delete newv;
@@ -858,8 +811,8 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
           else {
             std::map<int, MVertex*>::iterator it = vertexMap.find(numV);
             if(it == vertexMap.end()) {
-              mv[j] = new MVertex(lines[i].x(j), lines[i].y(j),
-                                  lines[i].z(j), 0, numV);
+              mv[j] = new MVertex(lines[i]->x(j), lines[i]->y(j),
+                                  lines[i]->z(j), 0, numV);
               vertexMap[numV] = mv[j];
             }
             else mv[j] = it->second;
@@ -868,7 +821,7 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
         MLine *lin;
         if(p1 || p2) lin = new MLineBorder(mv[0], mv[1], p1, p2, ++numEle, ePart);
         else lin = new MLine(mv[0], mv[1], ++numEle, ePart);
-        int lsL = lines[i].lsTag();
+        int lsL = lines[i]->lsTag();
         int c = elements[1].count(lsL);
         // suppose that the lines have been cut before the surfaces!
         int reg = getBorderTag(lsL, c, newElemTags[1][0], borderElemTags[0]);
@@ -883,17 +836,16 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
     {
       DI_Line L(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z(),
                 e->getVertex(1)->x(), e->getVertex(1)->y(), e->getVertex(1)->z());
-      std::map<int, double> nodeLs[2];
-      for(int i = 0; i < 2; i++) nodeLs[i] = verticesLs[e->getVertex(i)->getNum()];
-      isCut = L.cut(*ls, ipV, cp, integOrder, lines, 0, nodeLs);
+      for(int i = 0; i < 2; i++) nodeLs[i] = &verticesLs(e->getVertex(i)->getIndex(),0);
+      isCut = L.cut(RPN, ipV, cp, integOrder, lines, 0, nodeLs);
 
       if(isCut) {
         for (unsigned int i = nbL; i < lines.size(); i++){
           MVertex *mv[2] = {NULL, NULL};
           for(int j = 0; j < 2; j++){
-            int numV = getElementVertexNum(lines[i].pt(j), e);
+            int numV = getElementVertexNum(lines[i]->pt(j), e);
             if(numV == -1) {
-	      MVertex *newv = new MVertex(lines[i].x(j), lines[i].y(j), lines[i].z(j), 0);
+	      MVertex *newv = new MVertex(lines[i]->x(j), lines[i]->y(j), lines[i]->z(j), 0);
 	      std::pair<newVerticesContainer::iterator, bool> it = newVertices.insert(newv);
 	      mv[j] = *(it.first);
 	      if (!it.second) delete newv;
@@ -901,24 +853,24 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
             else {
               std::map<int, MVertex*>::iterator it = vertexMap.find(numV);
               if(it == vertexMap.end()) {
-                mv[j] = new MVertex(lines[i].x(j), lines[i].y(j), lines[i].z(j), 0, numV);
+                mv[j] = new MVertex(lines[i]->x(j), lines[i]->y(j), lines[i]->z(j), 0, numV);
                 vertexMap[numV] = mv[j];
               }
               else mv[j] = it->second;
             }
           }
           MLine *ml = new MLine(mv[0], mv[1], ++numEle, ePart);
-          int reg = getElementaryTag(lines[i].lsTag(), elementary, newElemTags[1]);
+          int reg = getElementaryTag(lines[i]->lsTag(), elementary, newElemTags[1]);
           std::vector<int> phys;
-          getPhysicalTag(lines[i].lsTag(), gePhysicals, phys, newPhysTags[1]);
+          getPhysicalTag(lines[i]->lsTag(), gePhysicals, phys, newPhysTags[1]);
           elements[1][reg].push_back(ml);
           assignPhysicals(GM, phys, reg, 1, physicals);
         }
       }
       else { // no cut
-        int reg = getElementaryTag(lines[nbL].lsTag(), elementary, newElemTags[1]);
+        int reg = getElementaryTag(lines[nbL]->lsTag(), elementary, newElemTags[1]);
         std::vector<int> phys;
-        getPhysicalTag(lines[nbL].lsTag(), gePhysicals, phys, newPhysTags[1]);
+        getPhysicalTag(lines[nbL]->lsTag(), gePhysicals, phys, newPhysTags[1]);
         elements[1][reg].push_back(copy);
         assignPhysicals(GM, phys, reg, 1, physicals);
       }
@@ -927,7 +879,7 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
   case MSH_PNT :
     {
       DI_Point P(e->getVertex(0)->x(), e->getVertex(0)->y(), e->getVertex(0)->z());
-      P.computeLs(*ls);
+      P.computeLs(RPN.back());
       int reg = getElementaryTag(P.lsTag(), elementary, newElemTags[0]);
       std::vector<int> phys;
       getPhysicalTag(P.lsTag(), gePhysicals, phys, newPhysTags[0]);
@@ -939,6 +891,14 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
     Msg::Error("This type of element cannot be cut.");
     return;
   }
+
+  for(unsigned int i = 0; i < ipS.size(); i++)
+    delete ipS[i];
+  for(unsigned int i = 0; i < ipV.size(); i++)
+    delete ipV[i];
+  //for(int i = 0; i < e->getNumPrimaryVertices(); i++)
+    //if(nodeLs[i]) delete [] nodeLs[i];
+  delete [] nodeLs;
 }
 
 #endif
@@ -949,14 +909,14 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
                      std::map<int, std::map<int, std::string> > physicals[4])
 {
 #if defined(HAVE_DINTEGRATION)
+  int numVert = gm->indexMeshVertices(true);
+
   GModel *cutGM = new GModel(gm->getName() + "_cut");
   cutGM->setFileName(cutGM->getName());
 
   newVerticesContainer newVertices;
-  //  std::set<MVertex*, MVertexLessThanLexicographic> newVertices;
 
   std::vector<GEntity*> gmEntities;
-
   gm->getEntities(gmEntities);
   int numEle = gm->getNumMeshElements();
 
@@ -971,31 +931,39 @@ GModel *buildCutMesh(GModel *gm, gLevelset *ls,
 
   std::vector<const gLevelset *> primitives;
   ls->getPrimitives(primitives);
-  std::map<int, std::map<int, double> > verticesLs;
+  fullMatrix<double> verticesLs(numVert + 1, primitives.size());
   for(unsigned int i = 0; i < gmEntities.size(); i++) {
     for(unsigned int j = 0; j < gmEntities[i]->getNumMeshVertices(); j++) {
       MVertex *vi = gmEntities[i]->getMeshVertex(j);
       for(unsigned int k = 0; k < primitives.size(); k++) {
-        verticesLs[vi->getNum()][primitives[k]->getTag()] = (*primitives[k])(vi->x(), vi->y(), vi->z());
+        verticesLs(vi->getIndex(), k) = (*primitives[k])(vi->x(), vi->y(), vi->z());
       }
     }
   }
 
-  std::vector<DI_CuttingPoint> cp;
-  std::vector<DI_Line> lines;
-  std::vector<DI_Triangle> triangles;
-  std::vector<DI_Quad> quads;
-  std::vector<DI_Tetra> tetras;
-  std::vector<DI_Hexa> hexas;
+  DI_Point::Container cp;
+  std::vector<DI_Line *> lines;
+  std::vector<DI_Triangle *> triangles;
+  std::vector<DI_Quad *> quads;
+  std::vector<DI_Tetra *> tetras;
+  std::vector<DI_Hexa *> hexas;
+  std::vector<const gLevelset *> RPN;
+  ls->getRPN(RPN);
   for(unsigned int i = 0; i < gmEntities.size(); i++) {
     for(unsigned int j = 0; j < gmEntities[i]->getNumMeshElements(); j++) {
       MElement *e = gmEntities[i]->getMeshElement(j);
       e->setVolumePositive();
-      elementCutMesh(e, ls, verticesLs, gmEntities[i], gm, numEle, vertexMap, newVertices,
+      elementCutMesh(e, RPN, verticesLs, gmEntities[i], gm, numEle, vertexMap, newVertices,
                      elements, physicals, newElemTags, newPhysTags, borderElemTags, borderPhysTags,
                      cp, lines, triangles, quads, tetras, hexas);
       cutGM->getMeshPartitions().insert(e->getPartition());
     }
+    for(DI_Point::Container::iterator it = cp.begin(); it != cp.end(); it++) delete *it;
+    for(unsigned int k = 0; k < lines.size(); k++) delete lines[k];
+    for(unsigned int k = 0; k < triangles.size(); k++) delete triangles[k];
+    for(unsigned int k = 0; k < quads.size(); k++) delete quads[k];
+    for(unsigned int k = 0; k < tetras.size(); k++) delete tetras[k];
+    for(unsigned int k = 0; k < hexas.size(); k++) delete hexas[k];
     cp.clear(); lines.clear(); triangles.clear(); quads.clear(); tetras.clear(); hexas.clear();
   }
 
diff --git a/Solver/multiscaleLaplace.cpp b/Solver/multiscaleLaplace.cpp
index 9324166fb3..b11d0812ae 100644
--- a/Solver/multiscaleLaplace.cpp
+++ b/Solver/multiscaleLaplace.cpp
@@ -11,7 +11,7 @@
 #include "linearSystemCSR.h"
 
 #ifdef HAVE_GMM
-#include "linearSystemGmm.h"
+#include "linearSystemGMM.h"
 #endif
 
 #include "linearSystemFull.h"
diff --git a/contrib/DiscreteIntegration/Integration3D.cpp b/contrib/DiscreteIntegration/Integration3D.cpp
index 0ca3b33943..a38316cc18 100644
--- a/contrib/DiscreteIntegration/Integration3D.cpp
+++ b/contrib/DiscreteIntegration/Integration3D.cpp
@@ -26,8 +26,8 @@ inline double norm(const double *v) {
 inline void vec (const double *x1, const double *x2, double *v) {
   v[0] = x2[0] - x1[0]; v[1] = x2[1] - x1[1]; v[2] = x2[2] - x1[2];
 }
-inline void vec (const DI_Point &p1, const DI_Point &p2, double *v) {
-  v[0] = p2.x() - p1.x(); v[1] = p2.y() - p1.y(); v[2] = p2.z() - p1.z();
+inline void vec (const DI_Point *p1, const DI_Point *p2, double *v) {
+  v[0] = p2->x() - p1->x(); v[1] = p2->y() - p1->y(); v[2] = p2->z() - p1->z();
 }
 inline double sq2 (const double a) {return a * a;}
 
@@ -48,29 +48,29 @@ inline double det4 (double d11, double d12, double d13, double d14,
 }
 
 // distance
-inline double distance(const DI_Point &p1, const DI_Point &p2) {
-  return sqrt((p1.x() - p2.x()) * (p1.x() - p2.x())
-            + (p1.y() - p2.y()) * (p1.y() - p2.y())
-            + (p1.z() - p2.z()) * (p1.z() - p2.z()));
+inline double distance(const DI_Point *p1, const DI_Point *p2) {
+  return sqrt((p1->x() - p2->x()) * (p1->x() - p2->x())
+            + (p1->y() - p2->y()) * (p1->y() - p2->y())
+            + (p1->z() - p2->z()) * (p1->z() - p2->z()));
 }
-inline double distance(const DI_CuttingPoint &p1, const DI_CuttingPoint &p2) {
-  return sqrt((p1.x() - p2.x()) * (p1.x() - p2.x())
-            + (p1.y() - p2.y()) * (p1.y() - p2.y())
-            + (p1.z() - p2.z()) * (p1.z() - p2.z()));
+inline double distance(const DI_CuttingPoint *p1, const DI_CuttingPoint *p2) {
+  return sqrt((p1->x() - p2->x()) * (p1->x() - p2->x())
+            + (p1->y() - p2->y()) * (p1->y() - p2->y())
+            + (p1->z() - p2->z()) * (p1->z() - p2->z()));
 }
 
 // middle of 2 points
-inline DI_Point middle (const DI_Point &p1, const DI_Point &p2) {
-  return DI_Point ((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2, (p1.z() + p2.z()) / 2);
+inline DI_Point* middle (const DI_Point *p1, const DI_Point *p2) {
+  return new DI_Point ((p1->x() + p2->x()) / 2, (p1->y() + p2->y()) / 2, (p1->z() + p2->z()) / 2);
 }
-inline DI_Point middle (const DI_Point &p1, const DI_Point &p2,
-                        const DI_Element *e, const std::vector<const gLevelset *> RPNi) {
-  return DI_Point ((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2, (p1.z() + p2.z()) / 2, e, RPNi);
+inline DI_Point* middle (const DI_Point *p1, const DI_Point *p2,
+                        const DI_Element *e, const std::vector<const gLevelset *> &RPNi) {
+  return new DI_Point ((p1->x() + p2->x()) / 2, (p1->y() + p2->y()) / 2, (p1->z() + p2->z()) / 2, e, RPNi);
 }
 
 // barycentre
-inline DI_Point barycenter (const DI_Element *el,
-                            const DI_Element *e, const std::vector<const gLevelset *> RPN) {
+inline DI_Point* barycenter (const DI_Element *el,
+                             const DI_Element *e, const std::vector<const gLevelset *> &RPN) {
   double x[3] = {0., 0., 0.};
   int n;
   for (n = 0; n < el->nbVert(); n++) {
@@ -78,7 +78,7 @@ inline DI_Point barycenter (const DI_Element *el,
     x[1] += el->y(n);
     x[2] += el->z(n);
   }
-  return DI_Point(x[0] / n,x[1] / n,x[2] / n, e, RPN);
+  return new DI_Point(x[0] / n, x[1] / n, x[2] / n, e, RPN);
 }
 
 // swap two integers
@@ -92,13 +92,13 @@ inline void swap(double &a, double &b) {
   a = b; b = t;
 }
 // swap two points
-inline void swap (DI_Point &p1, DI_Point &p2) {
-  DI_Point pt = p1;
-  p1 = p2; p2 = pt;
+inline void swap (DI_Point **p1, DI_Point **p2) {
+  DI_Point *pt = *p1;
+  *p1 = *p2; *p2 = pt;
 }
 
 // return true if the 4 points are planar
-inline bool isPlanar (const DI_Point &p1, const DI_Point &p2, const DI_Point &p3, const DI_Point &p4) {
+inline bool isPlanar (const DI_Point *p1, const DI_Point *p2, const DI_Point *p3, const DI_Point *p4) {
   double v12[3]; vec(p1, p2, v12);
   double v13[3]; vec(p1, p3, v13);
   double v14[3]; vec(p1, p4, v14);
@@ -108,14 +108,14 @@ inline bool isPlanar (const DI_Point &p1, const DI_Point &p2, const DI_Point &p3
   return (c[0] == 0. && c[1] == 0. && c[2] == 0.);
 }
 // return true if the 3 points are linear
-inline bool isLinear (const DI_Point &p1, const DI_Point &p2, const DI_Point &p3) {
+inline bool isLinear (const DI_Point *p1, const DI_Point *p2, const DI_Point *p3) {
   double v12[3]; vec(p1, p2, v12);
   double v13[3]; vec(p1, p3, v13);
   double c[3]; cross(v12, v13, c);
   return (c[0] == 0. && c[1] == 0. && c[2] == 0.);
 }
 // return true if the 4 points form a quad in good ordering
-inline bool ordered4Nodes (const DI_Point &p1, const DI_Point &p2, const DI_Point &p3, const DI_Point &p4) {
+inline bool ordered4Nodes (const DI_Point *p1, const DI_Point *p2, const DI_Point *p3, const DI_Point *p4) {
   double v21[3]; vec(p2, p1, v21);
   double v23[3]; vec(p2, p3, v23);
   double v24[3]; vec(p2, p4, v24);
@@ -130,52 +130,52 @@ inline bool ordered4Nodes (const DI_Point &p1, const DI_Point &p2, const DI_Poin
   return true;
 }
 
-bool isInQE (const DI_Triangle &t, const DI_QualError &QE) {
+bool isInQE (const DI_Triangle *t, const DI_QualError *QE) {
   int b = 0;
   for(int i = 0; i < 3; i++) {
     for(int j = 0; j < 4; j++)
-      if (t.pt(i).equal(QE.pt(j))) {b++; break;}
+      if (t->pt(i)->equal(QE->pt(j))) {b++; break;}
   }
   return (b == 3);
 }
-bool belongsTo (const DI_Element &e, const DI_Element &E) {
+bool belongsTo (const DI_Element *e, const DI_Element *E) {
   int b = 0;
-  for(int k = 0; k < E.nbVert(); k++) {
-    for(int l = 0; l < e.nbVert(); l++)
-      if((e.pt(l)).equal(E.pt(k))) {b++; break;}
-    if(b == e.nbVert()) return true;
+  for(int k = 0; k < E->nbVert(); k++) {
+    for(int l = 0; l < e->nbVert(); l++)
+      if((e->pt(l))->equal(E->pt(k))) {b++; break;}
+    if(b == e->nbVert()) return true;
   }
   return false;
 }
-bool isLastLnInV (const std::vector<DI_Line> &v, const int i1 = 0) {
+bool isLastLnInV (const std::vector<DI_Line *> &v, const int i1 = 0) {
   int b;
   for (int i = i1; i < (int)v.size() - 1; i++) {
     b = 0;
     for (int k = 0; k < 2; k++)
       for(int l = 0; l < 2; l++)
-        if(v[i].pt(k).equal(v[v.size() - 1].pt(l))) {b++; break;}
+        if(v[i]->pt(k)->equal(v[v.size() - 1]->pt(l))) {b++; break;}
     if(b == 2) return true;
   }
   return false;
 }
-bool isLastTrInV (const std::vector<DI_Triangle> &v, const int i1 = 0) {
+bool isLastTrInV (const std::vector<DI_Triangle *> &v, const int i1 = 0) {
   int b;
   for (int i = i1; i < (int)v.size() - 1; i++) {
     b = 0;
     for (int k = 0; k < 3; k++)
       for(int l = 0; l < 3; l++)
-        if(v[i].pt(k).equal(v[v.size() - 1].pt(l))) {b++; break;}
+        if(v[i]->pt(k)->equal(v[v.size() - 1]->pt(l))) {b++; break;}
     if(b == 3) return true;
   }
   return false;
 }
-bool isLastQInV (const std::vector<DI_Quad> &v, const int i1 = 0) {
+bool isLastQInV (const std::vector<DI_Quad *> &v, const int i1 = 0) {
   int b;
   for (int i = i1; i < (int)v.size() - 1; i++) {
     b = 0;
     for(int k = 0; k < 4; k++)
       for(int l = 0; l < 4; l++)
-        if(v[i].pt(k).equal(v[v.size() - 1].pt(l))) {b++; break;}
+        if(v[i]->pt(k)->equal(v[v.size() - 1]->pt(l))) {b++; break;}
     if(b == 4) return true;
   }
   return false;
@@ -192,10 +192,9 @@ int commonV (int &s11, int &s12, int &s21, int &s22) {
 inline double adjustLs (double ls) {
   return (fabs(ls) < ZERO_LS_TOL) ? 0. : ls;
 }
-inline bool isCrossed (const DI_Point &p1, const DI_Point &p2) {
-  double ls1 = p1.ls(), ls2 = p2.ls();
-  if(ls1 * ls2 >= 0.) return false;
-  return true;
+inline bool isCrossed (const DI_Point *p1, const DI_Point *p2) {
+  double ls1 = p1->ls(), ls2 = p2->ls();
+  return (ls1 * ls2 < 0.);
 }
 
 // return the index of the point with minimum x,y and z
@@ -220,7 +219,7 @@ int minimum(double *x, double *y, double *z, const int num) {
 }
 
 // Return the quality of a triangle
-double qualityTri(const DI_Point &p0, const DI_Point &p1, const DI_Point &p2) {
+double qualityTri(const DI_Point *p0, const DI_Point *p1, const DI_Point *p2) {
   double a = distance(p0, p1);
   double b = distance(p0, p2);
   double c = distance(p1, p2);
@@ -231,14 +230,13 @@ double qualityTri(const DI_Point &p0, const DI_Point &p1, const DI_Point &p2) {
 }
 
 // Return the best quality for a quad cut into 2 triangles
-int bestQuality(const DI_Point &p1, const DI_Point &p2, const DI_Point &p3, const DI_Point &p4,
-                DI_Triangle &t1, DI_Triangle &t2) {
+int bestQuality(const DI_Point *p1, const DI_Point *p2, const DI_Point *p3, const DI_Point *p4,
+                DI_Triangle **t1, DI_Triangle **t2) {
   int cut = 0;
   double qual11 = qualityTri(p1, p2, p3);
   double qual12 = qualityTri(p1, p3, p4);
   double qual21 = qualityTri(p1, p2, p4);
   double qual22 = qualityTri(p2, p3, p4);
-  //printf("quad, q11=%.18f,q12=%.18f,q21=%.18f,q22=%.18f\n",qual11,qual12,qual21,qual22);
   double worst1 = std::min(qual11, qual12);
   double worst2 = std::min(qual21, qual22);
   if(worst1 - worst2 > EQUALITY_TOL)
@@ -253,22 +251,22 @@ int bestQuality(const DI_Point &p1, const DI_Point &p2, const DI_Point &p3, cons
     else if(worst2 - worst1 > EQUALITY_TOL)
       cut = 2;
     else { // same min and max qualities
-      double x[4] = {p1.x(), p2.x(), p3.x(), p4.x()};
-      double y[4] = {p1.y(), p2.y(), p3.y(), p4.y()};
-      double z[4] = {p1.z(), p2.z(), p3.z(), p4.z()};
+      double x[4] = {p1->x(), p2->x(), p3->x(), p4->x()};
+      double y[4] = {p1->y(), p2->y(), p3->y(), p4->y()};
+      double z[4] = {p1->z(), p2->z(), p3->z(), p4->z()};
       int IND = minimum(x, y, z, 4);
       if(IND == 0 || IND == 2) cut = 1;
       else cut = 2;
     }
   }
   if(cut == 1) {
-    t1 = DI_Triangle(p1, p2, p3);
-    t2 = DI_Triangle(p1, p3, p4);
+    *t1 = new DI_Triangle(p1, p2, p3);
+    *t2 = new DI_Triangle(p1, p3, p4);
     return 1;
   }
   else {
-    t1 = DI_Triangle(p1, p2, p4);
-    t2 = DI_Triangle(p2, p3, p4);
+    *t1 = new DI_Triangle(p1, p2, p4);
+    *t2 = new DI_Triangle(p2, p3, p4);
     return 2;
   }
 }
@@ -307,8 +305,8 @@ inline double qualityTet (double x1, double y1, double z1, double x2, double y2,
 
 // Return the cutting of a pyramid cut into 2 tetras with the best quality faces
 // (x1,x2,x3,x4 form the base in ccw and x5 is the summit)
-int bestQuality(const DI_Point &p1, const DI_Point &p2, const DI_Point &p3,
-                const DI_Point &p4, const DI_Point &p5, DI_Tetra &t1, DI_Tetra &t2) {
+int bestQuality(const DI_Point *p1, const DI_Point *p2, const DI_Point *p3,
+                const DI_Point *p4, const DI_Point *p5, DI_Tetra **t1, DI_Tetra **t2) {
   int cut = 0;
   double qual11 = qualityTri(p1, p2, p3);
   double qual12 = qualityTri(p1, p3, p4);
@@ -329,33 +327,33 @@ int bestQuality(const DI_Point &p1, const DI_Point &p2, const DI_Point &p3,
     else if(worst2 - worst1 > EQUALITY_TOL)
       cut = 2;
     else { // same min and max qualities
-      double x[4] = {p1.x(), p2.x(), p3.x(), p4.x()};
-      double y[4] = {p1.y(), p2.y(), p3.y(), p4.y()};
-      double z[4] = {p1.z(), p2.z(), p3.z(), p4.z()};
+      double x[4] = {p1->x(), p2->x(), p3->x(), p4->x()};
+      double y[4] = {p1->y(), p2->y(), p3->y(), p4->y()};
+      double z[4] = {p1->z(), p2->z(), p3->z(), p4->z()};
       int IND = minimum(x, y, z, 4);
       if(IND == 0 || IND == 2) cut = 1;
       else cut = 2;
     }
   }
   if(cut == 1) {
-    t1 = DI_Tetra(p1, p2, p3, p5);
-    t2 = DI_Tetra(p1, p3, p4, p5);
+    *t1 = new DI_Tetra(p1, p2, p3, p5);
+    *t2 = new DI_Tetra(p1, p3, p4, p5);
     return 1;
   }
   else {
-    t1 = DI_Tetra(p1, p2, p4, p5);
-    t2 = DI_Tetra(p2, p3, p4, p5);
+    *t1 = new DI_Tetra(p1, p2, p4, p5);
+    *t2 = new DI_Tetra(p2, p3, p4, p5);
     return 2;
   }
 }
 
 // Return the cutting of a prism into 3 tetras with the best quality faces
-int bestQuality (const DI_Point &p0, const DI_Point &p1, const DI_Point &p2,
-                 const DI_Point &p3, const DI_Point &p4, const DI_Point &p5,
-                 DI_Tetra &t1, DI_Tetra &t2, DI_Tetra &t3, std::vector<DI_QualError> &QError) {
+int bestQuality (DI_Point *p0, DI_Point *p1, DI_Point *p2,
+                 DI_Point *p3, DI_Point *p4, DI_Point *p5,
+                 DI_Tetra **t1, DI_Tetra **t2, DI_Tetra **t3, std::vector<DI_QualError *> &QError) {
   int cut3[3] = {0, 0, 0}; int cut = -1;
   int fa[3][4] = {{0, 3, 4, 1}, {0, 2, 5, 3}, {1, 4, 5, 2}}; //faces
-  DI_Point pt[6] = {p0, p1, p2, p3, p4, p5};
+  DI_Point* pt[6] = {p0, p1, p2, p3, p4, p5};
   for(int f = 0; f < 3; f++){
     int i1 = fa[f][0], i2 = fa[f][1], i3 = fa[f][2], i4 = fa[f][3];
     double qual11 = qualityTri(pt[i1], pt[i2], pt[i3]);
@@ -377,9 +375,9 @@ int bestQuality (const DI_Point &p0, const DI_Point &p1, const DI_Point &p2,
       else if(worst2 - worst1 > EQUALITY_TOL)
         cut3[f] = 2;
       else { // same min and max qualities
-        double xc[4] = {pt[i1].x(), pt[i2].x(), pt[i3].x(), pt[i4].x()};
-        double yc[4] = {pt[i1].y(), pt[i2].y(), pt[i3].y(), pt[i4].y()};
-        double zc[4] = {pt[i1].z(), pt[i2].z(), pt[i3].z(), pt[i4].z()};
+        double xc[4] = {pt[i1]->x(), pt[i2]->x(), pt[i3]->x(), pt[i4]->x()};
+        double yc[4] = {pt[i1]->y(), pt[i2]->y(), pt[i3]->y(), pt[i4]->y()};
+        double zc[4] = {pt[i1]->z(), pt[i2]->z(), pt[i3]->z(), pt[i4]->z()};
         int IND = minimum(xc, yc, zc, 4);
         if(IND == 0 || IND == 2) cut3[f] = 1;
         else cut3[f] = 2;
@@ -393,13 +391,13 @@ int bestQuality (const DI_Point &p0, const DI_Point &p1, const DI_Point &p2,
       else cut = 2;
     }
     else{
-      if(cut3[2] == 1) QError.push_back(DI_QualError(p1, p5, p2, p4));
+      if(cut3[2] == 1) QError.push_back(new DI_QualError(p1, p5, p2, p4));
       cut = 3;
     }
   }
   else {
     if(cut3[1] == 1){
-      if(cut3[2] == 2) QError.push_back(DI_QualError(p1, p5, p2, p4));
+      if(cut3[2] == 2) QError.push_back(new DI_QualError(p1, p5, p2, p4));
       cut = 0;
     }
     else{
@@ -409,71 +407,72 @@ int bestQuality (const DI_Point &p0, const DI_Point &p1, const DI_Point &p2,
   }
 
   if(cut == 0) {
-    t1 = DI_Tetra(p0, p1, p2, p5);
-    t2 = DI_Tetra(p0, p1, p5, p3);
-    t3 = DI_Tetra(p1, p5, p3, p4);
+    *t1 = new DI_Tetra(p0, p1, p2, p5);
+    *t2 = new DI_Tetra(p0, p1, p5, p3);
+    *t3 = new DI_Tetra(p1, p5, p3, p4);
     return 1;
   }
   else if(cut == 1) {
-    t1 = DI_Tetra(p0, p1, p2, p5);
-    t2 = DI_Tetra(p0, p1, p5, p4);
-    t3 = DI_Tetra(p0, p4, p5, p3);
+    *t1 = new DI_Tetra(p0, p1, p2, p5);
+    *t2 = new DI_Tetra(p0, p1, p5, p4);
+    *t3 = new DI_Tetra(p0, p4, p5, p3);
     return 2;
   }
   else if(cut == 2) {
-    t1 = DI_Tetra(p0, p1, p2, p4);
-    t2 = DI_Tetra(p0, p4, p2, p5);
-    t3 = DI_Tetra(p0, p4, p5, p3);
+    *t1 = new DI_Tetra(p0, p1, p2, p4);
+    *t2 = new DI_Tetra(p0, p4, p2, p5);
+    *t3 = new DI_Tetra(p0, p4, p5, p3);
     return 3;
   }
   else if(cut == 3) {
-    t1 = DI_Tetra(p0, p1, p2, p4);
-    t2 = DI_Tetra(p0, p4, p2, p3);
-    t3 = DI_Tetra(p2, p3, p4, p5);
+    *t1 = new DI_Tetra(p0, p1, p2, p4);
+    *t2 = new DI_Tetra(p0, p4, p2, p3);
+    *t3 = new DI_Tetra(p2, p3, p4, p5);
     return 4;
   }
   else if(cut == 4) {
-    t1 = DI_Tetra(p0, p1, p2, p3);
-    t2 = DI_Tetra(p1, p2, p3, p4);
-    t3 = DI_Tetra(p2, p3, p4, p5);
+    *t1 = new DI_Tetra(p0, p1, p2, p3);
+    *t2 = new DI_Tetra(p1, p2, p3, p4);
+    *t3 = new DI_Tetra(p2, p3, p4, p5);
     return 5;
   }
   else if(cut == 5) {
-    t1 = DI_Tetra(p0, p1, p2, p3);
-    t2 = DI_Tetra(p1, p2, p3, p5);
-    t3 = DI_Tetra(p1, p5, p3, p4);
+    *t1 = new DI_Tetra(p0, p1, p2, p3);
+    *t2 = new DI_Tetra(p1, p2, p3, p5);
+    *t3 = new DI_Tetra(p1, p5, p3, p4);
     return 6;
   }
 }
 
 // computes the intersection between a level set and a linear edge
-DI_Point Newton(const DI_Point &p1, const DI_Point &p2,
-                const DI_Element *e, const std::vector<const gLevelset *> RPNi) {
-  double eps = -p1.ls() / (p2.ls() - p1.ls());
-  DI_Point p(p1.x() + eps * (p2.x() - p1.x()), p1.y() + eps * (p2.y() - p1.y()), p1.z() + eps * (p2.z() - p1.z()));
-  double pls = e->evalLs(p.x(), p.y(), p.z());
+DI_Point* Newton(const DI_Point *p1, const DI_Point *p2,
+                const DI_Element *e, const std::vector<const gLevelset *> &RPNi) {
+  double eps = -p1->ls() / (p2->ls() - p1->ls());
+  DI_Point* p = new DI_Point(p1->x() + eps * (p2->x() - p1->x()), p1->y() + eps * (p2->y() - p1->y()),
+                             p1->z() + eps * (p2->z() - p1->z()));
+  double pls = e->evalLs(p->x(), p->y(), p->z());
   // Newton iteration to find the intersection between the level set and the edge
   while(fabs(pls) > EQUALITY_TOL){
-    if(pls * p1.ls() < 0.) {
-      eps = -pls / (p1.ls() - pls);
-      p.move(p.x() + eps * (p1.x() - p.x()), p.y() + eps * (p1.y() - p.y()), p.z() + eps * (p1.z() - p.z()));
+    if(pls * p1->ls() < 0.) {
+      eps = -pls / (p1->ls() - pls);
+      p->move(p->x() + eps * (p1->x() - p->x()), p->y() + eps * (p1->y() - p->y()), p->z() + eps * (p1->z() - p->z()));
     }
     else {
-      eps = -pls / (p2.ls() - pls);
-      p.move(p.x() + eps * (p2.x() - p.x()), p.y() + eps * (p2.y() - p.y()), p.z() + eps * (p2.z() - p.z()));
+      eps = -pls / (p2->ls() - pls);
+      p->move(p->x() + eps * (p2->x() - p->x()), p->y() + eps * (p2->y() - p->y()), p->z() + eps * (p2->z() - p->z()));
     }
-    pls = e->evalLs(p.x(), p.y(), p.z());
+    pls = e->evalLs(p->x(), p->y(), p->z());
   }
-  p.computeLs(e, RPNi);
+  p->computeLs(e, RPNi);
   return p;
 }
 
 // compute the position of the middle of a quadratic edge
 //(intersection between the bisector of the linear edge and the levelset)
-DI_Point quadMidNode(const DI_Point &p1, const DI_Point &p2, const DI_Point &pf,
-                     const DI_Element *e, const std::vector<const gLevelset *> RPNi) {
+DI_Point* quadMidNode(const DI_Point *p1, const DI_Point *p2, const DI_Point *pf,
+                      const DI_Element *e, const std::vector<const gLevelset *> &RPNi) {
   // middle of the edge between the 2 cutting points
-  DI_Point midEN((p1.x() + p2.x()) / 2., (p1.y() + p2.y()) / 2., (p1.z() + p2.z()) / 2.);
+  DI_Point midEN((p1->x() + p2->x()) / 2., (p1->y() + p2->y()) / 2., (p1->z() + p2->z()) / 2.);
   midEN.addLs(e);
   // the bisector is computed in the plane of the face of the tetra [(x1,x2)x(x1,xf)]x(x1,x2)
   double v12[3]; vec(p1, p2, v12);
@@ -492,15 +491,16 @@ DI_Point quadMidNode(const DI_Point &p1, const DI_Point &p2, const DI_Point &pf,
     pt.move(midEN.x() - bisector[0], midEN.y() - bisector[1], midEN.z() - bisector[2]);
     pt.changeLs(e->evalLs(pt.x(), pt.y(), pt.z()));
   }
-  return Newton(midEN, pt, e, RPNi);
+  DI_Point* qmn = Newton(&midEN, &pt, e, RPNi);
+  return qmn;
 }
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 
 // DI_Point methods -------------------------------------------------------------------------------
-DI_Point::DI_Point (double x, double y, double z, gLevelset &ls) : x_(x), y_(y), z_(z) {
-  addLs(ls(x, y, z));
+DI_Point::DI_Point (double x, double y, double z, gLevelset *ls) : x_(x), y_(y), z_(z) {
+  addLs((*ls)(x, y, z));
 }
 DI_Point & DI_Point::operator= (const DI_Point &rhs) {
   if(this != &rhs){
@@ -521,7 +521,7 @@ void DI_Point::chooseLs (const gLevelset *Lsi) {
   Ls.pop_back(); Ls.pop_back();
   addLs(ls);
 }
-void DI_Point::computeLs (const DI_Element *e, const std::vector<const gLevelset*> RPNi) {
+void DI_Point::computeLs (const DI_Element *e, const std::vector<const gLevelset*> &RPNi) {
   int prim = 0; Ls.clear();
   if(e->sizeLs() == 0) return;
   for(int l = 0; l < (int)RPNi.size(); l++) {
@@ -531,16 +531,16 @@ void DI_Point::computeLs (const DI_Element *e, const std::vector<const gLevelset
       chooseLs(RPNi[l]);
   }
 }
-void DI_Point::computeLs (const gLevelset &ls) {
+void DI_Point::computeLs (const gLevelset *ls) {
   Ls.clear();
-  addLs(ls(x_, y_, z_));
+  addLs((*ls)(x_, y_, z_));
 }
-bool DI_Point::equal(const DI_Point &p) const {
-  return (fabs(x() - p.x()) < EQUALITY_TOL && fabs(y() - p.y()) < EQUALITY_TOL && fabs(z() - p.z()) < EQUALITY_TOL);
+bool DI_Point::equal(const DI_Point *p) const {
+  return (fabs(x() - p->x()) < EQUALITY_TOL && fabs(y() - p->y()) < EQUALITY_TOL && fabs(z() - p->z()) < EQUALITY_TOL);
 }
 
 // DI_IntegrationPoint methods --------------------------------------------------------------------
-void DI_IntegrationPoint::computeLs (const DI_Element *e, const std::vector<const gLevelset*> RPN) {
+void DI_IntegrationPoint::computeLs (const DI_Element *e, const std::vector<const gLevelset*> &RPN) {
   int prim = 0; std::vector<double> Ls;
   for(int l = 0; l < (int)RPN.size(); l++) {
     if(RPN[l]->isPrimitive())
@@ -556,26 +556,22 @@ void DI_IntegrationPoint::computeLs (const DI_Element *e, const std::vector<cons
 }
 
 // DI_CuttingPoint methods ------------------------------------------------------------------------
-DI_CuttingPoint::DI_CuttingPoint(const DI_Point &pt) : x_(pt.x()), y_(pt.y()), z_(pt.z()),
-                                                       xl_(pt.x()), yl_(pt.y()), zl_(pt.z()) {
-  for(int i = 0; i < pt.sizeLs(); i++)
-    addLs(pt.ls(i));
-}
-void DI_CuttingPoint::addLs (const double ls) {
-  Ls.push_back(adjustLs(ls));
-}
-void DI_CuttingPoint::addLs (const DI_Element *e) {
-  addLs(e->evalLs(x_, y_, z_));
+DI_CuttingPoint::DI_CuttingPoint(const DI_Point *pt) : DI_Point(pt->x(), pt->y(), pt->z()),
+                                                       xl_(pt->x()), yl_(pt->y()), zl_(pt->z()) {
+  for(int i = 0; i < pt->sizeLs(); i++)
+    addLs(pt->ls(i));
 }
-void DI_CuttingPoint::chooseLs (const gLevelset *Lsi) {
-  if(Ls.size() < 2) return;
-  double ls1 = Ls[Ls.size() - 2], ls2 = Ls[Ls.size() - 1];
-  double ls = Lsi->choose(ls1, ls2);
-  Ls.pop_back(); Ls.pop_back();
-  addLs(ls);
-}
-bool DI_CuttingPoint::equal (const DI_CuttingPoint &p) const {
-  return (fabs(x() - p.x()) < EQUALITY_TOL && fabs(y() - p.y()) < EQUALITY_TOL && fabs(z() - p.z()) < EQUALITY_TOL);
+
+// DI_PointLessThan methods -----------------------------------------------------------------------
+double DI_PointLessThan::tolerance = 1.e-6;
+bool DI_PointLessThan::operator()(const DI_Point *p1, const DI_Point *p2) const
+{
+  if(p1->x() - p2->x() >  tolerance) return true;
+  if(p1->x() - p2->x() < -tolerance) return false;
+  if(p1->y() - p2->y() >  tolerance) return true;
+  if(p1->y() - p2->y() < -tolerance) return false;
+  if(p1->z() - p2->z() >  tolerance) return true;
+  return false;
 }
 
 // DI_Element methods -----------------------------------------------------------------------------
@@ -584,11 +580,11 @@ DI_Element::DI_Element(const DI_Element &cp) : lsTag_(cp.lsTag()), polOrder_(cp.
   //printf("constructeur de copie d'element %d : ",cp.type()); cout << &cp << "->" << this << endl;
   pts_ = new DI_Point* [cp.nbVert()];
   for(int i = 0; i < cp.nbVert(); i++)
-    pts_[i] = new DI_Point(cp.pt(i));
+    pts_[i] = new DI_Point(*cp.pt(i));
   if(cp.getPolynomialOrder() > 1) {
     mid_ = new DI_Point* [cp.nbMid()];
     for(int i = 0; i < cp.nbMid(); i++)
-      mid_[i] = new DI_Point(cp.mid(i));
+      mid_[i] = new DI_Point(*cp.mid(i));
   }
   else
     mid_ = NULL;
@@ -610,7 +606,7 @@ DI_Element & DI_Element::operator= (const DI_Element &rhs){
   if(this != &rhs) {
     for(int i = 0; i < nbVert(); i++) {
       delete pts_[i];
-      pts_[i] = new DI_Point(rhs.pt(i));
+      pts_[i] = new DI_Point(*rhs.pt(i));
     }
     for(int i = 0; i < nbMid(); i++) {
       delete mid_[i];
@@ -621,7 +617,7 @@ DI_Element & DI_Element::operator= (const DI_Element &rhs){
       mid_ = new DI_Point*[rhs.nbMid()];
     }
     for(int i = 0; i < rhs.nbMid(); i++)
-      mid_[i] = new DI_Point(rhs.mid(i));
+      mid_[i] = new DI_Point(*rhs.mid(i));
     polOrder_ = rhs.getPolynomialOrder();
     integral_ = rhs.integral();
     lsTag_ = rhs.lsTag();
@@ -651,7 +647,7 @@ void DI_Element::setPolynomialOrder (int o) {
     printf("Order %d line function space not implemented ", o); print();
   }
 }
-void DI_Element::setPolynomialOrder (int o, const DI_Element *e, const std::vector<const gLevelset *> RPNi) {
+void DI_Element::setPolynomialOrder (int o, const DI_Element *e, const std::vector<const gLevelset *> &RPNi) {
   if(polOrder_ == o) return;
   for(int i = 0; i < nbMid(); i++)
     delete mid_[i];
@@ -687,12 +683,12 @@ void DI_Element::addLs (const DI_Element *e) {
   for(int i = 0; i < nbMid(); i++)
     mid_[i]->addLs(e);
 }
-void DI_Element::addLs (const DI_Element *e, const gLevelset &Ls) {
+void DI_Element::addLs (const DI_Element *e, const gLevelset *Ls) {
   if(type() != e->type()) {
     printf("Error : addLs with element of different type\n");
   }
   for(int j = 0; j < nbVert(); ++j) {
-    double ls = Ls(e->x(j), e->y(j), e->z(j));
+    double ls = (*Ls)(e->x(j), e->y(j), e->z(j));
     pts_[j]->addLs(ls);
   }
   for(int j = 0; j < nbMid(); ++j) {
@@ -701,25 +697,24 @@ void DI_Element::addLs (const DI_Element *e, const gLevelset &Ls) {
     double xc = 0, yc = 0, zc = 0;
     for(int k = 0; k < n; k++){
       xc += e->x(s[k]); yc += e->y(s[k]); zc += e->z(s[k]); }
-    double ls = Ls(xc/n, yc/n, zc/n);
+    double ls = (*Ls)(xc/n, yc/n, zc/n);
     mid_[j]->addLs(ls);
   }
 }
-void DI_Element::addLs (const DI_Element *e, const gLevelset &Ls, std::map<int, double> nodeLs[]) {
-  int primTag = Ls.getTag();
-  if(!nodeLs || !nodeLs[0].count(primTag)) {
+void DI_Element::addLs (const DI_Element *e, const gLevelset *Ls, int iLs, double **nodeLs) {
+  if(!nodeLs || !nodeLs[0][iLs]) {
     addLs(e, Ls);
     return;
   }
   for(int i = 0; i < nbVert(); i++)
-    pts_[i]->addLs(nodeLs[i][primTag]);
+    pts_[i]->addLs(nodeLs[i][iLs]);
   for(int j = 0; j < nbMid(); ++j) {
     std::vector<int> s(nbVert()); int n;
     e->midV(j, &s[0], n);
     double xc = 0, yc = 0, zc = 0;
     for(int k = 0; k < n; k++){
       xc += e->x(s[k]); yc += e->y(s[k]); zc += e->z(s[k]); }
-    double ls = Ls(xc/n, yc/n, zc/n);
+    double ls = (*Ls)(xc/n, yc/n, zc/n);
     mid_[j]->addLs(ls);
   }
 }
@@ -738,12 +733,12 @@ void DI_Element::clearLs() {
     mid_[i]->clearLs();
 }
 bool DI_Element::addQuadEdge (int edge, DI_Point *xm,
-                              const DI_Element *e, const std::vector<const gLevelset *> RPNi) {
+                              const DI_Element *e, const std::vector<const gLevelset *> &RPNi) {
   if(edge >= nbEdg()) {printf("wrong number (%d) for quadratic edge for a ", edge); print(); return false;}
   int s1, s2; vert(edge, s1, s2);
   int order0 = getPolynomialOrder();
   if(order0 == 1) setPolynomialOrder(2, e, RPNi);
-  double dist = distance(mid(edge), *xm);
+  double dist = distance(mid(edge), xm);
   double sideLength = distance(pt(s1), pt(s2));
   if (dist / sideLength < 1.e-5) {
     if(order0 == 1) setPolynomialOrder(1);
@@ -763,9 +758,9 @@ bool DI_Element::addQuadEdge (int edge, DI_Point *xm,
   computeIntegral();
   return true;
 }
-bool DI_Element::contain (const DI_Point &p) const {
+bool DI_Element::contain (const DI_Point *p) const {
   for(int i = 0; i < nbVert(); i++){
-    if(p.equal(pt(i)))
+    if(p->equal(pt(i)))
       return true;
   }
   switch(getDim()){
@@ -805,22 +800,19 @@ bool DI_Element::contain (const DI_Element *e) const {
     if(!contain(e->pt(p))) return false;
   return true;
 }
-DI_Point DI_Element::mappingP (DI_Point &pt) const {
-  double e[3]; evalC(pt.x(), pt.y(), pt.z(), e);
-  pt.move(e[0], e[1], e[2]);
-  return pt;
+void DI_Element::mappingP (DI_Point *pt) const {
+  double e[3]; evalC(pt->x(), pt->y(), pt->z(), e);
+  pt->move(e[0], e[1], e[2]);
 }
-DI_IntegrationPoint DI_Element::mappingIP (DI_IntegrationPoint &in) const {
-  double e[3]; evalC(in.x(), in.y(), in.z(), e);
-  double w = in.weight() * integral() / refIntegral();
-  in.move(e[0], e[1], e[2]);
-  in.setWeight(w);
-  return in;
+void DI_Element::mappingIP (DI_IntegrationPoint *in) const {
+  double e[3]; evalC(in->x(), in->y(), in->z(), e);
+  double w = in->weight() * integral() / refIntegral();
+  in->move(e[0], e[1], e[2]);
+  in->setWeight(w);
 }
-DI_CuttingPoint DI_Element::mappingCP (DI_CuttingPoint &cp) const {
-  double e[3]; evalC(cp.x(), cp.y(), cp.z(), e);
-  cp.move(e[0], e[1], e[2]);
-  return cp;
+void DI_Element::mappingCP (DI_CuttingPoint *cp) const {
+  double e[3]; evalC(cp->x(), cp->y(), cp->z(), e);
+  cp->move(e[0], e[1], e[2]);
 }
 void DI_Element::mappingEl (DI_Element *el) const {
   double s[3];
@@ -835,36 +827,40 @@ void DI_Element::mappingEl (DI_Element *el) const {
   el->computeIntegral();
 }
 void DI_Element::integrationPoints (const int polynomialOrder, const DI_Element *loc,
-                                    const DI_Element *e, const std::vector<const gLevelset *> RPN,
-                                    std::vector<DI_IntegrationPoint> &ip) const {
-  std::vector<DI_IntegrationPoint> ip_ref;
+                                    const DI_Element *e, const std::vector<const gLevelset *> &RPN,
+                                    std::vector<DI_IntegrationPoint *> &ip) const {
+  std::vector<DI_IntegrationPoint *> ip_ref;
   getRefIntegrationPoints(polynomialOrder, ip_ref);
   for (int j = 0; j < (int)ip_ref.size(); j++) {
-    DI_IntegrationPoint IPloc = ip_ref[j];
-    loc->mappingIP(IPloc);
+    DI_IntegrationPoint IPloc (*ip_ref[j]);
+    loc->mappingIP(&IPloc);
     mappingIP(ip_ref[j]);
-    ip_ref[j].addLocC(IPloc.x(), IPloc.y(), IPloc.z());
-    DI_IntegrationPoint pp = IPloc; pp.computeLs(e, RPN);
-    //ip_ref[j].setLs(loc->evalLs(IPloc.x(), IPloc.y(), IPloc.z()));//levelset computed in the subelement FIXME check sign!
-    //ip_ref[j].setLs(evalLs(ip_ref[j].x(), ip_ref[j].y(), ip_ref[j].z()));
-    ip_ref[j].setLs(pp.ls());
-    //printf("pt loc : "); IPloc.print(); printf("pt reel : "); ip_ref[j].print();
-    //printf("el loc : "); loc->printls(); printf("el reel : "); printls(); printf("el e : "); e->printls();
-    //printf("ls_loc=%g ls_reel=%g ls_e=%g\n\n", loc->evalLs(IPloc.x(), IPloc.y(), IPloc.z()), evalLs(ip_ref[j].x(), ip_ref[j].y(), ip_ref[j].z()), pp.ls());
+    ip_ref[j]->addLocC(IPloc.x(), IPloc.y(), IPloc.z());
+    DI_IntegrationPoint pp(IPloc); pp.computeLs(e, RPN);
+    //ip_ref[j]->setLs(loc->evalLs(IPloc.x(), IPloc.y(), IPloc.z()));//levelset computed in the subelement FIXME check sign!
+    //ip_ref[j]->setLs(evalLs(ip_ref[j]->x(), ip_ref[j]->y(), ip_ref[j]->z()));
+    ip_ref[j]->setLs(pp.ls());
+    /*printf("pt loc : "); IPloc.print(); printf("pt reel : "); ip_ref[j]->print();
+    printf("el loc : "); loc->printls(); printf("el reel : "); printls(); printf("el e : "); e->printls();
+    printf("ls_loc=%g ls_reel=%g ls_e=%g\n\n", loc->evalLs(IPloc.x(), IPloc.y(), IPloc.z()),
+                                               evalLs(ip_ref[j]->x(), ip_ref[j]->y(), ip_ref[j]->z()), pp.ls());*/
     ip.push_back(ip_ref[j]);
   }
 }
-void DI_Element::getCuttingPoints (const DI_Element *e, const std::vector<const gLevelset *> RPNi,
-                                   std::vector<DI_CuttingPoint> &cp) const {
+void DI_Element::getCuttingPoints (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+                                   std::vector<DI_CuttingPoint *> &cp) const {
   int s1, s2;
   for(int i = 0; i < nbEdg(); i++){
     vert(i, s1, s2);
     if (isCrossed(pt(s1), pt(s2))) {
-      DI_Point p = Newton(pt(s1), pt(s2), e, RPNi);
-      cp.push_back(DI_CuttingPoint(p));
+      DI_Point* p = Newton(pt(s1), pt(s2), e, RPNi);
+      cp.push_back(new DI_CuttingPoint(p));
+      delete p;
     }
-    if(ls(s1) == 0.)
-      cp.push_back(DI_CuttingPoint(pt(s1)));
+  }
+  for(int i = 0; i < nbVert(); i++){
+    if(ls(i) == 0.)
+      cp.push_back(new DI_CuttingPoint(pt(i)));
   }
 }
 void DI_Element::evalC (const double u, const double v, const double w, double *ev, int order) const {
@@ -938,34 +934,34 @@ double DI_Element::detJ (const double u, const double v, const double w) const {
   }
 }
 // set the lsTag to +1 if the element is inside the domain (lsTag is -1 by default)
-void DI_Element::computeLsTagDom(const DI_Element *e, const std::vector<const gLevelset *> RPN) {
+void DI_Element::computeLsTagDom(const DI_Element *e, const std::vector<const gLevelset *> &RPN) {
   for(int i = 0; i < nbVert(); i++) {
-    if(pt(i).isOutsideDomain())
+    if(pt(i)->isOutsideDomain())
       return;
-    if(pt(i).isInsideDomain())
+    if(pt(i)->isInsideDomain())
       {setLsTag(1); return;}
   }
-  DI_Point bar = barycenter(this, e, RPN);
-  if(bar.isOutsideDomain())
-    return;
-  if(bar.isInsideDomain())
-    {setLsTag(1); return;}
+  DI_Point* bar = barycenter(this, e, RPN);
+  if(bar->isOutsideDomain())
+    {delete bar; return;}
+  if(bar->isInsideDomain())
+    {setLsTag(1); delete bar; return;}
   for(int i = 0; i < nbVert(); i++) {
-    DI_Point mid = middle (pt(i), bar, e, RPN);
-    if(mid.isOutsideDomain())
-      return;
-    if(mid.isInsideDomain())
-      {setLsTag(1); return;}
+    DI_Point* mid = middle (pt(i), bar, e, RPN);
+    delete bar;
+    if(mid->isOutsideDomain())
+      {delete mid; return;}
+    if(mid->isInsideDomain())
+      {setLsTag(1); delete mid; return;}
   }
   printf("Error : Unable to determine the sign of the element : \n");
   printf("Parent element : "); e->printls();
   printf("Element : "); printls();
-  return;
 }
 // set the lsTag to -1 if the element is not on the border of the domain
-void DI_Element::computeLsTagBound(std::vector<DI_Hexa> &hexas, std::vector<DI_Tetra> &tetras){
+void DI_Element::computeLsTagBound(std::vector<DI_Hexa *> &hexas, std::vector<DI_Tetra *> &tetras){
   for(int i = 0; i < nbVert(); i++) {
-    if(!pt(i).isOnBorder()) {
+    if(!pt(i)->isOnBorder()) {
       setLsTag(-1);
       return;
     }
@@ -973,9 +969,9 @@ void DI_Element::computeLsTagBound(std::vector<DI_Hexa> &hexas, std::vector<DI_T
 
   /*DI_Element *e1 = NULL, *e2 = NULL;
   for(int i = 0; i < (int)tetras.size(); i++){
-    if(belongsTo(*this, tetras[i])) {
-      if(!e1) e1 = &tetras[i];
-      else {e2 = &tetras[i]; break;}
+    if(belongsTo(this, tetras[i])) {
+      if(!e1) e1 = tetras[i];
+      else {e2 = tetras[i]; break;}
     }
   }
   if(e1 && e2) {
@@ -983,14 +979,14 @@ void DI_Element::computeLsTagBound(std::vector<DI_Hexa> &hexas, std::vector<DI_T
     return;
   }
   for(int i = 0; i < (int)hexas.size(); i++){
-    if(belongsTo(*this, hexas[i])) {
-      if(!e1) e1 = &hexas[i];
-      else {e2 = &hexas[i]; break;}
+    if(belongsTo(this, hexas[i])) {
+      if(!e1) e1 = hexas[i];
+      else {e2 = hexas[i]; break;}
     }
   }
   if(e1 && e2 && e1->lsTag() * e2->lsTag() > 0.) setLsTag(-1);*/
 }
-void DI_Element::computeLsTagBound(std::vector<DI_Quad> &quads, std::vector<DI_Triangle> &triangles){
+void DI_Element::computeLsTagBound(std::vector<DI_Quad *> &quads, std::vector<DI_Triangle *> &triangles){
   for(int i = 0; i < nbVert(); i++) {
     if(ls(i) != 0.) {
       setLsTag(-1);
@@ -1001,10 +997,10 @@ void DI_Element::computeLsTagBound(std::vector<DI_Quad> &quads, std::vector<DI_T
   /*DI_Element *e1 = NULL, *e2 = NULL, *et = NULL;
   int NT = triangles.size(), NQ = quads.size();
   for(int i = 0; i < NT + NQ; i++){
-    if((i < NT  && belongsTo(*this, triangles[i])) ||
-       (i >= NT && belongsTo(*this, quads[i-NT]))) {
-      if(i < NT) et = &triangles[i];
-      else et = &quads[i-NT];
+    if((i < NT  && belongsTo(this, triangles[i])) ||
+       (i >= NT && belongsTo(this, quads[i-NT]))) {
+      if(i < NT) et = triangles[i];
+      else et = quads[i-NT];
       if(!e1) e1 = et;
       else {e2 = et; break;}
     }
@@ -1044,6 +1040,19 @@ void DI_Element::printls() const {
   printf("tag=%d\n", lsTag());
 }
 
+double DI_ElementLessThan::tolerance = 1.e-6;
+bool DI_ElementLessThan::operator()(const DI_Element *e1, const DI_Element *e2) const
+{
+  for(int i = 0; i < e1->nbVert(); i++) {
+    if(e1->x(i) - e2->x(i) >  tolerance) return true;
+    if(e1->x(i) - e2->x(i) < -tolerance) return false;
+    if(e1->y(i) - e2->y(i) >  tolerance) return true;
+    if(e1->y(i) - e2->y(i) < -tolerance) return false;
+    if(e1->z(i) - e2->z(i) >  tolerance) return true;
+    return false;
+  }
+}
+
 // DI_Line methods --------------------------------------------------------------------------------
 void DI_Line::computeIntegral() {
   switch (getPolynomialOrder()) {
@@ -1416,60 +1425,62 @@ void DI_Hexa::getGradShapeFunctions (const double u, const double v, const doubl
 
 // Split a reference line cut by a level set into sublines
 void DI_Line::selfSplit (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                          std::vector<DI_Line> &subLines, std::vector<DI_CuttingPoint> &cuttingPoints) const
+                          std::vector<DI_Line *> &subLines, std::vector<DI_CuttingPoint *> &cuttingPoints) const
 {
   if (!isCrossed(pt(0), pt(1))) {
-    subLines.push_back(*this);
+    subLines.push_back(new DI_Line(*this));
     return;
   }
 
   // compute the intersection between the line and the level set
-  DI_Point U = Newton(pt(0), pt(1), e, RPNi);
-  cuttingPoints.push_back(DI_CuttingPoint(U));
+  DI_Point *U = Newton(pt(0), pt(1), e, RPNi);
+  cuttingPoints.push_back(new DI_CuttingPoint(U));
 
   // line cut => split into 2 sublines
-  subLines.push_back(DI_Line(pt(0), U, lsTag()));
-  subLines.push_back(DI_Line(U, pt(1), lsTag()));
+  subLines.push_back(new DI_Line(pt(0), U, lsTag()));
+  subLines.push_back(new DI_Line(U, pt(1), lsTag()));
+  delete U;
 }
 
 // Split a triangle into 4 sub-triangles
-void DI_Triangle::splitIntoSubTriangles (std::vector<DI_Triangle> &subTriangles) const {
-  DI_Point p01 = middle(pt(0), pt(1));
-  DI_Point p02 = middle(pt(0), pt(2));
-  DI_Point p12 = middle(pt(1), pt(2));
+void DI_Triangle::splitIntoSubTriangles (std::vector<DI_Triangle *> &subTriangles) const {
+  DI_Point *p01 = middle(pt(0), pt(1));
+  DI_Point *p02 = middle(pt(0), pt(2));
+  DI_Point *p12 = middle(pt(1), pt(2));
 
-  subTriangles.push_back(DI_Triangle(p01, p02, p12));   // 01-02-12
-  subTriangles.push_back(DI_Triangle(pt(0), p01, p02)); // 0-01-02
-  subTriangles.push_back(DI_Triangle(pt(1), p01, p12)); // 1-01-12
-  subTriangles.push_back(DI_Triangle(pt(2), p02, p12)); // 2-02-12
+  subTriangles.push_back(new DI_Triangle(p01, p02, p12));   // 01-02-12
+  subTriangles.push_back(new DI_Triangle(pt(0), p01, p02)); // 0-01-02
+  subTriangles.push_back(new DI_Triangle(pt(1), p01, p12)); // 1-01-12
+  subTriangles.push_back(new DI_Triangle(pt(2), p02, p12)); // 2-02-12
+  delete p01; delete p02; delete p12;
 }
 // Split a reference triangle cut by a level set into subtriangles
 void DI_Triangle::selfSplit (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                             std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-                             std::vector<DI_Line> &surfLines, std::vector<DI_CuttingPoint> &cuttingPoints) const
+                             std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+                             std::vector<DI_Line *> &surfLines, std::vector<DI_CuttingPoint *> &cuttingPoints) const
 {
   bool quadT = (e->getPolynomialOrder() == 2) ? true : false; // if true, use quadratic sub triangles
   int LStag = RPNi.back()->getTag();
 
   int nbZe = 0, ze[2];
   for(int i = 0; i < 3; i++)
-    if(pt(i).isOnBorder())
+    if(pt(i)->isOnBorder())
       ze[nbZe++] = i;
   for(int i = 0; i < nbZe; i++)
-    cuttingPoints.push_back(DI_CuttingPoint(pt(ze[i])));
+    cuttingPoints.push_back(new DI_CuttingPoint(pt(ze[i])));
     // !! we add these points several times => remove later
 
   if (!isCrossed(pt(0), pt(1)) && !isCrossed(pt(0), pt(2)) && !isCrossed(pt(1), pt(2))) {
-    subTriangles.push_back(*this);
+    subTriangles.push_back(new DI_Triangle(*this));
     if(nbZe == 2)
-      surfLines.push_back(DI_Line(pt(ze[0]), pt(ze[1]), LStag));
+      surfLines.push_back(new DI_Line(pt(ze[0]), pt(ze[1]), LStag));
       // !! we add these lines twice => remove the second later
     return;
   }
 
-  DI_Point U[2];              // cutting points (max2)
-  int IND[2];                 // ids of edges cut
-  int COUNT = 0;                // number of edges cut
+  DI_Point *U[2];              // cutting points (max2)
+  int IND[2];                  // ids of edges cut
+  int COUNT = 0;               // number of edges cut
 
   // compute the intersections between the edges of the triangle and the level set
   for(int i = 0; i < 3; i++){
@@ -1481,7 +1492,7 @@ void DI_Triangle::selfSplit (const DI_Element *e, const std::vector<const gLevel
   }
 
   for(int i = 0; i < COUNT; i++)
-    cuttingPoints.push_back(DI_CuttingPoint(U[i]));
+    cuttingPoints.push_back(new DI_CuttingPoint(U[i]));
 
   // Adjust the indices of the nodes in order to have the same pattern for each case with the same number of edges cut;
   // compute the position of the middle nodes on the quadratic edges of the sub triangles;
@@ -1492,21 +1503,22 @@ void DI_Triangle::selfSplit (const DI_Element *e, const std::vector<const gLevel
       int s2 = (s1 + 1) % 3;
       int s3 = (s2 + 1) % 3;
 
-      DI_Triangle t1 = DI_Triangle(pt(s3), pt(s1), U[0], lsTag()); //t1.print();
-      DI_Triangle t2 = DI_Triangle(pt(s2), pt(s3), U[0], lsTag()); //t2.print();
-      DI_Line ln = DI_Line(U[0], pt(s3), LStag); //ln.print();
+      DI_Triangle *t1 = new DI_Triangle(pt(s3), pt(s1), U[0], lsTag());
+      DI_Triangle *t2 = new DI_Triangle(pt(s2), pt(s3), U[0], lsTag());
+      DI_Line *ln = new DI_Line(U[0], pt(s3), LStag);
 
       if(quadT){
-        DI_Point midEN2 = quadMidNode(U[0], pt(s3), pt(s1), e, RPNi); // intersection between ls and the bissector between the cutting points
-        cuttingPoints.push_back(DI_CuttingPoint(midEN2));
-        //midEN2.printls();
-        t1.addQuadEdge (2, &midEN2, e, RPNi); //t1.printls();
-        t2.addQuadEdge (1, &midEN2, e, RPNi); //t2.printls();
-        ln.addQuadEdge (0, &midEN2, e, RPNi); //ln.printls();
+        DI_Point *midEN2 = quadMidNode(U[0], pt(s3), pt(s1), e, RPNi); // intersection between ls and the bissector between the cutting points
+        cuttingPoints.push_back(new DI_CuttingPoint(midEN2));
+        t1->addQuadEdge (2, midEN2, e, RPNi);
+        t2->addQuadEdge (1, midEN2, e, RPNi);
+        ln->addQuadEdge (0, midEN2, e, RPNi);
+        delete midEN2;
       }
       subTriangles.push_back(t1);
       subTriangles.push_back(t2);
       surfLines.push_back(ln);
+      delete U[0];
       break;
     }
     case 2: {// 2 edges cut => 1 triangle + 1 quad => split into 3 triangles
@@ -1514,26 +1526,27 @@ void DI_Triangle::selfSplit (const DI_Element *e, const std::vector<const gLevel
       int s2 = (s1 + 1) % 3;
       int s3 = (s1 + 2) % 3;
       if(s1 == 0) { // (0,2) => swap U[0] and U[1]
-        swap(U[0], U[1]);
+        swap(&U[0], &U[1]);
       }
 
       bool useQuads = false; // if true, split the triangle into 1 triangle and 1 quad
 
-      DI_Triangle t1 = DI_Triangle(U[0], pt(s1), U[1], lsTag());
-      DI_Line ln = DI_Line(U[0], U[1], LStag);
-      DI_Quad q1; DI_Triangle t2, t3;
-      if(useQuads) q1 = DI_Quad(U[0], U[1], pt(s2), pt(s3), lsTag());
-      else bestQuality(U[0], U[1], pt(s2), pt(s3), t2, t3);
-      t2.setLsTag(lsTag()); t3.setLsTag(lsTag());
+      DI_Triangle *t1 = new DI_Triangle(U[0], pt(s1), U[1], lsTag());
+      DI_Line *ln = new DI_Line(U[0], U[1], LStag);
+      DI_Quad *q1; DI_Triangle *t2, *t3;
+      if(useQuads) q1 = new DI_Quad(U[0], U[1], pt(s2), pt(s3), lsTag());
+      else bestQuality(U[0], U[1], pt(s2), pt(s3), &t2, &t3);
+      t2->setLsTag(lsTag()); t3->setLsTag(lsTag());
 
       if(quadT){
-        DI_Point midEN2 = quadMidNode(U[0], U[1], pt(s2), e, RPNi); // intersection between ls and the bissector between the cutting points
-        cuttingPoints.push_back(DI_CuttingPoint(midEN2));
+        DI_Point *midEN2 = quadMidNode(U[0], U[1], pt(s2), e, RPNi); // intersection between ls and the bissector between the cutting points
+        cuttingPoints.push_back(new DI_CuttingPoint(midEN2));
         //midEN2.printls();
-        t1.addQuadEdge(2, &midEN2, e, RPNi); //t1.printls();
-        ln.addQuadEdge(0, &midEN2, e, RPNi); //ln.printls();
-        if(useQuads) q1.addQuadEdge(0, &midEN2, e, RPNi);
-        else t2.addQuadEdge(0, &midEN2, e, RPNi); //t2.printls();
+        t1->addQuadEdge(2, midEN2, e, RPNi); //t1.printls();
+        ln->addQuadEdge(0, midEN2, e, RPNi); //ln.printls();
+        if(useQuads) q1->addQuadEdge(0, midEN2, e, RPNi);
+        else t2->addQuadEdge(0, midEN2, e, RPNi); //t2.printls();
+        delete midEN2;
       }
       subTriangles.push_back(t1);
       surfLines.push_back(ln);
@@ -1542,49 +1555,50 @@ void DI_Triangle::selfSplit (const DI_Element *e, const std::vector<const gLevel
         subTriangles.push_back(t2);
         subTriangles.push_back(t3);
       }
+      delete U[0]; delete U[1];
       break;
     }
     default:
       printf("Error : %d edge(s) cut in the triangle (ls : %g %g %g)\n",
-             COUNT, pt(0).ls(), pt(1).ls(), pt(2).ls());
+             COUNT, ls(0), ls(1), ls(2));
   }
 }
 
 // Split a reference Quadrangle into 2 triangles
-void DI_Quad::splitIntoTriangles(std::vector<DI_Triangle> &triangles) const
+void DI_Quad::splitIntoTriangles(std::vector<DI_Triangle *> &triangles) const
 {
-  triangles.push_back(DI_Triangle(pt(0), pt(1), pt(3), lsTag())); // 013
-  triangles.push_back(DI_Triangle(pt(1), pt(2), pt(3), lsTag())); // 123
+  triangles.push_back(new DI_Triangle(pt(0), pt(1), pt(3), lsTag())); // 013
+  triangles.push_back(new DI_Triangle(pt(1), pt(2), pt(3), lsTag())); // 123
 }
 
 // Split a reference tetrahedron cut by a level set (defined in a hex) into sub tetrahedra
 // and create triangles on the surface of the level set
 void DI_Tetra::selfSplit (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                       std::vector<DI_Tetra> &subTetras, std::vector<DI_Triangle> &surfTriangles,
-                       std::vector<DI_CuttingPoint> &cuttingPoints, std::vector<DI_QualError> &QError) const
+                       std::vector<DI_Tetra *> &subTetras, std::vector<DI_Triangle *> &surfTriangles,
+                       std::vector<DI_CuttingPoint *> &cuttingPoints, std::vector<DI_QualError *> &QError) const
 {
   bool quadT = (e->getPolynomialOrder() == 2) ? true : false; // use of quadratic surf triangles and quadratic sub tetrahedra
   int tag = RPNi.back()->getTag();
 
   int nbZe = 0, ze[3];
   for(int i = 0; i < 4; i++)
-    if(pt(i).isOnBorder())
+    if(pt(i)->isOnBorder())
       ze[nbZe++] = i;
   for(int i = 0; i < nbZe; i++)
-    cuttingPoints.push_back(DI_CuttingPoint(pt(ze[i]))); // !! we add these points several times => remove later
+    cuttingPoints.push_back(new DI_CuttingPoint(pt(ze[i]))); // !! we add these points several times => remove later
 
   // case 0 : the tetrahedron is not cut by the level set
   if (!isCrossed(pt(0), pt(1)) && !isCrossed(pt(0), pt(2)) && !isCrossed(pt(1), pt(2)) &&
       !isCrossed(pt(0), pt(3)) && !isCrossed(pt(1), pt(3)) && !isCrossed(pt(2), pt(3))) {
-    subTetras.push_back(*this);
+    subTetras.push_back(new DI_Tetra(*this));
     if(nbZe == 3)
-      surfTriangles.push_back(DI_Triangle(pt(ze[0]), pt(ze[1]), pt(ze[2]), tag));
+      surfTriangles.push_back(new DI_Triangle(pt(ze[0]), pt(ze[1]), pt(ze[2]), tag));
       // !! we add these triangles twice => remove the second later
     return;
   }
 
-  DI_Point U[4];        // cutting points
-  int COUNT = 0;       // number of edges cut
+  DI_Point *U[4];    // cutting points
+  int COUNT = 0;     // number of edges cut
   int IND[4];        // ids of edges cut
 
   // edges nodes and opposite edges nodes
@@ -1594,13 +1608,12 @@ void DI_Tetra::selfSplit (const DI_Element *e, const std::vector<const gLevelset
   for(int i = 0; i < 6; i++){
     int n1 = tab[i][0], n2 = tab[i][1];
     if (isCrossed(pt(n1), pt(n2))) {
-      //printf("edge %d%d cut vls:%g/%g (%g,%g,%g) (%g,%g,%g)\n",n1,n2,vls[n1],vls[n2],x(n1),y(n1),z(n1),x(n2),y(n2),z(n2));
       U[COUNT] = Newton(pt(n1), pt(n2), e, RPNi);
       IND[COUNT++] = i;
     }
   }
   for(int i = 0; i < COUNT; i++)
-    cuttingPoints.push_back(DI_CuttingPoint(U[i]));
+    cuttingPoints.push_back(new DI_CuttingPoint(U[i]));
 
   // Adjust the indices of the nodes in order to have the same pattern for each case with the same number of edges cut;
   // compute the position of the middle nodes on the quadratic edges of the sub tetras;
@@ -1614,31 +1627,33 @@ void DI_Tetra::selfSplit (const DI_Element *e, const std::vector<const gLevelset
       int s3 = tab[i1][2];
       int s4 = tab[i1][3];
 
-      DI_Tetra t1 = DI_Tetra(U[0], pt(s4), pt(s3), pt(s1));
-      DI_Tetra t2 = DI_Tetra(pt(s4), U[0], pt(s3), pt(s2));
-      DI_Triangle tr = DI_Triangle(pt(s4), U[0], pt(s3), tag);
+      DI_Tetra *t1 = new DI_Tetra(U[0], pt(s4), pt(s3), pt(s1));
+      DI_Tetra *t2 = new DI_Tetra(pt(s4), U[0], pt(s3), pt(s2));
+      DI_Triangle *tr = new DI_Triangle(pt(s4), U[0], pt(s3), tag);
 
       if(quadT){
-        DI_Point midEN2[2]; // intersection between ls and the bissector between the cutting points
+        DI_Point *midEN2[2]; // intersection between ls and the bissector between the cutting points
         midEN2[0] = quadMidNode(U[0], pt(s4), pt(s1), e, RPNi);
         midEN2[1] = quadMidNode(U[0], pt(s3), pt(s1), e, RPNi);
-        tr.addQuadEdge (0, &midEN2[0], e, RPNi);
-        t1.addQuadEdge (0, &midEN2[0], e, RPNi);
-        t2.addQuadEdge (0, &midEN2[0], e, RPNi);
-        tr.addQuadEdge (1, &midEN2[1], e, RPNi);
-        t1.addQuadEdge (1, &midEN2[1], e, RPNi);
-        t2.addQuadEdge (3, &midEN2[1], e, RPNi);
+        tr->addQuadEdge (0, midEN2[0], e, RPNi);
+        t1->addQuadEdge (0, midEN2[0], e, RPNi);
+        t2->addQuadEdge (0, midEN2[0], e, RPNi);
+        tr->addQuadEdge (1, midEN2[1], e, RPNi);
+        t1->addQuadEdge (1, midEN2[1], e, RPNi);
+        t2->addQuadEdge (3, midEN2[1], e, RPNi);
+        delete midEN2[0]; delete midEN2[1];
       }
       subTetras.push_back(t1);
       subTetras.push_back(t2);
       surfTriangles.push_back(tr);
+      delete U[0];
       break;
     }
     case 2 : {// 2 edges cut => 1 tetra + 1 pyramid => split into 3 tetras
       int i1 = IND[0], i2 = IND[1];
 
       if((i1 == 0 && (i2 == 2 ||i2 == 3)) || (i1 == 1 && i2 == 4) || ((i1 == 2 || i1 == 3) && i2 == 5)) {
-        swap(U[0], U[1]); swap(i1, i2);
+        swap(&U[0], &U[1]); swap(i1, i2);
       }
       //printf("case 2 : ind : %d,%d\n",i1,i2);
 
@@ -1647,125 +1662,132 @@ void DI_Tetra::selfSplit (const DI_Element *e, const std::vector<const gLevelset
       int s3 = commonV(tab[i1][2], tab[i1][3], tab[i2][0], tab[i2][1]);
       int s4 = commonV(tab[i1][0], tab[i1][1], tab[i2][2], tab[i2][3]);
 
-      DI_Tetra t1 = DI_Tetra(U[0], U[1], pt(s2), pt(s1));
-      DI_Triangle tr = DI_Triangle(U[0], U[1], pt(s1), tag);
-      DI_Tetra t2, t3;
-      int qual = bestQuality(U[1], U[0], pt(s4), pt(s3), pt(s1), t2, t3);
+      DI_Tetra *t1 = new DI_Tetra(U[0], U[1], pt(s2), pt(s1));
+      DI_Triangle *tr = new DI_Triangle(U[0], U[1], pt(s1), tag);
+      DI_Tetra *t2, *t3;
+      int qual = bestQuality(U[1], U[0], pt(s4), pt(s3), pt(s1), &t2, &t3);
 
       if(quadT){
-        DI_Point midEN2[3]; // intersection between ls and the bissector between the cutting points
+        DI_Point *midEN2[3]; // intersection between ls and the bissector between the cutting points
         midEN2[0] = quadMidNode(U[1], pt(s1), pt(s2), e, RPNi);
         midEN2[1] = quadMidNode(U[0], pt(s1), pt(s2), e, RPNi);
         midEN2[2] = quadMidNode(U[1], U[0], pt(s4), e, RPNi);
-        tr.addQuadEdge(1, &midEN2[0], e, RPNi);
-        t1.addQuadEdge(5, &midEN2[0], e, RPNi);
-        t2.addQuadEdge(2, &midEN2[0], e, RPNi);
-        t3.addQuadEdge(2, &midEN2[0], e, RPNi);
-
-        tr.addQuadEdge(2, &midEN2[1], e, RPNi);
-        t1.addQuadEdge(2, &midEN2[1], e, RPNi);
-        t2.addQuadEdge(5, &midEN2[1], e, RPNi);
-
-        tr.addQuadEdge(0, &midEN2[2], e, RPNi);
-        if(t2.addQuadEdge(0, &midEN2[2], e, RPNi)) {
-          t1.addQuadEdge(0, &midEN2[2], e, RPNi);
+        tr->addQuadEdge(1, midEN2[0], e, RPNi);
+        t1->addQuadEdge(5, midEN2[0], e, RPNi);
+        t2->addQuadEdge(2, midEN2[0], e, RPNi);
+        t3->addQuadEdge(2, midEN2[0], e, RPNi);
+
+        tr->addQuadEdge(2, midEN2[1], e, RPNi);
+        t1->addQuadEdge(2, midEN2[1], e, RPNi);
+        t2->addQuadEdge(5, midEN2[1], e, RPNi);
+
+        tr->addQuadEdge(0, midEN2[2], e, RPNi);
+        if(t2->addQuadEdge(0, midEN2[2], e, RPNi)) {
+          t1->addQuadEdge(0, midEN2[2], e, RPNi);
         }
         else {
-          DI_Point mid = middle(pt(s3), pt(s4), e, RPNi);
-          DI_Point quad = middle(mid, midEN2[2], e, RPNi);
+          DI_Point* mid = middle(pt(s3), pt(s4), e, RPNi);
+          DI_Point* quad = middle(mid, midEN2[2], e, RPNi);
           if(qual == 1){
-            t2.addQuadEdge(1, &quad, e, RPNi);
-            t3.addQuadEdge(0, &quad, e, RPNi);
+            t2->addQuadEdge(1, quad, e, RPNi);
+            t3->addQuadEdge(0, quad, e, RPNi);
           }
           else {
-            t2.addQuadEdge(3, &quad, e, RPNi);
-            t3.addQuadEdge(1, &quad, e, RPNi);
+            t2->addQuadEdge(3, quad, e, RPNi);
+            t3->addQuadEdge(1, quad, e, RPNi);
           }
-          if(t2.addQuadEdge(0, &midEN2[2], e, RPNi)) {
-            t1.addQuadEdge(0, &midEN2[2], e, RPNi);
+          if(t2->addQuadEdge(0, midEN2[2], e, RPNi)) {
+            t1->addQuadEdge(0, midEN2[2], e, RPNi);
           }
           else printf("unable to add quadratic edge U0U1 to the subtetrahedra cas 2.\n");
+          delete mid; delete quad;
         }
+        delete midEN2[0]; delete midEN2[1]; delete midEN2[2];
       }
 
       subTetras.push_back(t1);
       subTetras.push_back(t2);
       subTetras.push_back(t3);
       surfTriangles.push_back(tr);
+      delete U[0]; delete U[1];
       break;
     }
     case 3 : {// 3 edges cut => 1 tetra + 1 prism => split into 4 tetras
       int i1 = IND[0], i2 = IND[1], i3 = IND[2];
 
       if(i1 == 0 && i2 == 3) {
-        swap(U[1], U[2]); swap(i2, i3);
+        swap(&U[1], &U[2]); swap(i2, i3);
       }
       //printf("case 3 : ind : %d,%d,%d\n",i1,i2,i3);
 
       int s1 = commonV(tab[i1][0], tab[i1][1], tab[i2][0], tab[i2][1]);
       int s2 = commonV(tab[i2][2], tab[i2][3], tab[i3][2], tab[i3][3]);
       int s3 = commonV(tab[i1][2], tab[i1][3], tab[i3][2], tab[i3][3]);
-      int s4 = commonV(tab[i1][2], tab[i1][3], tab[i2][2], tab[i2][3]);   //printf("s: %d %d %d %d\n",s1,s2,s3,s4);
+      int s4 = commonV(tab[i1][2], tab[i1][3], tab[i2][2], tab[i2][3]);
 
-      DI_Tetra t1 = DI_Tetra(pt(s1), U[0], U[1], U[2]);
-      DI_Triangle tr = DI_Triangle(U[0], U[1], U[2], tag); //t1.print(); tr.print();
-      DI_Tetra t2, t3, t4;
-      bestQuality(U[0], U[1], U[2], pt(s2), pt(s3), pt(s4), t2, t3, t4, QError); //t2.print(); t3.print(); t4.print();
+      DI_Tetra *t1 = new DI_Tetra(pt(s1), U[0], U[1], U[2]);
+      DI_Triangle *tr = new DI_Triangle(U[0], U[1], U[2], tag);
+      DI_Tetra *t2, *t3, *t4;
+      bestQuality(U[0], U[1], U[2], pt(s2), pt(s3), pt(s4), &t2, &t3, &t4, QError);
       /*t2 = DI_Tetra(U[0],V[0],W[0], x(s2),y(s2),z(s2), U[1],V[1],W[1], U[2],V[2],W[2]);
       t3 = DI_Tetra(U[2],V[2],W[2], U[1],V[1],W[1], x(s3),y(s3),z(s3), x(s2),y(s2),z(s2));
       t4 = DI_Tetra(U[2],V[2],W[2], x(s3),y(s3),z(s3), x(s4),y(s4),z(s4), x(s2),y(s2),z(s2));*/
       if(quadT){
-        DI_Point midEN2[3]; // intersection between ls and the bissector between the cutting points
+        DI_Point *midEN2[3]; // intersection between ls and the bissector between the cutting points
         midEN2[0] = quadMidNode(U[2], U[1], pt(s3), e, RPNi);
         midEN2[1] = quadMidNode(U[1], U[0], pt(s2), e, RPNi);
         midEN2[2] = quadMidNode(U[2], U[0], pt(s2), e, RPNi);
-        tr.addQuadEdge(1, &midEN2[0], e, RPNi);
-        if(t3.addQuadEdge(0, &midEN2[0], e, RPNi)) {
-          t1.addQuadEdge(5, &midEN2[0], e, RPNi);
-          t2.addQuadEdge(4, &midEN2[0], e, RPNi);
+        tr->addQuadEdge(1, midEN2[0], e, RPNi);
+        if(t3->addQuadEdge(0, midEN2[0], e, RPNi)) {
+          t1->addQuadEdge(5, midEN2[0], e, RPNi);
+          t2->addQuadEdge(4, midEN2[0], e, RPNi);
         }
         else {
-          DI_Point mid = middle(pt(s3), pt(s4), e, RPNi);
-          DI_Point quad = middle(mid, midEN2[0], e, RPNi);
-          t3.addQuadEdge(1, &quad, e, RPNi);
-          t4.addQuadEdge(0, &quad, e, RPNi);
-          if(t3.addQuadEdge(0, &midEN2[0], e, RPNi)) {
-            t1.addQuadEdge(5, &midEN2[0], e, RPNi);
-            t2.addQuadEdge(4, &midEN2[0], e, RPNi);
+          DI_Point *mid = middle(pt(s3), pt(s4), e, RPNi);
+          DI_Point *quad = middle(mid, midEN2[0], e, RPNi);
+          t3->addQuadEdge(1, quad, e, RPNi);
+          t4->addQuadEdge(0, quad, e, RPNi);
+          if(t3->addQuadEdge(0, midEN2[0], e, RPNi)) {
+            t1->addQuadEdge(5, midEN2[0], e, RPNi);
+            t2->addQuadEdge(4, midEN2[0], e, RPNi);
           }
           else printf("unable to add quadratic edge U1U2 to the subtetrahedra cas 3.\n");
+          delete mid; delete quad;
         }
 
-        tr.addQuadEdge(0, &midEN2[1], e, RPNi);
-        if(t2.addQuadEdge(1, &midEN2[1], e, RPNi)) {
-          t1.addQuadEdge(0, &midEN2[1], e, RPNi);
+        tr->addQuadEdge(0, midEN2[1], e, RPNi);
+        if(t2->addQuadEdge(1, midEN2[1], e, RPNi)) {
+          t1->addQuadEdge(0, midEN2[1], e, RPNi);
         }
         else {
-          DI_Point mid = middle(pt(s2), pt(s3), e, RPNi);
-          DI_Point quad = middle(mid, midEN2[1], e, RPNi);
-          t2.addQuadEdge(3, &quad, e, RPNi);
-          t3.addQuadEdge(5, &quad, e, RPNi);
-          if(t2.addQuadEdge(1, &midEN2[1], e, RPNi)) {
-            t1.addQuadEdge(0, &midEN2[1], e, RPNi);
+          DI_Point *mid = middle(pt(s2), pt(s3), e, RPNi);
+          DI_Point *quad = middle(mid, midEN2[1], e, RPNi);
+          t2->addQuadEdge(3, quad, e, RPNi);
+          t3->addQuadEdge(5, quad, e, RPNi);
+          if(t2->addQuadEdge(1, midEN2[1], e, RPNi)) {
+            t1->addQuadEdge(0, midEN2[1], e, RPNi);
           }
           else printf("unable to add quadratic edge U1U2 to the subtetrahedra cas 3.\n");
+          delete mid; delete quad;
         }
 
-        tr.addQuadEdge(2, &midEN2[2], e, RPNi);
-        if(t2.addQuadEdge(2, &midEN2[2], e, RPNi)) {
-          t1.addQuadEdge(2, &midEN2[2], e, RPNi);
+        tr->addQuadEdge(2, midEN2[2], e, RPNi);
+        if(t2->addQuadEdge(2, midEN2[2], e, RPNi)) {
+          t1->addQuadEdge(2, midEN2[2], e, RPNi);
         }
         else {
-          DI_Point mid = middle(pt(s2), pt(s4), e, RPNi);
-          DI_Point quad = middle(mid, midEN2[2], e, RPNi);
-          t2.addQuadEdge(5, &quad, e, RPNi);
-          t3.addQuadEdge(2, &quad, e, RPNi);
-          t4.addQuadEdge(2, &quad, e, RPNi);
-          if(t2.addQuadEdge(2, &midEN2[2], e, RPNi)) {
-            t1.addQuadEdge(2, &midEN2[2], e, RPNi);
+          DI_Point *mid = middle(pt(s2), pt(s4), e, RPNi);
+          DI_Point *quad = middle(mid, midEN2[2], e, RPNi);
+          t2->addQuadEdge(5, quad, e, RPNi);
+          t3->addQuadEdge(2, quad, e, RPNi);
+          t4->addQuadEdge(2, quad, e, RPNi);
+          if(t2->addQuadEdge(2, midEN2[2], e, RPNi)) {
+            t1->addQuadEdge(2, midEN2[2], e, RPNi);
           }
           else printf("unable to add quadratic edge U0U2 to the subtetrahedra cas 3.\n");
+          delete mid; delete quad;
         }
+        delete midEN2[0]; delete midEN2[1]; delete midEN2[2];
       }
 
       subTetras.push_back(t1);
@@ -1773,31 +1795,30 @@ void DI_Tetra::selfSplit (const DI_Element *e, const std::vector<const gLevelset
       subTetras.push_back(t3);
       subTetras.push_back(t4);
       surfTriangles.push_back(tr);
+      delete U[0]; delete U[1]; delete U[2];
       break;
     }
     case 4 : {// 4 edges cut => 2 prisms => split into 6 tetras
       int i1 = IND[0], i2 = IND[1], i3 = IND[2], i4 = IND[3];
 
       if(i1 == 0 && i2 == 2) {
-        swap(U[0], U[1]); swap(i1, i2);
+        swap(&U[0], &U[1]); swap(i1, i2);
       }
       else if(i1 == 1 && i2 == 2) {
-        swap(U[2], U[3]); swap(i3, i4);
+        swap(&U[2], &U[3]); swap(i3, i4);
       }
-      //printf("case 4 : ind : %d,%d,%d,%d\n",i1,i2,i3,i4);
 
       int s1 = commonV(tab[i1][0], tab[i1][1], tab[i2][0], tab[i2][1]);
       int s2 = commonV(tab[i1][0], tab[i1][1], tab[i2][2], tab[i2][3]);
       int s3 = commonV(tab[i1][2], tab[i1][3], tab[i2][0], tab[i2][1]);
-      int s4 = commonV(tab[i1][2], tab[i1][3], tab[i2][2], tab[i2][3]);   //printf("s: %d %d %d %d\n",s1,s2,s3,s4);
-
-      DI_Tetra t1, t2, t3, t4, t5, t6;
-      DI_Triangle tr1, tr2;
-      bestQuality(U[0], U[1], U[2], U[3], tr1, tr2);
-      tr1.setLsTag(tag); tr2.setLsTag(tag);
-      bestQuality(pt(s1), U[0], U[1], pt(s4), U[3], U[2], t1, t2, t3, QError);
-      bestQuality(pt(s2), U[0], U[3], pt(s3), U[1], U[2], t4, t5, t6, QError);
-      //tr1.print(); tr2.print(); t1.print(); t2.print(); t3.print(); t4.print(); t5.print(); t6.print();
+      int s4 = commonV(tab[i1][2], tab[i1][3], tab[i2][2], tab[i2][3]);
+
+      DI_Tetra *t1, *t2, *t3, *t4, *t5, *t6;
+      DI_Triangle *tr1, *tr2;
+      bestQuality(U[0], U[1], U[2], U[3], &tr1, &tr2);
+      tr1->setLsTag(tag); tr2->setLsTag(tag);
+      bestQuality(pt(s1), U[0], U[1], pt(s4), U[3], U[2], &t1, &t2, &t3, QError);
+      bestQuality(pt(s2), U[0], U[3], pt(s3), U[1], U[2], &t4, &t5, &t6, QError);
       /*t1 = DI_Tetra(U[0],V[0],W[0], x(s2),y(s2),z(s2), U[1],V[1],W[1],    U[3],V[3],W[3]);
       t2 = DI_Tetra(U[1],V[1],W[1], U[3],V[3],W[3],    x(s2),y(s2),z(s2), U[2],V[2],W[2]);
       t3 = DI_Tetra(U[1],V[1],W[1], x(s2),y(s2),z(s2), x(s3),y(s3),z(s3), U[2],V[2],W[2]);
@@ -1808,85 +1829,90 @@ void DI_Tetra::selfSplit (const DI_Element *e, const std::vector<const gLevelset
       tr2 = DI_Triangle(U[1],V[1],W[1], U[2],V[2],W[2], U[3],V[3],W[3]);*/
 
       if(quadT){
-        DI_Point midEN2[5]; // intersection between ls and the bissector between the cutting points
+        DI_Point *midEN2[5]; // intersection between ls and the bissector between the cutting points
         midEN2[0] = quadMidNode(U[1], U[2], pt(s4), e, RPNi);
         midEN2[1] = quadMidNode(U[1], U[0], pt(s2), e, RPNi);
         midEN2[2] = quadMidNode(U[0], U[3], pt(s4), e, RPNi);
         midEN2[3] = quadMidNode(U[2], U[3], pt(s2), e, RPNi);
         midEN2[4] = quadMidNode(U[1], U[3], pt(s2), e, RPNi);
         //quadMidNode(U[1], U[3], (pt(s2)+pt(s3))/2, (pt(s4)+pt(s1))/2, e, RPNi);
-        tr2.addQuadEdge(0, &midEN2[0], e, RPNi);
-        if(t6.addQuadEdge(5, &midEN2[0], e, RPNi)) {
-          t2.addQuadEdge(2, &midEN2[0], e, RPNi);
-          t3.addQuadEdge(2, &midEN2[0], e, RPNi);
+        tr2->addQuadEdge(0, midEN2[0], e, RPNi);
+        if(t6->addQuadEdge(5, midEN2[0], e, RPNi)) {
+          t2->addQuadEdge(2, midEN2[0], e, RPNi);
+          t3->addQuadEdge(2, midEN2[0], e, RPNi);
         }
         else {
-          DI_Point mid = middle(pt(s1), pt(s4), e, RPNi);
-          DI_Point quad = middle(mid, midEN2[0], e, RPNi);
-          t4.addQuadEdge(5, &quad, e, RPNi);
-          t5.addQuadEdge(3, &quad, e, RPNi);
-          t6.addQuadEdge(3, &quad, e, RPNi);
-          if(t6.addQuadEdge(5, &midEN2[0], e, RPNi)) {
-            t2.addQuadEdge(2, &midEN2[0], e, RPNi);
-            t3.addQuadEdge(2, &midEN2[0], e, RPNi);
+          DI_Point *mid = middle(pt(s1), pt(s4), e, RPNi);
+          DI_Point *quad = middle(mid, midEN2[0], e, RPNi);
+          t4->addQuadEdge(5, quad, e, RPNi);
+          t5->addQuadEdge(3, quad, e, RPNi);
+          t6->addQuadEdge(3, quad, e, RPNi);
+          if(t6->addQuadEdge(5, midEN2[0], e, RPNi)) {
+            t2->addQuadEdge(2, midEN2[0], e, RPNi);
+            t3->addQuadEdge(2, midEN2[0], e, RPNi);
           }
           else printf("unable to add quadratic edge U1U2 to the subtetrahedra cas 4.\n");
+          delete mid; delete quad;
         }
 
-        tr1.addQuadEdge(0, &midEN2[1], e, RPNi);
-        if(t1.addQuadEdge(1, &midEN2[1], e, RPNi)) {
-          t4.addQuadEdge(0, &midEN2[1], e, RPNi);
-          t5.addQuadEdge(0, &midEN2[1], e, RPNi);
+        tr1->addQuadEdge(0, midEN2[1], e, RPNi);
+        if(t1->addQuadEdge(1, midEN2[1], e, RPNi)) {
+          t4->addQuadEdge(0, midEN2[1], e, RPNi);
+          t5->addQuadEdge(0, midEN2[1], e, RPNi);
         }
         else {
-          DI_Point mid = middle(pt(s2), pt(s3), e, RPNi);
-          DI_Point quad = middle(mid, midEN2[1], e, RPNi);
-          t1.addQuadEdge(3, &quad, e, RPNi);
-          t2.addQuadEdge(1, &quad, e, RPNi);
-          t3.addQuadEdge(0, &quad, e, RPNi);
-          if(t1.addQuadEdge(1, &midEN2[1], e, RPNi)) {
-            t4.addQuadEdge(0, &midEN2[1], e, RPNi);
-            t5.addQuadEdge(0, &midEN2[1], e, RPNi);
+          DI_Point *mid = middle(pt(s2), pt(s3), e, RPNi);
+          DI_Point *quad = middle(mid, midEN2[1], e, RPNi);
+          t1->addQuadEdge(3, quad, e, RPNi);
+          t2->addQuadEdge(1, quad, e, RPNi);
+          t3->addQuadEdge(0, quad, e, RPNi);
+          if(t1->addQuadEdge(1, midEN2[1], e, RPNi)) {
+            t4->addQuadEdge(0, midEN2[1], e, RPNi);
+            t5->addQuadEdge(0, midEN2[1], e, RPNi);
           }
           else printf("unable to add quadratic edge U0U1 to the subtetrahedra cas 4.\n");
+          delete mid; delete quad;
         }
 
-        tr1.addQuadEdge(2, &midEN2[2], e, RPNi);
-        if(t5.addQuadEdge(2, &midEN2[2], e, RPNi)) {
-          t1.addQuadEdge(2, &midEN2[2], e, RPNi);
+        tr1->addQuadEdge(2, midEN2[2], e, RPNi);
+        if(t5->addQuadEdge(2, midEN2[2], e, RPNi)) {
+          t1->addQuadEdge(2, midEN2[2], e, RPNi);
         }
         else {
-          DI_Point mid = middle(pt(s1), pt(s4), e, RPNi);
-          DI_Point quad = middle(mid, midEN2[2], e, RPNi);
-          t4.addQuadEdge(2, &quad, e, RPNi);
-          t5.addQuadEdge(1, &quad, e, RPNi);
-          if(t5.addQuadEdge(2, &midEN2[2], e, RPNi)) {
-            t1.addQuadEdge(2, &midEN2[2], e, RPNi);
+          DI_Point *mid = middle(pt(s1), pt(s4), e, RPNi);
+          DI_Point *quad = middle(mid, midEN2[2], e, RPNi);
+          t4->addQuadEdge(2, quad, e, RPNi);
+          t5->addQuadEdge(1, quad, e, RPNi);
+          if(t5->addQuadEdge(2, midEN2[2], e, RPNi)) {
+            t1->addQuadEdge(2, midEN2[2], e, RPNi);
           }
           else printf("unable to add quadratic edge U0U3 to the subtetrahedra cas 4.\n");
+          delete mid; delete quad;
         }
 
-        tr2.addQuadEdge(1, &midEN2[3], e, RPNi);
-        if(t2.addQuadEdge(5, &midEN2[3], e, RPNi)) {
-          t6.addQuadEdge(2, &midEN2[3], e, RPNi);
+        tr2->addQuadEdge(1, midEN2[3], e, RPNi);
+        if(t2->addQuadEdge(5, midEN2[3], e, RPNi)) {
+          t6->addQuadEdge(2, midEN2[3], e, RPNi);
         }
         else {
-          DI_Point mid = middle(pt(s2), pt(s3), e, RPNi);
-          DI_Point quad = middle(mid, midEN2[3], e, RPNi);
-          t2.addQuadEdge(4, &quad, e, RPNi);
-          t3.addQuadEdge(5, &quad, e, RPNi);
-          if(t2.addQuadEdge(5, &midEN2[3], e, RPNi)) {
-            t6.addQuadEdge(2, &midEN2[3], e, RPNi);
+          DI_Point *mid = middle(pt(s2), pt(s3), e, RPNi);
+          DI_Point *quad = middle(mid, midEN2[3], e, RPNi);
+          t2->addQuadEdge(4, quad, e, RPNi);
+          t3->addQuadEdge(5, quad, e, RPNi);
+          if(t2->addQuadEdge(5, midEN2[3], e, RPNi)) {
+            t6->addQuadEdge(2, midEN2[3], e, RPNi);
           }
           else printf("unable to add quadratic edge U2U3 to the subtetrahedra cas 4.\n");
+          delete mid; delete quad;
         }
 
-        tr1.addQuadEdge(1, &midEN2[4], e, RPNi);
-        tr2.addQuadEdge(2, &midEN2[4], e, RPNi);
-        t1.addQuadEdge(4, &midEN2[4], e, RPNi);
-        t2.addQuadEdge(0, &midEN2[4], e, RPNi);
-        t5.addQuadEdge(5, &midEN2[4], e, RPNi);
-        t6.addQuadEdge(0, &midEN2[4], e, RPNi);
+        tr1->addQuadEdge(1, midEN2[4], e, RPNi);
+        tr2->addQuadEdge(2, midEN2[4], e, RPNi);
+        t1->addQuadEdge(4, midEN2[4], e, RPNi);
+        t2->addQuadEdge(0, midEN2[4], e, RPNi);
+        t5->addQuadEdge(5, midEN2[4], e, RPNi);
+        t6->addQuadEdge(0, midEN2[4], e, RPNi);
+        for(int i = 0; i < 5; i++) delete midEN2[i];
       }
 
       subTetras.push_back(t1);
@@ -1897,23 +1923,24 @@ void DI_Tetra::selfSplit (const DI_Element *e, const std::vector<const gLevelset
       subTetras.push_back(t6);
       surfTriangles.push_back(tr1);
       surfTriangles.push_back(tr2);
+      for(int i = 0; i < 4; i++) delete U[i];
       break;
     }
     default:
       printf("Error : %d edge(s) cut in the tetrahedron (ls : %g %g %g %g)\n",
-             COUNT, pt(0).ls(), pt(1).ls(), pt(2).ls(), pt(3).ls());
+             COUNT, ls(0), ls(1), ls(2), ls(3));
   }
 }
 
 // Split a reference Hexahedron into 6 tetrahedra
-void DI_Hexa::splitIntoTetras(std::vector<DI_Tetra> &tetras) const
+void DI_Hexa::splitIntoTetras(std::vector<DI_Tetra *> &tetras) const
 {
-  tetras.push_back(DI_Tetra(pt(0), pt(1), pt(3), pt(4))); // 0134
-  tetras.push_back(DI_Tetra(pt(1), pt(4), pt(5), pt(7))); // 1457
-  tetras.push_back(DI_Tetra(pt(1), pt(3), pt(4), pt(7))); // 1347
-  tetras.push_back(DI_Tetra(pt(2), pt(5), pt(6), pt(7))); // 2567
-  tetras.push_back(DI_Tetra(pt(1), pt(2), pt(3), pt(7))); // 1237
-  tetras.push_back(DI_Tetra(pt(1), pt(5), pt(2), pt(7))); // 1527
+  tetras.push_back(new DI_Tetra(pt(0), pt(1), pt(3), pt(4))); // 0134
+  tetras.push_back(new DI_Tetra(pt(1), pt(4), pt(5), pt(7))); // 1457
+  tetras.push_back(new DI_Tetra(pt(1), pt(3), pt(4), pt(7))); // 1347
+  tetras.push_back(new DI_Tetra(pt(2), pt(5), pt(6), pt(7))); // 2567
+  tetras.push_back(new DI_Tetra(pt(1), pt(2), pt(3), pt(7))); // 1237
+  tetras.push_back(new DI_Tetra(pt(1), pt(5), pt(2), pt(7))); // 1527
 }
 
 // -----------------------------------------------------------------------------
@@ -1921,52 +1948,52 @@ void DI_Hexa::splitIntoTetras(std::vector<DI_Tetra> &tetras) const
 // -----------------------------------------------------------------------------
 
 // return the integration points in the reference line
-void DI_Line::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint> &ip) const {
+void DI_Line::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint *> &ip) const {
   int N = getNGQLPts(polynomialOrder);
   IntPt* intpt (getGQLPts(polynomialOrder));
   for (int i = 0; i < N; ++i){
-    ip.push_back(DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
+    ip.push_back(new DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
   }
 }
 
 // return the integration points in the reference triangle
-void DI_Triangle::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint> &ip) const {
+void DI_Triangle::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint *> &ip) const {
   int pO = polynomialOrder;
   if(pO == 11 || pO == 16 || pO == 18 || pO == 20) pO++;
   if(pO == 15) pO = 17;
   int N = getNGQTPts(pO);
   IntPt* intpt (getGQTPts(pO));
   for (int i = 0; i < N; ++i){
-    ip.push_back(DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
+    ip.push_back(new DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
   }
 }
 
 // return the integration points in the reference triangle
-void DI_Quad::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint> &ip) const {
+void DI_Quad::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint *> &ip) const {
   int N = getNGQQPts(polynomialOrder);
   IntPt* intpt (getGQQPts(polynomialOrder));
   for (int i = 0; i < N; ++i){
-    ip.push_back(DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
+    ip.push_back(new DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
   }
 }
 
 // return the integration points in the reference tetra
-void DI_Tetra::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint> &ip) const {
+void DI_Tetra::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint *> &ip) const {
   int pO = polynomialOrder;
   if(pO == 9) pO++;
   int N = getNGQTetPts(pO);
   IntPt* intpt (getGQTetPts(pO));
   for (int i = 0; i < N; ++i){
-    ip.push_back(DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
+    ip.push_back(new DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
   }
 }
 
 // return the integration points in the reference Cube
-void DI_Hexa::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint> &ip) const {
+void DI_Hexa::getRefIntegrationPoints ( const int polynomialOrder , std::vector<DI_IntegrationPoint *> &ip) const {
   int N = getNGQHPts(polynomialOrder);
   IntPt* intpt (getGQHPts(polynomialOrder));
   for (int i = 0; i < N; ++i){
-    ip.push_back(DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
+    ip.push_back(new DI_IntegrationPoint(intpt[i].pt[0], intpt[i].pt[1], intpt[i].pt[2], intpt[i].weight));
   }
 }
 
@@ -1975,679 +2002,709 @@ void DI_Hexa::getRefIntegrationPoints ( const int polynomialOrder , std::vector<
 // -----------------------------------------------------------------------------
 
 // cut a line into sublines along the levelset curve
-bool DI_Line::cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-                   std::vector<DI_CuttingPoint> &cp, const int polynomialOrder,
-                   std::vector<DI_Line> &lines, int recurLevel, std::map<int, double> nodeLs[2]) const
+bool DI_Line::cut (std::vector<const gLevelset *> &RPN, std::vector<DI_IntegrationPoint *> &ip,
+                   DI_Point::Container &cp, const int polynomialOrder,
+                   std::vector<DI_Line *> &lines, int recurLevel, double **nodeLs) const
 {
   //printf(" "); print();
-  std::vector<const gLevelset *> RPN, RPNi;
-  Ls.getRPN(RPN);
+  std::vector<const gLevelset *> RPNi; RPNi.reserve(RPN.size());
 
-  DI_Line ll(-1, 0, 0, 1, 0, 0, 2.); //reference line
-  //ll.setPolynomialOrder(2);
-  std::vector<DI_Line> ll_subLines;
-  std::vector<DI_CuttingPoint> ll_cp;
+  DI_Line *ll = new DI_Line(-1, 0, 0, 1, 0, 0, 2.); //reference line
+  ll->setPolynomialOrder(getPolynomialOrder());
+  std::vector<DI_Line *> ll_subLines;
+  std::vector<DI_CuttingPoint *> ll_cp;
 
-  RecurElement re(&ll);
-  bool signChange = re.cut(recurLevel, this, Ls, -1., nodeLs);
-  pushSubElements(&re, ll_subLines);
+  RecurElement *re = new RecurElement(ll);
+  bool signChange = re->cut(recurLevel, this, RPN, -1., nodeLs);
+  pushSubElements(re, ll_subLines);
+  delete re;
 
   if(signChange){
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        ll.addLs(this, *Lsi, nodeLs);
+        ll->addLs(this, Lsi, l, nodeLs);
         int nbSubLn = ll_subLines.size();
         int nbCP = ll_cp.size();
-        for(int i = 0; i < nbSubLn; i++) ll_subLines[i].addLs(&ll);
-        for(int i = 0; i < nbCP; i++) ll_cp[i].addLs(&ll);
+        for(int i = 0; i < nbSubLn; i++) ll_subLines[i]->addLs(ll);
+        for(int i = 0; i < nbCP; i++) ll_cp[i]->addLs(ll);
 
         for(int ln = 0; ln < nbSubLn; ln++){
-          DI_Line lnt = ll_subLines[0];
+          DI_Line *lnt = ll_subLines[0];
           ll_subLines.erase(ll_subLines.begin());
-          lnt.cut(&ll, RPNi, ll_subLines, ll_cp);
+          bool c = lnt->cut(ll, RPNi, ll_subLines, ll_cp);
+          if(c) delete lnt;
         }
       }
       else {
         for(int l = 0; l < (int)ll_subLines.size(); l++)
-          ll_subLines[l].chooseLs(Lsi);
+          ll_subLines[l]->chooseLs(Lsi);
         for(int p = 0; p < (int)ll_cp.size(); p++)
-          ll_cp[p].chooseLs(Lsi);
+          ll_cp[p]->chooseLs(Lsi);
       }
     }
   }
   else{
-    ll_subLines[0].addLs(this, Ls);
+    ll_subLines[0]->addLs(this, RPN.back());
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        ll.addLs(this, *Lsi, nodeLs);
+        ll->addLs(this, Lsi, l, nodeLs);
       }
     }
   }
 
   for(int l = 0; l < (int)ll_subLines.size(); l++) {
-    ll_subLines[l].computeLsTagDom(&ll, RPN);
-    DI_Line ll_subLn = ll_subLines[l];
-    mappingEl(&ll_subLn);
-    ll_subLn.integrationPoints(polynomialOrder, &ll_subLines[l], &ll, RPN, ip);
-    lines.push_back(ll_subLn);
+    ll_subLines[l]->computeLsTagDom(ll, RPN);
+    DI_Line *ll_subLn = new DI_Line(*ll_subLines[l]);
+    mappingEl(ll_subLines[l]);
+    ll_subLines[l]->integrationPoints(polynomialOrder, ll_subLn, ll, RPN, ip);
+    lines.push_back(ll_subLines[l]);
+    delete ll_subLn;
   }
   for(int p = 0; p < (int)ll_cp.size(); p++) {
-    if(ll_cp[p].ls() != 0) continue;
+    if(ll_cp[p]->ls() != 0) {delete ll_cp[p]; continue;}
     mappingCP(ll_cp[p]);
-    bool isIn = false;
-    for(int i = (int)cp.size() - 1; i>= 0; i--)
-      if(cp[i].equal(ll_cp[p])) {isIn = true; break;}
-    if(!isIn) cp.push_back(ll_cp[p]);
+    std::pair<DI_Point::Container::iterator,bool> isIn = cp.insert(ll_cp[p]);
+    if(!isIn.second) delete ll_cp[p];
   }
+  delete ll;
   return signChange;
 }
 
-// cut a line into sublines along one levelset primitive
-void DI_Line::cut(const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-           std::vector<DI_Line> &subLines, std::vector<DI_CuttingPoint> &cp) const
+// cut a line into sublines along one levelset primitive and return true if it is cut
+bool DI_Line::cut(const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+           std::vector<DI_Line *> &subLines, std::vector<DI_CuttingPoint *> &cp)
 {
   // check if the line is cut by the level set
   int on = 0, pos = 0, neg = 0, ze[2];
   for (int i = 0; i < 2; i++){
-    if(pt(i).isOnBorder()) ze[on++] = i;
-    else if (pt(i).ls() > 0.) pos++;
+    if(pt(i)->isOnBorder()) ze[on++] = i;
+    else if (ls(i) > 0.) pos++;
     else neg++;
   }
   if(pos && neg)
     selfSplit(e, RPNi, subLines, cp);
   else {
     for(int i = 0; i < on; i++)
-      cp.push_back(DI_CuttingPoint(pt(ze[i])));
-    subLines.push_back(*this);
+      cp.push_back(new DI_CuttingPoint(pt(ze[i])));
+    subLines.push_back(this);
   }
+  return (pos && neg);
 }
 
 // cut a triangle into subtriangles along the levelset curve
-bool DI_Triangle::cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-                       std::vector<DI_IntegrationPoint> &ipS, std::vector<DI_CuttingPoint> &cp,
+bool DI_Triangle::cut (std::vector<const gLevelset *> &RPN, std::vector<DI_IntegrationPoint *> &ip,
+                       std::vector<DI_IntegrationPoint *> &ipS, DI_Point::Container &cp,
                        const int polynomialOrderQ, const int polynomialOrderTr, const int polynomialOrderL,
-                       std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-                       std::vector<DI_Line> &surfLines, int recurLevel, std::map<int, double> nodeLs[3]) const
+                       std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+                       std::vector<DI_Line *> &surfLines, int recurLevel, double **nodeLs) const
 {
   //printf(" ");print();
-  std::vector<const gLevelset *> RPN, RPNi;
-  Ls.getRPN(RPN);
+  std::vector<const gLevelset *> RPNi; RPNi.reserve(RPN.size());
 
-  DI_Triangle tt(0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5); //reference triangle
-  //tt.setPolynomialOrder(2);
-  std::vector<DI_Quad> tt_subQuads;
-  std::vector<DI_Triangle> tt_subTriangles;
-  std::vector<DI_Line> tt_surfLines;
-  std::vector<DI_CuttingPoint> tt_cp;
+  DI_Triangle *tt = new DI_Triangle(0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5); //reference triangle
+  tt->setPolynomialOrder(getPolynomialOrder());
+  std::vector<DI_Quad *> tt_subQuads;
+  std::vector<DI_Triangle *> tt_subTriangles;
+  std::vector<DI_Line *> tt_surfLines;
+  std::vector<DI_CuttingPoint *> tt_cp;
 
-  RecurElement re(&tt);
-  bool signChange = re.cut(recurLevel, this, Ls, -1., nodeLs);
-  pushSubElements(&re, tt_subTriangles);
+  RecurElement *re = new RecurElement(tt);
+  bool signChange = re->cut(recurLevel, this, RPN, -1., nodeLs);
+  pushSubElements(re, tt_subTriangles);
+  delete re;
 
   if(signChange){
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l]; //printf("LS(0,0)=%g LS(1,1)=%g\n",(*Lsi)(0,0,0),(*Lsi)(1,1,0));
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        tt.addLs(this, *Lsi, nodeLs);
+        tt->addLs(this, Lsi, l, nodeLs);
         int nbSubQ = tt_subQuads.size(), nbSubQ1 = nbSubQ;
         int nbSubTr = tt_subTriangles.size(), nbSubTr1 = nbSubTr;
         int nbSurfLn = tt_surfLines.size(), nbSurfLn1 = nbSurfLn;
         int nbCP = tt_cp.size();
-        for(int i = 0; i < nbSubQ; i++) tt_subQuads[i].addLs(&tt);
-        for(int i = 0; i < nbSubTr; i++) tt_subTriangles[i].addLs(&tt);
-        for(int i = 0; i < nbSurfLn; i++) tt_surfLines[i].addLs(&tt);
-        for(int i = 0; i < nbCP; i++) tt_cp[i].addLs(&tt);
+        for(int i = 0; i < nbSubQ; i++) tt_subQuads[i]->addLs(tt);
+        for(int i = 0; i < nbSubTr; i++) tt_subTriangles[i]->addLs(tt);
+        for(int i = 0; i < nbSurfLn; i++) tt_surfLines[i]->addLs(tt);
+        for(int i = 0; i < nbCP; i++) tt_cp[i]->addLs(tt);
         int ze[3], cz = 0;
-        for (int i = 0; i < 3; i++) if(tt.pt(i).isOnBorder()) ze[cz++] = i;
+        for (int i = 0; i < 3; i++) if(tt->pt(i)->isOnBorder()) ze[cz++] = i;
 
         for(int q = 0; q < nbSubQ; q++) {
           nbSubQ1 = tt_subQuads.size();
           nbSurfLn1 = tt_surfLines.size();
-          DI_Quad qt = tt_subQuads[0];
+          DI_Quad *qt = tt_subQuads[0];
           tt_subQuads.erase(tt_subQuads.begin());
-          qt.cut(&tt, RPNi, tt_subQuads, tt_subTriangles, tt_surfLines, tt_cp);
+          bool c = qt->cut(tt, RPNi, tt_subQuads, tt_subTriangles, tt_surfLines, tt_cp);
+          if(c) delete qt;
           if((int)tt_surfLines.size() - nbSurfLn1 == 1 && (int)tt_subQuads.size() == nbSubQ1){ // 1 line created on boundary of the quad
             if (cz == 2) { // 1 line created on boundary of the big triangle => check among surfLines
               DI_Line lf (pt(ze[0]), pt(ze[1]));
               for(int i = (int)surfLines.size() - 1; i >= 0; i--){
-                if (lf.contain(&surfLines[i])){ // line allready created on another surface => pop the new one
-                  tt_surfLines.pop_back(); break;
+                if (lf.contain(surfLines[i])){ // line allready created on another surface => pop the new one
+                  delete tt_surfLines.back(); tt_surfLines.pop_back(); break;
                 }
               }
             }
             else { // 1 line created inside the big triangle => check among tt_surfLines
-              if(isLastLnInV(tt_surfLines))
-                tt_surfLines.pop_back();
+              if(isLastLnInV(tt_surfLines)) {
+                delete tt_surfLines.back(); tt_surfLines.pop_back();
+              }
             }
           }
         }
         for(int t = 0; t < nbSubTr; t++){
           nbSubTr1 = tt_subTriangles.size();
           nbSurfLn1 = tt_surfLines.size();
-          DI_Triangle trt = tt_subTriangles[0];
+          DI_Triangle *trt = tt_subTriangles[0];
           tt_subTriangles.erase(tt_subTriangles.begin());
-          trt.cut(&tt, RPNi, tt_subQuads, tt_subTriangles, tt_surfLines, tt_cp);
+          bool c = trt->cut(tt, RPNi, tt_subQuads, tt_subTriangles, tt_surfLines, tt_cp);
+          if(c) delete trt;
           if((int)tt_surfLines.size() - nbSurfLn1 == 1  && (int)tt_subTriangles.size() == nbSubTr1) { // 1 line created on boundary of the triangle
             if(cz == 2) { // 1 line created on boundary of the big triangle => check among surfLines
               DI_Line lf(pt(ze[0]), pt(ze[1]));
               for(int i = (int)surfLines.size() - 1; i >= 0; i--){
-                if(lf.contain(&surfLines[i])) {
-                  tt_surfLines.pop_back(); break;
+                if(lf.contain(surfLines[i])) {
+                  delete tt_surfLines.back(); tt_surfLines.pop_back(); break;
                 }
               }
             }
             else{ // 1 line created inside the big triangle => check among tt_surfLines
-              if(isLastLnInV(tt_surfLines))
-                tt_surfLines.pop_back();
+              if(isLastLnInV(tt_surfLines)) {
+                delete tt_surfLines.back(); tt_surfLines.pop_back();
+              }
             }
           }
         }
         for(int ln = 0; ln < nbSurfLn; ln++){
-          DI_Line lnt = tt_surfLines[0];
+          DI_Line* lnt = tt_surfLines[0];
           tt_surfLines.erase(tt_surfLines.begin());
-          lnt.cut(&tt, RPNi, tt_surfLines, tt_cp);
+          bool c = lnt->cut(tt, RPNi, tt_surfLines, tt_cp);
+          if(c) delete lnt;
         }
       }
       else {
         for(int q = 0; q < (int)tt_subQuads.size(); q++)
-          tt_subQuads[q].chooseLs(Lsi);
+          tt_subQuads[q]->chooseLs(Lsi);
         for(int t = 0; t < (int)tt_subTriangles.size(); t++)
-          tt_subTriangles[t].chooseLs(Lsi);
+          tt_subTriangles[t]->chooseLs(Lsi);
         for(int l = 0; l < (int)tt_surfLines.size(); l++)
-          tt_surfLines[l].chooseLs(Lsi);
+          tt_surfLines[l]->chooseLs(Lsi);
         for(int p = 0; p < (int)tt_cp.size(); p++)
-          tt_cp[p].chooseLs(Lsi);
+          tt_cp[p]->chooseLs(Lsi);
       }
     }
   }
   else{
-    tt_subTriangles[0].addLs(this, Ls);
+    tt_subTriangles[0]->addLs(this, RPN.back());
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        tt.addLs(this, *Lsi, nodeLs);
+        tt->addLs(this, Lsi, l, nodeLs);
       }
     }
   }
 
   for(int q = 0; q < (int)tt_subQuads.size(); q++) {
-    tt_subQuads[q].computeLsTagDom(&tt, RPN);
-    DI_Quad tt_subQ = tt_subQuads[q];
-    mappingEl(&tt_subQ);
-    tt_subQ.integrationPoints(polynomialOrderQ, &tt_subQuads[q], &tt, RPN, ip);
-    subQuads.push_back(tt_subQ);
+    tt_subQuads[q]->computeLsTagDom(tt, RPN);
+    DI_Quad *tt_subQ = new DI_Quad(*tt_subQuads[q]);
+    mappingEl(tt_subQuads[q]);
+    tt_subQuads[q]->integrationPoints(polynomialOrderQ, tt_subQ, tt, RPN, ip);
+    subQuads.push_back(tt_subQuads[q]);
+    delete tt_subQ;
   }
   for(int t = 0; t < (int)tt_subTriangles.size(); t++) {
-    tt_subTriangles[t].computeLsTagDom(&tt, RPN);
-    DI_Triangle tt_subTr = tt_subTriangles[t];
-    mappingEl(&tt_subTr);
-    tt_subTr.integrationPoints(polynomialOrderTr, &tt_subTriangles[t], &tt, RPN, ip);
-    subTriangles.push_back(tt_subTr);
+    tt_subTriangles[t]->computeLsTagDom(tt, RPN);
+    DI_Triangle *tt_subTr = new DI_Triangle(*tt_subTriangles[t]);
+    mappingEl(tt_subTriangles[t]);
+    tt_subTriangles[t]->integrationPoints(polynomialOrderTr, tt_subTr, tt, RPN, ip);
+    subTriangles.push_back(tt_subTriangles[t]);
+    delete tt_subTr;
   }
   for(int l = 0; l < (int)tt_surfLines.size(); l++) {
-    tt_surfLines[l].computeLsTagBound(tt_subQuads, tt_subTriangles);
-    if(tt_surfLines[l].lsTag() == -1) continue;
-    DI_Line tt_surfLn = tt_surfLines[l];
-    mappingEl(&tt_surfLn);
-    tt_surfLn.integrationPoints(polynomialOrderL, &tt_surfLines[l], &tt, RPN, ipS);
-    surfLines.push_back(tt_surfLn);
+    tt_surfLines[l]->computeLsTagBound(tt_subQuads, tt_subTriangles);
+    if(tt_surfLines[l]->lsTag() == -1) {delete tt_surfLines[l]; continue;}
+    DI_Line *tt_surfLn = new DI_Line(*tt_surfLines[l]);
+    mappingEl(tt_surfLines[l]);
+    tt_surfLines[l]->integrationPoints(polynomialOrderL, tt_surfLn, tt, RPN, ipS);
+    surfLines.push_back(tt_surfLines[l]);
+    delete tt_surfLn;
   }
   for(int p = 0; p < (int)tt_cp.size(); p++) {
-    if(tt_cp[p].ls() != 0) continue;
+    if(tt_cp[p]->ls() != 0) {delete tt_cp[p]; continue;}
     mappingCP(tt_cp[p]);
-    bool isIn = false;
-    for(int i = (int)cp.size() - 1; i>= 0; i--)
-      if(cp[i].equal(tt_cp[p])) {isIn = true; break;}
-    if(!isIn) cp.push_back(tt_cp[p]);
+    std::pair<DI_Point::Container::iterator,bool> isIn = cp.insert(tt_cp[p]);
+    if(!isIn.second) delete tt_cp[p];
   }
+  delete tt;
   return signChange;
 }
 
 // cut a triangle into subtriangles along one levelset primitive
-void DI_Triangle::cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                    std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-                    std::vector<DI_Line> &surfLines, std::vector<DI_CuttingPoint> &cp) const
+bool DI_Triangle::cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+                    std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+                    std::vector<DI_Line *> &surfLines, std::vector<DI_CuttingPoint *> &cp)
 {
   // check if the triangle is cut by the level set
   int on = 0, pos = 0, neg = 0, ze[3];
   for (int i = 0; i < 3; i++){
-    if(pt(i).isOnBorder()) ze[on++] = i;
-    else if (pt(i).ls() > 0.) pos++;
+    if(pt(i)->isOnBorder()) ze[on++] = i;
+    else if (pt(i)->ls() > 0.) pos++;
     else neg++;
   }
   if(pos && neg)
     selfSplit(e, RPNi, subQuads, subTriangles, surfLines, cp);
   else {
     if(on == 2){ // the level set is zero on an edge of the triangle
-      surfLines.push_back(DI_Line(pt(ze[0]), pt(ze[1]), RPNi.back()->getTag()));
+      surfLines.push_back(new DI_Line(pt(ze[0]), pt(ze[1]), RPNi.back()->getTag()));
       // add the line twice if the edge belongs to 2 triangles => remove it later!
     }
     for(int i = 0; i < on; i++)
-      cp.push_back(DI_CuttingPoint(pt(ze[i])));
-    subTriangles.push_back(*this);
+      cp.push_back(new DI_CuttingPoint(pt(ze[i])));
+    subTriangles.push_back(this);
   }
+  return (pos && neg);
 }
 
 // cut a quadrangle into subtriangles along the levelset curve
-bool DI_Quad::cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-                   std::vector<DI_IntegrationPoint> &ipS, std::vector<DI_CuttingPoint> &cp,
+bool DI_Quad::cut (std::vector<const gLevelset *> &RPN, std::vector<DI_IntegrationPoint *> &ip,
+                   std::vector<DI_IntegrationPoint *> &ipS, DI_Point::Container &cp,
                    const int polynomialOrderQ, const int polynomialOrderTr, const int polynomialOrderL,
-                   std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-                   std::vector<DI_Line> &surfLines, int recurLevel, std::map<int, double> nodeLs[4]) const
+                   std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+                   std::vector<DI_Line *> &surfLines, int recurLevel, double **nodeLs) const
 {
-  printf(" "); printls();
-  std::vector<const gLevelset *> RPN, RPNi;
-  Ls.getRPN(RPN);
+  //printf(" "); printls();
+  std::vector<const gLevelset *> RPNi; RPNi.reserve(RPN.size());
 
-  DI_Quad qq(-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, 4.); // reference quad
-  //qq.setPolynomialOrder(2);
-  std::vector<DI_Quad> qq_subQuads;
-  std::vector<DI_Triangle> qq_subTriangles;
-  std::vector<DI_Line> qq_surfLines;
-  std::vector<DI_CuttingPoint> qq_cp;
+  DI_Quad *qq = new DI_Quad(-1, -1, 0, 1, -1, 0, 1, 1, 0, -1, 1, 0, 4.); // reference quad
+  qq->setPolynomialOrder(getPolynomialOrder());
+  std::vector<DI_Quad *> qq_subQuads;
+  std::vector<DI_Triangle *> qq_subTriangles;
+  std::vector<DI_Line *> qq_surfLines;
+  std::vector<DI_CuttingPoint *> qq_cp;
 
-  RecurElement re(&qq);
-  bool signChange = re.cut(recurLevel, this, Ls, -1., nodeLs);
-  pushSubElements(&re, qq_subQuads);
+  RecurElement *re =  new RecurElement(qq);
+  bool signChange = re->cut(recurLevel, this, RPN, -1., nodeLs);
+  pushSubElements(re, qq_subQuads);
+  delete re;
 
   if(signChange) {
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        qq.addLs(this, *Lsi, nodeLs);
+        qq->addLs(this, Lsi, l, nodeLs);
         int nbSubQ = qq_subQuads.size(), nbSubQ1 = nbSubQ;
         int nbSubTr = qq_subTriangles.size(), nbSubTr1 = nbSubTr;
         int nbSurfLn = qq_surfLines.size(), nbSurfLn1 = nbSurfLn;
         int nbCP = qq_cp.size();
-        for(int i = 0; i < nbSubQ; i++) qq_subQuads[i].addLs(&qq);
-        for(int i = 0; i < nbSubTr; i++) qq_subTriangles[i].addLs(&qq);
-        for(int i = 0; i < nbSurfLn; i++) qq_surfLines[i].addLs(&qq);
-        for(int i = 0; i < nbCP; i++) qq_cp[i].addLs(&qq);
+        for(int i = 0; i < nbSubQ; i++) qq_subQuads[i]->addLs(qq);
+        for(int i = 0; i < nbSubTr; i++) qq_subTriangles[i]->addLs(qq);
+        for(int i = 0; i < nbSurfLn; i++) qq_surfLines[i]->addLs(qq);
+        for(int i = 0; i < nbCP; i++) qq_cp[i]->addLs(qq);
         int pos = 0, neg = 0, ze[2], cz = 0;
         for (int i = 0; i < 4; i++){
-          if(qq.pt(i).isOnBorder()) ze[cz++] = i;
-          else if (qq.ls(i) > 0.) pos++;
+          if(qq->pt(i)->isOnBorder()) ze[cz++] = i;
+          else if (qq->ls(i) > 0.) pos++;
           else neg++;
         }
 
         for(int q = 0; q < nbSubQ; q++) {
           nbSubQ1 = qq_subQuads.size();
           nbSurfLn1 = qq_surfLines.size();
-          DI_Quad qt = qq_subQuads[0];
+          DI_Quad *qt = qq_subQuads[0];
           qq_subQuads.erase(qq_subQuads.begin());
-          qt.cut(&qq, RPNi, qq_subQuads, qq_subTriangles, qq_surfLines, qq_cp);
+          bool c = qt->cut(qq, RPNi, qq_subQuads, qq_subTriangles, qq_surfLines, qq_cp);
+          if(c) delete qt;
           if((int)qq_surfLines.size() - nbSurfLn1 == 1 && (int)qq_subQuads.size() == nbSubQ1){ // 1 line created on boundary of the quad
             if (cz == 2 && !(pos && neg)) { // 1 line created on boundary of the big quad => check among surfLines
               DI_Line lf (pt(ze[0]), pt(ze[1]));
               for(int i = (int)surfLines.size() - 1; i >= 0; i--){
-                if (lf.contain(&surfLines[i])){ // line allready created on another surface => pop the new one
-                  qq_surfLines.pop_back(); break;
+                if (lf.contain(surfLines[i])){ // line allready created on another surface => pop the new one
+                  delete qq_surfLines.back(); qq_surfLines.pop_back(); break;
                 }
               }
             }
             else { // 1 line created inside the big quad => check among qq_surfLines
-              if(isLastLnInV(qq_surfLines))
-                qq_surfLines.pop_back();
+              if(isLastLnInV(qq_surfLines)) {
+                delete qq_surfLines.back(); qq_surfLines.pop_back();
+              }
             }
           }
         }
         for(int t = 0; t < nbSubTr; t++){
           nbSubTr1 = qq_subTriangles.size();
           nbSurfLn1 = qq_surfLines.size();
-          DI_Triangle trt = qq_subTriangles[0];
+          DI_Triangle *trt = qq_subTriangles[0];
           qq_subTriangles.erase(qq_subTriangles.begin());
-          trt.cut(&qq, RPNi, qq_subQuads, qq_subTriangles, qq_surfLines, qq_cp);
+          bool c = trt->cut(qq, RPNi, qq_subQuads, qq_subTriangles, qq_surfLines, qq_cp);
+          if(c) delete trt;
           if((int)qq_surfLines.size() - nbSurfLn1 == 1  && (int)qq_subTriangles.size() == nbSubTr1) { // 1 line created on boundary of the triangle
             if(cz == 2 && !(pos && neg)) { // 1 line created on boundary of the big quad => check among surfLines
               DI_Line lf(pt(ze[0]), pt(ze[1]));
               for(int i = (int)surfLines.size() - 1; i >= 0; i--){
-                if(lf.contain(&surfLines[i])) {
-                  qq_surfLines.pop_back(); break;
+                if(lf.contain(surfLines[i])) {
+                  delete qq_surfLines.back(); qq_surfLines.pop_back(); break;
                 }
               }
             }
             else{ // 1 line created inside the big quad => check among qq_surfLines
-              if(isLastLnInV(qq_surfLines))
-                qq_surfLines.pop_back();
+              if(isLastLnInV(qq_surfLines)) {
+                delete qq_surfLines.back(); qq_surfLines.pop_back();
+              }
             }
           }
         }
         for(int ln = 0; ln < nbSurfLn; ln++){
-          DI_Line lnt = qq_surfLines[0];
+          DI_Line *lnt = qq_surfLines[0];
           qq_surfLines.erase(qq_surfLines.begin());
-          lnt.cut(&qq, RPNi, qq_surfLines, qq_cp);
+          bool c = lnt->cut(qq, RPNi, qq_surfLines, qq_cp);
+          if(c) delete lnt;
         }
       }
       else {
         for(int q = 0; q < (int)qq_subQuads.size(); q++)
-          qq_subQuads[q].chooseLs(Lsi);
+          qq_subQuads[q]->chooseLs(Lsi);
         for(int t = 0; t < (int)qq_subTriangles.size(); t++)
-          qq_subTriangles[t].chooseLs(Lsi);
+          qq_subTriangles[t]->chooseLs(Lsi);
         for(int l = 0; l < (int)qq_surfLines.size(); l++)
-          qq_surfLines[l].chooseLs(Lsi);
+          qq_surfLines[l]->chooseLs(Lsi);
         for(int p = 0; p < (int)qq_cp.size(); p++)
-          qq_cp[p].chooseLs(Lsi);
+          qq_cp[p]->chooseLs(Lsi);
       }
     }
   }
   else {
-    qq_subQuads[0].addLs(this, Ls);
+    qq_subQuads[0]->addLs(this, RPN.back());
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        qq.addLs(this, *Lsi, nodeLs);
+        qq->addLs(this, Lsi, l, nodeLs);
       }
     }
   }
 
   for(int q = 0; q < (int)qq_subQuads.size(); q++) {
-    qq_subQuads[q].computeLsTagDom(&qq, RPN);
-    DI_Quad qq_subQ = qq_subQuads[q];
-    mappingEl(&qq_subQ);
-    qq_subQ.integrationPoints(polynomialOrderQ, &qq_subQuads[q], &qq, RPN, ip);
-    subQuads.push_back(qq_subQ);
+    qq_subQuads[q]->computeLsTagDom(qq, RPN);
+    DI_Quad *qq_subQ = new DI_Quad(*qq_subQuads[q]);
+    mappingEl(qq_subQuads[q]);
+    qq_subQuads[q]->integrationPoints(polynomialOrderQ, qq_subQ, qq, RPN, ip);
+    subQuads.push_back(qq_subQuads[q]);
+    delete qq_subQ;
   }
   for(int t = 0; t < (int)qq_subTriangles.size(); t++) {
-    qq_subTriangles[t].computeLsTagDom(&qq, RPN);
-    DI_Triangle qq_subTr = qq_subTriangles[t];
-    mappingEl(&qq_subTr);  //qq_subTr.printls();
-    qq_subTr.integrationPoints(polynomialOrderTr, &qq_subTriangles[t], &qq, RPN, ip);
-    subTriangles.push_back(qq_subTr);
+    qq_subTriangles[t]->computeLsTagDom(qq, RPN);
+    DI_Triangle *qq_subTr = new DI_Triangle(*qq_subTriangles[t]);
+    mappingEl(qq_subTriangles[t]);
+    qq_subTriangles[t]->integrationPoints(polynomialOrderTr, qq_subTr, qq, RPN, ip);
+    subTriangles.push_back(qq_subTriangles[t]);
+    delete qq_subTr;
   }
   for(int l = 0; l < (int)qq_surfLines.size(); l++) {
-    qq_surfLines[l].computeLsTagBound(qq_subQuads, qq_subTriangles);
-    if(qq_surfLines[l].lsTag() == -1) continue;  //FIXME
-    DI_Line qq_surfLn = qq_surfLines[l];
-    mappingEl(&qq_surfLn);
-    qq_surfLn.integrationPoints(polynomialOrderL, &qq_surfLines[l], &qq, RPN, ipS);
-    surfLines.push_back(qq_surfLn);
+    qq_surfLines[l]->computeLsTagBound(qq_subQuads, qq_subTriangles);
+    if(qq_surfLines[l]->lsTag() == -1) {delete qq_surfLines[l]; continue;}  //FIXME
+    DI_Line *qq_surfLn = new DI_Line(*qq_surfLines[l]);
+    mappingEl(qq_surfLines[l]);
+    qq_surfLines[l]->integrationPoints(polynomialOrderL, qq_surfLn, qq, RPN, ipS);
+    surfLines.push_back(qq_surfLines[l]);
+    delete qq_surfLn;
   }
   for(int p = 0; p < (int)qq_cp.size(); p++) {
-    if(qq_cp[p].ls() != 0) continue;
+    if(qq_cp[p]->ls() != 0) {delete qq_cp[p]; continue;}
     mappingCP(qq_cp[p]);
-    bool isIn = false;
-    for(int i = (int)cp.size() - 1; i >= 0; i--)
-      if(cp[i].equal(qq_cp[p])) {isIn = true; break;}
-    if(!isIn) cp.push_back(qq_cp[p]);
+    std::pair<DI_Point::Container::iterator,bool> isIn = cp.insert(qq_cp[p]);
+    if(!isIn.second) delete qq_cp[p];
   }
+  delete qq;
   return signChange;
 }
 
 // cut a quadrangle into subtriangles along the levelset curve
-void DI_Quad::cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-                std::vector<DI_Line> &surfLines, std::vector<DI_CuttingPoint> &cp) const
+bool DI_Quad::cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+                std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+                std::vector<DI_Line *> &surfLines, std::vector<DI_CuttingPoint *> &cp)
 {
   // check if the quadrangle is cut by the level set
   int on = 0, pos = 0, neg = 0, ze[4];
   for (int i = 0; i < 4; i++){
-    if(pt(i).isOnBorder()) ze[on++] = i;
-    else if (pt(i).ls() > 0.) pos++;
+    if(pt(i)->isOnBorder()) ze[on++] = i;
+    else if (pt(i)->ls() > 0.) pos++;
     else neg++;
   }
   if (pos && neg) {
-    std::vector<DI_Triangle> triangles;
+    std::vector<DI_Triangle *> triangles;
     splitIntoTriangles (triangles); // Split the quad into 2 sub triangles
     int nl0 = surfLines.size(), nt1, nl1, nt2, nl2;
     for (int t = 0; t < (int)triangles.size(); t++) {
       nt1 = subTriangles.size(); nl1 = surfLines.size();
-      triangles[t].selfSplit(e, RPNi, subQuads, subTriangles, surfLines, cp);
+      triangles[t]->selfSplit(e, RPNi, subQuads, subTriangles, surfLines, cp);
       nt2 = subTriangles.size(); nl2 = surfLines.size();
       if((nt2 - nt1) == 1 && (nl2 - nl1) == 1){ // only 1 line created on an edge of a triangle => check if it was not yet created
-        if(isLastLnInV(surfLines, nl0)) {surfLines.pop_back(); nl2--;}
+        if(isLastLnInV(surfLines, nl0)) {delete surfLines.back(); surfLines.pop_back(); nl2--;}
       }
     }
   }
   else {
     if(on == 2){ // the level set is zero on an edge of the quad
-      surfLines.push_back(DI_Line(pt(ze[0]), pt(ze[1]), RPNi.back()->getTag()));
+      surfLines.push_back(new DI_Line(pt(ze[0]), pt(ze[1]), RPNi.back()->getTag()));
       // we add the line twice if the edge belongs to 2 quads => remove it later!
     }
     for(int i = 0; i < on; i++)
-      cp.push_back(DI_CuttingPoint(pt(ze[i])));
-    subQuads.push_back(*this);
+      cp.push_back(new DI_CuttingPoint(pt(ze[i])));
+    subQuads.push_back(this);
   }
+  return (pos && neg);
 }
 
 // cut a tetrahedron into subtetrahedra along the levelset surface
-bool DI_Tetra::cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-                    std::vector<DI_IntegrationPoint> &ipS, std::vector<DI_CuttingPoint> &cp,
+bool DI_Tetra::cut (std::vector<const gLevelset *> &RPN, std::vector<DI_IntegrationPoint *> &ip,
+                    std::vector<DI_IntegrationPoint *> &ipS, DI_Point::Container &cp,
                     const int polynomialOrderT, const int polynomialOrderQ, const int polynomialOrderTr,
-                    std::vector<DI_Tetra> &subTetras, std::vector<DI_Quad> &surfQuads,
-                    std::vector<DI_Triangle> &surfTriangles, int recurLevel, std::map<int, double> nodeLs[4]) const
+                    std::vector<DI_Tetra *> &subTetras, std::vector<DI_Quad *> &surfQuads,
+                    std::vector<DI_Triangle *> &surfTriangles, int recurLevel, double **nodeLs) const
 {
   //printf(" ");print();
-  std::vector<const gLevelset *> RPN, RPNi;
-  Ls.getRPN(RPN);
-
-  DI_Tetra tt(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1./6.); // reference tetra
-  //tt.setPolynomialOrder(2);
-  std::vector<DI_Hexa> tt_subHexas;
-  std::vector<DI_Tetra> tt_subTetras;
-  std::vector<DI_Quad> tt_surfQuads;
-  std::vector<DI_Triangle> tt_surfTriangles;
-  std::vector<DI_Line> tt_surfLines;  // not used ...
-  std::vector<DI_CuttingPoint> tt_cp;
-  std::vector<DI_QualError> QError;
-
-  RecurElement re(&tt);
-  bool signChange = re.cut(recurLevel, this, Ls, -1., nodeLs);
-  pushSubElements(&re, tt_subTetras);
+  std::vector<const gLevelset *> RPNi; RPNi.reserve(RPN.size());
+
+  DI_Tetra *tt = new DI_Tetra(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1./6.); // reference tetra
+  tt->setPolynomialOrder(getPolynomialOrder());
+  std::vector<DI_Hexa *> tt_subHexas;
+  std::vector<DI_Tetra *> tt_subTetras;
+  std::vector<DI_Quad *> tt_surfQuads;
+  std::vector<DI_Triangle *> tt_surfTriangles;
+  std::vector<DI_Line *> tt_surfLines;  // not used ...
+  std::vector<DI_CuttingPoint *> tt_cp;
+  std::vector<DI_QualError *> QError;
+
+  RecurElement *re = new RecurElement(tt);
+  bool signChange = re->cut(recurLevel, this, RPN, -1., nodeLs);
+  pushSubElements(re, tt_subTetras);
+  delete re;
 
   if(signChange) {
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        tt.addLs(this, *Lsi, nodeLs);
+        tt->addLs(this, Lsi, l, nodeLs);
         int nbSubT = tt_subTetras.size(), nbSubT1 = nbSubT;
         int nbSurfQ = tt_surfQuads.size();
         int nbSurfTr = tt_surfTriangles.size(), nbSurfTr1 = nbSurfTr;
         int nbCP = tt_cp.size();
-        for(int i = 0; i < nbSubT; i++) tt_subTetras[i].addLs(&tt);
-        for(int i = 0; i < nbSurfQ; i++) tt_surfQuads[i].addLs(&tt);
-        for(int i = 0; i < nbSurfTr; i++) tt_surfTriangles[i].addLs(&tt);
-        for(int i = 0; i < nbCP; i++) tt_cp[i].addLs(&tt);
+        for(int i = 0; i < nbSubT; i++) tt_subTetras[i]->addLs(tt);
+        for(int i = 0; i < nbSurfQ; i++) tt_surfQuads[i]->addLs(tt);
+        for(int i = 0; i < nbSurfTr; i++) tt_surfTriangles[i]->addLs(tt);
+        for(int i = 0; i < nbCP; i++) tt_cp[i]->addLs(tt);
         int ze[3], cz = 0;
-        for (int i = 0; i < 4; i++) if(tt.pt(i).isOnBorder()) ze[cz++] = i;
+        for (int i = 0; i < 4; i++) if(tt->pt(i)->isOnBorder()) ze[cz++] = i;
 
         for(int t = 0; t < nbSubT; t++) {
           nbSurfTr1 = tt_surfTriangles.size();
           nbSubT1 = tt_subTetras.size();
-          DI_Tetra tet = tt_subTetras[0];
+          DI_Tetra *tet = tt_subTetras[0];
           tt_subTetras.erase(tt_subTetras.begin());
-          tet.cut(&tt, RPNi, tt_subTetras, tt_surfQuads, tt_surfTriangles, tt_cp, QError);
+          bool c = tet->cut(tt, RPNi, tt_subTetras, tt_surfQuads, tt_surfTriangles, tt_cp, QError);
+          if(c) delete tet;
           if((int)tt_surfTriangles.size() - nbSurfTr1 == 1 && (int)tt_subTetras.size() == nbSubT1) { // 1 triangle created on surface of the subtetra
             // check among the tt_surfTriangles
-            if(isLastTrInV(tt_surfTriangles))
-              tt_surfTriangles.pop_back();
+            if(isLastTrInV(tt_surfTriangles)) {
+              delete tt_surfTriangles.back(); tt_surfTriangles.pop_back();
+            }
             else if(cz == 3) { // 1 triangle created on surface of the reference tet => check among surfTriangles
               DI_Triangle tf(pt(ze[0]), pt(ze[1]), pt(ze[2]));
               for(int i = (int)surfTriangles.size() - 1; i >= 0; i--){
-                if(tf.contain(&surfTriangles[i])) {
-                  tt_surfTriangles.pop_back(); break;
+                if(tf.contain(surfTriangles[i])) {
+                  delete tt_surfTriangles.back(); tt_surfTriangles.pop_back(); break;
                 }
               }
             }
           }
         }
         for(int q = 0; q < nbSurfQ; q++) {
-          DI_Quad qt = tt_surfQuads[0];
+          DI_Quad *qt = tt_surfQuads[0];
           tt_surfQuads.erase(tt_surfQuads.begin());
-          qt.cut(&tt, RPNi, tt_surfQuads, tt_surfTriangles, tt_surfLines, tt_cp);
+          bool c = qt->cut(tt, RPNi, tt_surfQuads, tt_surfTriangles, tt_surfLines, tt_cp);
+          if(c) delete qt;
         }
         for(int t = 0; t < nbSurfTr; t++){
-          DI_Triangle trt = tt_surfTriangles[0];
+          DI_Triangle *trt = tt_surfTriangles[0];
           tt_surfTriangles.erase(tt_surfTriangles.begin());
-          trt.cut(&tt, RPNi, tt_surfQuads, tt_surfTriangles, tt_surfLines, tt_cp);
+          bool c = trt->cut(tt, RPNi, tt_surfQuads, tt_surfTriangles, tt_surfLines, tt_cp);
+          if(c) delete trt;
         }
       }
       else {
         for(int t = 0; t < (int)tt_subTetras.size(); t++)
-          tt_subTetras[t].chooseLs(Lsi);
+          tt_subTetras[t]->chooseLs(Lsi);
         for(int q = 0; q < (int)tt_surfQuads.size(); q++)
-          tt_surfQuads[q].chooseLs(Lsi);
+          tt_surfQuads[q]->chooseLs(Lsi);
         for(int t = 0; t < (int)tt_surfTriangles.size(); t++)
-          tt_surfTriangles[t].chooseLs(Lsi);
+          tt_surfTriangles[t]->chooseLs(Lsi);
         for(int p = 0; p < (int)tt_cp.size(); p++)
-          tt_cp[p].chooseLs(Lsi);
+          tt_cp[p]->chooseLs(Lsi);
       }
     }
   }
   else {
-    tt_subTetras[0].addLs(this, Ls);
+    tt_subTetras[0]->addLs(this, RPN.back());
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        tt.addLs(this, *Lsi, nodeLs);
+        tt->addLs(this, Lsi, l, nodeLs);
       }
     }
   }
 
-  for(int i = 0; i < (int)QError.size(); i++)
-    QError[i].print(this);
+  for(int i = 0; i < (int)QError.size(); i++) {
+    QError[i]->print(this);
+    delete QError[i];
+  }
 
   for(int t = 0; t < (int)tt_subTetras.size(); t++) {
-    tt_subTetras[t].computeLsTagDom(&tt, RPN);
-    DI_Tetra tt_subT = tt_subTetras[t];
-    mappingEl(&tt_subT);
-    tt_subT.integrationPoints(polynomialOrderT, &tt_subTetras[t], &tt, RPN, ip);
-    subTetras.push_back(tt_subT);
+    tt_subTetras[t]->computeLsTagDom(tt, RPN);
+    DI_Tetra *tt_subT = new DI_Tetra(*tt_subTetras[t]);
+    mappingEl(tt_subTetras[t]);
+    tt_subTetras[t]->integrationPoints(polynomialOrderT, tt_subT, tt, RPN, ip);
+    subTetras.push_back(tt_subTetras[t]);
+    delete tt_subT;
   }
   for(int q = 0; q < (int)tt_surfQuads.size(); q++) {
-    tt_surfQuads[q].computeLsTagBound(tt_subHexas, tt_subTetras);
-    if(tt_surfQuads[q].lsTag() == -1) continue;
-    DI_Quad tt_surfQ = tt_surfQuads[q];
-    mappingEl(&tt_surfQ);
-    tt_surfQ.integrationPoints(polynomialOrderQ, &tt_surfQuads[q], &tt, RPN, ipS);
-    surfQuads.push_back(tt_surfQ);
+    tt_surfQuads[q]->computeLsTagBound(tt_subHexas, tt_subTetras);
+    if(tt_surfQuads[q]->lsTag() == -1) {delete tt_surfQuads[q]; continue;}
+    DI_Quad *tt_surfQ = new DI_Quad(*tt_surfQuads[q]);
+    mappingEl(tt_surfQuads[q]);
+    tt_surfQuads[q]->integrationPoints(polynomialOrderQ, tt_surfQ, tt, RPN, ipS);
+    surfQuads.push_back(tt_surfQuads[q]);
+    delete tt_surfQ;
   }
   for(int t = 0; t < (int)tt_surfTriangles.size(); t++) {
-    tt_surfTriangles[t].computeLsTagBound(tt_subHexas, tt_subTetras);
-    if(tt_surfTriangles[t].lsTag() == -1) continue;
-    DI_Triangle tt_surfTr = tt_surfTriangles[t];
-    mappingEl(&tt_surfTriangles[t]);
-    tt_surfTriangles[t].integrationPoints(polynomialOrderTr, &tt_surfTr, &tt, RPN, ipS);
+    tt_surfTriangles[t]->computeLsTagBound(tt_subHexas, tt_subTetras);
+    if(tt_surfTriangles[t]->lsTag() == -1) {delete tt_surfTriangles[t]; continue;}
+    DI_Triangle *tt_surfTr = new DI_Triangle(*tt_surfTriangles[t]);
+    mappingEl(tt_surfTriangles[t]);
+    tt_surfTriangles[t]->integrationPoints(polynomialOrderTr, tt_surfTr, tt, RPN, ipS);
     surfTriangles.push_back(tt_surfTriangles[t]);
+    delete tt_surfTr;
   }
   for(int p = 0; p < (int)tt_cp.size(); p++) {
-    if(tt_cp[p].ls() != 0) continue;
+    if(tt_cp[p]->ls() != 0) {delete tt_cp[p]; continue;}
     mappingCP(tt_cp[p]);
-    bool isIn = false;
-    for(int i = (int)cp.size() - 1; i >= 0; i--)
-      if(cp[i].equal(tt_cp[p])) {isIn = true; break;}
-    if(!isIn) cp.push_back(tt_cp[p]);
+    std::pair<DI_Point::Container::iterator,bool> isIn = cp.insert(tt_cp[p]);
+    if(!isIn.second) delete tt_cp[p];
   }
+  delete tt;
   return signChange;
 }
 
 // cut a tetrahedron into subtetrahedra along the levelset surface
-void DI_Tetra::cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                 std::vector<DI_Tetra> &subTetras, std::vector<DI_Quad> &surfQuads,
-                 std::vector<DI_Triangle> &surfTriangles, std::vector<DI_CuttingPoint> &cp,
-                 std::vector<DI_QualError> &QError) const
+bool DI_Tetra::cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+                 std::vector<DI_Tetra *> &subTetras, std::vector<DI_Quad *> &surfQuads,
+                 std::vector<DI_Triangle *> &surfTriangles, std::vector<DI_CuttingPoint *> &cp,
+                 std::vector<DI_QualError *> &QError)
 {
   // check if the tetra is cut by the level set
   int on = 0, pos = 0, neg = 0, ze[4];
   for (int i = 0; i < 4; i++){
-    if(pt(i).isOnBorder()) ze[on++] = i;
-    else if (pt(i).ls() > 0.) pos++;
+    if(pt(i)->isOnBorder()) ze[on++] = i;
+    else if (pt(i)->ls() > 0.) pos++;
     else neg++;
   }
   if (pos && neg)
     selfSplit(e, RPNi, subTetras, surfTriangles, cp, QError);
   else{
     if(on == 3){ // the level set is zero on a face of the tetra
-      surfTriangles.push_back(DI_Triangle(pt(ze[0]), pt(ze[1]), pt(ze[2]), RPNi.back()->getTag())); // add the triangle twice if the face belongs to 2 tetras => remove it later!
+      surfTriangles.push_back(new DI_Triangle(pt(ze[0]), pt(ze[1]), pt(ze[2]), RPNi.back()->getTag()));
+      // add the triangle twice if the face belongs to 2 tetras => remove it later!
     }
     for(int i = 0; i < on; i++)
-      cp.push_back(DI_CuttingPoint(pt(ze[i])));
-    subTetras.push_back(*this); // add the tetra to subTetras if it is not cut
+      cp.push_back(new DI_CuttingPoint(pt(ze[i])));
+    subTetras.push_back(this); // add the tetra to subTetras if it is not cut
   }
+  return (pos && neg);
 }
 
 // cut a hex into subtetras along the levelset surface
-bool DI_Hexa::cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-                   std::vector<DI_IntegrationPoint> &ipS, std::vector<DI_CuttingPoint> &cp,
+bool DI_Hexa::cut (std::vector<const gLevelset *> &RPN, std::vector<DI_IntegrationPoint *> &ip,
+                   std::vector<DI_IntegrationPoint *> &ipS, DI_Point::Container &cp,
                    const int polynomialOrderH, const int polynomialOrderT,
                    const int polynomialOrderQ, const int polynomialOrderTr,
-                   std::vector<DI_Hexa> &subHexas, std::vector<DI_Tetra> &subTetras,
-                   std::vector<DI_Quad> &surfQuads, std::vector<DI_Triangle> &surfTriangles,
-                   std::vector<DI_Line> &frontLines, int recurLevel, std::map<int, double> nodeLs[8]) const
+                   std::vector<DI_Hexa *> &subHexas, std::vector<DI_Tetra *> &subTetras,
+                   std::vector<DI_Quad *> &surfQuads, std::vector<DI_Triangle *> &surfTriangles,
+                   std::vector<DI_Line *> &frontLines, int recurLevel, double **nodeLs) const
 {
-  printf(" "); print();
-
-  std::vector<const gLevelset *> RPN, RPNi;
-  Ls.getRPN(RPN);
+  //printf(" "); print();
+  std::vector<const gLevelset *> RPNi; RPNi.reserve(RPN.size());
 
  // reference hexa
-  DI_Hexa hh(-1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 8.);
-  std::vector<DI_Hexa> hh_subHexas;
-  std::vector<DI_Tetra> hh_subTetras;
-  std::vector<DI_Quad> hh_surfQuads;
-  std::vector<DI_Triangle> hh_surfTriangles;
-  std::vector<DI_Line> hh_frontLines;
-  std::vector<DI_CuttingPoint> hh_cp;
-  std::vector<DI_QualError> QError;
-
-  RecurElement re(&hh);
-  bool signChange = re.cut(recurLevel, this, Ls, -1., nodeLs);
-  pushSubElements(&re, hh_subHexas);
+  DI_Hexa *hh = new DI_Hexa(-1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 8.);
+  hh->setPolynomialOrder(getPolynomialOrder());
+  std::vector<DI_Hexa *> hh_subHexas;
+  std::vector<DI_Tetra *> hh_subTetras;
+  std::vector<DI_Quad *> hh_surfQuads;
+  std::vector<DI_Triangle *> hh_surfTriangles;
+  std::vector<DI_Line *> hh_frontLines;
+  std::vector<DI_CuttingPoint *> hh_cp;
+  std::vector<DI_QualError *> QError;
+
+  RecurElement *re = new RecurElement(hh);
+  bool signChange = re->cut(recurLevel, this, RPN, -1., nodeLs);
+  pushSubElements(re, hh_subHexas);
+  delete re;
 
   if(signChange){
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        hh.addLs(this, *Lsi, nodeLs);
+        hh->addLs(this, Lsi, l, nodeLs);
         int nbSubH = hh_subHexas.size();
         int nbSubT = hh_subTetras.size(), nbSubT1 = nbSubT;
         int nbSurfQ = hh_surfQuads.size(), nbSurfQ1 = nbSurfQ;
         int nbSurfTr = hh_surfTriangles.size(), nbSurfTr1 = nbSurfTr;
         int nbFrontLn = hh_frontLines.size();
         int nbCP = hh_cp.size();
-        for(int i = 0; i < nbSubH; i++) hh_subHexas[i].addLs(&hh);
-        for(int i = 0; i < nbSubT; i++) hh_subTetras[i].addLs(&hh);
-        for(int i = 0; i < nbSurfQ; i++) hh_surfQuads[i].addLs(&hh);
-        for(int i = 0; i < nbSurfTr; i++) hh_surfTriangles[i].addLs(&hh);
-        for(int i = 0; i < nbFrontLn; i++) hh_frontLines[i].addLs(&hh);
-        for(int i = 0; i < nbCP; i++) hh_cp[i].addLs(&hh);
+        for(int i = 0; i < nbSubH; i++) hh_subHexas[i]->addLs(hh);
+        for(int i = 0; i < nbSubT; i++) hh_subTetras[i]->addLs(hh);
+        for(int i = 0; i < nbSurfQ; i++) hh_surfQuads[i]->addLs(hh);
+        for(int i = 0; i < nbSurfTr; i++) hh_surfTriangles[i]->addLs(hh);
+        for(int i = 0; i < nbFrontLn; i++) hh_frontLines[i]->addLs(hh);
+        for(int i = 0; i < nbCP; i++) hh_cp[i]->addLs(hh);
         int pos = 0, neg = 0, ze[4], cz = 0;
         for (int i = 0; i < 8; i++){
-          if(hh.pt(i).isOnBorder()) ze[cz++] = i;
-          else if (hh.ls(i) > 0.) pos++;
+          if(hh->pt(i)->isOnBorder()) ze[cz++] = i;
+          else if (hh->ls(i) > 0.) pos++;
           else neg++;
         }
 
         for(int h = 0; h < nbSubH; h++) {
           nbSurfQ1 = hh_surfQuads.size();
-          DI_Hexa ht = hh_subHexas[0];
+          DI_Hexa *ht = hh_subHexas[0];
           hh_subHexas.erase(hh_subHexas.begin());
-          ht.cut(&hh, RPNi, hh_subHexas, hh_subTetras, hh_surfQuads, hh_surfTriangles, hh_cp, QError);
+          bool c = ht->cut(hh, RPNi, hh_subHexas, hh_subTetras, hh_surfQuads, hh_surfTriangles, hh_cp, QError);
+          if(c) delete ht;
           if((int)hh_surfQuads.size() > nbSurfQ1){ // 1 quad created on surface of the subHexa
-            if(isLastQInV(hh_surfQuads))
-              hh_surfQuads.pop_back();
+            if(isLastQInV(hh_surfQuads)) {
+              delete hh_surfQuads.back(); hh_surfQuads.pop_back();
+            }
             else if (cz == 4) {
               if(!ordered4Nodes(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3])))
                 swap(ze[2], ze[3]);
               DI_Quad qf(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3]));
               for(int i = (int)surfQuads.size() - 1; i >= 0; i--){
-                if (qf.contain(&surfQuads[i])){
-                  hh_surfQuads.pop_back(); break;
+                if (qf.contain(surfQuads[i])){
+                  delete hh_surfQuads.back(); hh_surfQuads.pop_back(); break;
                 }
               }
               for(int i = (int)surfTriangles.size() - 1; i >= 0; i--){
-                if (qf.contain(&surfTriangles[i])) {
-                  hh_surfQuads.pop_back(); break;
+                if (qf.contain(surfTriangles[i])) {
+                  delete hh_surfQuads.back(); hh_surfQuads.pop_back(); break;
                 }
               }
             }
@@ -2656,20 +2713,22 @@ bool DI_Hexa::cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
         for(int t = 0; t < nbSubT; t++) {
           nbSurfTr1 = hh_surfTriangles.size();
           nbSubT1 = hh_subTetras.size();
-          DI_Tetra tet = hh_subTetras[0];
+          DI_Tetra *tet = hh_subTetras[0];
           hh_subTetras.erase(hh_subTetras.begin());
-          tet.cut(&hh, RPNi, hh_subTetras, hh_surfQuads, hh_surfTriangles, hh_cp, QError);
+          bool c = tet->cut(hh, RPNi, hh_subTetras, hh_surfQuads, hh_surfTriangles, hh_cp, QError);
+          if(c) delete tet;
           if((int)hh_surfTriangles.size() - nbSurfTr1 == 1 && (int)hh_subTetras.size() == nbSubT1) { // 1 triangle created on surface of the subtetra
             // check among hh_surfTriangles
-            if(isLastTrInV(hh_surfTriangles))
-              hh_surfTriangles.pop_back();
+            if(isLastTrInV(hh_surfTriangles)) {
+              delete hh_surfTriangles.back(); hh_surfTriangles.pop_back();
+            }
             else if (cz == 4 && !(pos && neg)){ // 1 triangle created on surface of the hex => check among surfTriangles
               if(!ordered4Nodes(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3])))
                 swap(ze[2], ze[3]);
               DI_Quad qt(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3]));
               for(int i = (int)surfTriangles.size() - 1; i >= 0; i--){
-                if(qt.contain(&surfTriangles[i])) {
-                  hh_surfTriangles.pop_back(); break;
+                if(qt.contain(surfTriangles[i])) {
+                  delete hh_surfTriangles.back(); hh_surfTriangles.pop_back(); break;
                 }
               }
             }
@@ -2677,7 +2736,7 @@ bool DI_Hexa::cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
               // check among the quads with quality error
               for(int i = 0; i < (int)QError.size(); i++){
                 if(isInQE(hh_surfTriangles[nbSurfTr1], QError[i])) {
-                  hh_surfTriangles.pop_back();
+                  delete hh_surfTriangles.back(); hh_surfTriangles.pop_back();
                   break;
                 }
               }
@@ -2685,126 +2744,135 @@ bool DI_Hexa::cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
           }
         }
         for(int q = 0; q < nbSurfQ; q++) {
-          DI_Quad qt = hh_surfQuads[0];
+          DI_Quad *qt = hh_surfQuads[0];
           hh_surfQuads.erase(hh_surfQuads.begin());
-          qt.cut(&hh, RPNi, hh_surfQuads, hh_surfTriangles, hh_frontLines, hh_cp);
+          bool c = qt->cut(hh, RPNi, hh_surfQuads, hh_surfTriangles, hh_frontLines, hh_cp);
+          if(c) delete qt;
         }
         for(int t = 0; t < nbSurfTr; t++){
-          DI_Triangle trt = hh_surfTriangles[0];
+          DI_Triangle *trt = hh_surfTriangles[0];
           hh_surfTriangles.erase(hh_surfTriangles.begin());
-          trt.cut(&hh, RPNi, hh_surfQuads, hh_surfTriangles, hh_frontLines, hh_cp);
+          bool c = trt->cut(hh, RPNi, hh_surfQuads, hh_surfTriangles, hh_frontLines, hh_cp);
+          if(c) delete trt;
         }
         for(int l = 0; l < nbFrontLn; l++){
-          DI_Line lnt = hh_frontLines[0];
+          DI_Line *lnt = hh_frontLines[0];
           hh_frontLines.erase(hh_frontLines.begin());
-          lnt.cut(&hh, RPNi, hh_frontLines, hh_cp);
+          bool c = lnt->cut(hh, RPNi, hh_frontLines, hh_cp);
+          if(c) delete lnt;
         }
       }
       else {
         for(int h = 0; h < (int)hh_subHexas.size(); h++)
-          hh_subHexas[h].chooseLs(Lsi);
+          hh_subHexas[h]->chooseLs(Lsi);
         for(int t = 0; t < (int)hh_subTetras.size(); t++)
-          hh_subTetras[t].chooseLs(Lsi);
+          hh_subTetras[t]->chooseLs(Lsi);
         for(int q = 0; q < (int)hh_surfQuads.size(); q++)
-          hh_surfQuads[q].chooseLs(Lsi);
+          hh_surfQuads[q]->chooseLs(Lsi);
         for(int t = 0; t < (int)hh_surfTriangles.size(); t++)
-          hh_surfTriangles[t].chooseLs(Lsi);
+          hh_surfTriangles[t]->chooseLs(Lsi);
         for(int l = 0; l < (int)hh_frontLines.size(); l++)
-          hh_frontLines[l].chooseLs(Lsi);
+          hh_frontLines[l]->chooseLs(Lsi);
         for(int p = 0; p < (int)hh_cp.size(); p++)
-          hh_cp[p].chooseLs(Lsi);
+          hh_cp[p]->chooseLs(Lsi);
       }
     //printf("Lsi=%d sizeLs=%d nbH=%d nbT=%d nbQ=%d nbTr=%d sizeLs(hh_cp)=%d\n",Lsi->type(),(hh_subHexas.size()>0)?hh_subHexas[0].sizeLs():hh_subTetras[0].sizeLs(), hh_subHexas.size(),hh_subTetras.size(),hh_surfQuads.size(),hh_surfTriangles.size(),(hh_cp.size() > 0)?hh_cp[0].sizeLs():0);
     }
   }
   else {
-    hh_subHexas[0].addLs(this, Ls);
+    hh_subHexas[0]->addLs(this, RPN.back());
     for(int l = 0; l < (int)RPN.size(); l++) {
       const gLevelset *Lsi = RPN[l];
       RPNi.push_back(Lsi);
       if(Lsi->isPrimitive()) {
-        hh.addLs(this, *Lsi, nodeLs);
+        hh->addLs(this, Lsi, l, nodeLs);
       }
     }
   }
 
-  for(int i = 0; i < (int)QError.size(); i++)
-    QError[i].print(this);
+  for(int i = 0; i < (int)QError.size(); i++) {
+    QError[i]->print(this);
+    delete QError[i];
+  }
 
   for(int h = 0; h < (int)hh_subHexas.size(); h++) {
-    hh_subHexas[h].computeLsTagDom(&hh, RPN);
-    DI_Hexa hh_subH = hh_subHexas[h];
-    mappingEl(&hh_subH);
-    hh_subH.integrationPoints(polynomialOrderH, &hh_subHexas[h], &hh, RPN, ip);
-    subHexas.push_back(hh_subH);
+    hh_subHexas[h]->computeLsTagDom(hh, RPN);
+    DI_Hexa *hh_subH = new DI_Hexa(*hh_subHexas[h]);
+    mappingEl(hh_subHexas[h]);
+    hh_subHexas[h]->integrationPoints(polynomialOrderH, hh_subH, hh, RPN, ip);
+    subHexas.push_back(hh_subHexas[h]);
+    delete hh_subH;
   }
   for(int t = 0; t < (int)hh_subTetras.size(); t++) {
-    hh_subTetras[t].computeLsTagDom(&hh, RPN);
-    DI_Tetra hh_subT = hh_subTetras[t];
-    mappingEl(&hh_subT);
-    hh_subT.integrationPoints(polynomialOrderT, &hh_subTetras[t], &hh, RPN, ip);
-    subTetras.push_back(hh_subT);
+    hh_subTetras[t]->computeLsTagDom(hh, RPN);
+    DI_Tetra *hh_subT = new DI_Tetra(*hh_subTetras[t]);
+    mappingEl(hh_subTetras[t]);
+    hh_subTetras[t]->integrationPoints(polynomialOrderT, hh_subT, hh, RPN, ip);
+    subTetras.push_back(hh_subTetras[t]);
+    delete hh_subT;
   }
   for(int q = 0; q < (int)hh_surfQuads.size(); q++) {
-    hh_surfQuads[q].computeLsTagBound(hh_subHexas, hh_subTetras);
-    if(hh_surfQuads[q].lsTag() == -1) continue;
-    DI_Quad hh_surfQ = hh_surfQuads[q];
-    mappingEl(&hh_surfQ);
-    hh_surfQ.integrationPoints(polynomialOrderQ, &hh_surfQuads[q], &hh, RPN, ipS);
-    surfQuads.push_back(hh_surfQ);
+    hh_surfQuads[q]->computeLsTagBound(hh_subHexas, hh_subTetras);
+    if(hh_surfQuads[q]->lsTag() == -1) {delete hh_surfQuads[q]; continue;}
+    DI_Quad *hh_surfQ = new DI_Quad(*hh_surfQuads[q]);
+    mappingEl(hh_surfQuads[q]);
+    hh_surfQuads[q]->integrationPoints(polynomialOrderQ, hh_surfQ, hh, RPN, ipS);
+    surfQuads.push_back(hh_surfQuads[q]);
+    delete hh_surfQ;
   }
   for(int t = 0; t < (int)hh_surfTriangles.size(); t++) {
-    hh_surfTriangles[t].computeLsTagBound(hh_subHexas, hh_subTetras);
-    if(hh_surfTriangles[t].lsTag() == -1) continue;
-    DI_Triangle hh_surfTr = hh_surfTriangles[t];
-    mappingEl(&hh_surfTr);
-    hh_surfTr.integrationPoints(polynomialOrderTr, &hh_surfTriangles[t], &hh, RPN, ipS);
-    surfTriangles.push_back(hh_surfTr);
+    hh_surfTriangles[t]->computeLsTagBound(hh_subHexas, hh_subTetras);
+    if(hh_surfTriangles[t]->lsTag() == -1) {delete hh_surfTriangles[t]; continue;}
+    DI_Triangle *hh_surfTr = new DI_Triangle(*hh_surfTriangles[t]);
+    mappingEl(hh_surfTriangles[t]);
+    hh_surfTriangles[t]->integrationPoints(polynomialOrderTr, hh_surfTr, hh, RPN, ipS);
+    surfTriangles.push_back(hh_surfTriangles[t]);
+    delete hh_surfTr;
   }
   for(int l = 0; l < (int)hh_frontLines.size(); l++) {
-    hh_frontLines[l].computeLsTagBound(hh_surfQuads, hh_surfTriangles);
-    if(hh_frontLines[l].lsTag() == -1) continue;
-    DI_Line hh_frontLn = hh_frontLines[l];
-    mappingEl(&hh_frontLn);                      //tt_surfLn.printls();
-    //hh_frontLn.integrationPoints(polynomialOrderL, &tt_surfLines[l], &tt, RPN, ipS);
-    frontLines.push_back(hh_frontLn);
+    hh_frontLines[l]->computeLsTagBound(hh_surfQuads, hh_surfTriangles);
+    if(hh_frontLines[l]->lsTag() == -1) {delete hh_frontLines[l]; continue;}
+    DI_Line *hh_frontLn = new DI_Line(*hh_frontLines[l]);
+    mappingEl(hh_frontLines[l]);
+    //hh_frontLines[l]->integrationPoints(polynomialOrderL, tt_surfLn, tt, RPN, ipS);
+    frontLines.push_back(hh_frontLines[l]);
+    delete hh_frontLn;
   }
   for(int p = 0; p < (int)hh_cp.size(); p++) {
-    if(hh_cp[p].ls() != 0) continue; // returns only the cutting points with ls==0
+    if(hh_cp[p]->ls() != 0) {delete hh_cp[p]; continue;} // returns only the cutting points with ls==0
     mappingCP(hh_cp[p]);
-    bool isIn = false;
-    for(int i = (int)cp.size() - 1; i >= 0; i--)
-      if(cp[i].equal(hh_cp[p])) {isIn = true; break;}
-    if(!isIn) cp.push_back(hh_cp[p]);
+    std::pair<DI_Point::Container::iterator,bool> isIn = cp.insert(hh_cp[p]);
+    if(!isIn.second) delete hh_cp[p];
   }
+  delete hh;
   return signChange;
 }
 
 // cut a hex into subtetras along the levelset surface
-void DI_Hexa::cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                   std::vector<DI_Hexa> &Hexas, std::vector<DI_Tetra> &subTetras,
-                   std::vector<DI_Quad> &surfQuads, std::vector<DI_Triangle> &surfTriangles,
-                   std::vector<DI_CuttingPoint> &cp, std::vector<DI_QualError> &QError) const
+bool DI_Hexa::cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+                   std::vector<DI_Hexa *> &Hexas, std::vector<DI_Tetra *> &subTetras,
+                   std::vector<DI_Quad *> &surfQuads, std::vector<DI_Triangle *> &surfTriangles,
+                   std::vector<DI_CuttingPoint *> &cp, std::vector<DI_QualError *> &QError)
 {
   // check if the hex is cut by the level set
   int on = 0, pos = 0, neg = 0, ze[8];
   for (int i = 0; i < 8; i++){
-    if(pt(i).isOnBorder()) ze[on++] = i;
-    else if (pt(i).ls() > 0.) pos++;
+    if(pt(i)->isOnBorder()) ze[on++] = i;
+    else if (pt(i)->ls() > 0.) pos++;
     else neg++;
   }
   if (pos && neg) {
-    std::vector<DI_Tetra> tetras;
+    std::vector<DI_Tetra *> tetras; tetras.reserve(6);
     // Split the quad into sub tetras
     splitIntoTetras (tetras);
     // each of the sub tetras is split again into sub tetras with respect to the levelset
     int nt0 = surfTriangles.size(), nT1, nt1, nT2, nt2;
     for (int t = 0; t < (int)tetras.size(); t++) {
       nT1 = subTetras.size(); nt1 = surfTriangles.size();
-      tetras[t].selfSplit(e, RPNi, subTetras, surfTriangles, cp, QError);
+      tetras[t]->selfSplit(e, RPNi, subTetras, surfTriangles, cp, QError);
       nT2 = subTetras.size(); nt2 = surfTriangles.size();
       if((nT2 - nT1) == 1 && (nt2 - nt1) == 1){ // only 1 triangle created on a face of a tetra => check if it was not yet created
-        if(isLastTrInV(surfTriangles, nt0)) {surfTriangles.pop_back(); nt2--;}
+        if(isLastTrInV(surfTriangles, nt0)) {delete surfTriangles.back(); surfTriangles.pop_back(); nt2--;}
       }
     }
   }
@@ -2813,18 +2881,21 @@ void DI_Hexa::cut (const DI_Element *e, const std::vector<const gLevelset *> &RP
     if(on == 4){ // the level set is zero on a face of the hex
       // assert the nodes are in the same plane
       if(!isPlanar(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3]))) {
-        printf("Error : The 4 nodes with zero levelset are not planar!\n"); return;}
-      // order the 4 nodes
-      if(!ordered4Nodes(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3]))) swap(ze[2], ze[3]);
-      // add the quad twice if the face belongs to 2 hexas => remove it later!
-      if(ze[0] == 2) surfQuads.push_back(DI_Quad(pt(ze[1]), pt(ze[2]), pt(ze[3]), pt(ze[0]), RPNi.back()->getTag()));
-      // to assert that the quad will be split into triangles in the same manner as the hexa into tetras.
-      else surfQuads.push_back(DI_Quad(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3]), RPNi.back()->getTag()));
+        printf("Error : The 4 nodes with zero levelset are not planar!\n");}
+      else {
+        // order the 4 nodes
+        if(!ordered4Nodes(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3]))) swap(ze[2], ze[3]);
+        // add the quad twice if the face belongs to 2 hexas => remove it later!
+        if(ze[0] == 2) surfQuads.push_back(new DI_Quad(pt(ze[1]), pt(ze[2]), pt(ze[3]), pt(ze[0]), RPNi.back()->getTag()));
+        // to assert that the quad will be split into triangles in the same manner as the hexa into tetras.
+        else surfQuads.push_back(new DI_Quad(pt(ze[0]), pt(ze[1]), pt(ze[2]), pt(ze[3]), RPNi.back()->getTag()));
+      }
     }
     for(int i = 0; i < on; i++)
-      cp.push_back(DI_CuttingPoint(pt(ze[i])));
-    Hexas.push_back(*this);
+      cp.push_back(new DI_CuttingPoint(pt(ze[i])));
+    Hexas.push_back(this);
   }
+  return (pos && neg);
 }
 
 #endif
diff --git a/contrib/DiscreteIntegration/Integration3D.h b/contrib/DiscreteIntegration/Integration3D.h
index 791fbea19a..f0006bbbd4 100644
--- a/contrib/DiscreteIntegration/Integration3D.h
+++ b/contrib/DiscreteIntegration/Integration3D.h
@@ -3,6 +3,7 @@
 
 #include <list>
 #include <vector>
+#include <set>
 #include <map>
 #include <cmath>
 #include "DILevelset.h"
@@ -17,6 +18,7 @@
 class DI_Point;
 class DI_IntegrationPoint;
 class DI_CuttingPoint;
+class DI_PointLessThan;
 class DI_Element;
 class DI_Line;              // : public DI_Element
 class DI_Triangle;          // : public DI_Element
@@ -28,6 +30,7 @@ class DI_QualError;
 // --------------------------------------------------------------------------------------------------
 class DI_Point
 {
+ protected :
   // coordinates of the point
   double x_, y_, z_;
   // vector containing the levelset values of the point
@@ -36,15 +39,15 @@ class DI_Point
   // constructors
   DI_Point () : x_(0), y_(0), z_(0) {}
   DI_Point (double x, double y, double z) : x_(x), y_(y), z_(z) {}
-  DI_Point (double x, double y, double z, gLevelset &ls);
+  DI_Point (double x, double y, double z, gLevelset *ls);
   DI_Point (double x, double y, double z, const double ls) : x_(x), y_(y), z_(z) {addLs(ls);}
   DI_Point (double x, double y, double z, const DI_Element *e,
-            const std::vector<const gLevelset *> RPNi) : x_(x), y_(y), z_(z) {computeLs(e, RPNi);}
+            const std::vector<const gLevelset *> &RPNi) : x_(x), y_(y), z_(z) {computeLs(e, RPNi);}
   DI_Point(const DI_Point &p) : x_(p.x()), y_(p.y()), z_(p.z()) {Ls.clear(); Ls = p.Ls;}
   // assignment
   DI_Point & operator=(const DI_Point & rhs);
   // destructor
-  ~DI_Point () {Ls.clear();}
+  virtual ~DI_Point () {Ls.clear();}
   // add a levelset value (adjusted to 0 if ls<ZERO_LS_TOL) into the vector Ls
   void addLs (const double ls);
   // add a levelset value evaluated into the element e
@@ -53,15 +56,15 @@ class DI_Point
   // delete the last two values and add the chosen one
   void chooseLs (const gLevelset *Lsi);
   // clear Ls and add the levelset values computed with RPNi
-  void computeLs (const DI_Element *e, const std::vector<const gLevelset *> RPNi);
+  void computeLs (const DI_Element *e, const std::vector<const gLevelset *> &RPNi);
   // clear Ls and add the levelset value computed with ls
-  void computeLs (const gLevelset &ls);
+  void computeLs (const gLevelset *ls);
   // remove the last value in Ls and add ls
   inline void changeLs (const double ls) {Ls.pop_back(); addLs(ls);}
   // change the coordinates
   inline void move (double x, double y, double z) {x_ = x; y_ = y; z_ = z;}
   // return true if the coordinates of this and p are equal (with a tolerance)
-  bool equal(const DI_Point &p) const;
+  bool equal(const DI_Point *p) const;
   // return the coordinates
   inline double x () const {return x_;}
   inline double y () const {return y_;}
@@ -84,12 +87,13 @@ class DI_Point
     return 0;
   }
   // print the coordiantes
-  inline void print() const {printf("Point (%g,%g,%g)\n", x_, y_, z_);}
-  void printls() const {
+  virtual void print() const {printf("Point (%g,%g,%g)\n", x_, y_, z_);}
+  virtual void printls() const {
     printf("Point (%g,%g,%g) ls=(", x_, y_, z_);
     for(int i = 0; i < (int)Ls.size(); i++) printf("%g,", Ls[i]);
     printf(")\n");
   }
+  typedef std::set<DI_Point*,DI_PointLessThan> Container;
 };
 // --------------------------------------------------------------------------------------------------
 class DI_IntegrationPoint
@@ -111,7 +115,7 @@ class DI_IntegrationPoint
   // change the value of ls_
   inline void setLs (double lsT) {ls_ = lsT;}
   // clear Ls and add the levelset values computed with RPNi
-  void computeLs (const DI_Element *e, const std::vector<const gLevelset *> RPNi);
+  void computeLs (const DI_Element *e, const std::vector<const gLevelset *> &RPNi);
   // change the value of weight_
   inline void setWeight (double w) {weight_ = w;}
   // return the coordinates
@@ -135,15 +139,43 @@ class DI_IntegrationPoint
     printf("IP : x=(%g,%g,%g) xl=(%g,%g,%g) w=%g ls=%g\n", x_, y_, z_, xl_, yl_, zl_, weight_, ls_); }
 };
 
+// --------------------------------------------------------------------------------------------------
+class DI_CuttingPoint : public DI_Point
+{
+  double xl_, yl_, zl_;
+ public:
+  DI_CuttingPoint (const DI_Point *pt);
+  inline void addLocC (double xl, double yl, double zl) {xl_ = xl; yl_ = yl; zl_ = zl;}
+  inline double xl() const {return xl_;}
+  inline double yl() const {return yl_;}
+  inline double zl() const {return zl_;}
+  void print() const {
+    printf("CP : x=(%g,%g,%g) xl=(%g,%g,%g)\n", x_, y_, z_, xl_, yl_, zl_);
+  }
+  void printls() const {
+    printf("CP : x=(%g,%g,%g) xl=(%g,%g,%g) ls=(", x_, y_, z_, xl_, yl_, zl_);
+    for(int i = 0; i < (int)Ls.size(); i++) printf("%g,", Ls[i]);
+    printf(")\n");
+  }
+};
+
+// --------------------------------------------------------------------------------------------------
+class DI_PointLessThan
+{
+ public:
+  static double tolerance;
+  bool operator()(const DI_Point *p1, const DI_Point *p2) const;
+};
+
 // --------------------------------------------------------------------------------------------------
 // compute the length of a line
 static inline double LineLength(double x1, double y1, double z1, double x2, double y2, double z2)
 {
   return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
 }
-static inline double LineLength (const DI_Point &p1, const DI_Point &p2)
+static inline double LineLength (const DI_Point *p1, const DI_Point *p2)
 {
-  return LineLength(p1.x(), p1.y(), p1.z(), p2.x(), p2.y(), p2.z());
+  return LineLength(p1->x(), p1->y(), p1->z(), p2->x(), p2->y(), p2->z());
 }
 // compute the surface of a triangle
 static inline double TriSurf(double x1, double y1, double z1, double x2, double y2, double z2,
@@ -156,9 +188,9 @@ static inline double TriSurf(double x1, double y1, double z1, double x2, double
                   + (z1 * (x2 - x3) - z2 * (x1 - x3) + z3 * (x1 - x2)) *
                     (z1 * (x2 - x3) - z2 * (x1 - x3) + z3 * (x1 - x2)));
 }
-static inline double TriSurf (const DI_Point &p1, const DI_Point &p2, const DI_Point &p3)
+static inline double TriSurf (const DI_Point *p1, const DI_Point *p2, const DI_Point *p3)
 {
-  return TriSurf(p1.x(), p1.y(), p1.z(), p2.x(), p2.y(), p2.z(), p3.x(), p3.y(), p3.z());
+  return TriSurf(p1->x(), p1->y(), p1->z(), p2->x(), p2->y(), p2->z(), p3->x(), p3->y(), p3->z());
 }
 
 // compute the volume of a tetrahedron (base in ccw order to have positive volume)
@@ -171,11 +203,11 @@ static inline double TetraVol(double x1, double y1, double z1, double x2, double
   if(vol < 0) {printf("TET HAS NEGATIVE VOLUME = %g\n", vol);}
   return vol;
 }
-static inline double TetraVol(const DI_Point &p1, const DI_Point &p2,
-                              const DI_Point &p3, const DI_Point &p4)
+static inline double TetraVol(const DI_Point *p1, const DI_Point *p2,
+                              const DI_Point *p3, const DI_Point *p4)
 {
-  return TetraVol (p1.x(), p1.y(), p1.z(), p2.x(), p2.y(), p2.z(),
-                   p3.x(), p3.y(), p3.z(), p4.x(), p4.y(), p4.z());
+  return TetraVol (p1->x(), p1->y(), p1->z(), p2->x(), p2->y(), p2->z(),
+                   p3->x(), p3->y(), p3->z(), p4->x(), p4->y(), p4->z());
 }
 
 // --------------------------------------------------------------------------------------------------
@@ -216,7 +248,7 @@ class DI_Element
   int getPolynomialOrder() const {return polOrder_;}
   // set the polynomial order of the shape functions
   void setPolynomialOrder(int o);
-  void setPolynomialOrder(int o, const DI_Element *e, const std::vector<const gLevelset *> RPNi);
+  void setPolynomialOrder(int o, const DI_Element *e, const std::vector<const gLevelset *> &RPNi);
   // return tag
   int lsTag() const {return lsTag_;}
   // return the position of the point with respect to the domain depending on ls_
@@ -238,8 +270,8 @@ class DI_Element
   // compute the level set at each vertex of the real element e (same type as this)
   // or take i from the map if exist
   // and add it to the vertices
-  void addLs (const DI_Element *e, const gLevelset &Ls);
-  void addLs (const DI_Element *e, const gLevelset &Ls, std::map<int, double> nodeLs[]);
+  void addLs (const DI_Element *e, const gLevelset *Ls);
+  void addLs (const DI_Element *e, const gLevelset *Ls, int iLs, double **nodeLs);
   // clear the levelset of the vertices
   void clearLs();
   // compute the levelset values at the mid edge points and add a quadratic edge,
@@ -247,39 +279,39 @@ class DI_Element
   // if xm is too close from the middle of the edgeth edge, do not add the quadratic edge
   // if the new quadratic edge create a negative detJ, do not add the quadratic edge and return false
   bool addQuadEdge (int edge, DI_Point *xm, const DI_Element *e,
-                    const std::vector<const gLevelset *> RPNi);
+                    const std::vector<const gLevelset *> &RPNi);
   // return true if the point pt is inside the element
-  bool contain (const DI_Point &pt) const;
+  bool contain (const DI_Point *pt) const;
   // return true if the element e is inside the element
   // (works only for triangles and quadrangles for the moment)
   bool contain (const DI_Element *e) const;
   // choose the levelset for each point
   void chooseLs (const gLevelset *Lsi);
   // map the point pt with local coordinates from the reference element into the element
-  DI_Point mappingP (DI_Point &pt) const;
+  void mappingP (DI_Point *pt) const;
   // map the DI_IntegrationPoint in with local coordinates from the reference element into the element
-  DI_IntegrationPoint mappingIP (DI_IntegrationPoint &in) const;
+  void mappingIP (DI_IntegrationPoint *in) const;
   // map the DI_CuttingPoint cp with local coordinates from the reference element into the element
-  DI_CuttingPoint mappingCP (DI_CuttingPoint &cp) const;
+  void mappingCP (DI_CuttingPoint *cp) const;
   // map the DI_Element el with local coordinates from the reference element into the element
   void mappingEl (DI_Element *el) const;
   // push into ip the reference integration points to integrate exactly a polynom of order polOrder
   virtual void getRefIntegrationPoints (const int polOrder,
-                                        std::vector<DI_IntegrationPoint> &ip) const = 0;
+                                        std::vector<DI_IntegrationPoint *> &ip) const = 0;
   // push into ip the integration points to integrate exactly a polynom of order polOrder
   // over the element
-  // the local coordiantes of the integration points are computed with loc
+  // the local coordinates of the integration points are computed with loc
   // the levelset value at the integration points is computed with e and RPN
   void integrationPoints (const int polyOrder, const DI_Element *loc, const DI_Element *e,
-                          const std::vector<const gLevelset *> RPN,
-                          std::vector<DI_IntegrationPoint> &ip) const;
+                          const std::vector<const gLevelset *> &RPN,
+                          std::vector<DI_IntegrationPoint *> &ip) const;
   // compute the cutting points on the edges with the last ls in the element
-  void getCuttingPoints (const DI_Element *e, const std::vector<const gLevelset *> RPNi,
-                         std::vector<DI_CuttingPoint> &cp) const;
+  void getCuttingPoints (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+                         std::vector<DI_CuttingPoint*> &cp) const;
   // return the ith point
-  inline DI_Point & pt (int i) const {return i < nbVert() ? *pts_[i] : *mid_[i - nbVert()];}
+  inline DI_Point* pt (int i) const {return i < nbVert() ? pts_[i] : mid_[i - nbVert()];}
   // return the ith middle point
-  inline DI_Point & mid (int i) const {return *mid_[i];}
+  inline DI_Point* mid (int i) const {return mid_[i];}
   // return the coordinates of the ith point
   inline double x (int i) const {return i < nbVert() ? pts_[i]->x() : mid_[i - nbVert()]->x();}
   inline double y (int i) const {return i < nbVert() ? pts_[i]->y() : mid_[i - nbVert()]->y();}
@@ -308,52 +340,22 @@ class DI_Element
   // compute DetJ at each point, return false if 2 values have opposite sign
   bool testDetJ() const;
   // set the lsTag to +1 if the element is inside the domain (compute in the reference element)
-  void computeLsTagDom(const DI_Element *e, const std::vector<const gLevelset *> RPN);
+  void computeLsTagDom(const DI_Element *e, const std::vector<const gLevelset *> &RPN);
   // set the lsTag to -1 if the element is not on the boundary of the final levelset
   // (compute in the reference element)
-  void computeLsTagBound(std::vector<DI_Hexa> &hexas, std::vector<DI_Tetra> &tetras);
-  void computeLsTagBound(std::vector<DI_Quad> &quads, std::vector<DI_Triangle> &triangles);
+  void computeLsTagBound(std::vector<DI_Hexa *> &hexas, std::vector<DI_Tetra *> &tetras);
+  void computeLsTagBound(std::vector<DI_Quad *> &quads, std::vector<DI_Triangle *> &triangles);
   // print the coordinates of the points of the element
   void print () const;
   // print the coordinates and the levelset values of the points of the element
   void printls () const;
 };
 
-// --------------------------------------------------------------------------------------------------
-class DI_CuttingPoint
+class DI_ElementLessThan
 {
-  double x_, y_, z_;
-  double xl_, yl_, zl_;
-  std::vector<double> Ls;
  public:
-  DI_CuttingPoint (const DI_Point &pt);
-  inline void addLocC (double xl, double yl, double zl) {xl_ = xl; yl_ = yl; zl_ = zl;}
-  inline void move (double x, double y, double z) {x_ = x; y_ = y; z_ = z;}
-  void addLs (const double ls);
-  void addLs (const DI_Element *e);
-  inline double x () const {return x_;}
-  inline double y () const {return y_;}
-  inline double z () const {return z_;}
-  inline double xl() const {return xl_;}
-  inline double yl() const {return yl_;}
-  inline double zl() const {return zl_;}
-  inline double ls() const {return Ls.back();}
-  inline double ls(int i) const {return Ls[i];}
-  // return the position of the point with respect to the domain depending on the last value in Ls
-  inline bool isInsideDomain  () const {return Ls.back() < 0.;}
-  inline bool isOutsideDomain () const {return Ls.back() > 0.;}
-  inline bool isOnBorder () const {return Ls.back() == 0.;}
-  inline int sizeLs() const {return Ls.size();}
-  void chooseLs (const gLevelset *Lsi);
-  bool equal (const DI_CuttingPoint &p) const;
-  inline void print() const {
-    printf("CP : x=(%g,%g,%g) xl=(%g,%g,%g)\n", x_, y_, z_, xl_, yl_, zl_);
-  }
-  void printls() const {
-    printf("CP : x=(%g,%g,%g) xl=(%g,%g,%g) ls=(", x_, y_, z_, xl_, yl_, zl_);
-    for(int i = 0; i < (int)Ls.size(); i++) printf("%g,", Ls[i]);
-    printf(")\n");
-  }
+  static double tolerance;
+  bool operator()(const DI_Element *v1, const DI_Element *v2) const;
 };
 
 // --------------------------------------------------------------------------------------------------
@@ -380,12 +382,12 @@ class DI_Line : public DI_Element
     pts_[1] = new DI_Point(x1, y1, z1);
     integral_ = length;
   }
-  DI_Line (const DI_Point &pt0, const DI_Point &pt1, const int tag = -1)
+  DI_Line (const DI_Point *pt0, const DI_Point *pt1, const int tag = -1)
   {
     lsTag_ = tag;
     pts_ = new DI_Point*[2];
-    pts_[0] = new DI_Point(pt0);
-    pts_[1] = new DI_Point(pt1);
+    pts_[0] = new DI_Point(*pt0);
+    pts_[1] = new DI_Point(*pt1);
     integral_ = LineLength(pt0, pt1);
   }
   ~DI_Line () {
@@ -407,7 +409,7 @@ class DI_Line : public DI_Element
   virtual void computeIntegral();
   virtual double refIntegral() const {return 2.;}
   virtual void getRefIntegrationPoints (const int polynomialOrder,
-                                        std::vector<DI_IntegrationPoint> &ipS) const;
+                                        std::vector<DI_IntegrationPoint *> &ipS) const;
   inline void vert(const int edge, int &s1, int &s2) const {
     s1 = 0; s2 = 1;}
   void midV (const int e, int *s, int &n) const {
@@ -417,13 +419,13 @@ class DI_Line : public DI_Element
   void getGradShapeFunctions (const double u, const double v, const double w,
                               double s[][3], int order = -1) const;
   double detJ (const double &xP, const double &yP, const double &zP) const;
-  bool cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-            std::vector<DI_CuttingPoint> &cp, const int polynomialOrderL,
-            std::vector<DI_Line> &subLines, int recurLevel = 0, std::map<int, double> nodeLs[2] = NULL) const;
-  void cut(const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-           std::vector<DI_Line> &subLines, std::vector<DI_CuttingPoint> &cp) const;
+  bool cut (std::vector<const gLevelset *> &LsRPN, std::vector<DI_IntegrationPoint *> &ip,
+            DI_Point::Container &cp, const int polynomialOrderL,
+            std::vector<DI_Line *> &subLines, int recurLevel = 0, double **nodeLs = NULL) const;
+  bool cut(const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+           std::vector<DI_Line *> &subLines, std::vector<DI_CuttingPoint*> &cp);
   void selfSplit (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                  std::vector<DI_Line> &subLines, std::vector<DI_CuttingPoint> &cuttingPoints) const;
+                  std::vector<DI_Line *> &subLines, std::vector<DI_CuttingPoint*> &cuttingPoints) const;
   inline double length() const {return integral_;}
 };
 
@@ -457,13 +459,13 @@ class DI_Triangle : public DI_Element
     pts_[2] = new DI_Point(x2, y2, z2);
     integral_ = surface;
   }
-  DI_Triangle (const DI_Point &pt0, const DI_Point &pt1, const DI_Point &pt2, const int tag = -1)
+  DI_Triangle (const DI_Point *pt0, const DI_Point *pt1, const DI_Point *pt2, const int tag = -1)
   {
     lsTag_ = tag;
     pts_ = new DI_Point*[3];
-    pts_[0] = new DI_Point(pt0);
-    pts_[1] = new DI_Point(pt1);
-    pts_[2] = new DI_Point(pt2);
+    pts_[0] = new DI_Point(*pt0);
+    pts_[1] = new DI_Point(*pt1);
+    pts_[2] = new DI_Point(*pt2);
     integral_ = TriSurf(pt0,pt1,pt2);
   }
   ~DI_Triangle () {
@@ -485,7 +487,7 @@ class DI_Triangle : public DI_Element
   virtual void computeIntegral();
   virtual double refIntegral() const {return 0.5;}
   virtual void getRefIntegrationPoints (const int polynomialOrder,
-                                        std::vector<DI_IntegrationPoint> &ipS) const;
+                                        std::vector<DI_IntegrationPoint *> &ipS) const;
   inline void vert(const int edge, int &s1, int &s2) const {
     int v[3][2] = {{0, 1}, {1, 2}, {2, 0}};
     s1 = v[edge][0]; s2 = v[edge][1];
@@ -502,18 +504,18 @@ class DI_Triangle : public DI_Element
   void getGradShapeFunctions (const double u, const double v, const double w,
                               double s[][3], int order = -1) const;
   double detJ (const double &xP, const double &yP, const double &zP) const;
-  bool cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-            std::vector<DI_IntegrationPoint> &ipS, std::vector<DI_CuttingPoint> &cp,
+  bool cut (std::vector<const gLevelset *> &LsRPN, std::vector<DI_IntegrationPoint *> &ip,
+            std::vector<DI_IntegrationPoint *> &ipS, DI_Point::Container &cp,
             const int polynomialOrderQ, const int polynomialOrderTr, const int polynomialOrderL,
-            std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-            std::vector<DI_Line> &surfLines, int recurLevel = 0, std::map<int, double> nodeLs[3] = NULL) const;
-  void cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-            std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-            std::vector<DI_Line> &surfLines, std::vector<DI_CuttingPoint> &cp) const;
-  void splitIntoSubTriangles (std::vector<DI_Triangle> &triangles) const;
+            std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+            std::vector<DI_Line *> &surfLines, int recurLevel = 0, double **nodeLs = NULL) const;
+  bool cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+            std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+            std::vector<DI_Line *> &surfLines, std::vector<DI_CuttingPoint*> &cp);
+  void splitIntoSubTriangles (std::vector<DI_Triangle *> &triangles) const;
   void selfSplit (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                  std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-                  std::vector<DI_Line> &surfLines, std::vector<DI_CuttingPoint> &cuttingPoints) const;
+                  std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+                  std::vector<DI_Line *> &surfLines, std::vector<DI_CuttingPoint*> &cuttingPoints) const;
   double quality () const;
   inline double surface() const {return integral_;}
 };
@@ -551,15 +553,15 @@ class DI_Quad : public DI_Element
     pts_[3] = new DI_Point(x3, y3, z3);
     integral_ = surf;
   }
-  DI_Quad (const DI_Point &pt0, const DI_Point &pt1, const DI_Point &pt2, const DI_Point &pt3,
+  DI_Quad (const DI_Point *pt0, const DI_Point *pt1, const DI_Point *pt2, const DI_Point *pt3,
            const int tag = -1)
   {
     lsTag_ = tag;
     pts_ = new DI_Point*[4];
-    pts_[0] = new DI_Point(pt0);
-    pts_[1] = new DI_Point(pt1);
-    pts_[2] = new DI_Point(pt2);
-    pts_[3] = new DI_Point(pt3);
+    pts_[0] = new DI_Point(*pt0);
+    pts_[1] = new DI_Point(*pt1);
+    pts_[2] = new DI_Point(*pt2);
+    pts_[3] = new DI_Point(*pt3);
     integral_ = TriSurf(pt0, pt1, pt2) + TriSurf(pt0, pt2, pt3);
   }
   ~DI_Quad () {
@@ -581,7 +583,7 @@ class DI_Quad : public DI_Element
   virtual void computeIntegral();
   virtual double refIntegral() const {return 4.;}
   virtual void getRefIntegrationPoints (const int polynomialOrder,
-                                        std::vector<DI_IntegrationPoint> &ipS) const;
+                                        std::vector<DI_IntegrationPoint *> &ipS) const;
   inline void vert(const int edge, int &s1, int &s2) const{
     int v[4][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}};
     s1 = v[edge][0]; s2 = v[edge][1];
@@ -600,15 +602,15 @@ class DI_Quad : public DI_Element
   void getGradShapeFunctions (const double u, const double v, const double w,
                               double s[][3], int order = -1) const;
   double detJ (const double &xP, const double &yP, const double &zP) const;
-  bool cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-            std::vector<DI_IntegrationPoint> &ipS, std::vector<DI_CuttingPoint> &cp,
+  bool cut (std::vector<const gLevelset *> &LsRPN, std::vector<DI_IntegrationPoint *> &ip,
+            std::vector<DI_IntegrationPoint *> &ipS, DI_Point::Container &cp,
             const int polynomialOrderQ, const int polynomialOrderTr, const int polynomialOrderL,
-            std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-            std::vector<DI_Line> &surfLines, int recurLevel = 0, std::map<int, double> nodeLs[4] = NULL) const;
-  void cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-            std::vector<DI_Quad> &subQuads, std::vector<DI_Triangle> &subTriangles,
-            std::vector<DI_Line> &surfLines, std::vector<DI_CuttingPoint> &cp) const;
-  void splitIntoTriangles (std::vector<DI_Triangle> &triangles) const;
+            std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+            std::vector<DI_Line *> &surfLines, int recurLevel = 0, double **nodeLs = NULL) const;
+  bool cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+            std::vector<DI_Quad *> &subQuads, std::vector<DI_Triangle *> &subTriangles,
+            std::vector<DI_Line *> &surfLines, std::vector<DI_CuttingPoint*> &cp);
+  void splitIntoTriangles (std::vector<DI_Triangle *> &triangles) const;
   inline double surface() const {return integral_;}
 };
 
@@ -647,13 +649,13 @@ class DI_Tetra : public DI_Element
     pts_[3] = new DI_Point(x3, y3, z3);
     integral_ = vol;
   }
-  DI_Tetra (const DI_Point &pt0, const DI_Point &pt1, const DI_Point &pt2, const DI_Point &pt3)
+  DI_Tetra (const DI_Point *pt0, const DI_Point *pt1, const DI_Point *pt2, const DI_Point *pt3)
   {
     pts_ = new DI_Point*[4];
-    pts_[0] = new DI_Point(pt0);
-    pts_[1] = new DI_Point(pt1);
-    pts_[2] = new DI_Point(pt2);
-    pts_[3] = new DI_Point(pt3);
+    pts_[0] = new DI_Point(*pt0);
+    pts_[1] = new DI_Point(*pt1);
+    pts_[2] = new DI_Point(*pt2);
+    pts_[3] = new DI_Point(*pt3);
     integral_ = TetraVol(pt0, pt1, pt2, pt3);
   }
   ~DI_Tetra () {
@@ -675,7 +677,7 @@ class DI_Tetra : public DI_Element
   virtual void computeIntegral();
   virtual double refIntegral() const {return 1. / 6.;}
   virtual void getRefIntegrationPoints (const int polynomialOrder,
-                                        std::vector<DI_IntegrationPoint> &ip) const;
+                                        std::vector<DI_IntegrationPoint *> &ip) const;
   inline void vert(const int edge, int &s1, int &s2) const {
     int v[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {2, 3}, {3, 1}};
     s1 = v[edge][0]; s2 = v[edge][1];
@@ -695,18 +697,18 @@ class DI_Tetra : public DI_Element
   void getGradShapeFunctions (const double u, const double v, const double w,
                               double s[][3], int order = -1) const;
   double detJ (const double &xP, const double &yP, const double &zP) const;
-  bool cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-            std::vector<DI_IntegrationPoint> &ipS, std::vector<DI_CuttingPoint> &cp,
+  bool cut (std::vector<const gLevelset *> &LsRPN, std::vector<DI_IntegrationPoint *> &ip,
+            std::vector<DI_IntegrationPoint *> &ipS, DI_Point::Container &cp,
             const int polynomialOrderT, const int polynomialOrderQ, const int polynomialOrderTr,
-            std::vector<DI_Tetra> &subTetras, std::vector<DI_Quad> &surfQuads,
-            std::vector<DI_Triangle> &surfTriangles, int recurLevel = 0, std::map<int, double> nodeLs[4] = NULL) const;
-  void cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-            std::vector<DI_Tetra> &subTetras, std::vector<DI_Quad> &surfQuads,
-            std::vector<DI_Triangle> &surfTriangles, std::vector<DI_CuttingPoint> &cp,
-            std::vector<DI_QualError> &QE) const;
+            std::vector<DI_Tetra *> &subTetras, std::vector<DI_Quad *> &surfQuads,
+            std::vector<DI_Triangle *> &surfTriangles, int recurLevel = 0, double **nodeLs = NULL) const;
+  bool cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+            std::vector<DI_Tetra *> &subTetras, std::vector<DI_Quad *> &surfQuads,
+            std::vector<DI_Triangle *> &surfTriangles, std::vector<DI_CuttingPoint*> &cp,
+            std::vector<DI_QualError *> &QE);
   void selfSplit ( const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-                   std::vector<DI_Tetra> &subTetras, std::vector<DI_Triangle> &surfTriangles,
-                   std::vector<DI_CuttingPoint> &cuttingPoints, std::vector<DI_QualError> &QE) const;
+                   std::vector<DI_Tetra *> &subTetras, std::vector<DI_Triangle *> &surfTriangles,
+                   std::vector<DI_CuttingPoint*> &cuttingPoints, std::vector<DI_QualError *> &QE) const;
   double quality () const;
   inline double volume() const {return integral_;}
 };
@@ -759,13 +761,13 @@ class DI_Hexa : public DI_Element
     pts_[6] = new DI_Point(x6, y6, z6); pts_[7] = new DI_Point(x7, y7, z7);
     integral_ = vol;
   }
-  DI_Hexa (const DI_Point &pt0, const DI_Point &pt1, const DI_Point &pt2, const DI_Point &pt3,
-           const DI_Point &pt4, const DI_Point &pt5, const DI_Point &pt6, const DI_Point &pt7) {
+  DI_Hexa (const DI_Point *pt0, const DI_Point *pt1, const DI_Point *pt2, const DI_Point *pt3,
+           const DI_Point *pt4, const DI_Point *pt5, const DI_Point *pt6, const DI_Point *pt7) {
     pts_ = new DI_Point*[8];
-    pts_[0] = new DI_Point(pt0);    pts_[1] = new DI_Point(pt1);
-    pts_[2] = new DI_Point(pt2);    pts_[3] = new DI_Point(pt3);
-    pts_[4] = new DI_Point(pt4);    pts_[5] = new DI_Point(pt5);
-    pts_[6] = new DI_Point(pt6);    pts_[7] = new DI_Point(pt7);
+    pts_[0] = new DI_Point(*pt0);    pts_[1] = new DI_Point(*pt1);
+    pts_[2] = new DI_Point(*pt2);    pts_[3] = new DI_Point(*pt3);
+    pts_[4] = new DI_Point(*pt4);    pts_[5] = new DI_Point(*pt5);
+    pts_[6] = new DI_Point(*pt6);    pts_[7] = new DI_Point(*pt7);
     integral_ = TetraVol(pt0, pt1, pt3, pt4) + TetraVol(pt1, pt4, pt5, pt7) +
                 TetraVol(pt1, pt3, pt4, pt7) + TetraVol(pt2, pt5, pt6, pt7) +
                 TetraVol(pt1, pt2, pt3, pt7) + TetraVol(pt1, pt5, pt2, pt7);
@@ -789,7 +791,7 @@ class DI_Hexa : public DI_Element
   virtual void computeIntegral();
   virtual double refIntegral() const {return 8.;}
   virtual void getRefIntegrationPoints (const int polynomialOrder,
-                                        std::vector<DI_IntegrationPoint> &ip) const;
+                                        std::vector<DI_IntegrationPoint *> &ip) const;
   inline void vert(const int edge, int &s1, int &s2) const {
     int v[12][2] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}, {0, 4}, {1, 5},
                     {2, 6}, {3, 7}, {4, 5}, {5, 6}, {6, 7}, {7, 4}};
@@ -824,18 +826,18 @@ class DI_Hexa : public DI_Element
   void getGradShapeFunctions (const double u, const double v, const double w,
                               double s[][3], int order = -1) const;
   double detJ (const double &xP, const double &yP, const double &zP) const;
-  bool cut (const gLevelset &Ls, std::vector<DI_IntegrationPoint> &ip,
-            std::vector<DI_IntegrationPoint> &ipS, std::vector<DI_CuttingPoint> &cp,
+  bool cut (std::vector<const gLevelset *> &LsRPN, std::vector<DI_IntegrationPoint *> &ip,
+            std::vector<DI_IntegrationPoint *> &ipS, DI_Point::Container &cp,
             const int polynomialOrderH, const int polynomialOrderT,
             const int polynomialOrderQ, const int polynomialOrderTr,
-            std::vector<DI_Hexa> &notCutHexas, std::vector<DI_Tetra> &subTetras,
-            std::vector<DI_Quad> &surfQuads, std::vector<DI_Triangle> &surfTriangles,
-            std::vector<DI_Line> &frontLines, int recurLevel = 0, std::map<int, double> nodeLs[8] = NULL) const;
-  void cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
-            std::vector<DI_Hexa> &unCutHexas, std::vector<DI_Tetra> &subTetras,
-            std::vector<DI_Quad> &surfQuads, std::vector<DI_Triangle> &surfTriangles,
-            std::vector<DI_CuttingPoint> &cp, std::vector<DI_QualError> &QE) const;
-  void splitIntoTetras(std::vector<DI_Tetra> &tetras) const;
+            std::vector<DI_Hexa *> &notCutHexas, std::vector<DI_Tetra *> &subTetras,
+            std::vector<DI_Quad *> &surfQuads, std::vector<DI_Triangle *> &surfTriangles,
+            std::vector<DI_Line *> &frontLines, int recurLevel = 0, double **nodeLs = NULL) const;
+  bool cut (const DI_Element *e, const std::vector<const gLevelset *> &RPNi,
+            std::vector<DI_Hexa *> &unCutHexas, std::vector<DI_Tetra *> &subTetras,
+            std::vector<DI_Quad *> &surfQuads, std::vector<DI_Triangle *> &surfTriangles,
+            std::vector<DI_CuttingPoint*> &cp, std::vector<DI_QualError *> &QE);
+  void splitIntoTetras(std::vector<DI_Tetra *> &tetras) const;
   inline double volume() const {return integral_;}
 };
 
@@ -845,21 +847,31 @@ class DI_Hexa : public DI_Element
 // -------------------------------------------------------------------------------------------------
 class DI_QualError
 {
-  DI_Point p11_, p12_, p21_, p22_;
+  DI_Point **pts_;
 public:
-  DI_QualError (DI_Point p11, DI_Point p12, DI_Point p21, DI_Point p22)
-    : p11_(p11), p12_(p12), p21_(p21), p22_(p22) {}
-  inline DI_Point pt (int i) const {
-    if(i == 0) return p11_;
-    if(i == 1) return p21_;
-    if(i == 2) return p12_;
-    if(i == 3) return p22_;
+  DI_QualError (DI_Point *p11, DI_Point *p12, DI_Point *p21, DI_Point *p22) {
+    pts_ = new DI_Point*[4];
+    pts_[0] = new DI_Point(*p11);
+    pts_[1] = new DI_Point(*p12);
+    pts_[2] = new DI_Point(*p21);
+    pts_[3] = new DI_Point(*p22);
+  }
+  ~DI_QualError () {
+    for(int i = 0; i < 4; i++)
+      delete pts_[i];
+    if(pts_) delete[] pts_;
+  }
+  inline DI_Point* pt (int i) const {
+    if(i == 0) return pts_[0];
+    if(i == 1) return pts_[1];
+    if(i == 2) return pts_[2];
+    if(i == 3) return pts_[3];
     printf("DI_QualError::pt only accept indices from 0 to 3!\n");
-    DI_Point p; return p;
+    DI_Point* p = NULL; return p;
   }
   void print(const DI_Element *e) const{
-    DI_Point pt1 = p11_, pt2 = p12_, pt3 = p21_, pt4 = p22_;
-    e->mappingP(pt1); e->mappingP(pt2); e->mappingP(pt3); e->mappingP(pt4);
+    DI_Point pt1(*pts_[0]), pt2(*pts_[1]), pt3(*pts_[2]), pt4(*pts_[3]);
+    e->mappingP(&pt1); e->mappingP(&pt2); e->mappingP(&pt3); e->mappingP(&pt4);
     printf("Cannot assert best quality for the last face of the Prism \n");
     printf("=> edges (%g,%g,%g),(%g,%g,%g) and (%g,%g,%g),(%g,%g,%g) may cross in ",
     pt1.x(), pt1.y(), pt1.z(), pt2.x(), pt2.y(), pt2.z(),
diff --git a/contrib/DiscreteIntegration/recurCut.cpp b/contrib/DiscreteIntegration/recurCut.cpp
index a54f06376d..aeb6a80c4e 100644
--- a/contrib/DiscreteIntegration/recurCut.cpp
+++ b/contrib/DiscreteIntegration/recurCut.cpp
@@ -3,8 +3,8 @@
 
 #include "recurCut.h"
 
-inline DI_Point middle (const DI_Point &p1, const DI_Point &p2) {
-  return DI_Point ((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2, (p1.z() + p2.z()) / 2);
+inline DI_Point* middle (const DI_Point *p1, const DI_Point *p2) {
+  return new DI_Point ((p1->x() + p2->x()) / 2, (p1->y() + p2->y()) / 2, (p1->z() + p2->z()) / 2);
 }
 
 // create sub-elements recursively (according to a pattern) until maxlevel
@@ -14,187 +14,241 @@ void recurCut(RecurElement *re, int maxlevel, int level)
 
   if(re->type() == DI_LIN) {
     // p1 p12 p2
-    DI_Point p1 = re->el->pt(0);
-    DI_Point p2 = re->el->pt(1);
-    DI_Point p12 = middle(p1, p2);
-    RecurElement *re0 = new RecurElement(&DI_Line(p1, p12));
+    DI_Point* p1 = re->el->pt(0);
+    DI_Point* p2 = re->el->pt(1);
+    DI_Point* p12 = middle(p1, p2);
+    DI_Line *l0 = new DI_Line(p1, p12);
+    RecurElement *re0 = new RecurElement(l0);
     recurCut(re0, maxlevel, level);
     re->sub[0] = re0; re0->super = re;
-    RecurElement *re1 = new RecurElement(&DI_Line(p12, p2));
+    DI_Line *l1 = new DI_Line(p12, p2);
+    RecurElement *re1 = new RecurElement(l1);
     recurCut(re1, maxlevel, level);
     re->sub[1] = re1; re1->super = re;
+    delete p12;
+    delete l0; delete l1;
   }
   if(re->type() == DI_TRI) {
     // p3
     // p13   p23
     // p1    p12    p2
-    DI_Point p1 = re->el->pt(0);
-    DI_Point p2 = re->el->pt(1);
-    DI_Point p3 = re->el->pt(2);
-    DI_Point p12 = middle(p1, p2);
-    DI_Point p13 = middle(p1, p3);
-    DI_Point p23 = middle(p2, p3);
-    RecurElement *re0 = new RecurElement(&DI_Triangle(p1, p12, p13));
+    DI_Point *p1 = re->el->pt(0);
+    DI_Point *p2 = re->el->pt(1);
+    DI_Point *p3 = re->el->pt(2);
+    DI_Point *p12 = middle(p1, p2);
+    DI_Point *p13 = middle(p1, p3);
+    DI_Point *p23 = middle(p2, p3);
+    DI_Triangle *t0 = new DI_Triangle(p1, p12, p13);
+    RecurElement *re0 = new RecurElement(t0);
     recurCut(re0, maxlevel, level);
     re->sub[0] = re0; re0->super = re;
-    RecurElement *re1 = new RecurElement(&DI_Triangle(p2, p23, p12));
+    DI_Triangle *t1 = new DI_Triangle(p2, p23, p12);
+    RecurElement *re1 = new RecurElement(t1);
     recurCut(re1, maxlevel, level);
     re->sub[1] = re1; re1->super = re;
-    RecurElement *re2 = new RecurElement(&DI_Triangle(p3, p13, p23));
+    DI_Triangle *t2 = new DI_Triangle(p3, p13, p23);
+    RecurElement *re2 = new RecurElement(t2);
     recurCut(re2, maxlevel, level);
     re->sub[2] = re2; re2->super = re;
-    RecurElement *re3 = new RecurElement(&DI_Triangle(p12, p23, p13));
+    DI_Triangle *t3 = new DI_Triangle(p12, p23, p13);
+    RecurElement *re3 = new RecurElement(t3);
     recurCut(re3, maxlevel, level);
     re->sub[3] = re3; re3->super = re;
+    delete p12; delete p13; delete p23;
+    delete t0; delete t1; delete t2; delete t3;
   }
   else if(re->type() == DI_QUA) {
     // p4    p34    p3
     // p14   p1234  p23
     // p1    p12    p2
-    DI_Point p1 = re->el->pt(0);
-    DI_Point p2 = re->el->pt(1);
-    DI_Point p3 = re->el->pt(2);
-    DI_Point p4 = re->el->pt(3);
-    DI_Point p12 = middle(p1, p2);
-    DI_Point p23 = middle(p2, p3);
-    DI_Point p34 = middle(p3, p4);
-    DI_Point p14 = middle(p1, p4);
-    DI_Point p1234 = middle(p12, p34);
-    RecurElement *re0 = new RecurElement(&DI_Quad(p1, p12, p1234, p14));
+    DI_Point *p1 = re->el->pt(0);
+    DI_Point *p2 = re->el->pt(1);
+    DI_Point *p3 = re->el->pt(2);
+    DI_Point *p4 = re->el->pt(3);
+    DI_Point *p12 = middle(p1, p2);
+    DI_Point *p23 = middle(p2, p3);
+    DI_Point *p34 = middle(p3, p4);
+    DI_Point *p14 = middle(p1, p4);
+    DI_Point *p1234 = middle(p12, p34);
+    DI_Quad *q0 = new DI_Quad(p1, p12, p1234, p14);
+    RecurElement *re0 = new RecurElement(q0);
     recurCut(re0, maxlevel, level);
     re->sub[0] = re0; re0->super = re;
-    RecurElement *re1 = new RecurElement(&DI_Quad(p12, p2, p23, p1234));
+    DI_Quad *q1 = new DI_Quad(p12, p2, p23, p1234);
+    RecurElement *re1 = new RecurElement(q1);
     recurCut(re1, maxlevel, level);
     re->sub[1] = re1; re1->super = re;
-    RecurElement *re2 = new RecurElement(&DI_Quad(p1234, p23, p3, p34));
+    DI_Quad *q2 = new DI_Quad(p1234, p23, p3, p34);
+    RecurElement *re2 = new RecurElement(q2);
     recurCut(re2, maxlevel, level);
     re->sub[2] = re2; re2->super = re;
-    RecurElement *re3 = new RecurElement(&DI_Quad(p14, p1234, p34, p4));
+    DI_Quad *q3 = new DI_Quad(p14, p1234, p34, p4);
+    RecurElement *re3 = new RecurElement(q3);
     recurCut(re3, maxlevel, level);
     re->sub[3] = re3; re3->super = re;
+    delete p12; delete p23; delete p34;
+    delete p14; delete p1234;
+    delete q0; delete q1; delete q2; delete q3;
   }
   else if(re->type() == DI_TET) {
-    DI_Point p1 = re->el->pt(0);
-    DI_Point p2 = re->el->pt(1);
-    DI_Point p3 = re->el->pt(2);
-    DI_Point p4 = re->el->pt(3);
-    DI_Point p12 = middle(p1, p2);
-    DI_Point p13 = middle(p1, p3);
-    DI_Point p14 = middle(p1, p4);
-    DI_Point p23 = middle(p2, p3);
-    DI_Point p24 = middle(p2, p4);
-    DI_Point p34 = middle(p3, p4);
-    RecurElement *re0 = new RecurElement(&DI_Tetra(p1, p12, p13, p14));
+    //       p4
+    //       p14   p34
+    //   p24 p1    p13    p3
+    //    p12   p23
+    // p2
+    DI_Point *p1 = re->el->pt(0);
+    DI_Point *p2 = re->el->pt(1);
+    DI_Point *p3 = re->el->pt(2);
+    DI_Point *p4 = re->el->pt(3);
+    DI_Point *p12 = middle(p1, p2);
+    DI_Point *p13 = middle(p1, p3);
+    DI_Point *p14 = middle(p1, p4);
+    DI_Point *p23 = middle(p2, p3);
+    DI_Point *p24 = middle(p2, p4);
+    DI_Point *p34 = middle(p3, p4);
+    DI_Tetra *t0 = new DI_Tetra(p1, p12, p13, p14);
+    RecurElement *re0 = new RecurElement(t0);
     recurCut(re0, maxlevel, level);
     re->sub[0] = re0; re0->super = re;
-    RecurElement *re1 = new RecurElement(&DI_Tetra(p2, p23, p12, p24));
+    DI_Tetra *t1 = new DI_Tetra(p2, p23, p12, p24);
+    RecurElement *re1 = new RecurElement(t1);
     recurCut(re1, maxlevel, level);
     re->sub[1] = re1; re1->super = re;
-    RecurElement *re2 = new RecurElement(&DI_Tetra(p3, p13, p23, p34));
+    DI_Tetra *t2 = new DI_Tetra(p3, p13, p23, p34);
+    RecurElement *re2 = new RecurElement(t2);
     recurCut(re2, maxlevel, level);
     re->sub[2] = re2; re2->super = re;
-    RecurElement *re3 = new RecurElement(&DI_Tetra(p4, p14, p34, p24));
+    DI_Tetra *t3 = new DI_Tetra(p4, p14, p34, p24);
+    RecurElement *re3 = new RecurElement(t3);
     recurCut(re3, maxlevel, level);
     re->sub[3] = re3; re3->super = re;
-    RecurElement *re4 = new RecurElement(&DI_Tetra(p12, p14, p24, p34));
+    DI_Tetra *t4 = new DI_Tetra(p12, p14, p24, p34);
+    RecurElement *re4 = new RecurElement(t4);
     recurCut(re4, maxlevel, level);
     re->sub[4] = re4; re4->super = re;
-    RecurElement *re5 = new RecurElement(&DI_Tetra(p12, p23, p34, p24));
+    DI_Tetra *t5 = new DI_Tetra(p12, p23, p34, p24);
+    RecurElement *re5 = new RecurElement(t5);
     recurCut(re5, maxlevel, level);
     re->sub[5] = re5; re5->super = re;
-    RecurElement *re6 = new RecurElement(&DI_Tetra(p12, p13, p34, p23));
+    DI_Tetra *t6 = new DI_Tetra(p12, p13, p34, p23);
+    RecurElement *re6 = new RecurElement(t6);
     recurCut(re6, maxlevel, level);
     re->sub[6] = re6; re6->super = re;
-    RecurElement *re7 = new RecurElement(&DI_Tetra(p12, p13, p14, p34));
+    DI_Tetra *t7 = new DI_Tetra(p12, p13, p14, p34);
+    RecurElement *re7 = new RecurElement(t7);
     recurCut(re7, maxlevel, level);
     re->sub[7] = re7; re7->super = re;
+    delete p12; delete p13; delete p14;
+    delete p23; delete p24; delete p34;
+    delete t0; delete t1; delete t2; delete t3;
+    delete t4; delete t5; delete t6; delete t7;
   }
   else if(re->type() == DI_HEX) {
-    DI_Point p1 = re->el->pt(0);
-    DI_Point p2 = re->el->pt(1);
-    DI_Point p3 = re->el->pt(2);
-    DI_Point p4 = re->el->pt(3);
-    DI_Point p5 = re->el->pt(4);
-    DI_Point p6 = re->el->pt(5);
-    DI_Point p7 = re->el->pt(6);
-    DI_Point p8 = re->el->pt(7);
-    DI_Point p12 = middle(p1, p2);
-    DI_Point p14 = middle(p1, p4);
-    DI_Point p15 = middle(p1, p5);
-    DI_Point p23 = middle(p2, p3);
-    DI_Point p26 = middle(p2, p6);
-    DI_Point p34 = middle(p3, p4);
-    DI_Point p37 = middle(p3, p7);
-    DI_Point p48 = middle(p4, p8);
-    DI_Point p56 = middle(p5, p6);
-    DI_Point p58 = middle(p5, p8);
-    DI_Point p67 = middle(p6, p7);
-    DI_Point p78 = middle(p7, p8);
-    DI_Point p1234 = middle(p12, p34);
-    DI_Point p1256 = middle(p12, p56);
-    DI_Point p1458 = middle(p14, p58);
-    DI_Point p2367 = middle(p23, p67);
-    DI_Point p3478 = middle(p34, p78);
-    DI_Point p5678 = middle(p56, p78);
-    DI_Point p12345678 = middle(p1234, p5678);
-    RecurElement *re0 = new RecurElement(&DI_Hexa(p1, p12, p1234, p14, p15, p1256, p12345678, p1458));
+    DI_Point *p1 = re->el->pt(0);
+    DI_Point *p2 = re->el->pt(1);
+    DI_Point *p3 = re->el->pt(2);
+    DI_Point *p4 = re->el->pt(3);
+    DI_Point *p5 = re->el->pt(4);
+    DI_Point *p6 = re->el->pt(5);
+    DI_Point *p7 = re->el->pt(6);
+    DI_Point *p8 = re->el->pt(7);
+    DI_Point *p12 = middle(p1, p2);
+    DI_Point *p14 = middle(p1, p4);
+    DI_Point *p15 = middle(p1, p5);
+    DI_Point *p23 = middle(p2, p3);
+    DI_Point *p26 = middle(p2, p6);
+    DI_Point *p34 = middle(p3, p4);
+    DI_Point *p37 = middle(p3, p7);
+    DI_Point *p48 = middle(p4, p8);
+    DI_Point *p56 = middle(p5, p6);
+    DI_Point *p58 = middle(p5, p8);
+    DI_Point *p67 = middle(p6, p7);
+    DI_Point *p78 = middle(p7, p8);
+    DI_Point *p1234 = middle(p12, p34);
+    DI_Point *p1256 = middle(p12, p56);
+    DI_Point *p1458 = middle(p14, p58);
+    DI_Point *p2367 = middle(p23, p67);
+    DI_Point *p3478 = middle(p34, p78);
+    DI_Point *p5678 = middle(p56, p78);
+    DI_Point *p12345678 = middle(p1234, p5678);
+    DI_Hexa *h0 = new DI_Hexa(p1, p12, p1234, p14, p15, p1256, p12345678, p1458);
+    RecurElement *re0 = new RecurElement(h0);
     recurCut(re0, maxlevel, level);
     re->sub[0] = re0; re0->super = re;
-    RecurElement *re1 = new RecurElement(&DI_Hexa(p12, p2, p23, p1234, p1256, p26, p2367, p12345678));
+    DI_Hexa *h1 = new DI_Hexa(p12, p2, p23, p1234, p1256, p26, p2367, p12345678);
+    RecurElement *re1 = new RecurElement(h1);
     recurCut(re1, maxlevel, level);
     re->sub[1] = re1; re1->super = re;
-    RecurElement *re2 = new RecurElement(&DI_Hexa(p1234, p23, p3, p34, p12345678, p2367, p37, p3478));
+    DI_Hexa *h2 = new DI_Hexa(p1234, p23, p3, p34, p12345678, p2367, p37, p3478);
+    RecurElement *re2 = new RecurElement(h2);
     recurCut(re2, maxlevel, level);
     re->sub[2] = re2; re2->super = re;
-    RecurElement *re3 = new RecurElement(&DI_Hexa(p14, p1234, p34, p4, p1458, p12345678, p3478, p48));
+    DI_Hexa *h3 = new DI_Hexa(p14, p1234, p34, p4, p1458, p12345678, p3478, p48);
+    RecurElement *re3 = new RecurElement(h3);
     recurCut(re3, maxlevel, level);
     re->sub[3] = re3; re3->super = re;
-    RecurElement *re4 = new RecurElement(&DI_Hexa(p15, p1256, p12345678, p1458, p5, p56, p5678, p58));
+    DI_Hexa *h4 = new DI_Hexa(p15, p1256, p12345678, p1458, p5, p56, p5678, p58);
+    RecurElement *re4 = new RecurElement(h4);
     recurCut(re4, maxlevel, level);
     re->sub[4] = re4; re4->super = re;
-    RecurElement *re5 = new RecurElement(&DI_Hexa(p1256, p26, p2367, p12345678, p56, p6, p67, p5678));
+    DI_Hexa *h5 = new DI_Hexa(p1256, p26, p2367, p12345678, p56, p6, p67, p5678);
+    RecurElement *re5 = new RecurElement(h5);
     recurCut(re5, maxlevel, level);
     re->sub[5] = re5; re5->super = re;
-    RecurElement *re6 = new RecurElement(&DI_Hexa(p12345678, p2367, p37, p3478, p5678, p67, p7, p78));
+    DI_Hexa *h6 = new DI_Hexa(p12345678, p2367, p37, p3478, p5678, p67, p7, p78);
+    RecurElement *re6 = new RecurElement(h6);
     recurCut(re6, maxlevel, level);
     re->sub[6] = re6; re6->super = re;
-    RecurElement *re7 = new RecurElement(&DI_Hexa(p1458, p12345678, p3478, p48, p58, p5678, p78, p8));
+    DI_Hexa *h7 = new DI_Hexa(p1458, p12345678, p3478, p48, p58, p5678, p78, p8);
+    RecurElement *re7 = new RecurElement(h7);
     recurCut(re7, maxlevel, level);
     re->sub[7] = re7; re7->super = re;
+    delete p12; delete p14; delete p15;
+    delete p23; delete p26; delete p34;
+    delete p37; delete p48; delete p56;
+    delete p58; delete p67; delete p78;
+    delete p1234; delete p1256;
+    delete p1458; delete p2367;
+    delete p3478; delete p5678;
+    delete p12345678;
+    delete h0; delete h1; delete h2; delete h3;
+    delete h4; delete h5; delete h6; delete h7;
   }
 }
 
 // return true if the element re->el is crossed or run along by a primitive levelset in RPN and by the final levelset
 // (the levelset is computed with the values at the nodes of the element e)
 bool signChange (RecurElement *re, const DI_Element *e, const std::vector<const gLevelset *> &RPN,
-                 std::map<int, double> nodeLs[8]) {
+                 double **nodeLs) {
   bool cS = false;
   DI_Element* elem = re->root()->el;
-  std::vector<DI_CuttingPoint> cp;
+  std::vector<DI_CuttingPoint *> cp;
   std::vector<const gLevelset *> RPNi;
   for(unsigned int l = 0; l < RPN.size(); l++) {
     const gLevelset *Lsi = RPN[l];
     RPNi.push_back(Lsi);
     if(Lsi->isPrimitive()) {
-      elem->addLs(e, *Lsi, nodeLs);
+      elem->addLs(e, Lsi, l, nodeLs);
       for(unsigned int i = 0; i < cp.size(); i++)
-        cp[i].addLs(elem);
+        cp[i]->addLs(elem);
       if (re->super) re->el->addLs(elem);
       re->el->getCuttingPoints(elem, RPNi, cp);
     }
     else {
       for(unsigned int p = 0; p < cp.size(); p++)
-        cp[p].chooseLs(Lsi);
+        cp[p]->chooseLs(Lsi);
       if (re->super) re->el->chooseLs(Lsi);
     }
   }
-  re->el->clearLs();
   re->root()->el->clearLs();
+  if(re->super) re->el->clearLs();
 
   if(cp.size() > 1 || (re->type() == DI_LIN && cp.size() > 0)) {
     for(int i = 0; i < (int)cp.size(); i++)
-      if(cp[i].ls() == 0) {cS = true; break;}
+      if(cp[i]->ls() == 0) {cS = true; break;}
   }
+  for(int i = 0; i < (int)cp.size(); i++)
+    delete cp[i];
   return cS;
 }
 
@@ -202,7 +256,7 @@ bool signChange (RecurElement *re, const DI_Element *e, const std::vector<const
 // If it has no sub RecurElement, set isCrossed to true if the element is crossed or run along by the levelset
 //(the levelset is computed with the values at the nodes of the triangle e)
 bool computeIsCrossed (RecurElement *re, const DI_Element *e, const std::vector<const gLevelset *> &RPN,
-                       std::map<int, double> nodeLs[8]) {
+                       double **nodeLs) {
   if (!re->sub[0])
     re->isCrossed = signChange(re, e, RPN, nodeLs);
   else {
@@ -236,20 +290,18 @@ void recurChangeVisibility(RecurElement *re, const std::vector<const gLevelset *
   }
   else {
     re->el->printls();
-    double v = re->Ls();
+    double v = re->ls();
     double vm = 0.;
     if(!re->sub[0]->sub[0]) {
       for(int i = 0; i < re->nbSub(); i++){
-        re->sub[i]->el->printls();
-        vm += re->sub[i]->Ls();
+        vm += re->sub[i]->ls();
       }
       vm = vm / re->nbSub();
     }
     else {
       for(int i = 0; i < re->nbSub(); i++){
         for(int j = 0; j < re->sub[0]->nbSub(); j++){
-          re->sub[i]->sub[j]->el->printls();
-          vm += re->sub[i]->sub[j]->Ls();
+          vm += re->sub[i]->sub[j]->ls();
         }
       }
       vm = vm / (re->nbSub()*re->sub[0]->nbSub());
@@ -260,7 +312,6 @@ void recurChangeVisibility(RecurElement *re, const std::vector<const gLevelset *
       for(int i = 0; i < re->nbSub(); i++)
         recurChangeVisibility(re->sub[i], RPN, TOL);
     }
-    printf("v=%g vm=%g vis=%d \n",v,vm,re->visible);
   }
 }
 
@@ -310,6 +361,7 @@ RecurElement::~RecurElement ()
 {
   for(int i = 0; i < nbSub(); i++)
     if(sub[i]) delete sub[i];
+  delete [] sub;
   if(el) delete el;
 }
 
@@ -337,7 +389,7 @@ RecurElement* RecurElement::root()
   return this;
 }
 
-double RecurElement::Ls() const
+double RecurElement::ls() const
 {
   double Tot = 0;
   for(int i = 0; i < nbVert(); i++)
@@ -345,292 +397,20 @@ double RecurElement::Ls() const
   return Tot / nbVert();
 }
 
-bool RecurElement::cut(int maxlevel, const DI_Element *e, const gLevelset &LS, double TOL,
-                       std::map<int, double> nodeLs[8])
+bool RecurElement::cut(int maxlevel, const DI_Element *e, std::vector<const gLevelset *> &LsRPN,
+                       double TOL, double **nodeLs)
 {
-  std::vector<const gLevelset *> RPN;
-  LS.getRPN(RPN);
   recurCut(this, maxlevel, 0);
-  bool iC = computeIsCrossed(root(), e, RPN, nodeLs);
+  bool iC = computeIsCrossed(root(), e, LsRPN, nodeLs);
   if(TOL < 0.)
     recurChangeVisibility(root());
   else {
-    root()->el->addLs(e, LS);
+    root()->el->addLs(e, LsRPN.back());
     recurAddLs(root());
-    recurChangeVisibility(root(), RPN, TOL);
+    recurChangeVisibility(root(), LsRPN, TOL);
     recurClearLs(root());
   }
   return iC;
 }
 
-
-/*
-//----------------------------------------------------------------------------------------------
-
-
-
-// create sub-triangles recursively (according to a 4-sub-triangles pattern) until maxlevel
-void recurCut(RecurTriangle *t, int maxlevel, int level)
-{
-  if(level++ >= maxlevel) return;
-
-  // p3
-  // p13   p23
-  // p1    p12    p2
-  DI_Point p1 = t->tri->pt(0);
-  DI_Point p2 = t->tri->pt(1);
-  DI_Point p3 = t->tri->pt(2);
-  DI_Point p12 ((p1.x()+p2.x())*0.5,(p1.y()+p2.y())*0.5,(p1.z()+p2.z())*0.5);
-  DI_Point p13 ((p1.x()+p3.x())*0.5,(p1.y()+p3.y())*0.5,(p1.z()+p3.z())*0.5);
-  DI_Point p23 ((p2.x()+p3.x())*0.5,(p2.y()+p3.y())*0.5,(p2.z()+p3.z())*0.5);
-  RecurTriangle *tr1 = new RecurTriangle(DI_Triangle(p1,p12,p13));
-  recurCut(tr1, maxlevel, level);
-  RecurTriangle *tr2 = new RecurTriangle(DI_Triangle(p2,p23,p12));
-  recurCut(tr2, maxlevel, level);
-  RecurTriangle *tr3 = new RecurTriangle(DI_Triangle(p3,p13,p23));
-  recurCut(tr3, maxlevel, level);
-  RecurTriangle *tr4 = new RecurTriangle(DI_Triangle(p12,p23,p13));
-  recurCut(tr4, maxlevel, level);
-  tr1->super = t;
-  tr2->super = t;
-  tr3->super = t;
-  tr4->super = t;
-  t->sub[0] = tr1;
-  t->sub[1] = tr2;
-  t->sub[2] = tr3;
-  t->sub[3] = tr4;
-}
-
-// return true if the triangle t->tri is crossed or run along by a primitive levelset in RPN and by the final levelset
-// (the levelset is computed with the values at the nodes of the triangle e)
-bool signChange (RecurTriangle *t, const DI_Triangle *e, const std::vector<const gLevelset *> RPN) {
-  bool cS=false;
-  std::vector<const gLevelset *> RPNi;
-  DI_Triangle tt(*(t->root()->tri));
-  std::vector<DI_CuttingPoint> cp;
-  for(int l=0;l<(int)RPN.size();l++) {
-    const gLevelset *Lsi = RPN[l];
-    RPNi.push_back(Lsi);
-    if(Lsi->isPrimitive()) {
-      tt.computeLs(e,*Lsi);
-      for(int i=0;i<(int)cp.size();i++)
-        cp[i].addLs(&tt);
-      t->tri->addLs(&tt);
-      t->tri->getCuttingPoints(&tt,RPNi,cp);
-    }
-    else {
-      for(int p=0;p<(int)cp.size();p++)
-        cp[p].chooseLs(Lsi);
-      t->tri->chooseLs(Lsi);
-    }
-  }
-  if(cp.size()>1) {
-    for(int i=0;i<(int)cp.size();i++)
-      if(cp[i].ls()==0) {cS=true; break;}
-  }
-  t->tri->clearLs();
-  return cS;
-}
-
-// Set isCrossed to true if a sub RecurTriangle is crossed. 
-// If it has no sub RecurTriangle, set isCrossed to true if the triangle is crossed or run along by the levelset
-//(the levelset is computed with the values at the nodes of the triangle e)
-bool computeIsCrossed (RecurTriangle *t, const DI_Triangle *e, const std::vector<const gLevelset *> RPN) {
-  if (t->sub[0]==NULL)
-    t->isCrossed = signChange(t,e,RPN);
-  else {
-    bool iC0 = computeIsCrossed(t->sub[0],e,RPN);
-    bool iC1 = computeIsCrossed(t->sub[1],e,RPN);
-    bool iC2 = computeIsCrossed(t->sub[2],e,RPN);
-    bool iC3 = computeIsCrossed(t->sub[3],e,RPN);
-    t->isCrossed = (iC0 || iC1 || iC2 || iC3);
-  }
-  return t->isCrossed;
-}
-
-// Recursively set the visibility to true if the RecurTriangle is crossed and has no sub recurTriangle
-// or if the RecurTriangle is not crossed and the super RecurTriangle is crossed.
-void changeVisibility(RecurTriangle *t){
-  bool superIC = true;
-  if(t->super)
-    superIC = t->super->isCrossed;
-  if((t->isCrossed && t->sub[0]==NULL) || (!t->isCrossed && superIC))
-    t->setVisibility(true);
-
-  if(t->sub[0]){
-    changeVisibility(t->sub[0]);
-    changeVisibility(t->sub[1]);
-    changeVisibility(t->sub[2]);
-    changeVisibility(t->sub[3]);
-  }
-}
-
-RecurTriangle* RecurTriangle::root()
-{
-  if(super) return super->root();
-  return this;
-}
-
-bool RecurTriangle::cut(int maxlevel, const DI_Triangle *e, const std::vector<const gLevelset *> RPN, double TOL)
-{
-  recurCut(this, maxlevel, 0);
-  bool iC=false;
-  if(TOL<0.){
-    iC = computeIsCrossed(root(),e,RPN);
-    changeVisibility(root());
-  }
-  else{
-    iC = computeIsCrossed(root(),e,RPN);
-    changeVisibility(root());
-  }
-  return iC;
-}
-
-void RecurTriangle::pushTriangles (std::vector<DI_Triangle> &vT)
-{
-  if(visible)
-    vT.push_back(DI_Triangle(*tri));
-  if(sub[0]){
-    sub[0]->pushTriangles(vT);
-    sub[1]->pushTriangles(vT);
-    sub[2]->pushTriangles(vT);
-    sub[3]->pushTriangles(vT);
-  }
-}
-
-//----------------------------------------------------------------------------------------------
-
-// create sub-quads recursively (according to a 4-sub-quads pattern) until maxlevel
-void recurCut(RecurQuad *q, int maxlevel, int level)
-{
-  if(level++ >= maxlevel) return;
-
-  // p4    p34    p3
-  // p14   p1234  p23
-  // p1    p12    p2
-  DI_Point p1 = q->quad->pt(0);
-  DI_Point p2 = q->quad->pt(1);
-  DI_Point p3 = q->quad->pt(2);
-  DI_Point p4 = q->quad->pt(3);
-  DI_Point p12 ((p1.x()+p2.x())*0.5,(p1.y()+p2.y())*0.5,(p1.z()+p2.z())*0.5);
-  DI_Point p23 ((p2.x()+p3.x())*0.5,(p2.y()+p3.y())*0.5,(p2.z()+p3.z())*0.5);
-  DI_Point p34 ((p3.x()+p4.x())*0.5,(p3.y()+p4.y())*0.5,(p3.z()+p4.z())*0.5);
-  DI_Point p14 ((p1.x()+p4.x())*0.5,(p1.y()+p4.y())*0.5,(p1.z()+p4.z())*0.5);
-  DI_Point p1234 ((p12.x()+p34.x())*0.5,(p12.y()+p34.y())*0.5,(p12.z()+p34.z())*0.5);
-  RecurQuad *q1 = new RecurQuad(DI_Quad(p1,p12,p1234,p14));
-  recurCut(q1, maxlevel, level);
-  RecurQuad *q2 = new RecurQuad(DI_Quad(p12,p2,p23,p1234));
-  recurCut(q2, maxlevel, level);
-  RecurQuad *q3 = new RecurQuad(DI_Quad(p1234,p23,p3,p34));
-  recurCut(q3, maxlevel, level);
-  RecurQuad *q4 = new RecurQuad(DI_Quad(p14,p1234,p34,p4));
-  recurCut(q4, maxlevel, level);
-  q1->super = q;
-  q2->super = q;
-  q3->super = q;
-  q4->super = q;
-  q->sub[0] = q1;
-  q->sub[1] = q2;
-  q->sub[2] = q3;
-  q->sub[3] = q4;
-}
-
-// return true if the quad q->quad is crossed or run along by a primitive levelset in RPN and by the final levelset
-// (the levelset is computed with the values at the nodes of the quad e)
-bool signChange (RecurQuad *q, const DI_Quad *e, const std::vector<const gLevelset *> RPN) {
-  bool cS=false;
-  std::vector<const gLevelset *> RPNi;
-  DI_Quad qq(*(q->root()->quad));
-  std::vector<DI_CuttingPoint> cp;
-  for(int l=0;l<(int)RPN.size();l++) {
-    const gLevelset *Lsi = RPN[l];
-    RPNi.push_back(Lsi);
-    if(Lsi->isPrimitive()) {
-      qq.computeLs(e,*Lsi);
-      for(int i=0;i<(int)cp.size();i++)
-        cp[i].addLs(&qq);
-      q->quad->addLs(&qq);
-      q->quad->getCuttingPoints(&qq,RPNi,cp);
-    }
-    else {
-      for(int p=0;p<(int)cp.size();p++)
-        cp[p].chooseLs(Lsi);
-      q->quad->chooseLs(Lsi);
-    }
-  }
-  if(cp.size()>1) {
-    for(int i=0;i<(int)cp.size();i++)
-      if(cp[i].ls()==0) {cS=true; break;}
-  }
-  q->quad->clearLs();
-  return cS;
-}
-
-// Set isCrossed to true if a sub RecurQuad is crossed. 
-// If it has no sub RecurQuad, set isCrossed to true if the quad is crossed or run along by the levelset
-//(the levelset is computed with the values at the nodes of the quad e)
-bool computeIsCrossed (RecurQuad *q, const DI_Quad *e, const std::vector<const gLevelset *> RPN) {
-  if (q->sub[0]==NULL)
-    q->isCrossed = signChange(q,e,RPN);
-  else {
-    bool iC0 = computeIsCrossed(q->sub[0],e,RPN);
-    bool iC1 = computeIsCrossed(q->sub[1],e,RPN);
-    bool iC2 = computeIsCrossed(q->sub[2],e,RPN);
-    bool iC3 = computeIsCrossed(q->sub[3],e,RPN);
-    q->isCrossed = (iC0 || iC1 || iC2 || iC3);
-  }
-  return q->isCrossed;
-}
-
-// Recursively set the visibility to true if the RecurQuad is crossed and has no sub RecurQuad
-// or if the RecurQuad is not crossed and the parent RecurQuad is crossed.
-void changeVisibility(RecurQuad *q){
-  bool superIC = true;
-  if(q->super)
-    superIC = q->super->isCrossed;
-  if((q->isCrossed && q->sub[0]==NULL) || (!q->isCrossed && superIC))
-    q->setVisibility(true);
-
-  if(q->sub[0]){
-    changeVisibility(q->sub[0]);
-    changeVisibility(q->sub[1]);
-    changeVisibility(q->sub[2]);
-    changeVisibility(q->sub[3]);
-  }
-}
-
-RecurQuad* RecurQuad::root()
-{
-  if(super) return super->root();
-  return this;
-}
-
-bool RecurQuad::cut(int maxlevel, const DI_Quad *e, const std::vector<const gLevelset *> RPN, double TOL)
-{
-  recurCut(this, maxlevel, 0);
-  bool iC=false;
-  if(TOL<0.){
-    iC = computeIsCrossed(root(),e,RPN);
-    changeVisibility(root());
-  }
-  else{
-    iC = computeIsCrossed(root(),e,RPN);
-    changeVisibility(root());
-  }
-  return iC;
-}
-
-void RecurQuad::pushQuads (std::vector<DI_Quad> &vQ)
-{
-  if(visible)
-    vQ.push_back(DI_Quad(*quad));
-  if(sub[0]){
-    sub[0]->pushQuads(vQ);
-    sub[1]->pushQuads(vQ);
-    sub[2]->pushQuads(vQ);
-    sub[3]->pushQuads(vQ);
-  }
-}
-*/
-
 #endif
diff --git a/contrib/DiscreteIntegration/recurCut.h b/contrib/DiscreteIntegration/recurCut.h
index 1144606ca2..132d333695 100644
--- a/contrib/DiscreteIntegration/recurCut.h
+++ b/contrib/DiscreteIntegration/recurCut.h
@@ -20,22 +20,22 @@ class RecurElement
   // return the reference element at the root of the tree structure
   RecurElement* root();
   // return a mean value of the levelset in the element
-  inline double Ls() const;
+  inline double ls() const;
   // creates RecurElements forming a mesh of the DI_Element e with refined elements close to the zero levelset
   // return false if the element is not crossed or run along by the levelset
-  bool cut (int maxlevel, const DI_Element *e, const gLevelset &LS, double TOL = -1.,
-            std::map<int, double> nodeLs[8] = NULL);
+  bool cut (int maxlevel, const DI_Element *e, std::vector<const gLevelset *> &LsRPN, double TOL = -1.,
+            double **nodeLs = NULL);
 };
 
 // push the DI_Elements of the visible RecurElements into v
 template <class T>
-static void pushSubElements (RecurElement *re, std::vector<T> &v)
+static void pushSubElements (RecurElement *re, std::vector<T *> &v)
 {
   if(re->visible)
-    v.push_back(T(*((T*)re->el)));
+    v.push_back(new T(*((T*)re->el)));
   if(re->sub[0]){
     for(int i = 0; i < re->nbSub(); i++)
-      pushSubElements(re->sub[i], v);  
+      pushSubElements(re->sub[i], v);
   }
 }
 
-- 
GitLab