From 1199fcd63cc145f4c70dd3bf537d3d4a7c344071 Mon Sep 17 00:00:00 2001 From: eap Date: Fri, 14 Dec 2012 13:19:01 +0000 Subject: [PATCH] 21948: EDF SMESH : Memory is not freed when deleting a mesh Optimize for large meshes --- src/SMESHDS/SMESHDS_GroupOnFilter.cxx | 219 ++++++++++++++++++++++---- src/SMESHDS/SMESHDS_GroupOnFilter.hxx | 20 ++- 2 files changed, 203 insertions(+), 36 deletions(-) diff --git a/src/SMESHDS/SMESHDS_GroupOnFilter.cxx b/src/SMESHDS/SMESHDS_GroupOnFilter.cxx index 32bd8c7f3..3850da28b 100644 --- a/src/SMESHDS/SMESHDS_GroupOnFilter.cxx +++ b/src/SMESHDS/SMESHDS_GroupOnFilter.cxx @@ -28,6 +28,9 @@ #include "SMESHDS_Mesh.hxx" #include "SMDS_SetIterator.hxx" +#include +#include + 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::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( 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( this ); if ( !IsUpToDate() ) { - SMESHDS_GroupOnFilter* me = const_cast( 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; } diff --git a/src/SMESHDS/SMESHDS_GroupOnFilter.hxx b/src/SMESHDS/SMESHDS_GroupOnFilter.hxx index b1e33e5fc..17b347a21 100644 --- a/src/SMESHDS/SMESHDS_GroupOnFilter.hxx +++ b/src/SMESHDS/SMESHDS_GroupOnFilter.hxx @@ -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