]> SALOME platform Git repositories - modules/smesh.git/commitdiff
Salome HOME
21948: EDF SMESH : Memory is not freed when deleting a mesh
authoreap <eap@opencascade.com>
Fri, 14 Dec 2012 13:19:01 +0000 (13:19 +0000)
committereap <eap@opencascade.com>
Fri, 14 Dec 2012 13:19:01 +0000 (13:19 +0000)
Optimize for large meshes

src/SMESHDS/SMESHDS_GroupOnFilter.cxx
src/SMESHDS/SMESHDS_GroupOnFilter.hxx

index 32bd8c7f3485553f1dcb7cc7e7bfd4bba304db29..3850da28be5c0bae05d2ebf3cb93db4c5849aa1e 100644 (file)
@@ -28,6 +28,9 @@
 #include "SMESHDS_Mesh.hxx"
 #include "SMDS_SetIterator.hxx"
 
+#include <numeric>
+#include <limits>
+
 using namespace std;
 
 //=============================================================================
@@ -40,9 +43,12 @@ SMESHDS_GroupOnFilter::SMESHDS_GroupOnFilter (const int                 theID,
                                               const SMESHDS_Mesh*       theMesh,
                                               const SMDSAbs_ElementType theType,
                                               const SMESH_PredicatePtr& thePredicate)
-  : SMESHDS_GroupBase(theID,theMesh,theType), myMeshModifTime(0), myPredicateTic(0)
+  : SMESHDS_GroupBase(theID,theMesh,theType),
+    myMeshInfo( SMDSEntity_Last, 0 ),
+    myMeshModifTime(0),
+    myPredicateTic(0),
+    myNbElemToSkip(0)
 {
-  setChanged();
   SetPredicate( thePredicate );
 }
 
@@ -52,7 +58,7 @@ SMESHDS_GroupOnFilter::SMESHDS_GroupOnFilter (const int                 theID,
  */
 //================================================================================
 
-void SMESHDS_GroupOnFilter::SetPredicate( const SMESH_PredicatePtr& thePredicate)
+void SMESHDS_GroupOnFilter::SetPredicate( const SMESH_PredicatePtr& thePredicate )
 {
   myPredicate = thePredicate;
   ++myPredicateTic;
@@ -70,7 +76,36 @@ void SMESHDS_GroupOnFilter::SetPredicate( const SMESH_PredicatePtr& thePredicate
 int SMESHDS_GroupOnFilter::Extent() const
 {
   update();
-  return myElements.size();
+  return std::accumulate( myMeshInfo.begin(), myMeshInfo.end(), 0 );
+}
+
+//================================================================================
+/*!
+ * \brief Checks emptyness
+ */
+//================================================================================
+
+bool SMESHDS_GroupOnFilter::IsEmpty()
+{
+  if ( IsUpToDate() )
+  {
+    return ( Extent() == 0 );
+  }
+  else // not up-to-date
+  {
+    setChanged();
+    SMDS_ElemIteratorPtr okElemIt = GetElements();
+    if ( !okElemIt->more() )
+    {
+      // no satisfying elements
+      setChanged( false );
+    }
+    else
+    {
+      return false;
+    }
+  }
+  return true;
 }
 
 //================================================================================
@@ -95,6 +130,53 @@ bool SMESHDS_GroupOnFilter::Contains (const SMDS_MeshElement* elem)
   return myPredicate ? myPredicate->IsSatisfy( elem->GetID() ) : false;
 }
 
+//================================================================================
+namespace // Iterator
+{
+  struct TIterator : public SMDS_ElemIterator
+  {
+    SMESH_PredicatePtr      myPredicate;
+    SMDS_ElemIteratorPtr    myElemIt;
+    const SMDS_MeshElement* myNextElem;
+    size_t                  myNbToFind, myNbFound;
+    TIterator( const SMESH_PredicatePtr& filter,
+               SMDS_ElemIteratorPtr&     elems,
+               size_t                    nbToFind):
+      myPredicate( filter ),
+      myElemIt( elems ),
+      myNextElem( 0 ),
+      myNbToFind( nbToFind ),
+      myNbFound( 0 )
+    {
+      next();
+    }
+    virtual bool more()
+    {
+      return myNextElem;
+    }
+    virtual const SMDS_MeshElement* next()
+    {
+      const SMDS_MeshElement* res = myNextElem;
+      myNbFound += bool( res );
+      myNextElem = 0;
+      if ( myNbFound < myNbToFind )
+        while ( myElemIt->more() && !myNextElem )
+        {
+          myNextElem = myElemIt->next();
+          if ( !myPredicate->IsSatisfy( myNextElem->GetID() ))
+            myNextElem = 0;
+        }
+      return res;
+    }
+  };
+
+  struct TEmptyIterator : public SMDS_ElemIterator
+  {
+    virtual bool more()                    { return false; }
+    virtual const SMDS_MeshElement* next() { return 0; }
+  };
+}
+
 //================================================================================
 /*!
  * \brief Return iterator on all elements
@@ -103,25 +185,83 @@ bool SMESHDS_GroupOnFilter::Contains (const SMDS_MeshElement* elem)
 
 SMDS_ElemIteratorPtr SMESHDS_GroupOnFilter::GetElements() const
 {
-  update();
-  return SMDS_ElemIteratorPtr
-    ( new SMDS_ElementVectorIterator( myElements.begin(), myElements.end() ));
+  size_t nbToFind = std::numeric_limits<size_t>::max();
+
+  SMDS_ElemIteratorPtr elemIt;
+  if ( myPredicate )
+  {
+    myPredicate->SetMesh( GetMesh() ); // hope myPredicate updates self here if necessary
+
+    elemIt = GetMesh()->elementsIterator( GetType() );
+    if ( IsUpToDate() )
+    {
+      nbToFind = Extent();
+      if ( nbToFind == GetMesh()->GetMeshInfo().NbElements( GetType() ))
+        return elemIt; // all elements are OK
+      for ( size_t i = 0; i < myNbElemToSkip; ++i )
+        elemIt->next(); // skip w/o check
+    }
+  }
+  else
+  {
+    elemIt = SMDS_ElemIteratorPtr( new TEmptyIterator );
+  }
+  return SMDS_ElemIteratorPtr ( new TIterator( myPredicate, elemIt, nbToFind ));
 }
 
 //================================================================================
 /*!
- * \brief return ID of theIndex-th element
- *  \param theIndex - index countered from 1
- *  \retval int - element ID
+ * \brief Return info on sub-types of elements
  */
 //================================================================================
 
-int SMESHDS_GroupOnFilter::GetID (const int theIndex)
+std::vector< int > SMESHDS_GroupOnFilter::GetMeshInfo() const
 {
   update();
-  if ( theIndex < 1 || theIndex > myElements.size() )
-    return -1;
-  return myElements[ theIndex-1 ]->GetID();
+  return myMeshInfo;
+}
+
+//================================================================================
+/*!
+ * \brief Fill ids of elements. And return their number.
+ *       \a ids must be pre-allocated using nb of elements of type == GetType()
+ */
+//================================================================================
+
+int SMESHDS_GroupOnFilter::GetElementIds( int* ids ) const
+{
+  SMESHDS_GroupOnFilter* me = const_cast<SMESHDS_GroupOnFilter*>( this );
+
+  int* curID = ids;
+  SMDS_ElemIteratorPtr elIt = GetElements();
+  if ( elIt->more() )
+  {
+    if ( IsUpToDate() )
+    {
+      while ( elIt->more() )
+        *curID++ = elIt->next()->GetID();
+    }
+    else
+    {
+      me->setChanged();
+
+      // find out nb of elements to skip w/o check before the 1st OK element
+      const SMDS_MeshElement* firstOkElem = me->setNbElemToSkip( elIt );
+
+      me->myMeshInfo.assign( SMDSEntity_Last, 0 );
+      me->myMeshInfo[ firstOkElem->GetEntityType() ]++;
+      *curID++ = firstOkElem->GetID();
+      while ( elIt->more() )
+      {
+        const SMDS_MeshElement* e = elIt->next();
+        me->myMeshInfo[ e->GetEntityType() ]++;
+        *curID++ = e->GetID();
+      }
+    }
+  }
+  me->setChanged( false );
+
+  return curID - ids;
 }
 
 //================================================================================
@@ -154,23 +294,17 @@ bool SMESHDS_GroupOnFilter::IsUpToDate() const
 
 void SMESHDS_GroupOnFilter::update() const
 {
+  SMESHDS_GroupOnFilter* me = const_cast<SMESHDS_GroupOnFilter*>( this );
   if ( !IsUpToDate() )
   {
-    SMESHDS_GroupOnFilter* me = const_cast<SMESHDS_GroupOnFilter*>( this );
-    me->myElements.clear();
-    if ( myPredicate )
-    {
-      myPredicate->SetMesh( GetMesh() ); // hope myPredicate updates self here if necessary
-      me->myElements.reserve( GetMesh()->GetMeshInfo().NbElements(GetType()));
-      SMDS_ElemIteratorPtr elIt = GetMesh()->elementsIterator(GetType());
+    me->setChanged();
+    SMDS_ElemIteratorPtr elIt = GetElements();
+    if ( elIt->more() ) {
+      // find out nb of elements to skip w/o check before the 1st OK element
+      const SMDS_MeshElement* e = me->setNbElemToSkip( elIt );
+      ++me->myMeshInfo[ e->GetEntityType() ];
       while ( elIt->more() )
-      {
-        const SMDS_MeshElement* e = elIt->next();
-        if ( myPredicate->IsSatisfy( e->GetID() ))
-          me->myElements.push_back( e );
-      }
-      vector< const SMDS_MeshElement*> elems( me->myElements.begin(), me->myElements.end() );
-      me->myElements.swap( elems );
+        ++me->myMeshInfo[ elIt->next()->GetEntityType() ];
     }
     me->setChanged( false );
   }
@@ -178,7 +312,7 @@ void SMESHDS_GroupOnFilter::update() const
 
 //================================================================================
 /*!
- * \brief Sets myMeshModifTime according to modification state
+ * \brief Sets myMeshModifTime and clear fields according to modification state
  */
 //================================================================================
 
@@ -187,4 +321,31 @@ void SMESHDS_GroupOnFilter::setChanged(bool changed)
   myMeshModifTime = GetMesh()->GetMTime();
   if ( changed && myMeshModifTime != 0 )
     --myMeshModifTime;
+  if ( changed ) {
+    myNbElemToSkip = 0;
+    myMeshInfo.assign( SMDSEntity_Last, 0 );
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Sets myNbElemToSkip
+ *  \param okElemIt - iterator on OK elements
+ *  \retval const SMDS_MeshElement* - the first OK element
+ */
+//================================================================================
+
+const SMDS_MeshElement*
+SMESHDS_GroupOnFilter::setNbElemToSkip( SMDS_ElemIteratorPtr& okElemIt )
+{
+  // find out nb of elements to skip w/o check before the 1st OK element
+  const SMDS_MeshElement* firstOkElem = okElemIt->next();
+  if ( myNbElemToSkip == 0 )
+  {
+    SMDS_ElemIteratorPtr elemIt = GetMesh()->elementsIterator( GetType() );
+    myNbElemToSkip = 0;
+    while ( elemIt->next() != firstOkElem )
+      ++myNbElemToSkip;
+  }
+  return firstOkElem;
 }
index b1e33e5fc7ba4a9065bbdf074d9ec3df3f115f8f..17b347a21abba889cec3f7c85b9946e9ce884075 100644 (file)
@@ -46,7 +46,13 @@ class SMESHDS_EXPORT SMESHDS_GroupOnFilter: public SMESHDS_GroupBase
 
   SMESH_PredicatePtr GetPredicate() const { return myPredicate; }
 
-  virtual int Extent() const;
+  std::vector< int > GetMeshInfo() const;
+
+  int          GetElementIds( int* ids ) const;
+
+  virtual int  Extent() const;
+
+  virtual bool IsEmpty();
 
   virtual bool Contains (const int theID);
 
@@ -54,21 +60,21 @@ class SMESHDS_EXPORT SMESHDS_GroupOnFilter: public SMESHDS_GroupBase
 
   virtual SMDS_ElemIteratorPtr GetElements() const;
 
-  virtual int GetID (const int theIndex);
-
-  virtual int GetTic() const;
+  virtual int  GetTic() const;
 
-  bool IsUpToDate() const;
+  bool         IsUpToDate() const;
 
  private:
 
   void update() const;
   void setChanged(bool changed=true);
+  const SMDS_MeshElement* setNbElemToSkip( SMDS_ElemIteratorPtr& elIt );
 
   SMESH_PredicatePtr                    myPredicate;
-  std::vector< const SMDS_MeshElement*> myElements;
-  unsigned long                         myMeshModifTime; // when myElements was filled
+  std::vector< int >                    myMeshInfo;
+  size_t                                myMeshModifTime; // when myMeshInfo was updated
   int                                   myPredicateTic;
+  size_t                                myNbElemToSkip;
 };
 
 #endif