Salome HOME
PAL14858 (The Mesh Info Dialog Box is too slow)
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
index 26a998117dc5fda2cd2acc490f44fbd73cb62ca5..3b11490705472721381667a449bd9c1676bbfb44 100644 (file)
 #include <map>
 using namespace std;
 
+#ifndef WIN32
+#include <sys/sysinfo.h>
+#endif
+
+
+//================================================================================
+/*!
+ * \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)
+{
+#ifndef WIN32
+  struct sysinfo si;
+  int err = sysinfo( &si );
+  if ( err )
+    return -1;
+
+  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);
+    }
+    if ( limit < 20 )
+      limit = 20;
+    else
+      limit = int( limit * 1.5 );
+#ifdef _DEBUG_
+    cout << "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" << endl;
+#endif
+  }
+
+  const unsigned long Mbyte = 1024 * 1024;
+  // compute separately to avoid overflow
+  int freeMb =
+    ( si.freeram  * si.mem_unit ) / Mbyte +
+    ( si.freeswap * si.mem_unit ) / Mbyte;
+
+  if ( freeMb > limit )
+    return freeMb - limit;
+
+  if ( doNotRaise )
+    return 0;
+#ifdef _DEBUG_
+  cout<<"SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" << endl;
+#endif
+  throw std::bad_alloc();
+#else
+  return -1;
+#endif
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 /// Create a new mesh object
 ///////////////////////////////////////////////////////////////////////////////
@@ -96,9 +152,11 @@ 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){
+    CheckMemory();
     SMDS_MeshNode * node=new SMDS_MeshNode(x, y, z);
     myNodes.Add(node);
     myNodeIDFactory->BindID(ID,node);
+    myInfo.myNbNodes++;
     return node;
   }else
     return NULL;
@@ -143,6 +201,7 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
 {
   if ( !n1 || !n2 ) return 0;
 
+  CheckMemory();
   SMDS_MeshEdge * edge=new SMDS_MeshEdge(n1,n2);
   if(myElementIDFactory->BindID(ID, edge)) {
     SMDS_MeshNode *node1,*node2;
@@ -151,6 +210,7 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
     node1->AddInverseElement(edge);
     node2->AddInverseElement(edge);            
     myEdges.Add(edge);
+    myInfo.myNbEdges++;
     return edge;
   } 
   else {
@@ -280,8 +340,10 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
     return NULL;
   if ( !e1 || !e2 || !e3 ) return 0;
 
+  CheckMemory();
   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
   myFaces.Add(face);
+  myInfo.myNbTriangles++;
 
   if (!registerElement(ID, face)) {
     RemoveElement(face, false);
@@ -318,8 +380,10 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
   if (!hasConstructionEdges())
     return NULL;
   if ( !e1 || !e2 || !e3 || !e4 ) return 0;
+  CheckMemory();
   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
   myFaces.Add(face);
+  myInfo.myNbQuadrangles++;
 
   if (!registerElement(ID, face))
   {
@@ -381,6 +445,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
 {
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4) return volume;
+  CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4);
@@ -388,6 +453,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n3,n4);
     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
     myVolumes.Add(volume);
+    myInfo.myNbTetras++;
   }
   else if(hasConstructionEdges()) {
     MESSAGE("Error : Not implemented");
@@ -396,6 +462,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   else {
     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4);
     myVolumes.Add(volume);
+    myInfo.myNbTetras++;
   }
 
   if (!registerElement(ID, volume)) {
@@ -464,6 +531,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
 {
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume;
+  CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n5);
@@ -471,6 +539,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     SMDS_MeshFace * f4=FindFaceOrCreate(n3,n4,n5);
     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
     myVolumes.Add(volume);
+    myInfo.myNbPyramids++;
   }
   else if(hasConstructionEdges()) {
     MESSAGE("Error : Not implemented");
@@ -479,6 +548,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   else {
     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5);
     myVolumes.Add(volume);
+    myInfo.myNbPyramids++;
   }
 
   if (!registerElement(ID, volume)) {
@@ -551,6 +621,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
 {
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume;
+  CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
     SMDS_MeshFace * f2=FindFaceOrCreate(n4,n5,n6);
@@ -559,6 +630,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     SMDS_MeshFace * f5=FindFaceOrCreate(n3,n6,n4,n1);
     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
     myVolumes.Add(volume);
+    myInfo.myNbPrisms++;
   }
   else if(hasConstructionEdges()) {
     MESSAGE("Error : Not implemented");
@@ -567,6 +639,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   else {
     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6);
     myVolumes.Add(volume);
+    myInfo.myNbPrisms++;
   }
 
   if (!registerElement(ID, volume)) {
@@ -650,6 +723,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
 {
   SMDS_MeshVolume* volume = 0;
   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
+  CheckMemory();
   if(hasConstructionFaces()) {
     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
     SMDS_MeshFace * f2=FindFaceOrCreate(n5,n6,n7,n8);
@@ -659,6 +733,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     SMDS_MeshFace * f6=FindFaceOrCreate(n3,n4,n8,n7);
     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
     myVolumes.Add(volume);
+    myInfo.myNbHexas++;
   }
   else if(hasConstructionEdges()) {
     MESSAGE("Error : Not implemented");
@@ -668,6 +743,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
 //    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);
+    myInfo.myNbHexas++;
   }
 
   if (!registerElement(ID, volume)) {
@@ -707,8 +783,10 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
   if (!hasConstructionFaces())
     return NULL;
   if ( !f1 || !f2 || !f3 || !f4) return 0;
+  CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4);
   myVolumes.Add(volume);
+  myInfo.myNbTetras++;
 
   if (!registerElement(ID, volume)) {
     RemoveElement(volume, false);
@@ -749,8 +827,10 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
   if (!hasConstructionFaces())
     return NULL;
   if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0;
+  CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
   myVolumes.Add(volume);
+  myInfo.myNbPyramids++;
 
   if (!registerElement(ID, volume)) {
     RemoveElement(volume, false);
@@ -793,8 +873,10 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
   if (!hasConstructionFaces())
     return NULL;
   if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0;
+  CheckMemory();
   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
   myVolumes.Add(volume);
+  myInfo.myNbPrisms++;
 
   if (!registerElement(ID, volume)) {
     RemoveElement(volume, false);
@@ -829,6 +911,7 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
 {
   SMDS_MeshFace * face;
 
+  CheckMemory();
   if (hasConstructionEdges())
   {
     MESSAGE("Error : Not implemented");
@@ -840,6 +923,7 @@ SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
       if ( !nodes[ i ] ) return 0;
     face = new SMDS_PolygonalFaceOfNodes(nodes);
     myFaces.Add(face);
+    myInfo.myNbPolygons++;
   }
 
   if (!registerElement(ID, face)) {
@@ -892,6 +976,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
                              const int                         ID)
 {
   SMDS_MeshVolume* volume;
+  CheckMemory();
   if (hasConstructionFaces()) {
     MESSAGE("Error : Not implemented");
     return NULL;
@@ -903,6 +988,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
       if ( !nodes[ i ] ) return 0;
     volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
     myVolumes.Add(volume);
+    myInfo.myNbPolyhedrons++;
   }
 
   if (!registerElement(ID, volume)) {
@@ -961,23 +1047,25 @@ SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
                                           const SMDS_MeshNode * node3)
 {
   if ( !node1 || !node2 || !node3) return 0;
-       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;
-       }
+  CheckMemory();
+  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;
+  }
+  myInfo.myNbTriangles++;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -990,24 +1078,26 @@ SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
                                            const SMDS_MeshNode * node4)
 {
   if ( !node1 || !node2 || !node3 || !node4 ) return 0;
-       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;
-       }
+  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);
+    myFaces.Add(face);
+    return face;
+  }
+  else
+  {
+    SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3,node4);
+    myFaces.Add(face);
+    return face;
+  }
+  myInfo.myNbTriangles++;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -1259,20 +1349,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);
@@ -1292,9 +1380,11 @@ SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
   SMDS_MeshEdge * toReturn=NULL;
   toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
   if(toReturn==NULL) {
+    CheckMemory();
     toReturn=new SMDS_MeshEdge(node1,node2);
     myEdges.Add(toReturn);
-  } 
+    myInfo.myNbEdges++;
+  }
   return toReturn;
 }
 
@@ -1317,25 +1407,27 @@ const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
                                          const SMDS_MeshNode * node2,
                                          const SMDS_MeshNode * node3)
 {
-  if ( !node1 || !node2 || !node3 ) return 0;
-  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;
 }
 
 
@@ -1357,27 +1449,27 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node2,
                                          const SMDS_MeshNode *node3)
 {
-  if ( !node1 || !node2 || !node3 ) return 0;
-  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,
@@ -1413,29 +1505,28 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node3,
                                          const SMDS_MeshNode *node4)
 {
-  if( (node1==NULL) || (node2==NULL) || (node3==NULL) || (node4==NULL) )
-    return NULL;
-  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,
@@ -1477,28 +1568,30 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node5,
                                          const SMDS_MeshNode *node6)
 {
-  if( (node1==NULL) || (node2==NULL) || (node3==NULL) ||
-      (node4==NULL) || (node5==NULL) || (node6==NULL) ) return NULL;
-  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;
 }
 
 
@@ -1532,31 +1625,32 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
                                          const SMDS_MeshNode *node7,
                                          const SMDS_MeshNode *node8)
 {
-  if( (node1==NULL) || (node2==NULL) || (node3==NULL) || (node4==NULL) ||
-      (node5==NULL) || (node6==NULL) || (node7==NULL) || (node8==NULL) )
-    return NULL;
-  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;
 }
 
 
@@ -1588,36 +1682,23 @@ const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<int> nodes_ids) const
 
 const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<const SMDS_MeshNode *> nodes)
 {
-  int nbNodes = nodes.size();
-  if (nbNodes < 1) return NULL;
-
-  bool isFound = true;
-  const SMDS_MeshFace * face;
-  set<const SMDS_MeshFace *> faces;
-
-  for (int inode = 0; inode < nbNodes && isFound; inode++) {
-    if ( !nodes[ inode ]) return 0;
-    
-    set<const SMDS_MeshFace *> new_faces;
-
-    SMDS_ElemIteratorPtr itF = nodes[inode]->facesIterator();
+  if ( nodes.size() > 2 && nodes[0] ) {
+    SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
     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* f = itF->next();
+      if ( f->NbNodes() == nodes.size() ) {
+        SMDS_ElemIteratorPtr it2 = f->nodesIterator();
+        while(it2->more()) {
+          if ( find( nodes.begin(), nodes.end(), it2->next() ) == nodes.end() ) {
+            f = 0;
+            break;
+          }
         }
+        if ( f )
+          return static_cast<const SMDS_MeshFace *> (f);
       }
     }
-    faces = new_faces;
-    if (new_faces.size() == 0) {
-      isFound = false;
-    }
   }
-
-  if (isFound)
-    return face;
-
   return NULL;
 }
 
@@ -2225,14 +2306,17 @@ void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
     case SMDSAbs_Edge:
       myEdges.Remove(static_cast<SMDS_MeshEdge*>
                     (const_cast<SMDS_MeshElement*>(*it)));
+      myInfo.RemoveEdge(*it);
       break;
     case SMDSAbs_Face:
       myFaces.Remove(static_cast<SMDS_MeshFace*>
                     (const_cast<SMDS_MeshElement*>(*it)));
+      myInfo.RemoveFace(*it);
       break;
     case SMDSAbs_Volume:
       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
                       (const_cast<SMDS_MeshElement*>(*it)));
+      myInfo.RemoveVolume(*it);
       break;
     }
     //MESSAGE( "SMDS: RM elem " << (*it)->GetID() );
@@ -2251,6 +2335,7 @@ void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
       //MESSAGE( "SMDS: RM node " << (*it)->GetID() );
       myNodes.Remove(static_cast<SMDS_MeshNode*>
                     (const_cast<SMDS_MeshElement*>(*it)));
+      myInfo.myNbNodes--;
       myNodeIDFactory->ReleaseID((*it)->GetID());
       removedNodes.push_back( (*it) );
       delete *it;
@@ -2275,6 +2360,7 @@ void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
     if (!itFe->more()) { // free node
       myNodes.Remove(const_cast<SMDS_MeshNode*>(n));
+      myInfo.myNbNodes--;
       myNodeIDFactory->ReleaseID(elem->GetID());
       delete elem;
     }
@@ -2296,14 +2382,17 @@ void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
     case SMDSAbs_Edge:
       myEdges.Remove(static_cast<SMDS_MeshEdge*>
                      (const_cast<SMDS_MeshElement*>(elem)));
+      myInfo.RemoveEdge(elem);
       break;
     case SMDSAbs_Face:
       myFaces.Remove(static_cast<SMDS_MeshFace*>
                      (const_cast<SMDS_MeshElement*>(elem)));
+      myInfo.RemoveFace(elem);
       break;
     case SMDSAbs_Volume:
       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
                        (const_cast<SMDS_MeshElement*>(elem)));
+      myInfo.RemoveVolume(elem);
       break;
     default:
       break;
@@ -2494,6 +2583,7 @@ SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
     node2->AddInverseElement(edge);
     node12->AddInverseElement(edge);
     myEdges.Add(edge);
+    myInfo.myNbQuadEdges++;
     return edge;
   } 
   else {
@@ -2555,6 +2645,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
   SMDS_QuadraticFaceOfNodes* face =
     new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n12,n23,n31);
   myFaces.Add(face);
+  myInfo.myNbQuadTriangles++;
 
   if (!registerElement(ID, face)) {
     RemoveElement(face, false);
@@ -2621,6 +2712,7 @@ SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
   SMDS_QuadraticFaceOfNodes* face =
     new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n4,n12,n23,n34,n41);
   myFaces.Add(face);
+  myInfo.myNbQuadQuadrangles++;
 
   if (!registerElement(ID, face)) {
     RemoveElement(face, false);
@@ -2699,6 +2791,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   SMDS_QuadraticVolumeOfNodes * volume =
     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n12,n23,n31,n14,n24,n34);
   myVolumes.Add(volume);
+  myInfo.myNbQuadTetras++;
 
   if (!registerElement(ID, volume)) {
     RemoveElement(volume, false);
@@ -2789,6 +2882,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n12,n23,
                                     n34,n41,n15,n25,n35,n45);
   myVolumes.Add(volume);
+  myInfo.myNbQuadPyramids++;
 
   if (!registerElement(ID, volume)) {
     RemoveElement(volume, false);
@@ -2887,6 +2981,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n12,n23,n31,
                                     n45,n56,n64,n14,n25,n36);
   myVolumes.Add(volume);
+  myInfo.myNbQuadPrisms++;
 
   if (!registerElement(ID, volume)) {
     RemoveElement(volume, false);
@@ -3000,6 +3095,7 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
     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);
+  myInfo.myNbQuadHexas++;
 
   if (!registerElement(ID, volume)) {
     RemoveElement(volume, false);
@@ -3007,4 +3103,3 @@ SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
   }
   return volume;
 }
-