diff --git a/Common/OpenFile.cpp b/Common/OpenFile.cpp
index 6db55cc2bcac00bc2dc9b7f37b43e99120b6cf33..5b6ba9dec75b96f5111f736011b2fd6b222176f5 100644
--- a/Common/OpenFile.cpp
+++ b/Common/OpenFile.cpp
@@ -235,7 +235,7 @@ int MergeFile(std::string fileName, bool warnIfMissing)
   }
 
   char header[256];
-  fgets(header, sizeof(header), fp);
+  if(!fgets(header, sizeof(header), fp)) return 0;
   fclose(fp);
 
   Msg::StatusBar(2, true, "Reading '%s'", fileName.c_str());
diff --git a/Geo/GModelIO_Mesh.cpp b/Geo/GModelIO_Mesh.cpp
index 8b9b89c58d0549322bc11cba49a1ac7209bb18d3..b19caf2898cd4d417288dc2a1610e58f18c9278c 100644
--- a/Geo/GModelIO_Mesh.cpp
+++ b/Geo/GModelIO_Mesh.cpp
@@ -80,17 +80,17 @@ static bool getVertices(int num, int *indices, std::vector<MVertex*> &vec,
   return true;
 }
 
-static void createElementMSH(GModel *m, int num, int typeMSH, int physical, 
-                             int reg, int part, std::vector<MVertex*> &v, 
-                             std::map<int, std::vector<MElement*> > elements[10],
-                             std::map<int, std::map<int, std::string> > physicals[4])
+static MElement *createElementMSH(GModel *m, int num, int typeMSH, int physical,
+                                  int reg, int part, std::vector<MVertex*> &v,
+                                  std::map<int, std::vector<MElement*> > elements[10],
+                                  std::map<int, std::map<int, std::string> > physicals[4])
 {
   MElementFactory factory;
   MElement *e = factory.create(typeMSH, v, num, part);
 
   if(!e){
     Msg::Error("Unknown type of element %d", typeMSH);
-    return;
+    return NULL;
   }
 
   switch(e->getType()){
@@ -114,7 +114,7 @@ static void createElementMSH(GModel *m, int num, int typeMSH, int physical,
     elements[8][reg].push_back(e); break;
   case TYPE_POLYH :
     elements[9][reg].push_back(e); break;
-  default : Msg::Error("Wrong type of element"); return;
+  default : Msg::Error("Wrong type of element"); return NULL;
   }
   
   int dim = e->getDim();
@@ -122,8 +122,48 @@ static void createElementMSH(GModel *m, int num, int typeMSH, int physical,
     physicals[dim][reg][physical] = "unnamed";
   
   if(part) m->getMeshPartitions().insert(part);
+  return e;
 }
 
+static MElement *getParent(int parentNum, std::map<int, std::vector<MElement*> > &elements)
+{
+  std::map<int, std::vector<MElement*> >::iterator it = elements.begin();
+  for(; it != elements.end(); ++it) {
+    std::vector<MElement*>::iterator itE = it->second.begin();
+    for(; itE != it->second.end(); itE++)
+      if((*itE)->getNum() == parentNum) {
+        MElement *p = (*itE);
+        it->second.erase(itE);
+        return p;
+      }
+  }
+  return NULL;
+}
+
+static MElement *getParent(int parentNum, int dim,
+                           std::map<int, std::vector<MElement*> > elements[10])
+{
+  MElement *parent = NULL;
+  switch(dim){
+  case 0 :
+    return getParent(parentNum, elements[0]);
+  case 1 :
+    return getParent(parentNum, elements[1]);
+  case 2 :
+    if(parent = getParent(parentNum, elements[2])) return parent;
+    if(parent = getParent(parentNum, elements[3])) return parent;
+    if(parent = getParent(parentNum, elements[8])) return parent;
+    return parent;
+  case 3 :
+    if(parent = getParent(parentNum, elements[4])) return parent;
+    if(parent = getParent(parentNum, elements[5])) return parent;
+    if(parent = getParent(parentNum, elements[6])) return parent;
+    if(parent = getParent(parentNum, elements[7])) return parent;
+    if(parent = getParent(parentNum, elements[9])) return parent;
+    return parent;
+  default : return parent;
+  }
+}
 
 int GModel::readMSH(const std::string &name)
 {
@@ -293,34 +333,38 @@ int GModel::readMSH(const std::string &name)
 
       if(!fgets(str, sizeof(str), fp)) return 0;
       int numElements;
+      std::map<int, MElement*> parents;
       sscanf(str, "%d", &numElements);
       Msg::Info("%d elements", numElements);
       Msg::ResetProgressMeter();
       if(!binary){
         for(int i = 0; i < numElements; i++) {
-          int num, type, physical = 0, elementary = 0, partition = 0, numVertices;
+          int num, type, physical = 0, elementary = 0, partition = 0, parentN = 0, numVertices;
           if(version <= 1.0){
-            fscanf(fp, "%d %d %d %d %d", &num, &type, &physical, &elementary, &numVertices);
+            if(fscanf(fp, "%d %d %d %d %d", &num, &type, &physical, &elementary, &numVertices) != 5)
+              return 0;
             if(numVertices != MElement::getInfoMSH(type)) return 0;
           }
           else{
             int numTags;
-            fscanf(fp, "%d %d %d", &num, &type, &numTags);
+            if(fscanf(fp, "%d %d %d", &num, &type, &numTags) != 3) return 0;
             for(int j = 0; j < numTags; j++){
               int tag;
-              fscanf(fp, "%d", &tag);       
+              if(fscanf(fp, "%d", &tag) != 1) return 0;
               if(j == 0)      physical = tag;
               else if(j == 1) elementary = tag;
               else if(j == 2) partition = tag;
+              else if(j == 3) parentN = tag;
               // ignore any other tags for now
             }
             if(!(numVertices = MElement::getInfoMSH(type))) {
               if(type != MSH_POLYG_ && type != MSH_POLYH_) return 0;
-              fscanf(fp, "%d", &numVertices);
+              if(fscanf(fp, "%d", &numVertices) != 1) return 0;
             }
           }
           int *indices = new int[numVertices];
-          for(int j = 0; j < numVertices; j++) fscanf(fp, "%d", &indices[j]);
+          for(int j = 0; j < numVertices; j++)
+            if(fscanf(fp, "%d", &indices[j]) != 1) return 0;
           std::vector<MVertex*> vertices;
           if(vertexVector.size()){
             if(!getVertices(numVertices, indices, vertexVector, vertices)) return 0;
@@ -328,8 +372,18 @@ int GModel::readMSH(const std::string &name)
           else{
             if(!getVertices(numVertices, indices, vertexMap, vertices)) return 0;
           }
-          createElementMSH(this, num, type, physical, elementary, partition, 
-                           vertices, elements, physicals);
+          MElement *e = createElementMSH(this, num, type, physical, elementary,
+                                         partition, vertices, elements, physicals);
+          if(parentN) {
+            MElement *parent = NULL;
+            if(parents.find(parentN) == parents.end()){
+              parent = getParent(parentN, e->getDim(), elements);
+              if(parent) parents[parentN] = parent;
+              else Msg::Error("Parent element %d not found!",parentN);
+            }
+            else parent = parents.find(parentN)->second;
+            e->setParent(parent);
+          }
           if(numElements > 100000) 
             Msg::ProgressMeter(i + 1, numElements, "Reading elements");
           delete [] indices;
@@ -372,7 +426,6 @@ int GModel::readMSH(const std::string &name)
           numElementsPartial += numElms;
         }
       }
-
     }
     else if(!strncmp(&str[1], "NodeData", 8)) {
 
@@ -384,7 +437,6 @@ int GModel::readMSH(const std::string &name)
         _vertexMapCache = vertexMap;
       postpro = true;
       break;
-
     }
     else if(!strncmp(&str[1], "ElementData", 11) ||
             !strncmp(&str[1], "ElementNodeData", 15)) {
@@ -392,7 +444,6 @@ int GModel::readMSH(const std::string &name)
       // there's some element post-processing data to read later on
       postpro = true;
       break;
-
     }
 
     do {
@@ -467,19 +518,42 @@ static void writeElementHeaderMSH(bool binary, FILE *fp, std::map<int,int> &elem
 }
 
 template<class T>
-static void writeElementsMSH(FILE *fp, const std::vector<T*> &ele, bool saveAll, 
+static void writeElementsMSH(FILE *fp, T *ele, bool saveAll, 
                              double version, bool binary, int &num, int elementary, 
+                             std::vector<int> &physicals, int parentNum)
+{
+  if(saveAll)
+    ele->writeMSH(fp, version, binary, ++num, elementary, 0, parentNum);
+  else
+    for(unsigned int j = 0; j < physicals.size(); j++)
+      ele->writeMSH(fp, version, binary, ++num, elementary, physicals[j], parentNum);
+}
+
+template<class T>
+static void writeElementsMSH(FILE *fp, const std::vector<T*> &ele, bool saveAll,
+                             double version, bool binary, int &num, int elementary,
                              std::vector<int> &physicals)
 {
   for(unsigned int i = 0; i < ele.size(); i++)
-    if(saveAll)
-      ele[i]->writeMSH(fp, version, binary, ++num, elementary, 0);
-    else
-      for(unsigned int j = 0; j < physicals.size(); j++)
-        ele[i]->writeMSH(fp, version, binary, ++num, elementary, physicals[j]);
+    writeElementsMSH(fp, ele[i], saveAll, version, binary, num,
+                     elementary, physicals, 0);
+}
+
+template<class T>
+static void writeElementsMSH(FILE *fp, const std::vector<T*> &ele, bool saveAll,
+                             double version, bool binary, int &num, int elementary,
+                             std::vector<int> &physicals, std::map<MElement *, int> &parentsNum)
+{
+  for(unsigned int i = 0; i < ele.size(); i++) {
+    int parentNum = (ele[i]->getParent() != NULL &&
+                     parentsNum.find(ele[i]->getParent()) != parentsNum.end()) ?
+      parentsNum.find(ele[i]->getParent())->second : 0;
+    writeElementsMSH(fp, ele[i], saveAll, version, binary, num,
+                     elementary, physicals, parentNum);
+  }
 }
 
-int GModel::writeMSH(const std::string &name, double version, bool binary, 
+int GModel::writeMSH(const std::string &name, double version, bool binary,
                      bool saveAll, bool saveParametric, double scalingFactor)
 {
   FILE *fp = fopen(name.c_str(), binary ? "wb" : "w");
@@ -491,8 +565,6 @@ int GModel::writeMSH(const std::string &name, double version, bool binary,
   // if there are no physicals we save all the elements
   if(noPhysicalGroups()) saveAll = true;
 
-
-
   // get the number of vertices and index the vertices in a continuous
   // sequence
   int numVertices = indexMeshVertices(saveAll);
@@ -504,6 +576,8 @@ int GModel::writeMSH(const std::string &name, double version, bool binary,
   // list have the same type, i.e., they are all of the same
   // polynomial order)
   std::map<int, int> elements;
+  std::map<MElement *, GEntity *> parents[2];
+  int numParents = 0;
   for(viter it = firstVertex(); it != lastVertex(); ++it){
     int p = (saveAll ? 1 : (*it)->physicals.size());
     int n = p * (*it)->points.size();
@@ -522,6 +596,11 @@ int GModel::writeMSH(const std::string &name, double version, bool binary,
     if(n) elements[(*it)->quadrangles[0]->getTypeForMSH()] += n;
     n = p * (*it)->polygons.size();
     if(n) elements[(*it)->polygons[0]->getTypeForMSH()] += n;
+    for(int i = 0; i < (*it)->polygons.size(); i++)
+      if((*it)->polygons[i]->ownsParent()) {
+        parents[0][(*it)->polygons[i]->getParent()] = (*it);
+        numParents += p;
+      }
   }
   for(riter it = firstRegion(); it != lastRegion(); ++it){
     int p = (saveAll ? 1 : (*it)->physicals.size());
@@ -535,14 +614,18 @@ int GModel::writeMSH(const std::string &name, double version, bool binary,
     if(n) elements[(*it)->pyramids[0]->getTypeForMSH()] += n;
     n = p * (*it)->polyhedra.size();
     if(n) elements[(*it)->polyhedra[0]->getTypeForMSH()] += n;
+    for(int i = 0; i < (*it)->polyhedra.size(); i++)
+      if((*it)->polyhedra[i]->ownsParent()) {
+        parents[1][(*it)->polyhedra[i]->getParent()] = (*it);
+        numParents += p;
+      }
   }
 
- 
-
   int numElements = 0;
   std::map<int, int>::const_iterator it = elements.begin();
   for(; it != elements.end(); ++it)
     numElements += it->second;
+  numElements += numParents;
 
   if(version >= 2.0){
     fprintf(fp, "$MeshFormat\n");
@@ -567,7 +650,6 @@ int GModel::writeMSH(const std::string &name, double version, bool binary,
       fprintf(fp, "$ParametricNodes\n");
     else
       fprintf(fp, "$Nodes\n");
-
   }
   else
     fprintf(fp, "$NOD\n");
@@ -580,8 +662,7 @@ int GModel::writeMSH(const std::string &name, double version, bool binary,
     for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++)
       entities[i]->mesh_vertices[j]->writeMSH(fp, binary, saveParametric, 
                                               scalingFactor);
-  
-  
+
   if(binary) fprintf(fp, "\n");
 
   if(version >= 2.0){
@@ -599,50 +680,102 @@ int GModel::writeMSH(const std::string &name, double version, bool binary,
   fprintf(fp, "%d\n", numElements);
   int num = 0;
 
+  std::map<MElement *, int> parentsNum;
+  std::map<MElement *, GEntity *>::const_iterator itP;
+
   writeElementHeaderMSH(binary, fp, elements, MSH_PNT);
   for(viter it = firstVertex(); it != lastVertex(); ++it)
     writeElementsMSH(fp, (*it)->points, saveAll, version, binary, num,
                      (*it)->tag(), (*it)->physicals);
-  writeElementHeaderMSH
-    (binary, fp, elements, MSH_LIN_2, MSH_LIN_3, MSH_LIN_4, MSH_LIN_5);
+
+  writeElementHeaderMSH(binary, fp, elements, MSH_LIN_2, MSH_LIN_3, MSH_LIN_4, MSH_LIN_5);
   for(eiter it = firstEdge(); it != lastEdge(); ++it)
    writeElementsMSH(fp, (*it)->lines, saveAll, version, binary, num,
                      (*it)->tag(), (*it)->physicals);
-  writeElementHeaderMSH(binary, fp, elements, MSH_TRI_3, MSH_TRI_6, MSH_TRI_9, 
+
+  writeElementHeaderMSH(binary, fp, elements, MSH_TRI_3, MSH_TRI_6, MSH_TRI_9,
                         MSH_TRI_10, MSH_TRI_12, MSH_TRI_15, MSH_TRI_15I, MSH_TRI_21);
+  for(itP = parents[0].begin(); itP != parents[0].end(); itP++)
+    if(itP->first->getType() == TYPE_TRI) {
+      writeElementsMSH(fp, itP->first, saveAll, version, binary, num,
+                       itP->second->tag(), itP->second->physicals, 0);
+      parentsNum[itP->first] = num;
+    }
   for(fiter it = firstFace(); it != lastFace(); ++it)
     writeElementsMSH(fp, (*it)->triangles, saveAll, version, binary, num,
                      (*it)->tag(), (*it)->physicals);
- 
   writeElementHeaderMSH(binary, fp, elements, MSH_QUA_4, MSH_QUA_9, MSH_QUA_8);
+  for(itP = parents[0].begin(); itP != parents[0].end(); itP++)
+    if(itP->first->getType() == TYPE_QUA) {
+      writeElementsMSH(fp, itP->first, saveAll, version, binary, num,
+                       itP->second->tag(), itP->second->physicals, 0);
+      parentsNum[itP->first] = num;
+    }
   for(fiter it = firstFace(); it != lastFace(); ++it)
     writeElementsMSH(fp, (*it)->quadrangles, saveAll, version, binary, num,
                      (*it)->tag(), (*it)->physicals);
   writeElementHeaderMSH(binary, fp, elements, MSH_POLYG_);
+  for(itP = parents[0].begin(); itP != parents[0].end(); itP++)
+    if(itP->first->getType() == TYPE_POLYG) {
+      writeElementsMSH(fp, itP->first, saveAll, version, binary, num,
+                       itP->second->tag(), itP->second->physicals, 0);
+      parentsNum[itP->first] = num;
+    }
   for(fiter it = firstFace(); it != lastFace(); it++)
     writeElementsMSH(fp, (*it)->polygons, saveAll, version, binary, num,
-                     (*it)->tag(), (*it)->physicals);
+                     (*it)->tag(), (*it)->physicals, parentsNum);
+
   writeElementHeaderMSH(binary, fp, elements, MSH_TET_4, MSH_TET_10, MSH_TET_20, 
                         MSH_TET_35, MSH_TET_56, MSH_TET_52);
+  for(itP = parents[1].begin(); itP != parents[1].end(); itP++)
+    if(itP->first->getType() == TYPE_TET) {
+      writeElementsMSH(fp, itP->first, saveAll, version, binary, num,
+                       itP->second->tag(), itP->second->physicals, 0);
+      parentsNum[itP->first] = num;
+    }
   for(riter it = firstRegion(); it != lastRegion(); ++it)
     writeElementsMSH(fp, (*it)->tetrahedra, saveAll, version, binary, num,
                      (*it)->tag(), (*it)->physicals);
   writeElementHeaderMSH(binary, fp, elements, MSH_HEX_8, MSH_HEX_27, MSH_HEX_20);
+  for(itP = parents[1].begin(); itP != parents[1].end(); itP++)
+    if(itP->first->getType() == TYPE_HEX) {
+      writeElementsMSH(fp, itP->first, saveAll, version, binary, num,
+                       itP->second->tag(), itP->second->physicals, 0);
+      parentsNum[itP->first] = num;
+    }
   for(riter it = firstRegion(); it != lastRegion(); ++it)
     writeElementsMSH(fp, (*it)->hexahedra, saveAll, version, binary, num,
                      (*it)->tag(), (*it)->physicals);
   writeElementHeaderMSH(binary, fp, elements, MSH_PRI_6, MSH_PRI_18, MSH_PRI_15);
+  for(itP = parents[1].begin(); itP != parents[1].end(); itP++)
+    if(itP->first->getType() == TYPE_PRI) {
+      writeElementsMSH(fp, itP->first, saveAll, version, binary, num,
+                       itP->second->tag(), itP->second->physicals, 0);
+      parentsNum[itP->first] = num;
+    }
   for(riter it = firstRegion(); it != lastRegion(); ++it)
     writeElementsMSH(fp, (*it)->prisms, saveAll, version, binary, num,
                      (*it)->tag(), (*it)->physicals);
   writeElementHeaderMSH(binary, fp, elements, MSH_PYR_5, MSH_PYR_14, MSH_PYR_13);
+  for(itP = parents[1].begin(); itP != parents[1].end(); itP++)
+    if(itP->first->getType() == TYPE_PYR) {
+      writeElementsMSH(fp, itP->first, saveAll, version, binary, num,
+                       itP->second->tag(), itP->second->physicals, 0);
+      parentsNum[itP->first] = num;
+    }
   for(riter it = firstRegion(); it != lastRegion(); ++it)
     writeElementsMSH(fp, (*it)->pyramids, saveAll, version, binary, num,
                      (*it)->tag(), (*it)->physicals);
   writeElementHeaderMSH(binary, fp, elements, MSH_POLYH_);
+  for(itP = parents[1].begin(); itP != parents[1].end(); itP++)
+    if(itP->first->getType() == TYPE_POLYH) {
+      writeElementsMSH(fp, itP->first, saveAll, version, binary, num,
+                       itP->second->tag(), itP->second->physicals, 0);
+      parentsNum[itP->first] = num;
+    }
   for(riter it = firstRegion(); it != lastRegion(); ++it)
     writeElementsMSH(fp, (*it)->polyhedra, saveAll, version, binary, num,
-                     (*it)->tag(), (*it)->physicals);
+                     (*it)->tag(), (*it)->physicals, parentsNum);
   
   if(binary) fprintf(fp, "\n");
 
@@ -732,7 +865,7 @@ int GModel::readSTL(const std::string &name, double tolerance)
 
   // "solid", or binary data header
   char buffer[256];
-  fgets(buffer, sizeof(buffer), fp);
+  if(!fgets(buffer, sizeof(buffer), fp)) return 0;
 
   // workaround for stupid tools which use "solid" to start their
   // binary files
@@ -946,7 +1079,7 @@ static int readElementsVRML(FILE *fp, std::vector<MVertex*> &vertexVector, int r
   const char *format;
   fpos_t position;
   fgetpos(fp, &position);
-  fgets(tmp, sizeof(tmp), fp);
+  if(!fgets(tmp, sizeof(tmp), fp)) return 0;;
   fsetpos(fp, &position);
   if(strstr(tmp, ","))
     format = " , %d";
@@ -1366,7 +1499,7 @@ int GModel::readMESH(const std::string &name)
   }
 
   char buffer[256];
-  fgets(buffer, sizeof(buffer), fp);
+  if(!fgets(buffer, sizeof(buffer), fp)) return 0;
 
   char str[256];
   int format;
@@ -2153,10 +2286,11 @@ int GModel::readVTK(const std::string &name, bool bigEndian)
   
   char buffer[256], buffer2[256];
   
-  fgets(buffer, sizeof(buffer), fp); // version line
-  fgets(buffer, sizeof(buffer), fp); // title
+  if(!fgets(buffer, sizeof(buffer), fp)) return 0; // version line
+  if(!fgets(buffer, sizeof(buffer), fp)) return 0; // title
   
-  fscanf(fp, "%s", buffer); // ASCII or BINARY
+  if(fscanf(fp, "%s", buffer) != 1) // ASCII or BINARY
+    Msg::Error("Failed reading buffer");
   bool binary = false;
   if(!strcmp(buffer, "BINARY")) binary = true;
   
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index 80e8823a6c15dff2e829fc3b07698c699bea13eb..69ee7515c946b8191fd4a146ee5b38a3f4654dcd 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -382,7 +382,7 @@ double MElement::interpolateDiv(double val[], double u, double v, double w, int
 }
 
 void MElement::writeMSH(FILE *fp, double version, bool binary, int num, 
-                        int elementary, int physical)
+                        int elementary, int physical, int parentNum)
 {
   int type = getTypeForMSH();
 
diff --git a/Geo/MElement.h b/Geo/MElement.h
index c259731866bae9ac59da2ac560504b0b8b43d07e..d7daec74470df49a46c9c14aba64ac7df0cb02d5 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -132,9 +132,11 @@ class MElement
   }
 
   // get parent and children for hierarchial grids
-  virtual MElement *getParent() const { return 0; }
+  virtual MElement *getParent() const { return NULL; }
+  virtual void setParent(MElement *p) {}
   virtual int getNumChildren() const { return 0; }
-  virtual MElement *getChild(int i) const { return 0; }
+  virtual MElement *getChild(int i) const { return NULL; }
+  virtual bool ownsParent() const { return false; }
 
   //get the type of the element
   virtual int getType() const = 0;
@@ -216,7 +218,7 @@ class MElement
 
   // IO routines
   virtual void writeMSH(FILE *fp, double version=1.0, bool binary=false, 
-                        int num=0, int elementary=1, int physical=1);
+                        int num=0, int elementary=1, int physical=1, int parentNum=0);
   virtual void writePOS(FILE *fp, bool printElementary, bool printElementNumber, 
                         bool printGamma, bool printEta, bool printRho, 
                         bool printDisto,double scalingFactor=1.0, int elementary=1);
diff --git a/Geo/MElementCut.cpp b/Geo/MElementCut.cpp
index 068374cc223609d14ab64cb03a474db913268658..2bd688d6fac21c34fcb676e4c74b6a2dadabcb5c 100644
--- a/Geo/MElementCut.cpp
+++ b/Geo/MElementCut.cpp
@@ -134,7 +134,7 @@ void MPolyhedron::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
 }
 
 void MPolyhedron::writeMSH(FILE *fp, double version, bool binary, int num, 
-                           int elementary, int physical)
+                           int elementary, int physical, int parentNum)
 {
   int type = getTypeForMSH();
 
@@ -151,8 +151,12 @@ void MPolyhedron::writeMSH(FILE *fp, double version, bool binary, int num,
     fprintf(fp, "%d %d", num ? num : numE, type);
     if(version < 2.0)
       fprintf(fp, " %d %d", abs(physical), elementary);
-    else
-      fprintf(fp, " 3 %d %d %d", abs(physical), elementary, partE);
+    else {
+      if(parentNum)
+        fprintf(fp, " 4 %d %d %d %d", abs(physical), elementary, partE, parentNum);
+      else
+        fprintf(fp, " 3 %d %d %d", abs(physical), elementary, partE);
+    }
   }
   else{
     int tags[4] = {num ? num : numE, abs(physical), elementary, partE};
@@ -306,7 +310,7 @@ void MPolygon::getIntegrationPoints(int pOrder, int *npts, IntPt **pts) const
 }
 
 void MPolygon::writeMSH(FILE *fp, double version, bool binary, int num, 
-                        int elementary, int physical)
+                        int elementary, int physical, int parentNum)
 {
   int type = getTypeForMSH();
 
@@ -323,8 +327,12 @@ void MPolygon::writeMSH(FILE *fp, double version, bool binary, int num,
     fprintf(fp, "%d %d", num ? num : numE, type);
     if(version < 2.0)
       fprintf(fp, " %d %d", abs(physical), elementary);
-    else
-      fprintf(fp, " 3 %d %d %d", abs(physical), elementary, partE);
+    else {
+      if(parentNum)
+        fprintf(fp, " 4 %d %d %d %d", abs(physical), elementary, partE, parentNum);
+      else
+        fprintf(fp, " 3 %d %d %d", abs(physical), elementary, partE);
+    }
   }
   else{
     int tags[4] = {num ? num : numE, abs(physical), elementary, partE};
@@ -495,7 +503,6 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
   unsigned int nbQ = quads.size();
   unsigned int nbTe = tetras.size();
   unsigned int nbH = hexas.size();
-  std::map<int, double> nodeLs[8];
 
   // copy element
   std::vector<MVertex*> vmv;
@@ -528,7 +535,7 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
     }
   }
   MElementFactory factory;
-  MElement *copy = factory.create(eType, vmv, e->getNum(), ePart);
+  MElement *copy = factory.create(eType, vmv, ++numEle, ePart);
 
   switch (eType) {
   case MSH_TET_4 :
@@ -542,6 +549,7 @@ 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,
                       tetras, quads, triangles, 0, nodeLs);
@@ -555,6 +563,7 @@ 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,
                       hexas, tetras, quads, triangles, lines, 0, nodeLs);
@@ -564,6 +573,7 @@ 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,
@@ -593,6 +603,7 @@ 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,
@@ -608,13 +619,14 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
         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[e->getVertex(i)->getNum()];
+          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,
                             tetras, quads, triangles, 0, nodeLs);
           isCut = (isCut || iC);
@@ -657,13 +669,13 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
             poly[1].push_back(mt);
         }
         if(poly[0].size()) {
-          p1 = new MPolyhedron(poly[0], copy, true, ++numEle, ePart);
+          p1 = new MPolyhedron(poly[0], ++numEle, ePart, true, copy);
           int reg = getElementaryTag(-1, elementary, newtags[3]);
           elements[9][reg].push_back(p1);
           assignPhysicals(GM, gePhysicals, reg, 3, physicals);
         }
         if(poly[1].size()) {
-          p2 = new MPolyhedron(poly[1], copy, false, ++numEle, ePart);
+          p2 = new MPolyhedron(poly[1], ++numEle, ePart, false, copy);
           elements[9][elementary].push_back(p2);
           assignPhysicals(GM, gePhysicals, elementary, 3, physicals);
         }
@@ -728,6 +740,7 @@ 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,
                       quads, triangles, lines, 0, nodeLs);
@@ -737,17 +750,19 @@ 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,
                       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[e->getVertex(i)->getNum()];
+          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,
                             quads, triangles, lines, 0, nodeLs);
           isCut = (isCut || iC);
@@ -790,13 +805,13 @@ static void elementCutMesh(MElement *e, gLevelset *ls,
             poly[1].push_back(mt);
         }
         if(poly[0].size()) {
-          p1 = new MPolygon(poly[0], copy, true, ++numEle, ePart);
+          p1 = new MPolygon(poly[0], ++numEle, ePart, true, copy);
           int reg = getElementaryTag(-1, elementary, newtags[2]);
           elements[8][reg].push_back(p1);
           assignPhysicals(GM, gePhysicals, reg, 2, physicals);
         }
         if(poly[1].size()) {
-          p2 = new MPolygon(poly[1], copy, false, ++numEle, ePart);
+          p2 = new MPolygon(poly[1], ++numEle, ePart, false, copy);
           elements[8][elementary].push_back(p2);
           assignPhysicals(GM, gePhysicals, elementary, 2, physicals);
         }
@@ -852,6 +867,7 @@ 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);
 
diff --git a/Geo/MElementCut.h b/Geo/MElementCut.h
index c52f486ab741108c2c2fbd03065b9dd31cdb1066..7277f0fb4c1672e6800277d1fa3d1adb9ceeda63 100644
--- a/Geo/MElementCut.h
+++ b/Geo/MElementCut.h
@@ -26,8 +26,9 @@ class MPolyhedron : public MElement {
   std::vector<MFace> _faces;
   void _init();
  public:
-  MPolyhedron(std::vector<MVertex*> v, int num=0, int part=0)
-    : MElement(num, part), _owner(false), _orig(0) 
+  MPolyhedron(std::vector<MVertex*> v, int num = 0, int part = 0,
+              bool owner = false, MElement* orig = NULL)
+    : MElement(num, part), _owner(owner), _orig(orig)
   {
     if(v.size() % 4){
       Msg::Error("Got %d vertices for polyhedron", (int)v.size());
@@ -37,14 +38,8 @@ class MPolyhedron : public MElement {
       _parts.push_back(new MTetrahedron(v[i], v[i + 1], v[i + 2], v[i + 3]));
     _init();
   }
-  MPolyhedron(std::vector<MTetrahedron*> vT, int num=0, int part=0)
-    : MElement(num, part), _owner(false), _orig(0)
-  {
-    for(unsigned int i = 0; i < vT.size(); i++)
-      _parts.push_back(vT[i]);
-    _init();
-  }
-  MPolyhedron(std::vector<MTetrahedron*> vT, MElement* orig, bool owner, int num=0, int part=0)
+  MPolyhedron(std::vector<MTetrahedron*> vT, int num = 0, int part = 0,
+              bool owner = false, MElement* orig = NULL)
     : MElement(num, part), _owner(owner), _orig(orig)
   {
     for(unsigned int i = 0; i < vT.size(); i++)
@@ -131,10 +126,12 @@ class MPolyhedron : public MElement {
     return _parts.size() * getNGQTetPts(pOrder);
   }
   virtual void writeMSH(FILE *fp, double version=1.0, bool binary=false, 
-                        int num=0, int elementary=1, int physical=1);
+                        int num=0, int elementary=1, int physical=1, int parentNum=0);
   virtual MElement *getParent() const { return _orig; }
+  virtual void setParent(MElement *p) { _orig = p; }
   virtual int getNumChildren() const { return _parts.size(); }
   virtual MElement *getChild(int i) const { return _parts[i]; }
+  virtual bool ownsParent() const { return _owner; }
 };
 
 class MPolygon : public MElement {
@@ -147,15 +144,17 @@ class MPolygon : public MElement {
   std::vector<MEdge> _edges;
   void _initVertices();
  public:
-  MPolygon(std::vector<MVertex*> v, int num=0, int part=0)
-    : MElement(num, part), _owner(false), _orig(0)
+  MPolygon(std::vector<MVertex*> v, int num = 0, int part = 0,
+           bool owner = false, MElement* orig = NULL)
+    : MElement(num, part), _owner(owner), _orig(orig)
   {
     for(unsigned int i = 0; i < v.size() / 3; i++)
       _parts.push_back(new MTriangle(v[i * 3], v[i * 3 + 1], v[i * 3 + 2]));
     _initVertices();
   }
-  MPolygon(std::vector<MElement*> vT, int num=0, int part=0)
-    : MElement(num, part), _owner(false), _orig(0)
+  MPolygon(std::vector<MTriangle*> vT, int num = 0, int part = 0,
+           bool owner = false, MElement* orig = NULL)
+    : MElement(num, part), _owner(owner), _orig(orig)
   {
     for(unsigned int i = 0; i < vT.size(); i++){
       MTriangle *t = (MTriangle*) vT[i];
@@ -163,20 +162,6 @@ class MPolygon : public MElement {
     }
     _initVertices();
   }
-  MPolygon(std::vector<MTriangle*> vT, int num=0, int part=0)
-    : MElement(num, part), _owner(false), _orig(0)
-  {
-    for(unsigned int i = 0; i < vT.size(); i++)
-      _parts.push_back(vT[i]);
-    _initVertices();
-  }
-  MPolygon(std::vector<MTriangle*> vT, MElement* orig, bool owner, int num=0, int part=0)
-    : MElement(num, part), _owner(owner), _orig(orig)
-  {
-    for(unsigned int i = 0; i < vT.size(); i++)
-      _parts.push_back(vT[i]);
-    _initVertices();
-  }
   ~MPolygon() 
   {
     if(_owner)
@@ -245,10 +230,12 @@ class MPolygon : public MElement {
     return _parts.size() * getNGQTPts(pOrder);
   }
   virtual void writeMSH(FILE *fp, double version=1.0, bool binary=false, 
-                        int num=0, int elementary=1, int physical=1);
+                        int num=0, int elementary=1, int physical=1, int parentNum=0);
   virtual MElement *getParent() const { return _orig; }
+  virtual void setParent(MElement *p) { _orig = p; }
   virtual int getNumChildren() const { return _parts.size(); }
   virtual MElement *getChild(int i) const { return _parts[i]; }
+  virtual bool ownsParent() const { return _owner; }
 };
 
 class MTriangleBorder : public MTriangle {
diff --git a/contrib/DiscreteIntegration/Integration3D.cpp b/contrib/DiscreteIntegration/Integration3D.cpp
index 5cc6391926fc28bd621b2b9e6911a7abd2da0d56..e7288d6fd7b419ab93a297df83527a349fe8803a 100644
--- a/contrib/DiscreteIntegration/Integration3D.cpp
+++ b/contrib/DiscreteIntegration/Integration3D.cpp
@@ -662,7 +662,7 @@ void DI_Element::addLs (const double *ls) {
   for(int i = 0; i < nbMid(); i++)
     mid_[i]->addLs(ls[nbVert()+i]);
 }
-void DI_Element::addLs (int primTag, std::map<int, double> nodeLs[8]) { printf("p");
+void DI_Element::addLs (int primTag, std::map<int, double> nodeLs[8]) {
   for(int i = 0; i < nbVert(); i++)
     pts_[i]->addLs(nodeLs[i][primTag]);
 }
@@ -673,7 +673,7 @@ 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) { printf("e");
+void DI_Element::addLs (const DI_Element *e, const gLevelset &Ls) {
   if(type() != e->type()) {
     printf("Error : addLs with element of different type\n");
   }