BUG: EDF 2655: Hexa splitting into tetra low performance

A better fix has been found by improving the getNextFree() method in ObjectPool.hxx. When there is no "hole" in the ID list we don't iterate on the _freeList to find the next free ID. We jump straight to the last occupied ID.
This fix is simpler and can benefit to other methods of SMESH_Editor like QuadTo4Tri for example.
This commit is contained in:
rnc 2013-07-22 08:46:57 +00:00
parent 3f3beb8b95
commit 094287b4df
2 changed files with 22 additions and 38 deletions

View File

@ -42,9 +42,16 @@ private:
int _nextFree; int _nextFree;
int _maxAvail; int _maxAvail;
int _chunkSize; int _chunkSize;
int _maxOccupied;
int _nbHoles;
int getNextFree() int getNextFree()
{ {
// Don't iterate on the _freeList if all the "holes"
// are filled. Go straight to the last occupied ID + 1
if ( _nbHoles == 0 )
return std::min(_maxOccupied + 1, _maxAvail);
for (int i = _nextFree; i < _maxAvail; i++) for (int i = _nextFree; i < _maxAvail; i++)
if (_freeList[i] == true) if (_freeList[i] == true)
{ {
@ -73,6 +80,8 @@ public:
_chunkSize = nblk; _chunkSize = nblk;
_nextFree = 0; _nextFree = 0;
_maxAvail = 0; _maxAvail = 0;
_maxOccupied = 0;
_nbHoles = 0;
_chunkList.clear(); _chunkList.clear();
_freeList.clear(); _freeList.clear();
} }
@ -103,6 +112,14 @@ public:
_freeList[_nextFree] = false; _freeList[_nextFree] = false;
obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank]; obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank];
} }
if (_nextFree < _maxOccupied)
{
_nbHoles-=1;
}
else
{
_maxOccupied = _nextFree;
}
//obj->init(); //obj->init();
return obj; return obj;
} }
@ -124,6 +141,8 @@ public:
_freeList[toFree] = true; _freeList[toFree] = true;
if (toFree < _nextFree) if (toFree < _nextFree)
_nextFree = toFree; _nextFree = toFree;
if (toFree < _maxOccupied)
_nbHoles += 1;
//obj->clean(); //obj->clean();
//checkDelete(i); compactage non fait //checkDelete(i); compactage non fait
break; break;
@ -134,6 +153,8 @@ public:
{ {
_nextFree = 0; _nextFree = 0;
_maxAvail = 0; _maxAvail = 0;
_maxOccupied = 0;
_nbHoles = 0;
for (size_t i = 0; i < _chunkList.size(); i++) for (size_t i = 0; i < _chunkList.size(); i++)
delete[] _chunkList[i]; delete[] _chunkList[i];
clearVector( _chunkList ); clearVector( _chunkList );

View File

@ -1899,20 +1899,6 @@ namespace
}; };
} // namespace } // namespace
class TElemToDelete
{
public:
TElemToDelete(const SMDS_MeshElement* theElem, SMESHDS_SubMesh* theSubMesh)
{
elem = theElem;
subMesh = theSubMesh;
}
const SMDS_MeshElement* Elem() const {return elem;}
SMESHDS_SubMesh* Submesh() {return subMesh;}
const SMDS_MeshElement* elem;
SMESHDS_SubMesh* subMesh;
};
//======================================================================= //=======================================================================
//function : SplitVolumesIntoTetra //function : SplitVolumesIntoTetra
//purpose : Split volume elements into tetrahedra. //purpose : Split volume elements into tetrahedra.
@ -1938,7 +1924,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
double bc[3]; double bc[3];
TIDSortedElemSet::const_iterator elem = theElems.begin(); TIDSortedElemSet::const_iterator elem = theElems.begin();
std::vector<TElemToDelete> elem_to_delete;
for ( ; elem != theElems.end(); ++elem ) for ( ; elem != theElems.end(); ++elem )
{ {
if ( (*elem)->GetType() != SMDSAbs_Volume ) if ( (*elem)->GetType() != SMDSAbs_Volume )
@ -2102,26 +2087,11 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
} }
ReplaceElemInGroups( face, triangles, GetMeshDS() ); ReplaceElemInGroups( face, triangles, GetMeshDS() );
GetMeshDS()->RemoveFreeElement( face, fSubMesh, /*fromGroups=*/false ); GetMeshDS()->RemoveFreeElement( face, fSubMesh, /*fromGroups=*/false );
// TElemToDelete faceToDelete(face, fSubMesh);
// elem_to_delete.push_back(faceToDelete);
} }
} // loop on volume faces to split them into triangles } // loop on volume faces to split them into triangles
// GetMeshDS()->RemoveFreeElement( *elem, subMesh, /*fromGroups=*/false ); GetMeshDS()->RemoveFreeElement( *elem, subMesh, /*fromGroups=*/false );
// rnc : don't delete the elem here because it results in a mesh with a free
// ID at the beginning of the ID list. The first tetra is then inserted in O(1)
// but the second one is inserted in O(n), then the whole procedure has almost a O(n^2)
// complexity. If all elements to remove are stored and removed after tetra creation
// we get a O(n) complexity for the whole procedure.
// The memory cost is at worst a 6*n*constant memory occupation (where n is the number of elements)
// before deletion of the hexas and then 5*n*constant instead of a maximum of 5*n*constant.
// So there is a transient 1/5*(memory occupation) additional cost.
// Store the elements to delete
TElemToDelete elemToDelete(*elem, subMesh);
elem_to_delete.push_back(elemToDelete);
if ( geomType == SMDSEntity_TriQuad_Hexa ) if ( geomType == SMDSEntity_TriQuad_Hexa )
{ {
@ -2132,13 +2102,6 @@ void SMESH_MeshEditor::SplitVolumesIntoTetra (const TIDSortedElemSet & theElems,
} }
} // loop on volumes to split } // loop on volumes to split
// Delete stored elements
std::vector<TElemToDelete>::iterator it;
for( it = elem_to_delete.begin(); it!= elem_to_delete.end(); it++)
{
GetMeshDS()->RemoveFreeElement( it->Elem(), it->Submesh(), /*fromGroups=*/false );
}
myLastCreatedNodes = newNodes; myLastCreatedNodes = newNodes;
myLastCreatedElems = newElems; myLastCreatedElems = newElems;
} }