Salome HOME
Patch for MacOS (from SALOME forum)
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
index 5df2090e9abbf6bb74a520d9de7e39c21d042e58..ffb2926b9016757bfdf694052d5c2c00f21899bf 100644 (file)
-//  SMESH SMDS : implementaion of Salome mesh data structure
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
-//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
-// 
-//  This library is free software; you can redistribute it and/or 
-//  modify it under the terms of the GNU Lesser General Public 
-//  License as published by the Free Software Foundation; either 
-//  version 2.1 of the License. 
-// 
-//  This library is distributed in the hope that it will be useful, 
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-//  Lesser General Public License for more details. 
-// 
-//  You should have received a copy of the GNU Lesser General Public 
-//  License along with this library; if not, write to the Free Software 
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
-// 
-//  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
 
+//  SMESH SMDS : implementation of Salome mesh data structure
+//
 #ifdef _MSC_VER
 #pragma warning(disable:4786)
 #endif
 
-#include "utilities.h"
-#include "SMDS_Mesh.hxx"
-#include "SMDS_VolumeOfNodes.hxx"
-#include "SMDS_VolumeOfFaces.hxx"
-#include "SMDS_FaceOfNodes.hxx"
 #include "SMDS_FaceOfEdges.hxx"
-#include "SMDS_PolyhedralVolumeOfNodes.hxx"
+#include "SMDS_FaceOfNodes.hxx"
+#include "SMDS_Mesh.hxx"
 #include "SMDS_PolygonalFaceOfNodes.hxx"
+#include "SMDS_PolyhedralVolumeOfNodes.hxx"
 #include "SMDS_QuadraticEdge.hxx"
 #include "SMDS_QuadraticFaceOfNodes.hxx"
 #include "SMDS_QuadraticVolumeOfNodes.hxx"
+#include "SMDS_SetIterator.hxx"
+#include "SMDS_SpacePosition.hxx"
+#include "SMDS_UnstructuredGrid.hxx"
+#include "SMDS_VolumeOfFaces.hxx"
+#include "SMDS_VolumeOfNodes.hxx"
+
+#include "utilities.h"
+
+#include <vtkUnstructuredGrid.h>
+#include <vtkUnstructuredGridWriter.h>
+#include <vtkUnsignedCharArray.h>
+#include <vtkCell.h>
+#include <vtkCellLinks.h>
+#include <vtkIdList.h>
 
 #include <algorithm>
 #include <map>
+#include <iostream>
+#include <fstream>
+#include <iterator>
 using namespace std;
 
+#if !defined WIN32 && !defined __APPLE__
+#include <sys/sysinfo.h>
+#endif
+
+// number of added entities to check memory after
+#define CHECKMEMORY_INTERVAL 100000
+
+vector<SMDS_Mesh*> SMDS_Mesh::_meshList = vector<SMDS_Mesh*>();
+int SMDS_Mesh::chunkSize = 1024;
+
+
+//================================================================================
+/*!
+ * \brief Raise an exception if free memory (ram+swap) too low
+ * \param doNotRaise - if true, suppres exception, just return free memory size
+ * \retval int - amount of available memory in MB or negative number in failure case
+ */
+//================================================================================
+
+int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
+{
+#if !defined WIN32 && !defined __APPLE__
+  struct sysinfo si;
+  int err = sysinfo( &si );
+  if ( err )
+    return -1;
+
+  const unsigned long Mbyte = 1024 * 1024;
+
+  static int limit = -1;
+  if ( limit < 0 ) {
+    int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
+    if (status >= 0 ) {
+      limit = WEXITSTATUS(status);
+    }
+    else {
+      double factor = ( si.totalswap == 0 ) ? 0.1 : 0.2;
+      limit = int(( factor * si.totalram * si.mem_unit ) / Mbyte );
+    }
+    if ( limit < 20 )
+      limit = 20;
+    else
+      limit = int ( limit * 1.5 );
+    MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
+  }
+
+  // compute separately to avoid overflow
+  int freeMb =
+    ( si.freeram  * si.mem_unit ) / Mbyte +
+    ( si.freeswap * si.mem_unit ) / Mbyte;
+  //cout << "freeMb = " << freeMb << " limit = " << limit << endl;
+
+  if ( freeMb > limit )
+    return freeMb - limit;
+
+  if ( doNotRaise )
+    return 0;
+
+  MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
+  throw std::bad_alloc();
+#else
+  return -1;
+#endif
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /// Create a new mesh object
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_Mesh::SMDS_Mesh()
-       :myParent(NULL),
-        myNodeIDFactory(new SMDS_MeshElementIDFactory()),
-       myElementIDFactory(new SMDS_MeshElementIDFactory()),
-       myHasConstructionEdges(false), myHasConstructionFaces(false),
-       myHasInverseElements(true)
-{
+SMDS_Mesh::SMDS_Mesh():
+  myNodePool(0), myVolumePool(0), myFacePool(0), myEdgePool(0), myBallPool(0),
+  myParent(NULL),
+  myNodeIDFactory(new SMDS_MeshNodeIDFactory()),
+  myElementIDFactory(new SMDS_MeshElementIDFactory()),
+  myModified(false), myModifTime(0), myCompactTime(0),
+  myHasConstructionEdges(false), myHasConstructionFaces(false),
+  myHasInverseElements(true),
+  xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0)
+{
+  myMeshId = _meshList.size();         // --- index of the mesh to push back in the vector
+  myNodeIDFactory->SetMesh(this);
+  myElementIDFactory->SetMesh(this);
+  _meshList.push_back(this);
+  myNodePool = new ObjectPool<SMDS_MeshNode>(SMDS_Mesh::chunkSize);
+  myEdgePool = new ObjectPool<SMDS_VtkEdge>(SMDS_Mesh::chunkSize);
+  myFacePool = new ObjectPool<SMDS_VtkFace>(SMDS_Mesh::chunkSize);
+  myVolumePool = new ObjectPool<SMDS_VtkVolume>(SMDS_Mesh::chunkSize);
+  myBallPool = new ObjectPool<SMDS_BallElement>(SMDS_Mesh::chunkSize);
+
+  myNodes.clear();
+  myCells.clear();
+  //myCellIdSmdsToVtk.clear();
+  myCellIdVtkToSmds.clear();
+  myGrid = SMDS_UnstructuredGrid::New();
+  myGrid->setSMDS_mesh(this);
+  myGrid->Initialize();
+  myGrid->Allocate();
+  vtkPoints* points = vtkPoints::New();
+  // bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
+  // Use double type for storing coordinates of nodes instead of float.
+  points->SetDataType(VTK_DOUBLE);
+  points->SetNumberOfPoints(0 /*SMDS_Mesh::chunkSize*/);
+  myGrid->SetPoints( points );
+  points->Delete();
+  //myGrid->BuildLinks();
+  this->Modified();
+
+  // initialize static maps in SMDS_MeshCell, to be thread-safe
+  if ( myMeshId == 0 )
+  {
+    SMDS_MeshCell::toVtkType( SMDSEntity_Node );
+    SMDS_MeshCell::toVtkOrder( SMDSEntity_Node );
+    SMDS_MeshCell::reverseSmdsOrder( SMDSEntity_Node );
+    SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Node );
+    SMDS_MeshCell::toSmdsType( VTK_VERTEX );
+    SMDS_MeshCell::fromVtkOrder( SMDSEntity_Node );
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -56,11 +179,16 @@ SMDS_Mesh::SMDS_Mesh()
 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
 /// (2003-09-08) of SMESH
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
-       :myParent(parent), myNodeIDFactory(parent->myNodeIDFactory),
-       myElementIDFactory(parent->myElementIDFactory),
-       myHasConstructionEdges(false), myHasConstructionFaces(false),
-       myHasInverseElements(true)
+SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent):
+  myNodePool(parent->myNodePool),
+  myVolumePool(parent->myVolumePool),
+  myFacePool(parent->myFacePool),
+  myEdgePool(parent->myEdgePool),
+  myBallPool(parent->myBallPool),
+  myParent(parent), myNodeIDFactory(parent->myNodeIDFactory),
+  myElementIDFactory(parent->myElementIDFactory),
+  myHasConstructionEdges(false), myHasConstructionFaces(false),
+  myHasInverseElements(true)
 {
 }
 
@@ -70,9 +198,9 @@ SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
 
 SMDS_Mesh *SMDS_Mesh::AddSubMesh()
 {
-       SMDS_Mesh *submesh = new SMDS_Mesh(this);
-       myChildren.insert(myChildren.end(), submesh);
-       return submesh;
+  SMDS_Mesh *submesh = new SMDS_Mesh(this);
+  myChildren.insert(myChildren.end(), submesh);
+  return submesh;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -96,20 +224,131 @@ SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
   // find the MeshNode corresponding to ID
   const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
   if(!node){
-    SMDS_MeshNode * node=new SMDS_MeshNode(x, y, z);
-    myNodes.Add(node);
+    if (ID < 1)
+      {
+        MESSAGE("=============>  Bad Node Id: " << ID);
+        ID = myNodeIDFactory->GetFreeID();
+      }
+    myNodeIDFactory->adjustMaxId(ID);
+    SMDS_MeshNode * node = myNodePool->getNew();
+    node->init(ID, myMeshId, 0, x, y, z);
+
+    if (ID >= (int)myNodes.size())
+    {
+        myNodes.resize(ID+SMDS_Mesh::chunkSize, 0);
+//         MESSAGE(" ------------------ myNodes resize " << ID << " --> " << ID+SMDS_Mesh::chunkSize);
+    }
+    myNodes[ID] = node;
     myNodeIDFactory->BindID(ID,node);
+    myInfo.myNbNodes++;
+    myModified = true;
+    this->adjustBoundingBox(x, y, z);
     return node;
   }else
     return NULL;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+/// create a Mesh0DElement and add it to the current Mesh
+/// @return : The created Mesh0DElement
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
+{
+  SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
+  if (!node) return NULL;
+  return SMDS_Mesh::Add0DElementWithID(node, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Mesh0DElement and add it to the current Mesh
+/// @return : The created Mesh0DElement
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElement(const SMDS_MeshNode * node)
+{
+  return SMDS_Mesh::Add0DElementWithID(node, myElementIDFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new Mesh0DElement and at it to the mesh
+/// @param idnode ID of the node
+/// @param ID ID of the 0D element to create
+/// @return The created 0D element or NULL if an element with this
+///         ID already exists or if input node is not found.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int ID)
+{
+  if (!n) return 0;
+
+  if (Nb0DElements() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+  //MESSAGE("Add0DElementWithID" << ID)
+  SMDS_Mesh0DElement * el0d = new SMDS_Mesh0DElement(n);
+  if (myElementIDFactory->BindID(ID, el0d)) {
+    //SMDS_MeshNode *node = const_cast<SMDS_MeshNode*>(n);
+    //node->AddInverseElement(el0d);// --- fait avec BindID
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = el0d;
+    myInfo.myNb0DElements++;
+    return el0d;
+  }
+
+  delete el0d;
+  return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Ball and add it to the current Mesh
+/// @return : The created Ball
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBallWithID(int idnode, double diameter, int ID)
+{
+  SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
+  if (!node) return NULL;
+  return SMDS_Mesh::AddBallWithID(node, diameter, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// create a Ball and add it to the current Mesh
+/// @return : The created Ball
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBall(const SMDS_MeshNode * node, double diameter)
+{
+  return SMDS_Mesh::AddBallWithID(node, diameter, myElementIDFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new Ball and at it to the mesh
+/// @param idnode ID of the node
+//  @param diameter ball diameter
+/// @param ID ID of the 0D element to create
+/// @return The created 0D element or NULL if an element with this
+///         ID already exists or if input node is not found.
+///////////////////////////////////////////////////////////////////////////////
+SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diameter, int ID)
+{
+  if (!n) return 0;
+
+  if (NbBalls() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+
+  SMDS_BallElement *ball = myBallPool->getNew();
+  ball->init(n->getVtkId(), diameter, this);
+  if (!this->registerElement(ID,ball))
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(ball->getVtkId(), VTK_EMPTY_CELL);
+    myBallPool->destroy(ball);
+    return 0;
+  }
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = ball;
+  myInfo.myNbBalls++;
+  return ball;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /// create a MeshEdge and add it to the current Mesh
 /// @return : The created MeshEdge
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID) 
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
 {
   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
@@ -123,7 +362,7 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
-                                 const SMDS_MeshNode * node2)
+                                  const SMDS_MeshNode * node2)
 {
   return SMDS_Mesh::AddEdgeWithID(node1, node2, myElementIDFactory->GetFreeID());
 }
@@ -138,23 +377,37 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
-                                       const SMDS_MeshNode * n2, 
-                                       int ID)
-{
-  SMDS_MeshEdge * edge=new SMDS_MeshEdge(n1,n2);
-  if(myElementIDFactory->BindID(ID, edge)) {
-    SMDS_MeshNode *node1,*node2;
-    node1=const_cast<SMDS_MeshNode*>(n1);
-    node2=const_cast<SMDS_MeshNode*>(n2);
-    node1->AddInverseElement(edge);
-    node2->AddInverseElement(edge);            
-    myEdges.Add(edge);
-    return edge;
-  } 
-  else {
-    delete edge;
-    return NULL;
-  }
+                                        const SMDS_MeshNode * n2,
+                                        int ID)
+{
+  if ( !n1 || !n2 ) return 0;
+  SMDS_MeshEdge * edge = 0;
+
+  // --- retreive nodes ID
+  vector<vtkIdType> nodeIds;
+  nodeIds.clear();
+  nodeIds.push_back(n1->getVtkId());
+  nodeIds.push_back(n2->getVtkId());
+
+  SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
+  edgevtk->init(nodeIds, this);
+  if (!this->registerElement(ID,edgevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
+      myEdgePool->destroy(edgevtk);
+      return 0;
+    }
+  edge = edgevtk;
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = edge;
+  myInfo.myNbEdges++;
+
+//  if (edge && !registerElement(ID, edge))
+//  {
+//    RemoveElement(edge, false);
+//    edge = NULL;
+//  }
+  return edge;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -163,8 +416,8 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
-                                 const SMDS_MeshNode * n2,
-                                 const SMDS_MeshNode * n3)
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3)
 {
   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myElementIDFactory->GetFreeID());
 }
@@ -179,7 +432,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, i
   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
   SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
   if(!node1 || !node2 || !node3) return NULL;
-  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);    
+  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -191,12 +444,13 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n3,
                                         int ID)
 {
-  SMDS_MeshFace * face=createTriangle(n1, n2, n3);
+  //MESSAGE("AddFaceWithID " << ID)
+  SMDS_MeshFace * face=createTriangle(n1, n2, n3, ID);
 
-  if (!registerElement(ID, face)) {
-    RemoveElement(face, false);
-    face = NULL;
-  }
+//  if (face && !registerElement(ID, face)) {
+//    RemoveElement(face, false);
+//    face = NULL;
+//  }
   return face;
 }
 
@@ -206,9 +460,9 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
-                                 const SMDS_MeshNode * n2,
-                                 const SMDS_MeshNode * n3,
-                                 const SMDS_MeshNode * n4)
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4)
 {
   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myElementIDFactory->GetFreeID());
 }
@@ -217,11 +471,11 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
 /// Add a quadrangle defined by its nodes IDs
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, 
-                                       int idnode2, 
-                                       int idnode3,
-                                       int idnode4, 
-                                       int ID)
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
+                                        int idnode2,
+                                        int idnode3,
+                                        int idnode4,
+                                        int ID)
 {
   SMDS_MeshNode *node1, *node2, *node3, *node4;
   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
@@ -229,7 +483,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
   if(!node1 || !node2 || !node3 || !node4) return NULL;
-  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);     
+  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -242,12 +496,13 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n4,
                                         int ID)
 {
-  SMDS_MeshFace * face=createQuadrangle(n1, n2, n3, n4);
+  //MESSAGE("AddFaceWithID " << ID);
+  SMDS_MeshFace * face=createQuadrangle(n1, n2, n3, n4, ID);
 
-  if (!registerElement(ID, face)) {
-    RemoveElement(face, false);
-    face = NULL;
-  }
+//  if (face && !registerElement(ID, face)) {
+//    RemoveElement(face, false);
+//    face = NULL;
+//  }
   return face;
 }
 
@@ -262,7 +517,8 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
 {
   if (!hasConstructionEdges())
     return NULL;
-  return AddFaceWithID(e1,e2,e3, myElementIDFactory->GetFreeID());
+     //MESSAGE("AddFaceWithID");
+ return AddFaceWithID(e1,e2,e3, myElementIDFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -276,12 +532,19 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
 {
   if (!hasConstructionEdges())
     return NULL;
+  if ( !e1 || !e2 || !e3 ) return 0;
+
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+
   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
-  myFaces.Add(face);
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = face;
+  myInfo.myNbTriangles++;
 
   if (!registerElement(ID, face)) {
-    RemoveElement(face, false);
-    face = NULL;
+    registerElement(myElementIDFactory->GetFreeID(), face);
+    //RemoveElement(face, false);
+    //face = NULL;
   }
   return face;
 }
@@ -298,7 +561,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
 {
   if (!hasConstructionEdges())
     return NULL;
 return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID());
+ return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -313,26 +576,31 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
 {
   if (!hasConstructionEdges())
     return NULL;
+  if ( !e1 || !e2 || !e3 || !e4 ) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
-  myFaces.Add(face);
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = face;
+  myInfo.myNbQuadrangles++;
 
   if (!registerElement(ID, face))
   {
-    RemoveElement(face, false);
-    face = NULL;
+    registerElement(myElementIDFactory->GetFreeID(), face);
+    //RemoveElement(face, false);
+    //face = NULL;
   }
   return face;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new tetrahedron and add it to the mesh. 
-///@return The created tetrahedron 
+///Create a new tetrahedron and add it to the mesh.
+///@return The created tetrahedron
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-                                     const SMDS_MeshNode * n2, 
-                                     const SMDS_MeshNode * n3,
-                                     const SMDS_MeshNode * n4)
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4)
 {
   int ID = myElementIDFactory->GetFreeID();
   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID);
@@ -341,17 +609,17 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new tetrahedron and add it to the mesh. 
+///Create a new tetrahedron and add it to the mesh.
 ///@param ID The ID of the new volume
 ///@return The created tetrahedron or NULL if an element with this ID already exists
 ///or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
-                                            int idnode2,
-                                            int idnode3, 
-                                            int idnode4, 
-                                            int ID)
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int ID)
 {
   SMDS_MeshNode *node1, *node2, *node3, *node4;
   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
@@ -361,11 +629,11 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
   if(!node1 || !node2 || !node3 || !node4) return NULL;
   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
 }
-       
+
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new tetrahedron and add it to the mesh. 
+///Create a new tetrahedron and add it to the mesh.
 ///@param ID The ID of the new volume
-///@return The created tetrahedron 
+///@return The created tetrahedron
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
@@ -374,42 +642,62 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n4,
                                             int ID)
 {
-  SMDS_MeshVolume* volume;
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4) return volume;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4);
     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n3,n4);
     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n3,n4);
     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
-    myVolumes.Add(volume);
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbTetras++;
   }
   else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
     return NULL;
   }
   else {
-    volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4);
-    myVolumes.Add(volume);
+    // --- retrieve nodes ID
+    myNodeIds.resize(4);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n3->getVtkId(); // order SMDS-->VTK
+    myNodeIds[2] = n2->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+
+    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+    volvtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,volvtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
+    volume = volvtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbTetras++;
   }
 
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
-  }
+  //  if (!registerElement(ID, volume)) {
+  //    RemoveElement(volume, false);
+  //    volume = NULL;
+  //  }
   return volume;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new pyramid and add it to the mesh. 
+///Create a new pyramid and add it to the mesh.
 ///Nodes 1,2,3 and 4 define the base of the pyramid
-///@return The created pyramid 
+///@return The created pyramid
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-                                     const SMDS_MeshNode * n2, 
-                                     const SMDS_MeshNode * n3,
-                                     const SMDS_MeshNode * n4, 
-                                     const SMDS_MeshNode * n5)
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5)
 {
   int ID = myElementIDFactory->GetFreeID();
   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, ID);
@@ -418,19 +706,19 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new pyramid and add it to the mesh. 
+///Create a new pyramid and add it to the mesh.
 ///Nodes 1,2,3 and 4 define the base of the pyramid
 ///@param ID The ID of the new volume
 ///@return The created pyramid or NULL if an element with this ID already exists
 ///or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
-                                            int idnode2,
-                                            int idnode3, 
-                                            int idnode4, 
-                                            int idnode5, 
-                                            int ID)
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int ID)
 {
   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
@@ -441,7 +729,7 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
   if(!node1 || !node2 || !node3 || !node4 || !node5) return NULL;
   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, ID);
 }
-       
+
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new pyramid and add it to the mesh.
 ///Nodes 1,2,3 and 4 define the base of the pyramid
@@ -456,43 +744,64 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n5,
                                             int ID)
 {
-  SMDS_MeshVolume* volume;
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n5);
     SMDS_MeshFace * f3=FindFaceOrCreate(n2,n3,n5);
     SMDS_MeshFace * f4=FindFaceOrCreate(n3,n4,n5);
     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
-    myVolumes.Add(volume);
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbPyramids++;
   }
   else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
     return NULL;
   }
   else {
-    volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5);
-    myVolumes.Add(volume);
+    // --- retrieve nodes ID
+    myNodeIds.resize(5);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n4->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n2->getVtkId();
+    myNodeIds[4] = n5->getVtkId();
+
+    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+    volvtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,volvtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
+    volume = volvtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbPyramids++;
   }
 
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
-  }
+  //  if (!registerElement(ID, volume)) {
+  //    RemoveElement(volume, false);
+  //    volume = NULL;
+  //  }
   return volume;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new prism and add it to the mesh. 
+///Create a new prism and add it to the mesh.
 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
-///@return The created prism 
+///@return The created prism
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-                                     const SMDS_MeshNode * n2, 
-                                     const SMDS_MeshNode * n3,
-                                     const SMDS_MeshNode * n4, 
-                                     const SMDS_MeshNode * n5,
-                                     const SMDS_MeshNode * n6)
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6)
 {
   int ID = myElementIDFactory->GetFreeID();
   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
@@ -501,20 +810,20 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new prism and add it to the mesh. 
+///Create a new prism and add it to the mesh.
 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
 ///@param ID The ID of the new volume
 ///@return The created prism or NULL if an element with this ID already exists
 ///or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
-                                            int idnode2,
-                                            int idnode3, 
-                                            int idnode4, 
-                                            int idnode5, 
-                                            int idnode6, 
-                                            int ID)
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int ID)
 {
   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
@@ -526,7 +835,7 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
   if(!node1 || !node2 || !node3 || !node4 || !node5 || !node6) return NULL;
   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
 }
-       
+
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new prism and add it to the mesh.
 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
@@ -542,7 +851,9 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n6,
                                             int ID)
 {
-  SMDS_MeshVolume* volume;
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
     SMDS_MeshFace * f2=FindFaceOrCreate(n4,n5,n6);
@@ -550,62 +861,211 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n5,n6,n3);
     SMDS_MeshFace * f5=FindFaceOrCreate(n3,n6,n4,n1);
     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
-    myVolumes.Add(volume);
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbPrisms++;
   }
   else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
     return NULL;
   }
   else {
-    volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6);
-    myVolumes.Add(volume);
+    // --- retrieve nodes ID
+    myNodeIds.resize(6);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+    myNodeIds[4] = n5->getVtkId();
+    myNodeIds[5] = n6->getVtkId();
+
+    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+    volvtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,volvtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
+    volume = volvtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbPrisms++;
   }
 
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+  //  if (!registerElement(ID, volume)) {
+  //    RemoveElement(volume, false);
+  //    volume = NULL;
+  //  }
+  return volume;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
+                                      const SMDS_MeshNode * n7,
+                                      const SMDS_MeshNode * n8,
+                                      const SMDS_MeshNode * n9,
+                                      const SMDS_MeshNode * n10,
+                                      const SMDS_MeshNode * n11,
+                                      const SMDS_MeshNode * n12)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6,
+                                                   n7, n8, n9, n10, n11, n12,
+                                                   ID);
+  if(v==NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created prism or NULL if an element with this ID already exists
+///or if input nodes are not found.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int idnode7,
+                                             int idnode8,
+                                             int idnode9,
+                                             int idnode10,
+                                             int idnode11,
+                                             int idnode12,
+                                             int ID)
+{
+  SMDS_MeshNode *node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
+  SMDS_MeshNode *node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
+  SMDS_MeshNode *node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
+  SMDS_MeshNode *node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
+  SMDS_MeshNode *node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
+  SMDS_MeshNode *node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
+  SMDS_MeshNode *node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
+  SMDS_MeshNode *node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
+  SMDS_MeshNode *node9 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode9);
+  SMDS_MeshNode *node10 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode10);
+  SMDS_MeshNode *node11 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode11);
+  SMDS_MeshNode *node12 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode12);
+  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
+                                    node7, node8, node9, node10, node11, node12,
+                                    ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///Create a new hexagonal prism and add it to the mesh.
+///@param ID The ID of the new volume
+///@return The created prism
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
+                                            const SMDS_MeshNode * n7,
+                                            const SMDS_MeshNode * n8,
+                                            const SMDS_MeshNode * n9,
+                                            const SMDS_MeshNode * n10,
+                                            const SMDS_MeshNode * n11,
+                                            const SMDS_MeshNode * n12,
+                                            int ID)
+{
+  SMDS_MeshVolume* volume = 0;
+  if(!n1 || !n2 || !n3 || !n4 || !n5 || !n6 ||
+     !n7 || !n8 || !n9 || !n10 || !n11 || !n12 )
+    return volume;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if(hasConstructionFaces()) {
+    return NULL;
+  }
+  else if(hasConstructionEdges()) {
+    return NULL;
+  }
+  else {
+    // --- retrieve nodes ID
+    myNodeIds.resize(12);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n6->getVtkId();
+    myNodeIds[2] = n5->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+    myNodeIds[4] = n3->getVtkId();
+    myNodeIds[5] = n2->getVtkId();
+
+    myNodeIds[6] = n7->getVtkId();
+    myNodeIds[7] = n12->getVtkId();
+    myNodeIds[8] = n11->getVtkId();
+    myNodeIds[9] = n10->getVtkId();
+    myNodeIds[10] = n9->getVtkId();
+    myNodeIds[11] = n8->getVtkId();
+
+    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+    volvtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,volvtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
+    volume = volvtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbHexPrism++;
   }
+
   return volume;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new hexahedron and add it to the mesh. 
+///Create a new hexahedron and add it to the mesh.
 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
-///@return The created hexahedron 
+///@return The created hexahedron
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-                                     const SMDS_MeshNode * n2, 
-                                     const SMDS_MeshNode * n3,
-                                     const SMDS_MeshNode * n4, 
-                                     const SMDS_MeshNode * n5,
-                                     const SMDS_MeshNode * n6, 
-                                     const SMDS_MeshNode * n7,
-                                     const SMDS_MeshNode * n8)
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
+                                      const SMDS_MeshNode * n7,
+                                      const SMDS_MeshNode * n8)
 {
   int ID = myElementIDFactory->GetFreeID();
 SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
+ SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
   if(v==NULL) myElementIDFactory->ReleaseID(ID);
   return v;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a new hexahedron and add it to the mesh. 
+///Create a new hexahedron and add it to the mesh.
 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
 ///@param ID The ID of the new volume
 ///@return The created hexahedron or NULL if an element with this ID already
 ///exists or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
-                                            int idnode2,
-                                            int idnode3, 
-                                            int idnode4, 
-                                            int idnode5, 
-                                            int idnode6, 
-                                            int idnode7,
-                                            int idnode8, 
-                                            int ID)
+SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
+                                             int idnode2,
+                                             int idnode3,
+                                             int idnode4,
+                                             int idnode5,
+                                             int idnode6,
+                                             int idnode7,
+                                             int idnode8,
+                                             int ID)
 {
   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
@@ -621,7 +1081,7 @@ SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
                                     node7, node8, ID);
 }
-       
+
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new hexahedron and add it to the mesh.
 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
@@ -640,7 +1100,9 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n8,
                                             int ID)
 {
-  SMDS_MeshVolume* volume;
+  SMDS_MeshVolume* volume = 0;
+  if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
     SMDS_MeshFace * f2=FindFaceOrCreate(n5,n6,n7,n8);
@@ -649,22 +1111,43 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     SMDS_MeshFace * f5=FindFaceOrCreate(n2,n3,n7,n6);
     SMDS_MeshFace * f6=FindFaceOrCreate(n3,n4,n8,n7);
     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
-    myVolumes.Add(volume);
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbHexas++;
   }
   else if(hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
     return NULL;
   }
   else {
-//    volume=new SMDS_HexahedronOfNodes(n1,n2,n3,n4,n5,n6,n7,n8);
-    volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8);
-    myVolumes.Add(volume);
+    // --- retrieve nodes ID
+    myNodeIds.resize(8);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n4->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n2->getVtkId();
+    myNodeIds[4] = n5->getVtkId();
+    myNodeIds[5] = n8->getVtkId();
+    myNodeIds[6] = n7->getVtkId();
+    myNodeIds[7] = n6->getVtkId();
+
+    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+    volvtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,volvtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
+    volume = volvtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbHexas++;
   }
 
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
-  }
+  //  if (!registerElement(ID, volume)) {
+  //    RemoveElement(volume, false);
+  //    volume = NULL;
+  //  }
   return volume;
 }
 
@@ -686,7 +1169,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new tetrahedron defined by its faces and add it to the mesh.
 ///@param ID The ID of the new volume
-///@return The created tetrahedron 
+///@return The created tetrahedron
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
@@ -697,12 +1180,17 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
 {
   if (!hasConstructionFaces())
     return NULL;
+  if ( !f1 || !f2 || !f3 || !f4) return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4);
-  myVolumes.Add(volume);
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volume;
+  myInfo.myNbTetras++;
 
   if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+    registerElement(myElementIDFactory->GetFreeID(), volume);
+    //RemoveElement(volume, false);
+    //volume = NULL;
   }
   return volume;
 }
@@ -718,7 +1206,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
                                       const SMDS_MeshFace * f4,
                                       const SMDS_MeshFace * f5)
 {
 if (!hasConstructionFaces())
+ if (!hasConstructionFaces())
     return NULL;
   return AddVolumeWithID(f1,f2,f3,f4,f5, myElementIDFactory->GetFreeID());
 }
@@ -726,7 +1214,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new pyramid defined by its faces and add it to the mesh.
 ///@param ID The ID of the new volume
-///@return The created pyramid 
+///@return The created pyramid
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
@@ -738,12 +1226,17 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
 {
   if (!hasConstructionFaces())
     return NULL;
+  if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
-  myVolumes.Add(volume);
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volume;
+  myInfo.myNbPyramids++;
 
   if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+    registerElement(myElementIDFactory->GetFreeID(), volume);
+    //RemoveElement(volume, false);
+    //volume = NULL;
   }
   return volume;
 }
@@ -760,7 +1253,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
                                       const SMDS_MeshFace * f5,
                                       const SMDS_MeshFace * f6)
 {
 if (!hasConstructionFaces())
+ if (!hasConstructionFaces())
     return NULL;
   return AddVolumeWithID(f1,f2,f3,f4,f5,f6, myElementIDFactory->GetFreeID());
 }
@@ -768,7 +1261,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
 ///////////////////////////////////////////////////////////////////////////////
 ///Create a new prism defined by its faces and add it to the mesh.
 ///@param ID The ID of the new volume
-///@return The created prism 
+///@return The created prism
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
@@ -781,12 +1274,17 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
 {
   if (!hasConstructionFaces())
     return NULL;
+  if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0;
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
-  myVolumes.Add(volume);
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volume;
+  myInfo.myNbPrisms++;
 
   if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+    registerElement(myElementIDFactory->GetFreeID(), volume);
+    //RemoveElement(volume, false);
+    //volume = NULL;
   }
   return volume;
 }
@@ -795,43 +1293,54 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
 /// Add a polygon defined by its nodes IDs
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (std::vector<int> nodes_ids,
-                                                  const int        ID)
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const vector<int> & nodes_ids,
+                                                  const int           ID)
 {
   int nbNodes = nodes_ids.size();
-  std::vector<const SMDS_MeshNode*> nodes (nbNodes);
+  vector<const SMDS_MeshNode*> nodes (nbNodes);
   for (int i = 0; i < nbNodes; i++) {
     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
     if (!nodes[i]) return NULL;
   }
-  return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID); 
+  return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Add a polygon defined by its nodes
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
-                          (std::vector<const SMDS_MeshNode*> nodes,
-                           const int                         ID)
+SMDS_MeshFace*
+SMDS_Mesh::AddPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
+                                   const int                            ID)
 {
   SMDS_MeshFace * face;
 
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
   if (hasConstructionEdges())
   {
-    MESSAGE("Error : Not implemented");
     return NULL;
   }
   else
   {
-    face = new SMDS_PolygonalFaceOfNodes(nodes);
-    myFaces.Add(face);
-  }
+    myNodeIds.resize( nodes.size() );
+    for ( size_t i = 0; i < nodes.size(); ++i )
+      myNodeIds[i] = nodes[i]->getVtkId();
 
-  if (!registerElement(ID, face)) {
-    RemoveElement(face, false);
-    face = NULL;
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->initPoly(myNodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbPolygons++;
   }
+
   return face;
 }
 
@@ -840,25 +1349,87 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
 /// An ID is automatically affected to the created face.
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (std::vector<const SMDS_MeshNode*> nodes)
+SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
 {
   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Create a new polyhedral volume and add it to the mesh. 
+/// Add a quadratic polygon defined by its nodes IDs
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<int> & nodes_ids,
+                                                      const int           ID)
+{
+  vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
+  for ( size_t i = 0; i < nodes.size(); i++) {
+    nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
+    if (!nodes[i]) return NULL;
+  }
+  return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace*
+SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
+                                       const int                            ID)
+{
+  SMDS_MeshFace * face;
+
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if (hasConstructionEdges())
+  {
+    return NULL;
+  }
+  else
+  {
+    myNodeIds.resize( nodes.size() );
+    for ( size_t i = 0; i < nodes.size(); ++i )
+      myNodeIds[i] = nodes[i]->getVtkId();
+
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->initQuadPoly(myNodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbQuadPolygons++;
+  }
+  return face;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Add a quadratic polygon defined by its nodes.
+/// An ID is automatically affected to the created face.
+///////////////////////////////////////////////////////////////////////////////
+
+SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
+{
+  return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Create a new polyhedral volume and add it to the mesh.
 /// @param ID The ID of the new volume
 /// @return The created volume or NULL if an element with this ID already exists
 /// or if input nodes are not found.
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
-                             (std::vector<int> nodes_ids,
-                              std::vector<int> quantities,
-                              const int        ID)
+                             (const vector<int> & nodes_ids,
+                              const vector<int> & quantities,
+                              const int           ID)
 {
   int nbNodes = nodes_ids.size();
-  std::vector<const SMDS_MeshNode*> nodes (nbNodes);
+  vector<const SMDS_MeshNode*> nodes (nbNodes);
   for (int i = 0; i < nbNodes; i++) {
     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
     if (!nodes[i]) return NULL;
@@ -867,43 +1438,73 @@ SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Create a new polyhedral volume and add it to the mesh. 
+/// Create a new polyhedral volume and add it to the mesh.
 /// @param ID The ID of the new volume
 /// @return The created  volume
 ///////////////////////////////////////////////////////////////////////////////
 
-SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
-                            (std::vector<const SMDS_MeshNode*> nodes,
-                             std::vector<int>                  quantities,
-                             const int                         ID)
+SMDS_MeshVolume*
+SMDS_Mesh::AddPolyhedralVolumeWithID (const vector<const SMDS_MeshNode*>& nodes,
+                                      const vector<int>                 & quantities,
+                                      const int                           ID)
 {
-  SMDS_MeshVolume* volume;
-  if (hasConstructionFaces()) {
-    MESSAGE("Error : Not implemented");
+  SMDS_MeshVolume* volume = 0;
+  if ( nodes.empty() || quantities.empty() )
     return NULL;
-  } else if (hasConstructionEdges()) {
-    MESSAGE("Error : Not implemented");
+  if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if (hasConstructionFaces())
+  {
     return NULL;
-  } else {
-    volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
-    myVolumes.Add(volume);
   }
-
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+  else if (hasConstructionEdges())
+  {
+    return NULL;
   }
+  else
+  {
+    //#ifdef VTK_HAVE_POLYHEDRON
+    myNodeIds.resize( nodes.size() );
+    for ( size_t i = 0; i < nodes.size(); ++i )
+      myNodeIds[i] = nodes[i]->getVtkId();
+
+    SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+    volvtk->initPoly(myNodeIds, quantities, this);
+    if (!this->registerElement(ID, volvtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
+    volume = volvtk;
+    //#else
+    //      for ( int i = 0; i < nodes.size(); ++i )
+    //      if ( !nodes[ i ] ) return 0;
+    //      volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
+    //#endif
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = volume;
+    myInfo.myNbPolyhedrons++;
+  }
+
+  //#ifndef VTK_HAVE_POLYHEDRON
+  //  if (!registerElement(ID, volume))
+  //    {
+  //      registerElement(myElementIDFactory->GetFreeID(), volume);
+  //      //RemoveElement(volume, false);
+  //      //volume = NULL;
+  //    }
+  //#endif
   return volume;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Create a new polyhedral volume and add it to the mesh. 
+/// Create a new polyhedral volume and add it to the mesh.
 /// @return The created  volume
 ///////////////////////////////////////////////////////////////////////////////
 
 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
-                            (std::vector<const SMDS_MeshNode*> nodes,
-                             std::vector<int>                  quantities)
+                            (const vector<const SMDS_MeshNode*> & nodes,
+                             const vector<int>                  & quantities)
 {
   int ID = myElementIDFactory->GetFreeID();
   SMDS_MeshVolume * v = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
@@ -911,56 +1512,232 @@ SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
   return v;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-/// Registers element with the given ID, maintains inverse connections
-///////////////////////////////////////////////////////////////////////////////
-bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement * element)
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
 {
-  if (myElementIDFactory->BindID(ID, element)) {
-    SMDS_ElemIteratorPtr it = element->nodesIterator();
-    while (it->more()) {
-      SMDS_MeshNode *node = static_cast<SMDS_MeshNode*>
-        (const_cast<SMDS_MeshElement*>(it->next()));
-      node->AddInverseElement(element);
-    }
-    return true;
-  }
-  return false;
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeFromVtkIdsWithID(vtkNodeIds, ID);
+  if (v == NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
+}
+
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
+{
+  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+  volvtk->init(vtkNodeIds, this);
+  if (!this->registerElement(ID,volvtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+      myVolumePool->destroy(volvtk);
+      return 0;
+    }
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volvtk;
+  vtkIdType aVtkType = volvtk->GetVtkType();
+  switch (aVtkType)
+  {
+    case VTK_TETRA:
+      myInfo.myNbTetras++;
+      break;
+    case VTK_PYRAMID:
+      myInfo.myNbPyramids++;
+      break;
+    case VTK_WEDGE:
+      myInfo.myNbPrisms++;
+      break;
+    case VTK_HEXAHEDRON:
+      myInfo.myNbHexas++;
+      break;
+    case VTK_QUADRATIC_TETRA:
+      myInfo.myNbQuadTetras++;
+      break;
+    case VTK_QUADRATIC_PYRAMID:
+      myInfo.myNbQuadPyramids++;
+      break;
+    case VTK_QUADRATIC_WEDGE:
+      myInfo.myNbQuadPrisms++;
+      break;
+    case VTK_QUADRATIC_HEXAHEDRON:
+      myInfo.myNbQuadHexas++;
+      break;
+//#ifdef VTK_HAVE_POLYHEDRON
+    case VTK_POLYHEDRON:
+      myInfo.myNbPolyhedrons++;
+      break;
+//#endif
+    default:
+      myInfo.myNbPolyhedrons++;
+      break;
+  }
+  return volvtk;
+}
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshFace * f = SMDS_Mesh::AddFaceFromVtkIdsWithID(vtkNodeIds, ID);
+  if (f == NULL) myElementIDFactory->ReleaseID(ID);
+  return f;
+}
+
+SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
+{
+  SMDS_VtkFace *facevtk = myFacePool->getNew();
+  facevtk->init(vtkNodeIds, this);
+  if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = facevtk;
+  vtkIdType aVtkType = facevtk->GetVtkType();
+  switch (aVtkType)
+  {
+    case VTK_TRIANGLE:
+      myInfo.myNbTriangles++;
+      break;
+    case VTK_QUAD:
+      myInfo.myNbQuadrangles++;
+      break;
+    case VTK_QUADRATIC_TRIANGLE:
+      myInfo.myNbQuadTriangles++;
+      break;
+    case VTK_QUADRATIC_QUAD:
+      myInfo.myNbQuadQuadrangles++;
+      break;
+    case VTK_BIQUADRATIC_QUAD:
+      myInfo.myNbBiQuadQuadrangles++;
+      break;
+    case VTK_BIQUADRATIC_TRIANGLE:
+      myInfo.myNbBiQuadTriangles++;
+      break;
+    case VTK_POLYGON:
+      myInfo.myNbPolygons++;
+      break;
+     default:
+      myInfo.myNbPolygons++;
+  }
+  return facevtk;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Registers element with the given ID, maintains inverse connections
+///////////////////////////////////////////////////////////////////////////////
+bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement* element)
+{
+  if ((ID >=0) && (ID < (int)myCells.size()) && myCells[ID]) // --- already bound
+  {
+    MESSAGE(" ------------------ already bound "<< ID << " " << myCells[ID]->getVtkId());
+    return false;
+  }
+
+  element->myID = ID;
+  element->myMeshId = myMeshId;
+
+  SMDS_MeshCell *cell = dynamic_cast<SMDS_MeshCell*>(element);
+  MYASSERT(cell);
+  int vtkId = cell->getVtkId();  
+  if (vtkId == -1)
+    vtkId = myElementIDFactory->SetInVtkGrid(element);
+
+  if (vtkId >= (int)myCellIdVtkToSmds.size()) // --- resize local vector
+  {
+    myCellIdVtkToSmds.resize(vtkId + SMDS_Mesh::chunkSize, -1);
+  }
+  myCellIdVtkToSmds[vtkId] = ID;
+
+  myElementIDFactory->updateMinMax(ID);
+  return true;
+}
+
+//=======================================================================
+//function : MoveNode
+//purpose  : 
+//=======================================================================
+
+void SMDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
+{
+  SMDS_MeshNode * node=const_cast<SMDS_MeshNode*>(n);
+  node->setXYZ(x,y,z);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Return the node whose ID is 'ID'.
-///////////////////////////////////////////////////////////////////////////////
+/// Return the node whose SMDS ID is 'ID'.
+///////////////////////////////////////////////////////////////////////////////
 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
 {
-  return (const SMDS_MeshNode *)myNodeIDFactory->MeshElement(ID);
+  if (ID < 1 || ID >= (int)myNodes.size())
+  {
+    return 0;
+  }
+  return (const SMDS_MeshNode *)myNodes[ID];
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the node whose VTK ID is 'vtkId'.
+///////////////////////////////////////////////////////////////////////////////
+const SMDS_MeshNode * SMDS_Mesh::FindNodeVtk(int vtkId) const
+{
+  // TODO if needed use mesh->nodeIdFromVtkToSmds
+  if ( vtkId < 0 || vtkId+1 >= (int) myNodes.size() )
+  {
+    MESSAGE("------------------------------------------------------------------------- ");
+    MESSAGE("---------------------------- bad VTK ID " << vtkId << " " << myNodes.size());
+    MESSAGE("------------------------------------------------------------------------- ");
+    return 0;
+  }
+  return (const SMDS_MeshNode *)myNodes[vtkId+1];
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Create a triangle and add it to the current mesh. This methode do not bind a
+///Create a triangle and add it to the current mesh. This method do not bind an
 ///ID to the create triangle.
 ///////////////////////////////////////////////////////////////////////////////
 SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
                                           const SMDS_MeshNode * node2,
-                                          const SMDS_MeshNode * node3)
+                                          const SMDS_MeshNode * node3,
+                                          int ID)
 {
-       if(hasConstructionEdges())
-       {
-               SMDS_MeshEdge *edge1, *edge2, *edge3;
-               edge1=FindEdgeOrCreate(node1,node2);
-               edge2=FindEdgeOrCreate(node2,node3);
-               edge3=FindEdgeOrCreate(node3,node1);
-
-               SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
-               myFaces.Add(face);
-               return face;
-       }
-       else
-       {
-               SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3);
-               myFaces.Add(face);
-               return face;
-       }
+  if ( !node1 || !node2 || !node3) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if(hasConstructionEdges())
+  {
+    SMDS_MeshEdge *edge1, *edge2, *edge3;
+    edge1=FindEdgeOrCreate(node1,node2);
+    edge2=FindEdgeOrCreate(node2,node3);
+    edge3=FindEdgeOrCreate(node3,node1);
+
+    //int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
+    SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbTriangles++;
+    return face;
+  }
+  else
+  {
+    // --- retrieve nodes ID
+    myNodeIds.resize(3);
+    myNodeIds[0] = node1->getVtkId();
+    myNodeIds[1] = node2->getVtkId();
+    myNodeIds[2] = node3->getVtkId();
+
+    SMDS_MeshFace * face = 0;
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->init(myNodeIds, this); // put in vtkUnstructuredGrid
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbTriangles++;
+    return face;
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -968,28 +1745,51 @@ SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
 ///a ID to the create triangle.
 ///////////////////////////////////////////////////////////////////////////////
 SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
-                                           const SMDS_MeshNode * node2,
-                                           const SMDS_MeshNode * node3,
-                                           const SMDS_MeshNode * node4)
-{
-       if(hasConstructionEdges())
-       {
-               SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
-               edge1=FindEdgeOrCreate(node1,node2);
-               edge2=FindEdgeOrCreate(node2,node3);
-               edge3=FindEdgeOrCreate(node3,node4);
-               edge4=FindEdgeOrCreate(node4,node1);
-
-               SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
-               myFaces.Add(face);
-               return face;
-       }
-       else
-       {
-               SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3,node4);
-               myFaces.Add(face);
-               return face;
-       }
+                                            const SMDS_MeshNode * node2,
+                                            const SMDS_MeshNode * node3,
+                                            const SMDS_MeshNode * node4,
+                                            int ID)
+{
+  if ( !node1 || !node2 || !node3 || !node4 ) return 0;
+  if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+  if(hasConstructionEdges())
+  {
+    SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
+    edge1=FindEdgeOrCreate(node1,node2);
+    edge2=FindEdgeOrCreate(node2,node3);
+    edge3=FindEdgeOrCreate(node3,node4);
+    edge4=FindEdgeOrCreate(node4,node1);
+
+    SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbQuadrangles++;
+    return face;
+  }
+  else
+  {
+    // --- retrieve nodes ID
+    myNodeIds.resize(4);
+    myNodeIds[0] = node1->getVtkId();
+    myNodeIds[1] = node2->getVtkId();
+    myNodeIds[2] = node3->getVtkId();
+    myNodeIds[3] = node4->getVtkId();
+
+    SMDS_MeshFace * face = 0;
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbQuadrangles++;
+    return face;
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -998,7 +1798,16 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
 
 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
 {
-       RemoveElement(node, true);
+  RemoveElement(node, true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Remove an edge and all the elements which own this edge
+///////////////////////////////////////////////////////////////////////////////
+
+void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d)
+{
+  RemoveElement(elem0d,true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1007,7 +1816,7 @@ void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
 
 void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
 {
-       RemoveElement(edge,true);
+  RemoveElement(edge,true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1016,7 +1825,7 @@ void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
 
 void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
 {
-       RemoveElement(face, true);
+  RemoveElement(face, true);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1025,7 +1834,7 @@ void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
 
 void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
 {
-       RemoveElement(volume, true);
+  RemoveElement(volume, true);
 }
 
 //=======================================================================
@@ -1035,8 +1844,8 @@ void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
 
 bool SMDS_Mesh::RemoveFromParent()
 {
-       if (myParent==NULL) return false;
-       else return (myParent->RemoveSubMesh(this));
+  if (myParent==NULL) return false;
+  else return (myParent->RemoveSubMesh(this));
 }
 
 //=======================================================================
@@ -1046,124 +1855,65 @@ bool SMDS_Mesh::RemoveFromParent()
 
 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
 {
-       bool found = false;
+  bool found = false;
 
-       list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
-       for (; itmsh!=myChildren.end() && !found; itmsh++)
-       {
-               SMDS_Mesh * submesh = *itmsh;
-               if (submesh == aMesh)
-               {
-                       found = true;
-                       myChildren.erase(itmsh);
-               }
-       }
+  list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
+  for (; itmsh!=myChildren.end() && !found; itmsh++)
+  {
+    SMDS_Mesh * submesh = *itmsh;
+    if (submesh == aMesh)
+    {
+      found = true;
+      myChildren.erase(itmsh);
+    }
+  }
 
-       return found;
+  return found;
 }
 
 //=======================================================================
 //function : ChangeElementNodes
-//purpose  : 
+//purpose  :
 //=======================================================================
 
-bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
+bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
                                    const SMDS_MeshNode    * nodes[],
                                    const int                nbnodes)
 {
   // keep current nodes of elem
-  set<const SMDS_MeshElement*> oldNodes;
-  SMDS_ElemIteratorPtr itn = elem->nodesIterator();
-  while(itn->more())
-    oldNodes.insert(  itn->next() );
+  set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
 
   // change nodes
   bool Ok = false;
-  switch ( elem->GetType() )
+  SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element);
+  if (cell)
   {
-  case SMDSAbs_Edge: {
-    if ( nbnodes == 2 ) {
-      const SMDS_MeshEdge* edge = dynamic_cast<const SMDS_MeshEdge*>( elem );
-      if ( edge )
-        Ok = const_cast<SMDS_MeshEdge*>( edge )->ChangeNodes( nodes[0], nodes[1] );
-    }
-    else if ( nbnodes == 3 ) {
-      const SMDS_QuadraticEdge* edge = dynamic_cast<const SMDS_QuadraticEdge*>( elem );
-      if ( edge )
-        Ok = const_cast<SMDS_QuadraticEdge*>( edge )->ChangeNodes( nodes[0], nodes[1], nodes[2] );
-    }
-    break;
-  }
-  case SMDSAbs_Face: {
-    const SMDS_FaceOfNodes* face = dynamic_cast<const SMDS_FaceOfNodes*>( elem );
-    if ( face ) {
-      Ok = const_cast<SMDS_FaceOfNodes*>( face )->ChangeNodes( nodes, nbnodes );
-    }
-    else {
-      const SMDS_QuadraticFaceOfNodes* QF =
-        dynamic_cast<const SMDS_QuadraticFaceOfNodes*>( elem );
-      if ( QF ) {
-        Ok = const_cast<SMDS_QuadraticFaceOfNodes*>( QF )->ChangeNodes( nodes, nbnodes );
-      }
-      else {
-        /// ??? begin
-        const SMDS_PolygonalFaceOfNodes* face = dynamic_cast<const SMDS_PolygonalFaceOfNodes*>(elem);
-        if (face) {
-          Ok = const_cast<SMDS_PolygonalFaceOfNodes*>(face)->ChangeNodes(nodes, nbnodes);
-        }
-        /// ??? end
-      }
-    }
-    break;
-  }
-  //case SMDSAbs_PolygonalFace: {
-  //  const SMDS_PolygonalFaceOfNodes* face = dynamic_cast<const SMDS_PolygonalFaceOfNodes*>(elem);
-  //  if (face) {
-  //    Ok = const_cast<SMDS_PolygonalFaceOfNodes*>(face)->ChangeNodes(nodes, nbnodes);
-  //  }
-  //  break;
-  //}
-  case SMDSAbs_Volume: {
-    const SMDS_VolumeOfNodes* vol = dynamic_cast<const SMDS_VolumeOfNodes*>( elem );
-    if ( vol ) {
-      Ok = const_cast<SMDS_VolumeOfNodes*>( vol )->ChangeNodes( nodes, nbnodes );
-    }
-    else {
-      const SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<const SMDS_QuadraticVolumeOfNodes*>( elem );
-      if ( QV ) {
-        Ok = const_cast<SMDS_QuadraticVolumeOfNodes*>( QV )->ChangeNodes( nodes, nbnodes );
-      }
-    }
-    break;
-  }
-  default:
-    MESSAGE ( "WRONG ELEM TYPE");
+    Ok = cell->vtkOrder(nodes, nbnodes);
+    Ok = cell->ChangeNodes(nodes, nbnodes);
   }
 
   if ( Ok ) { // update InverseElements
 
+    set<const SMDS_MeshNode*>::iterator it;
+
     // AddInverseElement to new nodes
-    for ( int i = 0; i < nbnodes; i++ )
-      if ( oldNodes.find( nodes[i] ) == oldNodes.end() )
+    for ( int i = 0; i < nbnodes; i++ ) {
+      it = oldNodes.find( nodes[i] );
+      if ( it == oldNodes.end() )
         // new node
-        const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( elem );
+        const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( cell );
       else
         // remove from oldNodes a node that remains in elem
-        oldNodes.erase( nodes[i] );
-
-
+        oldNodes.erase( it );
+    }
     // RemoveInverseElement from the nodes removed from elem
-    set<const SMDS_MeshElement*>::iterator it;
     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
     {
-      SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
-        (const_cast<SMDS_MeshElement *>( *it ));
-      n->RemoveInverseElement( elem );
+      SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
+      n->RemoveInverseElement( cell );
     }
   }
 
-  //MESSAGE ( "::ChangeNodes() Ok = " << Ok);
-
   return Ok;
 }
 
@@ -1171,16 +1921,16 @@ bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
 //function : ChangePolyhedronNodes
 //purpose  : to change nodes of polyhedral volume
 //=======================================================================
-bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
-                                       std::vector<const SMDS_MeshNode*> nodes,
-                                       std::vector<int>                  quantities)
+bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement *            elem,
+                                       const vector<const SMDS_MeshNode*>& nodes,
+                                       const vector<int>                 & quantities)
 {
   if (elem->GetType() != SMDSAbs_Volume) {
     MESSAGE("WRONG ELEM TYPE");
     return false;
   }
 
-  const SMDS_PolyhedralVolumeOfNodes* vol = dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>(elem);
+  const SMDS_VtkVolume* vol = dynamic_cast<const SMDS_VtkVolume*>(elem);
   if (!vol) {
     return false;
   }
@@ -1193,7 +1943,9 @@ bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
   }
 
   // change nodes
-  bool Ok = const_cast<SMDS_PolyhedralVolumeOfNodes*>(vol)->ChangeNodes(nodes, quantities);
+  // TODO remove this function
+  //bool Ok = const_cast<SMDS_VtkVolume*>(vol)->ChangeNodes(nodes, quantities);
+  bool Ok = false;
   if (!Ok) {
     return false;
   }
@@ -1202,18 +1954,19 @@ bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
 
   // AddInverseElement to new nodes
   int nbnodes = nodes.size();
+  set<const SMDS_MeshElement*>::iterator it;
   for (int i = 0; i < nbnodes; i++) {
-    if (oldNodes.find(nodes[i]) == oldNodes.end()) {
+    it = oldNodes.find(nodes[i]);
+    if (it == oldNodes.end()) {
       // new node
       const_cast<SMDS_MeshNode*>(nodes[i])->AddInverseElement(elem);
     } else {
       // remove from oldNodes a node that remains in elem
-      oldNodes.erase(nodes[i]);
+      oldNodes.erase(it);
     }
   }
 
   // RemoveInverseElement from the nodes removed from elem
-  set<const SMDS_MeshElement*>::iterator it;
   for (it = oldNodes.begin(); it != oldNodes.end(); it++) {
     SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
       (const_cast<SMDS_MeshElement *>( *it ));
@@ -1224,6 +1977,75 @@ bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
 }
 
 
+//=======================================================================
+//function : Find0DElement
+//purpose  :
+//=======================================================================
+const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(int idnode) const
+{
+  const SMDS_MeshNode * node = FindNode(idnode);
+  if(node == NULL) return NULL;
+  return Find0DElement(node);
+}
+
+const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
+{
+  if (!node) return 0;
+  const SMDS_Mesh0DElement* toReturn = NULL;
+  SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_0DElement);
+  while (it1->more() && (toReturn == NULL)) {
+    const SMDS_MeshElement* e = it1->next();
+    if (e->NbNodes() == 1) {
+      toReturn = static_cast<const SMDS_Mesh0DElement*>(e);
+    }
+  }
+  return toReturn;
+}
+
+//=======================================================================
+//function : FindBall
+//purpose  :
+//=======================================================================
+
+const SMDS_BallElement* SMDS_Mesh::FindBall(int idnode) const
+{
+  const SMDS_MeshNode * node = FindNode(idnode);
+  if(node == NULL) return NULL;
+  return FindBall(node);
+}
+
+const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
+{
+  if (!node) return 0;
+  const SMDS_BallElement* toReturn = NULL;
+  SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_Ball);
+  while (it1->more() && (toReturn == NULL)) {
+    const SMDS_MeshElement* e = it1->next();
+    if (e->GetGeomType() == SMDSGeom_BALL)
+      toReturn = static_cast<const SMDS_BallElement*>(e);
+  }
+  return toReturn;
+}
+
+//=======================================================================
+//function : Find0DElementOrCreate
+//purpose  :
+//=======================================================================
+//SMDS_Mesh0DElement* SMDS_Mesh::Find0DElementOrCreate(const SMDS_MeshNode * node)
+//{
+//  if (!node) return 0;
+//  SMDS_Mesh0DElement * toReturn = NULL;
+//  toReturn = const_cast<SMDS_Mesh0DElement*>(Find0DElement(node));
+//  if (toReturn == NULL) {
+//    //if (my0DElements.Extent() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
+//    toReturn = new SMDS_Mesh0DElement(node);
+//    my0DElements.Add(toReturn);
+//    myInfo.myNb0DElements++;
+//  }
+//  return toReturn;
+//}
+
+
 //=======================================================================
 //function : FindEdge
 //purpose  :
@@ -1241,20 +2063,18 @@ const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
                                          const SMDS_MeshNode * node2)
 {
+  if ( !node1 ) return 0;
   const SMDS_MeshEdge * toReturn=NULL;
   //PROFILER_Init();
   //PROFILER_Set();
-  SMDS_ElemIteratorPtr it1=node1->edgesIterator();
+  SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
   //PROFILER_Get(0);
   //PROFILER_Set();
   while(it1->more()) {
-    const SMDS_MeshEdge * e=static_cast<const SMDS_MeshEdge *> (it1->next());
-    SMDS_ElemIteratorPtr it2=e->nodesIterator();
-    while(it2->more()) {
-      if(it2->next()->GetID()==node2->GetID()) {
-        toReturn = e;
-        break;
-      }
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
+      toReturn = static_cast<const SMDS_MeshEdge*>( e );
+      break;
     }
   }
   //PROFILER_Get(1);
@@ -1268,14 +2088,31 @@ const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
 //=======================================================================
 
 SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
-                                           const SMDS_MeshNode * node2) 
+                                           const SMDS_MeshNode * node2)
 {
+  if ( !node1 || !node2) return 0;
   SMDS_MeshEdge * toReturn=NULL;
   toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
   if(toReturn==NULL) {
-    toReturn=new SMDS_MeshEdge(node1,node2);
-    myEdges.Add(toReturn);
-  } 
+    if ( NbEdges() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
+    int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
+    adjustmyCellsCapacity(ID);
+    myNodeIds.resize(2);
+    myNodeIds[0] = node1->getVtkId();
+    myNodeIds[1] = node2->getVtkId();
+
+    SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
+    edgevtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,edgevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
+      myEdgePool->destroy(edgevtk);
+      return 0;
+    }
+    toReturn = edgevtk;
+    myCells[ID] = toReturn;
+    myInfo.myNbEdges++;
+  }
   return toReturn;
 }
 
@@ -1291,7 +2128,6 @@ const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2,
   const SMDS_MeshNode * node1=FindNode(idnode1);
   const SMDS_MeshNode * node2=FindNode(idnode2);
   const SMDS_MeshNode * node3=FindNode(idnode3);
-  if( (node1==NULL) || (node2==NULL)  || (node3==NULL) ) return NULL;
   return FindEdge(node1,node2,node3);
 }
 
@@ -1299,24 +2135,27 @@ const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
                                          const SMDS_MeshNode * node2,
                                          const SMDS_MeshNode * node3)
 {
-  const SMDS_MeshEdge * toReturn = NULL;
-  SMDS_ElemIteratorPtr it1 = node1->edgesIterator();
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
   while(it1->more()) {
-    const SMDS_MeshEdge * e = static_cast<const SMDS_MeshEdge *> (it1->next());
-    SMDS_ElemIteratorPtr it2 = e->nodesIterator();
-    int tmp = 0;
-    while(it2->more()) {
-      int nID = it2->next()->GetID();
-      if( nID==node2->GetID() || nID==node3->GetID() ) {
-        tmp++;
-        if(tmp==2) {
-          toReturn = e;
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 3 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 )
+        {
+          e = 0;
           break;
         }
       }
+      if ( e )
+        return static_cast<const SMDS_MeshEdge *> (e);
     }
   }
-  return toReturn;
+  return 0;
 }
 
 
@@ -1326,12 +2165,11 @@ const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
 //=======================================================================
 
 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
-       int idnode3) const
+        int idnode3) const
 {
   const SMDS_MeshNode * node1=FindNode(idnode1);
   const SMDS_MeshNode * node2=FindNode(idnode2);
   const SMDS_MeshNode * node3=FindNode(idnode3);
-  if( (node1==NULL) || (node2==NULL) || (node3==NULL) ) return NULL;
   return FindFace(node1, node2, node3);
 }
 
@@ -1339,26 +2177,27 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node2,
                                          const SMDS_MeshNode *node3)
 {
-  const SMDS_MeshFace * face;
-  const SMDS_MeshElement * node;
-  bool node2found, node3found;
-
-  SMDS_ElemIteratorPtr it1 = node1->facesIterator();
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
   while(it1->more()) {
-    face = static_cast<const SMDS_MeshFace*>(it1->next());
-    if(face->NbNodes()!=3) continue;
-    SMDS_ElemIteratorPtr it2 = face->nodesIterator();
-    node2found = false;
-    node3found = false;
-    while(it2->more()) {
-      node = it2->next();
-      if(node->GetID()==node2->GetID()) node2found = true;
-      if(node->GetID()==node3->GetID()) node3found = true;
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 3 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
     }
-    if( node2found && node3found )
-      return face;
   }
-  return NULL;
+  return 0;
 }
 
 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
@@ -1368,7 +2207,8 @@ SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
   SMDS_MeshFace * toReturn=NULL;
   toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
   if(toReturn==NULL) {
-    toReturn = createTriangle(node1,node2,node3);
+    int ID = myElementIDFactory->GetFreeID();
+    toReturn = createTriangle(node1,node2,node3, ID);
   }
   return toReturn;
 }
@@ -1386,8 +2226,6 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
   const SMDS_MeshNode * node2=FindNode(idnode2);
   const SMDS_MeshNode * node3=FindNode(idnode3);
   const SMDS_MeshNode * node4=FindNode(idnode4);
-  if( (node1==NULL) || (node2==NULL) || (node3==NULL) || (node4==NULL) )
-    return NULL;
   return FindFace(node1, node2, node3, node4);
 }
 
@@ -1396,27 +2234,28 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node3,
                                          const SMDS_MeshNode *node4)
 {
-  const SMDS_MeshFace * face;
-  const SMDS_MeshElement * node;
-  bool node2found, node3found, node4found;
-  SMDS_ElemIteratorPtr it1 = node1->facesIterator();
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
   while(it1->more()) {
-    face = static_cast<const SMDS_MeshFace *>(it1->next());
-    if(face->NbNodes()!=4) continue;
-    SMDS_ElemIteratorPtr it2 = face->nodesIterator();
-    node2found = false;
-    node3found = false;
-    node4found = false;
-    while(it2->more()) {
-      node=it2->next();
-      if(node->GetID()==node2->GetID()) node2found = true;
-      if(node->GetID()==node3->GetID()) node3found = true;
-      if(node->GetID()==node4->GetID()) node4found = true;
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 4 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
     }
-    if( node2found && node3found && node4found )
-      return face;
   }
-  return NULL;
+  return 0;
 }
 
 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
@@ -1427,7 +2266,8 @@ SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
   SMDS_MeshFace * toReturn=NULL;
   toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
   if(toReturn==NULL) {
-    toReturn=createQuadrangle(node1,node2,node3,node4);
+    int ID = myElementIDFactory->GetFreeID();
+    toReturn=createQuadrangle(node1,node2,node3,node4,ID);
   }
   return toReturn;
 }
@@ -1448,8 +2288,6 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
   const SMDS_MeshNode * node4 = FindNode(idnode4);
   const SMDS_MeshNode * node5 = FindNode(idnode5);
   const SMDS_MeshNode * node6 = FindNode(idnode6);
-  if( (node1==NULL) || (node2==NULL) || (node3==NULL) ||
-      (node4==NULL) || (node5==NULL) || (node6==NULL) ) return NULL;
   return FindFace(node1, node2, node3, node4, node5, node6);
 }
 
@@ -1460,26 +2298,30 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node5,
                                          const SMDS_MeshNode *node6)
 {
-  const SMDS_MeshFace * face;
-  const SMDS_MeshElement * node;
-  SMDS_ElemIteratorPtr it1 = node1->facesIterator();
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
   while(it1->more()) {
-    face = static_cast<const SMDS_MeshFace*>(it1->next());
-    if(face->NbNodes()!=6) continue;
-    SMDS_ElemIteratorPtr it2 = face->nodesIterator();
-    int tmp = 0;
-    while(it2->more()) {
-      node = it2->next();
-      if(node->GetID()==node2->GetID()) tmp++;
-      if(node->GetID()==node3->GetID()) tmp++;
-      if(node->GetID()==node4->GetID()) tmp++;
-      if(node->GetID()==node5->GetID()) tmp++;
-      if(node->GetID()==node6->GetID()) tmp++;
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 6 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 &&
+            n!=node5 &&
+            n!=node6 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
     }
-    if( tmp==5 )
-      return static_cast<const SMDS_MeshFace*>(face);
   }
-  return NULL;
+  return 0;
 }
 
 
@@ -1501,9 +2343,6 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
   const SMDS_MeshNode * node6 = FindNode(idnode6);
   const SMDS_MeshNode * node7 = FindNode(idnode7);
   const SMDS_MeshNode * node8 = FindNode(idnode8);
-  if( (node1==NULL) || (node2==NULL) || (node3==NULL) || (node4==NULL) ||
-      (node5==NULL) || (node6==NULL) || (node7==NULL) || (node8==NULL) )
-    return NULL;
   return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
 }
 
@@ -1516,28 +2355,32 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node7,
                                          const SMDS_MeshNode *node8)
 {
-  const SMDS_MeshFace * face;
-  const SMDS_MeshElement * node;
-  SMDS_ElemIteratorPtr it1 = node1->facesIterator();
+  if ( !node1 ) return 0;
+  SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
   while(it1->more()) {
-    face = static_cast<const SMDS_MeshFace *>(it1->next());
-    if(face->NbNodes()!=8) continue;
-    SMDS_ElemIteratorPtr it2 = face->nodesIterator();
-    int tmp = 0;
-    while(it2->more()) {
-      node = it2->next();
-      if(node->GetID()==node2->GetID()) tmp++;
-      if(node->GetID()==node3->GetID()) tmp++;
-      if(node->GetID()==node4->GetID()) tmp++;
-      if(node->GetID()==node5->GetID()) tmp++;
-      if(node->GetID()==node6->GetID()) tmp++;
-      if(node->GetID()==node7->GetID()) tmp++;
-      if(node->GetID()==node8->GetID()) tmp++;
+    const SMDS_MeshElement * e = it1->next();
+    if ( e->NbNodes() == 8 ) {
+      SMDS_ElemIteratorPtr it2 = e->nodesIterator();
+      while(it2->more()) {
+        const SMDS_MeshElement* n = it2->next();
+        if( n!=node1 &&
+            n!=node2 &&
+            n!=node3 &&
+            n!=node4 &&
+            n!=node5 &&
+            n!=node6 &&
+            n!=node7 &&
+            n!=node8 )
+        {
+          e = 0;
+          break;
+        }
+      }
+      if ( e )
+        return static_cast<const SMDS_MeshFace *> (e);
     }
-    if( tmp==7 )
-      return face;
   }
-  return NULL;
+  return 0;
 }
 
 
@@ -1548,7 +2391,11 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
 
 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
 {
-  return myElementIDFactory->MeshElement(IDelem);
+  if ( IDelem <= 0 || IDelem >= (int)myCells.size() )
+  {
+    return 0;
+  }
+  return myCells[IDelem];
 }
 
 //=======================================================================
@@ -1556,146 +2403,163 @@ const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
 //purpose  : find polygon
 //=======================================================================
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<int> nodes_ids) const
+const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<int>& nodes_ids) const
 {
   int nbnodes = nodes_ids.size();
-  std::vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
+  vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
   for (int inode = 0; inode < nbnodes; inode++) {
     const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
     if (node == NULL) return NULL;
+    poly_nodes[inode] = node;
   }
   return FindFace(poly_nodes);
 }
 
-const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<const SMDS_MeshNode *> nodes)
+const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<const SMDS_MeshNode *>& nodes)
 {
-  int nbNodes = nodes.size();
-  if (nbNodes < 1) return NULL;
+  return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
+}
 
-  bool isFound = true;
-  const SMDS_MeshFace * face;
-  set<const SMDS_MeshFace *> faces;
 
-  for (int inode = 0; inode < nbNodes && isFound; inode++) {
-    set<const SMDS_MeshFace *> new_faces;
+//================================================================================
+/*!
+ * \brief Return element based on all given nodes
+ *  \param nodes - node of element
+ *  \param type - type of element
+ *  \param noMedium - true if medium nodes of quadratic element are not included in <nodes>
+ *  \retval const SMDS_MeshElement* - found element or NULL
+ */
+//================================================================================
 
-    SMDS_ElemIteratorPtr itF = nodes[inode]->facesIterator();
-    while (itF->more()) {
-      face = static_cast<const SMDS_MeshFace *>(itF->next());
-      if (face->NbNodes() == nbNodes) {
-        if (inode == 0 || faces.find(face) != faces.end()) {
-          new_faces.insert(face);
+const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode *>& nodes,
+                                                const SMDSAbs_ElementType            type,
+                                                const bool                           noMedium)
+{
+  if ( nodes.size() > 0 && nodes[0] )
+  {
+    SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(type);
+    while (itF->more())
+    {
+      const SMDS_MeshElement* e = itF->next();
+      int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
+      if ( nbNodesToCheck == (int)nodes.size() )
+      {
+        for ( size_t i = 1; e && i < nodes.size(); ++i )
+        {
+          int nodeIndex = e->GetNodeIndex( nodes[ i ]);
+          if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
+            e = 0;
         }
+        if ( e )
+          return e;
       }
     }
-    faces = new_faces;
-    if (new_faces.size() == 0) {
-      isFound = false;
-    }
   }
-
-  if (isFound)
-    return face;
-
   return NULL;
 }
 
 //=======================================================================
 //function : DumpNodes
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMDS_Mesh::DumpNodes() const
 {
-       MESSAGE("dump nodes of mesh : ");
-       SMDS_NodeIteratorPtr itnode=nodesIterator();
-       while(itnode->more()) MESSAGE(itnode->next());
+  SMDS_NodeIteratorPtr itnode=nodesIterator();
+  while(itnode->more()) ; //MESSAGE(itnode->next());
+}
+
+//=======================================================================
+//function : Dump0DElements
+//purpose  :
+//=======================================================================
+void SMDS_Mesh::Dump0DElements() const
+{
+  SMDS_ElemIteratorPtr it0d = elementsIterator(SMDSAbs_0DElement);
+  while(it0d->more()) ; //MESSAGE(it0d->next());
 }
 
 //=======================================================================
 //function : DumpEdges
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMDS_Mesh::DumpEdges() const
 {
-       MESSAGE("dump edges of mesh : ");
-       SMDS_EdgeIteratorPtr itedge=edgesIterator();
-       while(itedge->more()) MESSAGE(itedge->next());
+  SMDS_EdgeIteratorPtr itedge=edgesIterator();
+  while(itedge->more()) ; //MESSAGE(itedge->next());
 }
 
 //=======================================================================
 //function : DumpFaces
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMDS_Mesh::DumpFaces() const
 {
-       MESSAGE("dump faces of mesh : ");
-       SMDS_FaceIteratorPtr itface=facesIterator();
-       while(itface->more()) MESSAGE(itface->next());
+  SMDS_FaceIteratorPtr itface=facesIterator();
+  while(itface->more()) ; //MESSAGE(itface->next());
 }
 
 //=======================================================================
 //function : DumpVolumes
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMDS_Mesh::DumpVolumes() const
 {
-       MESSAGE("dump volumes of mesh : ");
-       SMDS_VolumeIteratorPtr itvol=volumesIterator();
-       while(itvol->more()) MESSAGE(itvol->next());
+  SMDS_VolumeIteratorPtr itvol=volumesIterator();
+  while(itvol->more()) ; //MESSAGE(itvol->next());
 }
 
 //=======================================================================
 //function : DebugStats
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 void SMDS_Mesh::DebugStats() const
 {
-       MESSAGE("Debug stats of mesh : ");
+  MESSAGE("Debug stats of mesh : ");
 
-       MESSAGE("===== NODES ====="<<NbNodes());
-       MESSAGE("===== EDGES ====="<<NbEdges());
-       MESSAGE("===== FACES ====="<<NbFaces());
-       MESSAGE("===== VOLUMES ====="<<NbVolumes());
+  MESSAGE("===== NODES ====="<<NbNodes());
+  MESSAGE("===== 0DELEMS ====="<<Nb0DElements());
+  MESSAGE("===== EDGES ====="<<NbEdges());
+  MESSAGE("===== FACES ====="<<NbFaces());
+  MESSAGE("===== VOLUMES ====="<<NbVolumes());
 
-       MESSAGE("End Debug stats of mesh ");
+  MESSAGE("End Debug stats of mesh ");
 
-       //#ifdef DEB
-       
-       SMDS_NodeIteratorPtr itnode=nodesIterator();
-       int sizeofnodes = 0;
-       int sizeoffaces = 0;
+  //#ifdef DEB
 
-       while(itnode->more())
-       {
-               const SMDS_MeshNode *node = itnode->next();
+  SMDS_NodeIteratorPtr itnode=nodesIterator();
+  int sizeofnodes = 0;
+  int sizeoffaces = 0;
 
-               sizeofnodes += sizeof(*node);
-               
-               SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
-               while(it->more())
-               {
-                       const SMDS_MeshElement *me = it->next();
-                       sizeofnodes += sizeof(me);
-               }
+  while(itnode->more())
+  {
+    const SMDS_MeshNode *node = itnode->next();
+
+    sizeofnodes += sizeof(*node);
 
-       }
+    SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
+    while(it->more())
+    {
+      const SMDS_MeshElement *me = it->next();
+      sizeofnodes += sizeof(me);
+    }
+  }
 
-       SMDS_FaceIteratorPtr itface=facesIterator();
-       while(itface->more())
-       {
-               const SMDS_MeshElement *face = itface->next();          
-               sizeoffaces += sizeof(*face);
+  SMDS_FaceIteratorPtr itface=facesIterator();
+  while(itface->more())
+  {
+    const SMDS_MeshElement *face = itface->next();
+    sizeoffaces += sizeof(*face);
+  }
 
-       }
-       MESSAGE("total size of node elements = " << sizeofnodes);;
-       MESSAGE("total size of face elements = " << sizeoffaces);;
+  MESSAGE("total size of node elements = " << sizeofnodes);;
+  MESSAGE("total size of face elements = " << sizeoffaces);;
 
-       //#endif
+  //#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1703,7 +2567,30 @@ void SMDS_Mesh::DebugStats() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbNodes() const
 {
-       return myNodes.Size();
+  return myInfo.NbNodes();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbElements() const
+{
+  return myInfo.NbElements();
+}
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of 0D elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::Nb0DElements() const
+{
+  return myInfo.Nb0DElements();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+/// Return the number of 0D elements
+///////////////////////////////////////////////////////////////////////////////
+int SMDS_Mesh::NbBalls() const
+{
+  return myInfo.NbBalls();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1711,7 +2598,7 @@ int SMDS_Mesh::NbNodes() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbEdges() const
 {
-       return myEdges.Size();
+  return myInfo.NbEdges();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1719,7 +2606,7 @@ int SMDS_Mesh::NbEdges() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbFaces() const
 {
-       return myFaces.Size();
+  return myInfo.NbFaces();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1727,17 +2614,16 @@ int SMDS_Mesh::NbFaces() const
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbVolumes() const
 {
-       return myVolumes.Size();
+  return myInfo.NbVolumes();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Return the number of child mesh of this mesh.
-/// Note that the tree structure of SMDS_Mesh seems to be unused in this version
-/// (2003-09-08) of SMESH
+/// Note that the tree structure of SMDS_Mesh is unused in SMESH
 ///////////////////////////////////////////////////////////////////////////////
 int SMDS_Mesh::NbSubMesh() const
 {
-       return myChildren.size();
+  return myChildren.size();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1753,52 +2639,115 @@ SMDS_Mesh::~SMDS_Mesh()
     itc++;
   }
 
-  SetOfNodes::Iterator itn(myNodes);
-  for (; itn.More(); itn.Next())
-    delete itn.Value();
-
-  SetOfEdges::Iterator ite(myEdges);
-  for (; ite.More(); ite.Next())
-  {
-    SMDS_MeshElement* elem = ite.Value();
-    if(myParent!=NULL)
-      myElementIDFactory->ReleaseID(elem->GetID());
-    delete elem;
-  }
-
-  SetOfFaces::Iterator itf(myFaces);
-  for (; itf.More(); itf.Next())
-  {
-    SMDS_MeshElement* elem = itf.Value();
-    if(myParent!=NULL)
-      myElementIDFactory->ReleaseID(elem->GetID());
-    delete elem;
-  }
-
-  SetOfVolumes::Iterator itv(myVolumes);
-  for (; itv.More(); itv.Next())
-  {
-    SMDS_MeshElement* elem = itv.Value();
-    if(myParent!=NULL)
-      myElementIDFactory->ReleaseID(elem->GetID());
-    delete elem;
-  }
-
   if(myParent==NULL)
   {
     delete myNodeIDFactory;
     delete myElementIDFactory;
   }
+  else
+  {
+    SMDS_ElemIteratorPtr eIt = elementsIterator();
+    while ( eIt->more() )
+      {
+        const SMDS_MeshElement *elem = eIt->next();
+        myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
+      }
+    SMDS_NodeIteratorPtr itn = nodesIterator();
+    while (itn->more())
+      {
+        const SMDS_MeshNode *node = itn->next();
+        ((SMDS_MeshNode*)node)->SetPosition(SMDS_SpacePosition::originSpacePosition());
+        myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
+      }
+  }
+  myGrid->Delete();
+
+  delete myNodePool;
+  delete myVolumePool;
+  delete myFacePool;
+  delete myEdgePool;
+  delete myBallPool;
 }
 
-///////////////////////////////////////////////////////////////////////////////
+//================================================================================
+/*!
+ * \brief Clear all data
+ */
+//================================================================================
+
+void SMDS_Mesh::Clear()
+{
+  if (myParent!=NULL)
+  {
+    SMDS_ElemIteratorPtr eIt = elementsIterator();
+    while ( eIt->more() )
+    {
+      const SMDS_MeshElement *elem = eIt->next();
+      myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
+    }
+    SMDS_NodeIteratorPtr itn = nodesIterator();
+    while (itn->more())
+    {
+      const SMDS_MeshNode *node = itn->next();
+      myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
+    }
+  }
+  else
+  {
+    myNodeIDFactory->Clear();
+    myElementIDFactory->Clear();
+  }
+
+  myVolumePool->clear();
+  myFacePool->clear();
+  myEdgePool->clear();
+  myBallPool->clear();
+
+  clearVector( myCells );
+  clearVector( myCellIdVtkToSmds );
+
+  SMDS_NodeIteratorPtr itn = nodesIterator();
+  while (itn->more())
+  {
+    SMDS_MeshNode *node = (SMDS_MeshNode*)(itn->next());
+    node->SetPosition(SMDS_SpacePosition::originSpacePosition());
+    //myNodePool->destroy(node);
+  }
+  myNodePool->clear();
+  clearVector( myNodes );
+
+  list<SMDS_Mesh*>::iterator itc=myChildren.begin();
+  while(itc!=myChildren.end())
+    (*itc)->Clear();
+
+  myModified = false;
+  myModifTime++;
+  xmin = 0; xmax = 0;
+  ymin = 0; ymax = 0;
+  zmin = 0; zmax = 0;
+
+  myInfo.Clear();
+
+  myGrid->Initialize();
+  myGrid->Allocate();
+  vtkPoints* points = vtkPoints::New();
+  // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
+  // using double type for storing coordinates of nodes instead float.
+  points->SetDataType(VTK_DOUBLE);
+  points->SetNumberOfPoints( 0 );
+  myGrid->SetPoints( points );
+  points->Delete();
+  myGrid->DeleteLinks();
+}
+
+///////////////////////////////////////////////////////////////////////////////
 /// Return true if this mesh create faces with edges.
 /// A false returned value mean that faces are created with nodes. A concequence
 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
 ///////////////////////////////////////////////////////////////////////////////
 bool SMDS_Mesh::hasConstructionEdges()
 {
-       return myHasConstructionEdges;
+  return myHasConstructionEdges;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1810,7 +2759,7 @@ bool SMDS_Mesh::hasConstructionEdges()
 ///////////////////////////////////////////////////////////////////////////////
 bool SMDS_Mesh::hasConstructionFaces()
 {
-       return myHasConstructionFaces;
+  return myHasConstructionFaces;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1819,7 +2768,7 @@ bool SMDS_Mesh::hasConstructionFaces()
 ///////////////////////////////////////////////////////////////////////////////
 bool SMDS_Mesh::hasInverseElements()
 {
-       return myHasInverseElements;
+  return myHasInverseElements;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1828,7 +2777,7 @@ bool SMDS_Mesh::hasInverseElements()
 ///////////////////////////////////////////////////////////////////////////////
 void SMDS_Mesh::setConstructionEdges(bool b)
 {
-       myHasConstructionEdges=b;
+  myHasConstructionEdges=b;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1837,7 +2786,7 @@ void SMDS_Mesh::setConstructionEdges(bool b)
 ///////////////////////////////////////////////////////////////////////////////
 void SMDS_Mesh::setConstructionFaces(bool b)
 {
-        myHasConstructionFaces=b;
+  myHasConstructionFaces=b;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1846,283 +2795,343 @@ void SMDS_Mesh::setConstructionFaces(bool b)
 ///////////////////////////////////////////////////////////////////////////////
 void SMDS_Mesh::setInverseElements(bool b)
 {
-       if(!b) MESSAGE("Error : inverseElement=false not implemented");
-       myHasInverseElements=b;
+  if(!b) MESSAGE("Error : inverseElement=false not implemented");
+  myHasInverseElements=b;
+}
+
+namespace {
+
+  //================================================================================
+  /*!
+   * \brief Iterator on elements in id increasing order
+   */
+  //================================================================================
+
+  template <typename ELEM=const SMDS_MeshElement*>
+  class IdSortedIterator : public SMDS_Iterator<ELEM>
+  {
+    SMDS_MeshElementIDFactory&       myIDFact;
+    int                              myID, myMaxID, myNbFound, myTotalNb;
+    SMDSAbs_ElementType              myType;
+    ELEM                             myElem;
+
+  public:
+    IdSortedIterator(const SMDS_MeshElementIDFactory& fact,
+                     const SMDSAbs_ElementType        type, // SMDSAbs_All NOT allowed!!! 
+                     const int                        totalNb)
+      :myIDFact( const_cast<SMDS_MeshElementIDFactory&>(fact) ),
+       myID(1), myMaxID( myIDFact.GetMaxID() ),myNbFound(0), myTotalNb( totalNb ),
+       myType( type ),
+       myElem(0)
+    {
+      next();
+    }
+    bool more()
+    {
+      return myElem;
+    }
+    ELEM next()
+    {
+      ELEM current = myElem;
+
+      for ( myElem = 0;  !myElem && myNbFound < myTotalNb && myID <= myMaxID; ++myID )
+        if ((myElem = (ELEM) myIDFact.MeshElement( myID ))
+            && myElem->GetType() != myType )
+          myElem = 0;
+
+      myNbFound += bool(myElem);
+
+      return current;
+    }
+  };
+
+  //================================================================================
+  /*!
+   * \brief Iterator on vector of elements, possibly being resized while iteration
+   */
+  //================================================================================
+
+  template<typename RETURN_VALUE,
+           typename VECTOR_VALUE=SMDS_MeshCell*,
+           typename VALUE_FILTER=SMDS::NonNullFilter<VECTOR_VALUE> >
+  class ElemVecIterator: public SMDS_Iterator<RETURN_VALUE>
+  {
+    const std::vector<VECTOR_VALUE>& _vector;
+    size_t                           _index;
+    bool                             _more;
+    VALUE_FILTER                     _filter;
+  public:
+    ElemVecIterator(const std::vector<VECTOR_VALUE>& vec,
+                    const VALUE_FILTER&              filter=VALUE_FILTER() )
+      :_vector( vec ), _index(0), _more( !vec.empty() ), _filter( filter )
+    {
+      if ( _more && !_filter( _vector[ _index ]))
+        next();
+    }
+    virtual bool more()
+    {
+      return _more;
+    }
+    virtual RETURN_VALUE next()
+    {
+      if ( !_more ) return NULL;
+      VECTOR_VALUE current = _vector[ _index ];
+      _more = 0;
+      while ( !_more && ++_index < _vector.size() )
+        _more = _filter( _vector[ _index ]);
+      return (RETURN_VALUE) current;
+    }
+  };
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Return an iterator on nodes of the current mesh factory
 ///////////////////////////////////////////////////////////////////////////////
-class SMDS_Mesh_MyNodeIterator:public SMDS_NodeIterator
+
+SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
 {
-  SMDS_ElemIteratorPtr myIterator;
- public:
-  SMDS_Mesh_MyNodeIterator(const SMDS_ElemIteratorPtr& it):myIterator(it)
-  {}
+  // naturally always sorted by ID
+  typedef ElemVecIterator<const SMDS_MeshNode*, SMDS_MeshNode*> TIterator;
+  return SMDS_NodeIteratorPtr( new TIterator(myNodes));
+}
 
-  bool more()
-  {
-    return myIterator->more();
-  }
+SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
+{
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::GeomFilter > TIterator;
+  return SMDS_ElemIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::GeomFilter( type )));
+}
 
-  const SMDS_MeshNode* next()
+SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
+{
+  if ( type == SMDSEntity_Node )
   {
-    return static_cast<const SMDS_MeshNode*>(myIterator->next());
+    typedef ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*> TIterator;
+    return SMDS_ElemIteratorPtr( new TIterator(myNodes));
   }
-};
-
-SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
-{
-  return SMDS_NodeIteratorPtr
-    (new SMDS_Mesh_MyNodeIterator(myNodeIDFactory->elementsIterator()));
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::EntityFilter > TIterator;
+  return SMDS_ElemIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::EntityFilter( type )));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Return an iterator on elements of the current mesh factory
 ///////////////////////////////////////////////////////////////////////////////
-SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator() const
+SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
 {
-  return myElementIDFactory->elementsIterator();
+  // naturally always sorted by ID
+  switch ( type ) {
+
+  case SMDSAbs_All:
+    return SMDS_ElemIteratorPtr (new ElemVecIterator<const SMDS_MeshElement*>(myCells));
+
+  case SMDSAbs_Node:
+    return SMDS_ElemIteratorPtr
+      ( new ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*>( myNodes ));
+
+  default:
+    typedef ElemVecIterator
+      < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+    return SMDS_ElemIteratorPtr (new TIterator(myCells, SMDS_MeshElement::TypeFilter( type )));
+  }
+  return SMDS_ElemIteratorPtr();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 ///Return an iterator on edges of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
-class SMDS_Mesh_MyEdgeIterator:public SMDS_EdgeIterator
-{
-  typedef SMDS_Mesh::SetOfEdges SetOfEdges;
-  SetOfEdges::Iterator myIterator;
- public:
-  SMDS_Mesh_MyEdgeIterator(const SetOfEdges& s):myIterator(s)
-  {}
-
-  bool more()
-  {
-    while(myIterator.More())
-    {
-      if(myIterator.Value()->GetID()!=-1)
-        return true;
-      myIterator.Next();
-    }
-    return false;
-  }
-
-  const SMDS_MeshEdge* next()
-  {
-    const SMDS_MeshEdge* current = myIterator.Value();
-    myIterator.Next();
-    return current;
-  }
-};
 
-SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
+SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
 {
-  return SMDS_EdgeIteratorPtr(new SMDS_Mesh_MyEdgeIterator(myEdges));
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshEdge*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+  return SMDS_EdgeIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Edge )));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 ///Return an iterator on faces of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
-class SMDS_Mesh_MyFaceIterator:public SMDS_FaceIterator
-{
-  typedef SMDS_Mesh::SetOfFaces SetOfFaces;
-  SetOfFaces::Iterator myIterator;
- public:
-  SMDS_Mesh_MyFaceIterator(const SetOfFaces& s):myIterator(s)
-  {}
 
-  bool more()
-  {
-    while(myIterator.More())
-    {
-      if(myIterator.Value()->GetID()!=-1)
-        return true;
-      myIterator.Next();
-    }
-    return false;
-  }
-
-  const SMDS_MeshFace* next()
-  {
-    const SMDS_MeshFace* current = myIterator.Value();
-    myIterator.Next();
-    return current;
-  }
-};
-
-SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
+SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
 {
-  return SMDS_FaceIteratorPtr(new SMDS_Mesh_MyFaceIterator(myFaces));
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshFace*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+  return SMDS_FaceIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Face )));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 ///Return an iterator on volumes of the current mesh.
 ///////////////////////////////////////////////////////////////////////////////
-class SMDS_Mesh_MyVolumeIterator:public SMDS_VolumeIterator
-{
-  typedef SMDS_Mesh::SetOfVolumes SetOfVolumes;
-  SetOfVolumes::Iterator myIterator;
- public:
-  SMDS_Mesh_MyVolumeIterator(const SetOfVolumes& s):myIterator(s)
-  {}
 
-  bool more()
-  {
-    return myIterator.More() != Standard_False;
-  }
-
-  const SMDS_MeshVolume* next()
-  {
-    const SMDS_MeshVolume* current = myIterator.Value();
-    myIterator.Next();
-    return current;
-  }
-};
-
-SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
+SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
 {
-  return SMDS_VolumeIteratorPtr(new SMDS_Mesh_MyVolumeIterator(myVolumes));
+  // naturally always sorted by ID
+  typedef ElemVecIterator
+    < const SMDS_MeshVolume*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
+  return SMDS_VolumeIteratorPtr
+    (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Volume )));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Do intersection of sets (more than 2)
 ///////////////////////////////////////////////////////////////////////////////
 static set<const SMDS_MeshElement*> * intersectionOfSets(
-       set<const SMDS_MeshElement*> vs[], int numberOfSets)
-{
-       set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
-       set<const SMDS_MeshElement*>* rsetB;
-
-       for(int i=0; i<numberOfSets-1; i++)
-       {
-               rsetB=new set<const SMDS_MeshElement*>();
-               set_intersection(
-                       rsetA->begin(), rsetA->end(),
-                       vs[i+1].begin(), vs[i+1].end(),
-                       inserter(*rsetB, rsetB->begin()));
-               delete rsetA;
-               rsetA=rsetB;
-       }
-       return rsetA;
+        set<const SMDS_MeshElement*> vs[], int numberOfSets)
+{
+        set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
+        set<const SMDS_MeshElement*>* rsetB;
+
+        for(int i=0; i<numberOfSets-1; i++)
+        {
+                rsetB=new set<const SMDS_MeshElement*>();
+                set_intersection(
+                        rsetA->begin(), rsetA->end(),
+                        vs[i+1].begin(), vs[i+1].end(),
+                        inserter(*rsetB, rsetB->begin()));
+                delete rsetA;
+                rsetA=rsetB;
+        }
+        return rsetA;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-/// Return the list of finit elements owning the given element
+/// Return the list of finite elements owning the given element: elements
+/// containing all the nodes of the given element, for instance faces and
+/// volumes containing a given edge.
 ///////////////////////////////////////////////////////////////////////////////
 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
 {
-       int numberOfSets=element->NbNodes();
-       set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
+  int numberOfSets=element->NbNodes();
+  set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
 
-       SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
+  SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
 
-       int i=0;
-       while(itNodes->more())
-       {
-               const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
-               SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
+  int i = 0;
+  while ( itNodes->more() )
+  {
+    const SMDS_MeshElement* node = itNodes->next();
+    MYASSERT(node);
+    const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(node);
+    SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
 
-               //initSet[i]=set<const SMDS_MeshElement*>();
-               while(itFe->more())
-                  initSet[i].insert(itFe->next());
+    while ( itFe->more() )
+    {
+      const SMDS_MeshElement* elem = itFe->next();
+      MYASSERT(elem);
+      initSet[i].insert(elem);
+    }
 
-               i++;
-       }
-       set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
-        delete [] initSet;
-       return retSet;
+    i++;
+  }
+  set<const SMDS_MeshElement*> *retSet = intersectionOfSets( initSet, numberOfSets );
+  delete [] initSet;
+  return retSet;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 /// Return the list of nodes used only by the given elements
 ///////////////////////////////////////////////////////////////////////////////
-static set<const SMDS_MeshElement*> * getExclusiveNodes(
-       set<const SMDS_MeshElement*>& elements)
+static set<const SMDS_MeshElement*> * getExclusiveNodes(set<const SMDS_MeshElement*>& elements)
 {
-       set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
-       set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
+  set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
+  set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
+
+  while(itElements!=elements.end())
+  {
+    SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
+    itElements++;
 
-       while(itElements!=elements.end())
-       {
-               SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
-               itElements++;
-       
-               while(itNodes->more())
-               {
-                       const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
-                       SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
-                       set<const SMDS_MeshElement*> s;
-                       while(itFe->more())
-                          s.insert(itFe->next());
-                       if(s==elements) toReturn->insert(n);
-               }
-       }
-       return toReturn;        
+    while(itNodes->more())
+    {
+      const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
+      SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
+      set<const SMDS_MeshElement*> s;
+      while(itFe->more())
+        s.insert(itFe->next());
+      if(s==elements) toReturn->insert(n);
+    }
+  }
+  return toReturn;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
-///Find the children of an element that are made of given nodes 
+///Find the children of an element that are made of given nodes
 ///@param setOfChildren The set in which matching children will be inserted
 ///@param element The element were to search matching children
 ///@param nodes The nodes that the children must have to be selected
 ///////////////////////////////////////////////////////////////////////////////
-void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>&     setOfChildren, 
-       const SMDS_MeshElement * element, set<const SMDS_MeshElement*>& nodes)
-{
-       
-       switch(element->GetType())
-       {
-       case SMDSAbs_Node:
-               MESSAGE("Internal Error: This should not append");
-               break;
-       case SMDSAbs_Edge:
-       {
-               SMDS_ElemIteratorPtr itn=element->nodesIterator();
-               while(itn->more())
-               {
-                       const SMDS_MeshElement * e=itn->next();
-                       if(nodes.find(e)!=nodes.end())
-                        {
-                          setOfChildren.insert(element);
-                          break;
-                        }
-               }
-       } break;
-       case SMDSAbs_Face:
-       {
-               SMDS_ElemIteratorPtr itn=element->nodesIterator();
-               while(itn->more())
-               {
-                       const SMDS_MeshElement * e=itn->next();
-                       if(nodes.find(e)!=nodes.end())
-                        {
-                          setOfChildren.insert(element);
-                          break;
-                        }
-               }
-               if(hasConstructionEdges())
-               {
-                       SMDS_ElemIteratorPtr ite=element->edgesIterator();
-                       while(ite->more())
-                               addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-               }
-       } break;        
-       case SMDSAbs_Volume:
-       {
-               if(hasConstructionFaces())
-               {
-                       SMDS_ElemIteratorPtr ite=element->facesIterator();
-                       while(ite->more())
-                               addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-               }
-               else if(hasConstructionEdges())
-               {
-                       SMDS_ElemIteratorPtr ite=element->edgesIterator();
-                       while(ite->more())
-                               addChildrenWithNodes(setOfChildren, ite->next(), nodes);
-               }
-       }
-       }
+void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>& setOfChildren,
+                                     const SMDS_MeshElement *      element,
+                                     set<const SMDS_MeshElement*>& nodes)
+{
+  switch(element->GetType())
+  {
+  case SMDSAbs_Node:
+    MESSAGE("Internal Error: This should not happen");
+    break;
+  case SMDSAbs_0DElement:
+  case SMDSAbs_Ball:
+  {
+  }
+  break;
+  case SMDSAbs_Edge:
+  {
+    SMDS_ElemIteratorPtr itn=element->nodesIterator();
+    while(itn->more())
+    {
+      const SMDS_MeshElement * e=itn->next();
+      if(nodes.find(e)!=nodes.end())
+      {
+        setOfChildren.insert(element);
+        break;
+      }
+    }
+  } break;
+  case SMDSAbs_Face:
+  {
+    SMDS_ElemIteratorPtr itn=element->nodesIterator();
+    while(itn->more())
+    {
+      const SMDS_MeshElement * e=itn->next();
+      if(nodes.find(e)!=nodes.end())
+      {
+        setOfChildren.insert(element);
+        break;
+      }
+    }
+    if(hasConstructionEdges())
+    {
+      SMDS_ElemIteratorPtr ite=element->edgesIterator();
+      while(ite->more())
+        addChildrenWithNodes(setOfChildren, ite->next(), nodes);
+    }
+  } break;
+  case SMDSAbs_Volume:
+  {
+    if(hasConstructionFaces())
+    {
+      SMDS_ElemIteratorPtr ite=element->facesIterator();
+      while(ite->more())
+        addChildrenWithNodes(setOfChildren, ite->next(), nodes);
+    }
+    else if(hasConstructionEdges())
+    {
+      SMDS_ElemIteratorPtr ite=element->edgesIterator();
+      while(ite->more())
+        addChildrenWithNodes(setOfChildren, ite->next(), nodes);
+    }
+  }
+  case SMDSAbs_NbElementTypes:
+  case SMDSAbs_All: break;
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -2130,17 +3139,17 @@ void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>&      setOfChildren
 ///@param removenodes if true remaining nodes will be removed
 ///////////////////////////////////////////////////////////////////////////////
 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
-       const bool removenodes)
+                              const bool removenodes)
 {
   list<const SMDS_MeshElement *> removedElems;
   list<const SMDS_MeshElement *> removedNodes;
   RemoveElement( elem, removedElems, removedNodes, removenodes );
 }
-  
+
 ///////////////////////////////////////////////////////////////////////////////
 ///@param elem The element to delete
-///@param removedElems contains all removed elements
-///@param removedNodes contains all removed nodes
+///@param removedElems to be filled with all removed elements
+///@param removedNodes to be filled with all removed nodes
 ///@param removenodes if true remaining nodes will be removed
 ///////////////////////////////////////////////////////////////////////////////
 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
@@ -2150,89 +3159,161 @@ void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
 {
   // get finite elements built on elem
   set<const SMDS_MeshElement*> * s1;
-  if (!hasConstructionEdges() && elem->GetType() == SMDSAbs_Edge ||
-      !hasConstructionFaces() && elem->GetType() == SMDSAbs_Face ||
-      elem->GetType() == SMDSAbs_Volume)
-  {
-    s1 = new set<const SMDS_MeshElement*>();
-    s1->insert(elem);
-  }
+  if (    (elem->GetType() == SMDSAbs_0DElement)
+      || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
+      || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
+      ||  (elem->GetType() == SMDSAbs_Volume) )
+    {
+      s1 = new set<const SMDS_MeshElement*> ();
+      s1->insert(elem);
+    }
   else
     s1 = getFinitElements(elem);
 
   // get exclusive nodes (which would become free afterwards)
   set<const SMDS_MeshElement*> * s2;
   if (elem->GetType() == SMDSAbs_Node) // a node is removed
-  {
-    // do not remove nodes except elem
-    s2 = new set<const SMDS_MeshElement*>();
-    s2->insert(elem);
-    removenodes = true;
-  }
+    {
+      // do not remove nodes except elem
+      s2 = new set<const SMDS_MeshElement*> ();
+      s2->insert(elem);
+      removenodes = true;
+    }
   else
     s2 = getExclusiveNodes(*s1);
 
   // form the set of finite and construction elements to remove
   set<const SMDS_MeshElement*> s3;
-  set<const SMDS_MeshElement*>::iterator it=s1->begin();
-  while(it!=s1->end())
-  {
-    addChildrenWithNodes(s3, *it ,*s2);
-    s3.insert(*it);
-    it++;
-  }
-  if(elem->GetType()!=SMDSAbs_Node) s3.insert(elem);
-
-  // remove finite and construction elements
-  it=s3.begin();
-  while(it!=s3.end())
-  {
-    // Remove element from <InverseElements> of its nodes
-    SMDS_ElemIteratorPtr itn=(*it)->nodesIterator();
-    while(itn->more())
+  set<const SMDS_MeshElement*>::iterator it = s1->begin();
+  while (it != s1->end())
     {
-      SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
-        (const_cast<SMDS_MeshElement *>(itn->next()));
-      n->RemoveInverseElement( (*it) );
+      addChildrenWithNodes(s3, *it, *s2);
+      s3.insert(*it);
+      it++;
     }
+  if (elem->GetType() != SMDSAbs_Node)
+    s3.insert(elem);
 
-    switch((*it)->GetType())
+  // remove finite and construction elements
+  it = s3.begin();
+  while (it != s3.end())
     {
-    case SMDSAbs_Node:
-      MESSAGE("Internal Error: This should not happen");
-      break;
-    case SMDSAbs_Edge:
-      myEdges.Remove(static_cast<SMDS_MeshEdge*>
-                    (const_cast<SMDS_MeshElement*>(*it)));
-      break;
-    case SMDSAbs_Face:
-      myFaces.Remove(static_cast<SMDS_MeshFace*>
-                    (const_cast<SMDS_MeshElement*>(*it)));
-      break;
-    case SMDSAbs_Volume:
-      myVolumes.Remove(static_cast<SMDS_MeshVolume*>
-                      (const_cast<SMDS_MeshElement*>(*it)));
-      break;
+      // Remove element from <InverseElements> of its nodes
+      SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
+      while (itn->more())
+      {
+        SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
+        n->RemoveInverseElement((*it));
+      }
+      int IdToRemove = (*it)->GetID();
+      int vtkid = (*it)->getVtkId();
+      switch ((*it)->GetType())
+      {
+        case SMDSAbs_Node:
+          MYASSERT("Internal Error: This should not happen");
+          break;
+        case SMDSAbs_0DElement:
+          if (IdToRemove >= 0)
+            {
+              myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
+              myInfo.remove(*it);
+            }
+          removedElems.push_back((*it));
+          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+          delete (*it);
+          break;
+        case SMDSAbs_Edge:
+          if (IdToRemove >= 0)
+            {
+              myCells[IdToRemove] = 0;
+              myInfo.RemoveEdge(*it);
+            }
+          removedElems.push_back((*it));
+          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+          if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
+            myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
+          else {
+            ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
+            delete (*it);
+          }
+          break;
+        case SMDSAbs_Face:
+          if (IdToRemove >= 0)
+            {
+              myCells[IdToRemove] = 0;
+              myInfo.RemoveFace(*it);
+            }
+          removedElems.push_back((*it));
+          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+          if (const SMDS_VtkFace* vtkElem = dynamic_cast<const SMDS_VtkFace*>(*it))
+            myFacePool->destroy((SMDS_VtkFace*) vtkElem);
+          else {
+            ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
+            delete (*it);
+          }
+          break;
+        case SMDSAbs_Volume:
+          if (IdToRemove >= 0)
+            {
+              myCells[IdToRemove] = 0;
+              myInfo.RemoveVolume(*it);
+            }
+          removedElems.push_back((*it));
+          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+          if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
+            myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
+          else {
+            ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
+            delete (*it);
+          }
+          break;
+        case SMDSAbs_Ball:
+          if (IdToRemove >= 0)
+            {
+              myCells[IdToRemove] = 0;
+              myInfo.remove(*it);
+            }
+          removedElems.push_back((*it));
+          myElementIDFactory->ReleaseID(IdToRemove, vtkid);
+          if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
+            myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
+          else {
+            ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
+            delete (*it);
+          }
+          break;
+
+        case SMDSAbs_All: // avoid compilation warning
+        case SMDSAbs_NbElementTypes: break;
+      }
+      if (vtkid >= 0)
+      {
+        this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
+      }
+      it++;
     }
-    //MESSAGE( "SMDS: RM elem " << (*it)->GetID() );
-    removedElems.push_back( (*it) );
-    myElementIDFactory->ReleaseID((*it)->GetID());
-    delete (*it);
-    it++;
-  }
 
   // remove exclusive (free) nodes
-  if(removenodes)
+  if (removenodes)
   {
-    it=s2->begin();
-    while(it!=s2->end())
+    it = s2->begin();
+    while (it != s2->end())
     {
-      //MESSAGE( "SMDS: RM node " << (*it)->GetID() );
-      myNodes.Remove(static_cast<SMDS_MeshNode*>
-                    (const_cast<SMDS_MeshElement*>(*it)));
-      myNodeIDFactory->ReleaseID((*it)->GetID());
-      removedNodes.push_back( (*it) );
-      delete *it;
+      int IdToRemove = (*it)->GetID();
+      if (IdToRemove >= 0)
+      {
+        myNodes[IdToRemove] = 0;
+        myInfo.myNbNodes--;
+      }
+      myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
+      removedNodes.push_back((*it));
+      if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
+      {
+        ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
+        myNodePool->destroy((SMDS_MeshNode*) vtkElem);
+      }
+      else
+        delete (*it);
       it++;
     }
   }
@@ -2241,23 +3322,31 @@ void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
   delete s1;
 }
 
-  
+
 ///////////////////////////////////////////////////////////////////////////////
 ///@param elem The element to delete
 ///////////////////////////////////////////////////////////////////////////////
 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
 {
+  int elemId = elem->GetID();
+  int  vtkId = elem->getVtkId();
   SMDSAbs_ElementType aType = elem->GetType();
-  if (aType == SMDSAbs_Node) {
+  SMDS_MeshElement*  todest = (SMDS_MeshElement*)(elem);
+  if ( aType == SMDSAbs_Node )
+  {
     // only free node can be removed by this method
-    const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>(elem);
-    SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
-    if (!itFe->more()) { // free node
-      myNodes.Remove(const_cast<SMDS_MeshNode*>(n));
-      myNodeIDFactory->ReleaseID(elem->GetID());
-      delete elem;
+    const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
+    if ( n->NbInverseElements() == 0 ) { // free node
+      myNodes[elemId] = 0;
+      myInfo.myNbNodes--;
+      ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
+      ((SMDS_MeshNode*) n)->SMDS_MeshElement::init( -1, -1, -1 ); // avoid reuse
+      myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
+      myNodeIDFactory->ReleaseID(elemId, vtkId);
     }
-  } else {
+  }
+  else
+  {
     if (hasConstructionEdges() || hasConstructionFaces())
       // this methods is only for meshes without descendants
       return;
@@ -2272,23 +3361,42 @@ void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
 
     // in meshes without descendants elements are always free
     switch (aType) {
+    case SMDSAbs_0DElement:
+      myCells[elemId] = 0;
+      myInfo.remove(elem);
+      delete elem;
+      elem = 0;
+      break;
     case SMDSAbs_Edge:
-      myEdges.Remove(static_cast<SMDS_MeshEdge*>
-                     (const_cast<SMDS_MeshElement*>(elem)));
+      myCells[elemId] = 0;
+      myInfo.RemoveEdge(elem);
+      myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
       break;
     case SMDSAbs_Face:
-      myFaces.Remove(static_cast<SMDS_MeshFace*>
-                     (const_cast<SMDS_MeshElement*>(elem)));
+      myCells[elemId] = 0;
+      myInfo.RemoveFace(elem);
+      myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
       break;
     case SMDSAbs_Volume:
-      myVolumes.Remove(static_cast<SMDS_MeshVolume*>
-                       (const_cast<SMDS_MeshElement*>(elem)));
+      myCells[elemId] = 0;
+      myInfo.RemoveVolume(elem);
+      myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
+      break;
+    case SMDSAbs_Ball:
+      myCells[elemId] = 0;
+      myInfo.remove(elem);
+      myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
       break;
     default:
       break;
     }
-    myElementIDFactory->ReleaseID(elem->GetID());
-    delete elem;
+    myElementIDFactory->ReleaseID(elemId, vtkId);
+
+    this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
+    // --- to do: keep vtkid in a list of reusable cells
+
+    if ( elem )
+      ((SMDS_MeshElement*) elem)->init( -1, -1, -1 ); // avoid reuse
   }
 }
 
@@ -2298,30 +3406,22 @@ void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
  */
 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
 {
-  // we should not imply on validity of *elem, so iterate on containers
+  // we should not rely on validity of *elem, so iterate on containers
   // of all types in the hope of finding <elem> somewhere there
   SMDS_NodeIteratorPtr itn = nodesIterator();
   while (itn->more())
     if (elem == itn->next())
       return true;
-  SMDS_EdgeIteratorPtr ite = edgesIterator();
+  SMDS_ElemIteratorPtr ite = elementsIterator();
   while (ite->more())
     if (elem == ite->next())
       return true;
-  SMDS_FaceIteratorPtr itf = facesIterator();
-  while (itf->more())
-    if (elem == itf->next())
-      return true;
-  SMDS_VolumeIteratorPtr itv = volumesIterator();
-  while (itv->more())
-    if (elem == itv->next())
-      return true;
   return false;
 }
 
 //=======================================================================
 //function : MaxNodeID
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 int SMDS_Mesh::MaxNodeID() const
@@ -2331,7 +3431,7 @@ int SMDS_Mesh::MaxNodeID() const
 
 //=======================================================================
 //function : MinNodeID
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 int SMDS_Mesh::MinNodeID() const
@@ -2341,7 +3441,7 @@ int SMDS_Mesh::MinNodeID() const
 
 //=======================================================================
 //function : MaxElementID
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 int SMDS_Mesh::MaxElementID() const
@@ -2351,7 +3451,7 @@ int SMDS_Mesh::MaxElementID() const
 
 //=======================================================================
 //function : MinElementID
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 int SMDS_Mesh::MinElementID() const
@@ -2369,7 +3469,7 @@ void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  del
   if ( deltaID == 0 )
     return;
 
-  SMDS_MeshElementIDFactory * idFactory =
+  SMDS_MeshNodeIDFactory * idFactory =
     isNodes ? myNodeIDFactory : myElementIDFactory;
 
   // get existing elements in the order of ID increasing
@@ -2382,11 +3482,12 @@ void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  del
   }
   // release their ids
   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
-  for ( ; elemIt != elemMap.end(); elemIt++ )
-  {
-    int id = (*elemIt).first;
-    idFactory->ReleaseID( id );
-  }
+  idFactory->Clear();
+//   for ( ; elemIt != elemMap.end(); elemIt++ )
+//   {
+//     int id = (*elemIt).first;
+//     idFactory->ReleaseID( id );
+//   }
   // set new IDs
   int ID = startID;
   elemIt = elemMap.begin();
@@ -2431,23 +3532,23 @@ SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem )
 
 //=======================================================================
 //function : AddEdgeWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
-SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID) 
+SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
 {
-  SMDS_MeshNode* node1 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1);
-  SMDS_MeshNode* node2 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2);
-  SMDS_MeshNode* node12 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12);
-  if(!node1 || !node2 || !node12) return NULL;
-  return SMDS_Mesh::AddEdgeWithID(node1, node2, node12, ID);
+  return SMDS_Mesh::AddEdgeWithID
+    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
+     ID);
 }
 
 //=======================================================================
 //function : AddEdge
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
-                                 const SMDS_MeshNode* n2,
+                                  const SMDS_MeshNode* n2,
                                   const SMDS_MeshNode* n12)
 {
   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
@@ -2455,39 +3556,51 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
 
 //=======================================================================
 //function : AddEdgeWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
-                                       const SMDS_MeshNode * n2, 
-                                       const SMDS_MeshNode * n12, 
-                                       int ID)
-{
-  SMDS_QuadraticEdge* edge = new SMDS_QuadraticEdge(n1,n2,n12);
-  if(myElementIDFactory->BindID(ID, edge)) {
-    SMDS_MeshNode *node1,*node2, *node12;
-    node1 = const_cast<SMDS_MeshNode*>(n1);
-    node2 = const_cast<SMDS_MeshNode*>(n2);
-    node12 = const_cast<SMDS_MeshNode*>(n12);
-    node1->AddInverseElement(edge);
-    node2->AddInverseElement(edge);
-    node12->AddInverseElement(edge);
-    myEdges.Add(edge);
-    return edge;
-  } 
-  else {
-    delete edge;
-    return NULL;
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n12,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n12 ) return 0;
+
+  // --- retrieve nodes ID
+  myNodeIds.resize(3);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n2->getVtkId();
+  myNodeIds[2] = n12->getVtkId();
+
+  SMDS_MeshEdge * edge = 0;
+  SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
+  edgevtk->init(myNodeIds, this);
+  if (!this->registerElement(ID,edgevtk))
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
+    myEdgePool->destroy(edgevtk);
+    return 0;
   }
+  edge = edgevtk;
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = edge;
+  myInfo.myNbQuadEdges++;
+
+  //  if (!registerElement(ID, edge)) {
+  //        RemoveElement(edge, false);
+  //        edge = NULL;
+  //  }
+  return edge;
+
 }
 
 
 //=======================================================================
 //function : AddFace
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
-                                 const SMDS_MeshNode * n2,
-                                 const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
                                   const SMDS_MeshNode * n12,
                                   const SMDS_MeshNode * n23,
                                   const SMDS_MeshNode * n31)
@@ -2498,57 +3611,167 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
 
 //=======================================================================
 //function : AddFaceWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
                                         int n12,int n23,int n31, int ID)
 {
-  SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1);
-  SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2);
-  SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3);
-  SMDS_MeshNode * node12 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12);
-  SMDS_MeshNode * node23 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23);
-  SMDS_MeshNode * node31 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31);
-  if(!node1 || !node2 || !node3 || !node12 || !node23 || !node31) return NULL;
-  return SMDS_Mesh::AddFaceWithID(node1, node2, node3,
-                                  node12, node23, node31, ID);
+  return SMDS_Mesh::AddFaceWithID
+    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
+     ID);
 }
 
 //=======================================================================
 //function : AddFaceWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n2,
                                         const SMDS_MeshNode * n3,
                                         const SMDS_MeshNode * n12,
                                         const SMDS_MeshNode * n23,
-                                        const SMDS_MeshNode * n31, 
+                                        const SMDS_MeshNode * n31,
                                         int ID)
 {
+  if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
   if(hasConstructionEdges()) {
     // creation quadratic edges - not implemented
+    return 0;
   }
-  SMDS_QuadraticFaceOfNodes* face =
-    new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n12,n23,n31);
-  myFaces.Add(face);
+  else
+  {
+    // --- retrieve nodes ID
+    myNodeIds.resize(6);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n12->getVtkId();
+    myNodeIds[4] = n23->getVtkId();
+    myNodeIds[5] = n31->getVtkId();
+
+    SMDS_MeshFace * face = 0;
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbQuadTriangles++;
+
+    //    if (!registerElement(ID, face)) {
+    //      RemoveElement(face, false);
+    //      face = NULL;
+    //    }
+    return face;
+  }
+}
 
-  if (!registerElement(ID, face)) {
-    RemoveElement(face, false);
-    face = NULL;
+
+//=======================================================================
+//function : AddFace
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n31,
+                                  const SMDS_MeshNode * nCenter)
+{
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
+                                  myElementIDFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
+                                        int n12,int n23,int n31, int nCenter, int ID)
+{
+  return SMDS_Mesh::AddFaceWithID
+    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
+     ID);
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n31,
+                                        const SMDS_MeshNode * nCenter,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
+  if(hasConstructionEdges()) {
+    // creation quadratic edges - not implemented
+    return 0;
+  }
+  else
+  {
+    // --- retrieve nodes ID
+    myNodeIds.resize(7);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n12->getVtkId();
+    myNodeIds[4] = n23->getVtkId();
+    myNodeIds[5] = n31->getVtkId();
+    myNodeIds[6] = nCenter->getVtkId();
+
+    SMDS_MeshFace * face = 0;
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbBiQuadTriangles++;
+
+    //    if (!registerElement(ID, face)) {
+    //      RemoveElement(face, false);
+    //      face = NULL;
+    //    }
+    return face;
   }
-  return face;
 }
 
 
 //=======================================================================
 //function : AddFace
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
-                                 const SMDS_MeshNode * n2,
-                                 const SMDS_MeshNode * n3,
-                                 const SMDS_MeshNode * n4,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4,
                                   const SMDS_MeshNode * n12,
                                   const SMDS_MeshNode * n23,
                                   const SMDS_MeshNode * n34,
@@ -2560,28 +3783,26 @@ SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
 
 //=======================================================================
 //function : AddFaceWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
                                         int n12,int n23,int n34,int n41, int ID)
 {
-  SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1);
-  SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2);
-  SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3);
-  SMDS_MeshNode * node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4);
-  SMDS_MeshNode * node12 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12);
-  SMDS_MeshNode * node23 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23);
-  SMDS_MeshNode * node34 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34);
-  SMDS_MeshNode * node41 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41);
-  if(!node1 || !node2 || !node3 || !node4 ||
-     !node12 || !node23 || !node34 || !node41) return NULL;
-  return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4,
-                                  node12, node23, node34, node41, ID);
+  return SMDS_Mesh::AddFaceWithID
+    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
+     ID);
 }
 
 //=======================================================================
 //function : AddFaceWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n2,
@@ -2589,37 +3810,157 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
                                         const SMDS_MeshNode * n4,
                                         const SMDS_MeshNode * n12,
                                         const SMDS_MeshNode * n23,
-                                        const SMDS_MeshNode * n34, 
-                                        const SMDS_MeshNode * n41, 
+                                        const SMDS_MeshNode * n34,
+                                        const SMDS_MeshNode * n41,
                                         int ID)
 {
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
   if(hasConstructionEdges()) {
     // creation quadratic edges - not implemented
+    return 0;
   }
-  SMDS_QuadraticFaceOfNodes* face =
-    new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n4,n12,n23,n34,n41);
-  myFaces.Add(face);
+  else
+  {
+    // --- retrieve nodes ID
+    myNodeIds.resize(8);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+    myNodeIds[4] = n12->getVtkId();
+    myNodeIds[5] = n23->getVtkId();
+    myNodeIds[6] = n34->getVtkId();
+    myNodeIds[7] = n41->getVtkId();
+
+    SMDS_MeshFace * face = 0;
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbQuadQuadrangles++;
+
+    //    if (!registerElement(ID, face)) {
+    //      RemoveElement(face, false);
+    //      face = NULL;
+    //    }
+    return face;
+  }
+}
 
-  if (!registerElement(ID, face)) {
-    RemoveElement(face, false);
-    face = NULL;
+//=======================================================================
+//function : AddFace
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
+                                  const SMDS_MeshNode * n2,
+                                  const SMDS_MeshNode * n3,
+                                  const SMDS_MeshNode * n4,
+                                  const SMDS_MeshNode * n12,
+                                  const SMDS_MeshNode * n23,
+                                  const SMDS_MeshNode * n34,
+                                  const SMDS_MeshNode * n41,
+                                  const SMDS_MeshNode * nCenter)
+{
+  return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
+                                  myElementIDFactory->GetFreeID());
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
+                                        int n12,int n23,int n34,int n41, int nCenter, int ID)
+{
+  return SMDS_Mesh::AddFaceWithID
+    ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
+     (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
+     ID);
+}
+
+//=======================================================================
+//function : AddFaceWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
+                                        const SMDS_MeshNode * n2,
+                                        const SMDS_MeshNode * n3,
+                                        const SMDS_MeshNode * n4,
+                                        const SMDS_MeshNode * n12,
+                                        const SMDS_MeshNode * n23,
+                                        const SMDS_MeshNode * n34,
+                                        const SMDS_MeshNode * n41,
+                                        const SMDS_MeshNode * nCenter,
+                                        int ID)
+{
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
+  if(hasConstructionEdges()) {
+    // creation quadratic edges - not implemented
+    return 0;
+  }
+  else
+  {
+    // --- retrieve nodes ID
+    myNodeIds.resize(9);
+    myNodeIds[0] = n1->getVtkId();
+    myNodeIds[1] = n2->getVtkId();
+    myNodeIds[2] = n3->getVtkId();
+    myNodeIds[3] = n4->getVtkId();
+    myNodeIds[4] = n12->getVtkId();
+    myNodeIds[5] = n23->getVtkId();
+    myNodeIds[6] = n34->getVtkId();
+    myNodeIds[7] = n41->getVtkId();
+    myNodeIds[8] = nCenter->getVtkId();
+
+    SMDS_MeshFace * face = 0;
+    SMDS_VtkFace *facevtk = myFacePool->getNew();
+    facevtk->init(myNodeIds, this);
+    if (!this->registerElement(ID,facevtk))
+    {
+      this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
+      myFacePool->destroy(facevtk);
+      return 0;
+    }
+    face = facevtk;
+    adjustmyCellsCapacity(ID);
+    myCells[ID] = face;
+    myInfo.myNbBiQuadQuadrangles++;
+
+    //    if (!registerElement(ID, face)) {
+    //      RemoveElement(face, false);
+    //      face = NULL;
+    //    }
+    return face;
   }
-  return face;
 }
 
 
 //=======================================================================
 //function : AddVolume
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-                                     const SMDS_MeshNode * n2, 
-                                     const SMDS_MeshNode * n3,
-                                     const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
                                       const SMDS_MeshNode * n12,
                                       const SMDS_MeshNode * n23,
                                       const SMDS_MeshNode * n31,
-                                      const SMDS_MeshNode * n14, 
+                                      const SMDS_MeshNode * n14,
                                       const SMDS_MeshNode * n24,
                                       const SMDS_MeshNode * n34)
 {
@@ -2632,30 +3973,26 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
 
 //=======================================================================
 //function : AddVolumeWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
                                             int n12,int n23,int n31,
                                             int n14,int n24,int n34, int ID)
 {
-  SMDS_MeshNode *node1, *node2, *node3, *node4, *node12, *node23;
-  SMDS_MeshNode *node31, *node14, *node24, *node34;
-  node1 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1);
-  node2 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2);
-  node3 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3);
-  node4 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4);
-  node12 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12);
-  node23 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23);
-  node31 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31);
-  node14 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14);
-  node24 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24);
-  node34 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34);
-  if( !node1 || !node2 || !node3 || !node4 || !node12 || !node23 ||
-     !node31 || !node14 || !node24 || !node34 ) return NULL;
-  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node12, node23,
-                                    node31, node14, node24, node34, ID);
-}
-       
+  return SMDS_Mesh::AddVolumeWithID
+    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
+     ID);
+}
+
 //=======================================================================
 //function : AddVolumeWithID
 //purpose  : 2d order tetrahedron of 10 nodes
@@ -2667,40 +4004,66 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n12,
                                             const SMDS_MeshNode * n23,
                                             const SMDS_MeshNode * n31,
-                                            const SMDS_MeshNode * n14, 
+                                            const SMDS_MeshNode * n14,
                                             const SMDS_MeshNode * n24,
                                             const SMDS_MeshNode * n34,
                                             int ID)
 {
+  if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
+    return 0;
   if(hasConstructionFaces()) {
     // creation quadratic faces - not implemented
+    return 0;
   }
-  SMDS_QuadraticVolumeOfNodes * volume =
-    new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n12,n23,n31,n14,n24,n34);
-  myVolumes.Add(volume);
-
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+  // --- retrieve nodes ID
+  myNodeIds.resize(10);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n3->getVtkId();
+  myNodeIds[2] = n2->getVtkId();
+  myNodeIds[3] = n4->getVtkId();
+
+  myNodeIds[4] = n31->getVtkId();
+  myNodeIds[5] = n23->getVtkId();
+  myNodeIds[6] = n12->getVtkId();
+
+  myNodeIds[7] = n14->getVtkId();
+  myNodeIds[8] = n34->getVtkId();
+  myNodeIds[9] = n24->getVtkId();
+
+  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+  volvtk->init(myNodeIds, this);
+  if (!this->registerElement(ID,volvtk))
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
   }
-  return volume;
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volvtk;
+  myInfo.myNbQuadTetras++;
+
+  //  if (!registerElement(ID, volvtk)) {
+  //    RemoveElement(volvtk, false);
+  //    volvtk = NULL;
+  //  }
+  return volvtk;
 }
 
 
 //=======================================================================
 //function : AddVolume
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-                                     const SMDS_MeshNode * n2, 
-                                     const SMDS_MeshNode * n3,
-                                     const SMDS_MeshNode * n4,
-                                      const SMDS_MeshNode * n5, 
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
                                       const SMDS_MeshNode * n12,
                                       const SMDS_MeshNode * n23,
                                       const SMDS_MeshNode * n34,
                                       const SMDS_MeshNode * n41,
-                                      const SMDS_MeshNode * n15, 
+                                      const SMDS_MeshNode * n15,
                                       const SMDS_MeshNode * n25,
                                       const SMDS_MeshNode * n35,
                                       const SMDS_MeshNode * n45)
@@ -2715,36 +4078,29 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
 
 //=======================================================================
 //function : AddVolumeWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
                                             int n12,int n23,int n34,int n41,
                                             int n15,int n25,int n35,int n45, int ID)
 {
-  SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
-  SMDS_MeshNode *node12, *node23, *node34, *node41;
-  SMDS_MeshNode *node15, *node25, *node35, *node45;
-  node1 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1);
-  node2 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2);
-  node3 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3);
-  node4 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4);
-  node5 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5);
-  node12 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12);
-  node23 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23);
-  node34 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34);
-  node41 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41);
-  node15 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15);
-  node25 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25);
-  node35 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35);
-  node45 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45);
-  if( !node1 || !node2 || !node3 || !node4 || !node5 ||
-      !node12 || !node23 || !node34 || !node41 ||
-      !node15 || !node25 || !node35 || !node45 ) return NULL;
-  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5,
-                                    node12, node23, node34, node41,
-                                    node15, node25, node35, node45, ID);
-}
-       
+  return SMDS_Mesh::AddVolumeWithID
+    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
+     ID);
+}
+
 //=======================================================================
 //function : AddVolumeWithID
 //purpose  : 2d order pyramid of 13 nodes
@@ -2753,49 +4109,78 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n2,
                                             const SMDS_MeshNode * n3,
                                             const SMDS_MeshNode * n4,
-                                            const SMDS_MeshNode * n5, 
+                                            const SMDS_MeshNode * n5,
                                             const SMDS_MeshNode * n12,
                                             const SMDS_MeshNode * n23,
                                             const SMDS_MeshNode * n34,
                                             const SMDS_MeshNode * n41,
-                                            const SMDS_MeshNode * n15, 
+                                            const SMDS_MeshNode * n15,
                                             const SMDS_MeshNode * n25,
                                             const SMDS_MeshNode * n35,
                                             const SMDS_MeshNode * n45,
                                             int ID)
 {
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
+      !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
+    return 0;
   if(hasConstructionFaces()) {
     // creation quadratic faces - not implemented
+    return 0;
   }
-  SMDS_QuadraticVolumeOfNodes * volume =
-    new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n12,n23,
-                                    n34,n41,n15,n25,n35,n45);
-  myVolumes.Add(volume);
-
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+  // --- retrieve nodes ID
+  myNodeIds.resize(13);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n4->getVtkId();
+  myNodeIds[2] = n3->getVtkId();
+  myNodeIds[3] = n2->getVtkId();
+  myNodeIds[4] = n5->getVtkId();
+
+  myNodeIds[5] = n41->getVtkId();
+  myNodeIds[6] = n34->getVtkId();
+  myNodeIds[7] = n23->getVtkId();
+  myNodeIds[8] = n12->getVtkId();
+
+  myNodeIds[9] = n15->getVtkId();
+  myNodeIds[10] = n45->getVtkId();
+  myNodeIds[11] = n35->getVtkId();
+  myNodeIds[12] = n25->getVtkId();
+
+  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+  volvtk->init(myNodeIds, this);
+  if (!this->registerElement(ID,volvtk))
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
   }
-  return volume;
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volvtk;
+  myInfo.myNbQuadPyramids++;
+
+  //  if (!registerElement(ID, volvtk)) {
+  //    RemoveElement(volvtk, false);
+  //    volvtk = NULL;
+  //  }
+  return volvtk;
 }
 
 
 //=======================================================================
 //function : AddVolume
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-                                     const SMDS_MeshNode * n2, 
-                                     const SMDS_MeshNode * n3,
-                                     const SMDS_MeshNode * n4,
-                                      const SMDS_MeshNode * n5, 
-                                      const SMDS_MeshNode * n6, 
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
                                       const SMDS_MeshNode * n12,
                                       const SMDS_MeshNode * n23,
-                                      const SMDS_MeshNode * n31, 
+                                      const SMDS_MeshNode * n31,
                                       const SMDS_MeshNode * n45,
                                       const SMDS_MeshNode * n56,
-                                      const SMDS_MeshNode * n64, 
+                                      const SMDS_MeshNode * n64,
                                       const SMDS_MeshNode * n14,
                                       const SMDS_MeshNode * n25,
                                       const SMDS_MeshNode * n36)
@@ -2810,7 +4195,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
 
 //=======================================================================
 //function : AddVolumeWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
                                             int n4, int n5, int n6,
@@ -2818,33 +4203,25 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
                                             int n45,int n56,int n64,
                                             int n14,int n25,int n36, int ID)
 {
-  SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
-  SMDS_MeshNode *node12, *node23, *node31;
-  SMDS_MeshNode *node45, *node56, *node64;
-  SMDS_MeshNode *node14, *node25, *node36;
-  node1 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1);
-  node2 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2);
-  node3 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3);
-  node4 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4);
-  node5 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5);
-  node6 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6);
-  node12 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12);
-  node23 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23);
-  node31 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31);
-  node45 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45);
-  node56 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56);
-  node64 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64);
-  node14 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14);
-  node25 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25);
-  node36 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36);
-  if( !node1 || !node2 || !node3 || !node4 || !node5 || !node6 ||
-      !node12 || !node23 || !node31 || !node45 || !node56 ||
-      !node64 || !node14 || !node25 || !node36 ) return NULL;
-  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
-                                    node12, node23, node31, node45, node56,
-                                    node64, node14, node25, node36, ID);
+  return SMDS_Mesh::AddVolumeWithID
+    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
+     ID);
 }
-       
+
 //=======================================================================
 //function : AddVolumeWithID
 //purpose  : 2d order Pentahedron with 15 nodes
@@ -2853,55 +4230,88 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n2,
                                             const SMDS_MeshNode * n3,
                                             const SMDS_MeshNode * n4,
-                                            const SMDS_MeshNode * n5, 
-                                            const SMDS_MeshNode * n6, 
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
                                             const SMDS_MeshNode * n12,
                                             const SMDS_MeshNode * n23,
-                                            const SMDS_MeshNode * n31, 
+                                            const SMDS_MeshNode * n31,
                                             const SMDS_MeshNode * n45,
                                             const SMDS_MeshNode * n56,
-                                            const SMDS_MeshNode * n64, 
+                                            const SMDS_MeshNode * n64,
                                             const SMDS_MeshNode * n14,
                                             const SMDS_MeshNode * n25,
                                             const SMDS_MeshNode * n36,
                                             int ID)
 {
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
+      !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
+    return 0;
   if(hasConstructionFaces()) {
     // creation quadratic faces - not implemented
+    return 0;
   }
-  SMDS_QuadraticVolumeOfNodes * volume =
-    new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n12,n23,n31,
-                                    n45,n56,n64,n14,n25,n36);
-  myVolumes.Add(volume);
-
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+  // --- retrieve nodes ID
+  myNodeIds.resize(15);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n2->getVtkId();
+  myNodeIds[2] = n3->getVtkId();
+
+  myNodeIds[3] = n4->getVtkId();
+  myNodeIds[4] = n5->getVtkId();
+  myNodeIds[5] = n6->getVtkId();
+
+  myNodeIds[6] = n12->getVtkId();
+  myNodeIds[7] = n23->getVtkId();
+  myNodeIds[8] = n31->getVtkId();
+
+  myNodeIds[9] = n45->getVtkId();
+  myNodeIds[10] = n56->getVtkId();
+  myNodeIds[11] = n64->getVtkId();
+
+  myNodeIds[12] = n14->getVtkId();
+  myNodeIds[13] = n25->getVtkId();
+  myNodeIds[14] = n36->getVtkId();
+
+  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+  volvtk->init(myNodeIds, this);
+  if (!this->registerElement(ID,volvtk))
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
   }
-  return volume;
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volvtk;
+  myInfo.myNbQuadPrisms++;
+
+  //  if (!registerElement(ID, volvtk)) {
+  //    RemoveElement(volvtk, false);
+  //    volvtk = NULL;
+  //  }
+  return volvtk;
 }
 
 
 //=======================================================================
 //function : AddVolume
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
-                                     const SMDS_MeshNode * n2, 
-                                     const SMDS_MeshNode * n3,
-                                     const SMDS_MeshNode * n4,
-                                      const SMDS_MeshNode * n5, 
-                                      const SMDS_MeshNode * n6, 
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
                                       const SMDS_MeshNode * n7,
-                                      const SMDS_MeshNode * n8, 
+                                      const SMDS_MeshNode * n8,
                                       const SMDS_MeshNode * n12,
                                       const SMDS_MeshNode * n23,
                                       const SMDS_MeshNode * n34,
-                                      const SMDS_MeshNode * n41, 
+                                      const SMDS_MeshNode * n41,
                                       const SMDS_MeshNode * n56,
                                       const SMDS_MeshNode * n67,
                                       const SMDS_MeshNode * n78,
-                                      const SMDS_MeshNode * n85, 
+                                      const SMDS_MeshNode * n85,
                                       const SMDS_MeshNode * n15,
                                       const SMDS_MeshNode * n26,
                                       const SMDS_MeshNode * n37,
@@ -2917,7 +4327,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
 
 //=======================================================================
 //function : AddVolumeWithID
-//purpose  : 
+//purpose  :
 //=======================================================================
 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
                                             int n5, int n6, int n7, int n8,
@@ -2925,43 +4335,30 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
                                             int n56,int n67,int n78,int n85,
                                             int n15,int n26,int n37,int n48, int ID)
 {
-  SMDS_MeshNode *node1, *node2, *node3, *node4;
-  SMDS_MeshNode *node5, *node6, *node7, *node8;
-  SMDS_MeshNode *node12, *node23, *node34, *node41;
-  SMDS_MeshNode *node56, *node67, *node78, *node85;
-  SMDS_MeshNode *node15, *node26, *node37, *node48;
-  node1 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1);
-  node2 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2);
-  node3 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3);
-  node4 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4);
-  node5 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5);
-  node6 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6);
-  node7 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7);
-  node8 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8);
-  node12 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12);
-  node23 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23);
-  node34 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34);
-  node41 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41);
-  node56 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56);
-  node67 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67);
-  node78 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78);
-  node85 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85);
-  node15 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15);
-  node26 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26);
-  node37 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37);
-  node48 = (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48);
-  if( !node1 || !node2 || !node3 || !node4 ||
-      !node5 || !node6 || !node7 || !node8 ||
-      !node12 || !node23 || !node34 || !node41 ||
-      !node56 || !node67 || !node78 || !node85 ||
-      !node15 || !node26 || !node37 || !node48 ) return NULL;
-  return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4,
-                                    node5, node6, node7, node8,
-                                    node12, node23, node34, node41,
-                                    node56, node67, node78, node85,
-                                    node15, node26, node37, node48, ID);
-}
-       
+  return SMDS_Mesh::AddVolumeWithID
+    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
+     ID);
+}
+
 //=======================================================================
 //function : AddVolumeWithID
 //purpose  : 2d order Hexahedrons with 20 nodes
@@ -2970,36 +4367,362 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
                                             const SMDS_MeshNode * n2,
                                             const SMDS_MeshNode * n3,
                                             const SMDS_MeshNode * n4,
-                                            const SMDS_MeshNode * n5, 
-                                            const SMDS_MeshNode * n6, 
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
                                             const SMDS_MeshNode * n7,
-                                            const SMDS_MeshNode * n8, 
+                                            const SMDS_MeshNode * n8,
                                             const SMDS_MeshNode * n12,
                                             const SMDS_MeshNode * n23,
                                             const SMDS_MeshNode * n34,
-                                            const SMDS_MeshNode * n41, 
+                                            const SMDS_MeshNode * n41,
                                             const SMDS_MeshNode * n56,
                                             const SMDS_MeshNode * n67,
                                             const SMDS_MeshNode * n78,
-                                            const SMDS_MeshNode * n85, 
+                                            const SMDS_MeshNode * n85,
                                             const SMDS_MeshNode * n15,
                                             const SMDS_MeshNode * n26,
                                             const SMDS_MeshNode * n37,
                                             const SMDS_MeshNode * n48,
                                             int ID)
 {
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
+      !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
+    return 0;
   if(hasConstructionFaces()) {
+    return 0;
     // creation quadratic faces - not implemented
   }
-  SMDS_QuadraticVolumeOfNodes * volume =
-    new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8,n12,n23,n34,n41,
-                                    n56,n67,n78,n85,n15,n26,n37,n48);
-  myVolumes.Add(volume);
+  // --- retrieve nodes ID
+  myNodeIds.resize(20);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n4->getVtkId();
+  myNodeIds[2] = n3->getVtkId();
+  myNodeIds[3] = n2->getVtkId();
+
+  myNodeIds[4] = n5->getVtkId();
+  myNodeIds[5] = n8->getVtkId();
+  myNodeIds[6] = n7->getVtkId();
+  myNodeIds[7] = n6->getVtkId();
+
+  myNodeIds[8] = n41->getVtkId();
+  myNodeIds[9] = n34->getVtkId();
+  myNodeIds[10] = n23->getVtkId();
+  myNodeIds[11] = n12->getVtkId();
+
+  myNodeIds[12] = n85->getVtkId();
+  myNodeIds[13] = n78->getVtkId();
+  myNodeIds[14] = n67->getVtkId();
+  myNodeIds[15] = n56->getVtkId();
+
+  myNodeIds[16] = n15->getVtkId();
+  myNodeIds[17] = n48->getVtkId();
+  myNodeIds[18] = n37->getVtkId();
+  myNodeIds[19] = n26->getVtkId();
+
+  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+  volvtk->init(myNodeIds, this);
+  if (!this->registerElement(ID,volvtk))
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
+  }
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volvtk;
+  myInfo.myNbQuadHexas++;
 
-  if (!registerElement(ID, volume)) {
-    RemoveElement(volume, false);
-    volume = NULL;
+  //  if (!registerElement(ID, volvtk)) {
+  //    RemoveElement(volvtk, false);
+  //    volvtk = NULL;
+  //  }
+  return volvtk;
+}
+
+//=======================================================================
+//function : AddVolume
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
+                                      const SMDS_MeshNode * n2,
+                                      const SMDS_MeshNode * n3,
+                                      const SMDS_MeshNode * n4,
+                                      const SMDS_MeshNode * n5,
+                                      const SMDS_MeshNode * n6,
+                                      const SMDS_MeshNode * n7,
+                                      const SMDS_MeshNode * n8,
+                                      const SMDS_MeshNode * n12,
+                                      const SMDS_MeshNode * n23,
+                                      const SMDS_MeshNode * n34,
+                                      const SMDS_MeshNode * n41,
+                                      const SMDS_MeshNode * n56,
+                                      const SMDS_MeshNode * n67,
+                                      const SMDS_MeshNode * n78,
+                                      const SMDS_MeshNode * n85,
+                                      const SMDS_MeshNode * n15,
+                                      const SMDS_MeshNode * n26,
+                                      const SMDS_MeshNode * n37,
+                                      const SMDS_MeshNode * n48,
+                                      const SMDS_MeshNode * n1234,
+                                      const SMDS_MeshNode * n1256,
+                                      const SMDS_MeshNode * n2367,
+                                      const SMDS_MeshNode * n3478,
+                                      const SMDS_MeshNode * n1458,
+                                      const SMDS_MeshNode * n5678,
+                                      const SMDS_MeshNode * nCenter)
+{
+  int ID = myElementIDFactory->GetFreeID();
+  SMDS_MeshVolume * v =
+    SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
+                               n56, n67, n78, n85, n15, n26, n37, n48,
+                               n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
+                               ID);
+  if(v==NULL) myElementIDFactory->ReleaseID(ID);
+  return v;
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  :
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
+                                            int n5, int n6, int n7, int n8,
+                                            int n12,int n23,int n34,int n41,
+                                            int n56,int n67,int n78,int n85,
+                                            int n15,int n26,int n37,int n48,
+                                            int n1234,int n1256,int n2367,int n3478,
+                                            int n1458,int n5678,int nCenter, int ID)
+{
+  return SMDS_Mesh::AddVolumeWithID
+    ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
+     (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
+     ID);
+}
+
+//=======================================================================
+//function : AddVolumeWithID
+//purpose  : 2d order Hexahedrons with 20 nodes
+//=======================================================================
+SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
+                                            const SMDS_MeshNode * n2,
+                                            const SMDS_MeshNode * n3,
+                                            const SMDS_MeshNode * n4,
+                                            const SMDS_MeshNode * n5,
+                                            const SMDS_MeshNode * n6,
+                                            const SMDS_MeshNode * n7,
+                                            const SMDS_MeshNode * n8,
+                                            const SMDS_MeshNode * n12,
+                                            const SMDS_MeshNode * n23,
+                                            const SMDS_MeshNode * n34,
+                                            const SMDS_MeshNode * n41,
+                                            const SMDS_MeshNode * n56,
+                                            const SMDS_MeshNode * n67,
+                                            const SMDS_MeshNode * n78,
+                                            const SMDS_MeshNode * n85,
+                                            const SMDS_MeshNode * n15,
+                                            const SMDS_MeshNode * n26,
+                                            const SMDS_MeshNode * n37,
+                                            const SMDS_MeshNode * n48,
+                                            const SMDS_MeshNode * n1234,
+                                            const SMDS_MeshNode * n1256,
+                                            const SMDS_MeshNode * n2367,
+                                            const SMDS_MeshNode * n3478,
+                                            const SMDS_MeshNode * n1458,
+                                            const SMDS_MeshNode * n5678,
+                                            const SMDS_MeshNode * nCenter,
+                                            int ID)
+{
+  if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
+      !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
+      !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
+    return 0;
+  if(hasConstructionFaces()) {
+    return 0;
+    // creation quadratic faces - not implemented
   }
-  return volume;
+  // --- retrieve nodes ID
+  myNodeIds.resize(27);
+  myNodeIds[0] = n1->getVtkId();
+  myNodeIds[1] = n4->getVtkId();
+  myNodeIds[2] = n3->getVtkId();
+  myNodeIds[3] = n2->getVtkId();
+
+  myNodeIds[4] = n5->getVtkId();
+  myNodeIds[5] = n8->getVtkId();
+  myNodeIds[6] = n7->getVtkId();
+  myNodeIds[7] = n6->getVtkId();
+
+  myNodeIds[8] = n41->getVtkId();
+  myNodeIds[9] = n34->getVtkId();
+  myNodeIds[10] = n23->getVtkId();
+  myNodeIds[11] = n12->getVtkId();
+
+  myNodeIds[12] = n85->getVtkId();
+  myNodeIds[13] = n78->getVtkId();
+  myNodeIds[14] = n67->getVtkId();
+  myNodeIds[15] = n56->getVtkId();
+
+  myNodeIds[16] = n15->getVtkId();
+  myNodeIds[17] = n48->getVtkId();
+  myNodeIds[18] = n37->getVtkId();
+  myNodeIds[19] = n26->getVtkId();
+
+  myNodeIds[20] = n1256->getVtkId();
+  myNodeIds[21] = n3478->getVtkId();
+  myNodeIds[22] = n1458->getVtkId();
+  myNodeIds[23] = n2367->getVtkId();
+  myNodeIds[24] = n1234->getVtkId();
+  myNodeIds[25] = n5678->getVtkId();
+  myNodeIds[26] = nCenter->getVtkId();
+
+  SMDS_VtkVolume *volvtk = myVolumePool->getNew();
+  volvtk->init(myNodeIds, this);
+  if (!this->registerElement(ID,volvtk))
+  {
+    this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
+    myVolumePool->destroy(volvtk);
+    return 0;
+  }
+  adjustmyCellsCapacity(ID);
+  myCells[ID] = volvtk;
+  myInfo.myNbTriQuadHexas++;
+
+  return volvtk;
 }
 
+void SMDS_Mesh::dumpGrid(string ficdump)
+{
+  //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
+  //  aWriter->SetFileName(ficdump.c_str());
+  //  aWriter->SetInput(myGrid);
+  //  if(myGrid->GetNumberOfCells())
+  //  {
+  //    aWriter->Write();
+  //  }
+  //  aWriter->Delete();
+  ficdump = ficdump + "_connectivity";
+  ofstream ficcon(ficdump.c_str(), ios::out);
+  int nbPoints = myGrid->GetNumberOfPoints();
+  ficcon << "-------------------------------- points " <<  nbPoints << endl;
+  for (int i=0; i<nbPoints; i++)
+  {
+    ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
+  }
+  int nbCells = myGrid->GetNumberOfCells();
+  ficcon << "-------------------------------- cells " <<  nbCells << endl;
+  for (int i=0; i<nbCells; i++)
+  {
+    ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
+    int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
+    vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
+    for (int j=0; j<nbptcell; j++)
+    {
+      ficcon << " " <<  listid->GetId(j);
+    }
+    ficcon << endl;
+  }
+  ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
+  vtkCellLinks *links = myGrid->GetLinks();
+  for (int i=0; i<nbPoints; i++)
+  {
+    int ncells = links->GetNcells(i);
+    vtkIdType *cells = links->GetCells(i);
+    ficcon << i << " - " << ncells << " -";
+    for (int j=0; j<ncells; j++)
+    {
+      ficcon << " " << cells[j];
+    }
+    ficcon << endl;
+  }
+  ficcon.close();
+
+}
+
+void SMDS_Mesh::compactMesh()
+{
+  this->myCompactTime = this->myModifTime;
+}
+
+int SMDS_Mesh::fromVtkToSmds(int vtkid)
+{
+  if (vtkid >= 0 && vtkid < (int)myCellIdVtkToSmds.size())
+    return myCellIdVtkToSmds[vtkid];
+  throw SALOME_Exception(LOCALIZED ("vtk id out of bounds"));
+}
+
+// void SMDS_Mesh::updateBoundingBox()
+// {
+//   xmin = 0; xmax = 0;
+//   ymin = 0; ymax = 0;
+//   zmin = 0; zmax = 0;
+//   vtkPoints *points = myGrid->GetPoints();
+//   int myNodesSize = this->myNodes.size();
+//   for (int i = 0; i < myNodesSize; i++)
+//     {
+//       if (SMDS_MeshNode *n = myNodes[i])
+//         {
+//           double coords[3];
+//           points->GetPoint(n->myVtkID, coords);
+//           if (coords[0] < xmin) xmin = coords[0];
+//           else if (coords[0] > xmax) xmax = coords[0];
+//           if (coords[1] < ymin) ymin = coords[1];
+//           else if (coords[1] > ymax) ymax = coords[1];
+//           if (coords[2] < zmin) zmin = coords[2];
+//           else if (coords[2] > zmax) zmax = coords[2];
+//         }
+//     }
+// }
+
+double SMDS_Mesh::getMaxDim()
+{
+  double dmax = 1.e-3;
+  if ((xmax - xmin) > dmax) dmax = xmax -xmin;
+  if ((ymax - ymin) > dmax) dmax = ymax -ymin;
+  if ((zmax - zmin) > dmax) dmax = zmax -zmin;
+  return dmax;
+}
+
+//! modification that needs compact structure and redraw
+void SMDS_Mesh::Modified()
+{
+  if (this->myModified)
+  {
+    this->myModifTime++;
+    myModified = false;
+  }
+}
+
+//! get last modification timeStamp
+vtkMTimeType SMDS_Mesh::GetMTime() const
+{
+  return this->myModifTime;
+}
+
+bool SMDS_Mesh::isCompacted()
+{
+  return this->myCompactTime == this->myModifTime;
+}