0023444: EDF 14244 - Viscous Layer

+ 54237: Invalid viscous layers (in Grids/smesh/viscous_layers_02/A3)
+ Improve viscous layers performance
     - by avoiding unnecessary intersection checks
     - by using std::vector instead of std::set in SMESH_ElementSearcher
+ Fix minor errors in ObjectPool which is now used in SMESH_ElementSearcher
This commit is contained in:
eap 2017-06-19 18:42:49 +03:00
parent 288e301997
commit ab008b333b
3 changed files with 399 additions and 123 deletions

View File

@ -21,9 +21,10 @@
#define _OBJECTPOOL_HXX_ #define _OBJECTPOOL_HXX_
#include <vector> #include <vector>
//#include <stack>
#include <iostream> #include <iostream>
#include "SMDS_Iterator.hxx"
namespace namespace
{ {
// assure deallocation of memory of a vector // assure deallocation of memory of a vector
@ -33,18 +34,22 @@ namespace
} }
} }
template<class X> class ObjectPoolIterator;
template<class X> class ObjectPool template<class X> class ObjectPool
{ {
private: private:
std::vector<X*> _chunkList; std::vector<X*> _chunkList;
std::vector<bool> _freeList; std::vector<bool> _freeList;
int _nextFree; int _nextFree; // either the 1st hole or last added
int _maxAvail; int _maxAvail; // nb allocated elements
int _chunkSize; int _chunkSize;
int _maxOccupied; int _maxOccupied; // max used ID
int _nbHoles; int _nbHoles;
int _lastDelChunk; int _lastDelChunk;
friend class ObjectPoolIterator<X>;
int getNextFree() int getNextFree()
{ {
@ -76,16 +81,16 @@ private:
} }
public: public:
ObjectPool(int nblk) ObjectPool(int nblk = 1024)
{ {
_chunkSize = nblk; _chunkSize = nblk;
_nextFree = 0; _nextFree = 0;
_maxAvail = 0; _maxAvail = 0;
_maxOccupied = 0; _maxOccupied = -1;
_nbHoles = 0; _nbHoles = 0;
_lastDelChunk = 0;
_chunkList.clear(); _chunkList.clear();
_freeList.clear(); _freeList.clear();
_lastDelChunk = 0;
} }
virtual ~ObjectPool() virtual ~ObjectPool()
@ -105,16 +110,16 @@ public:
_freeList.insert(_freeList.end(), _chunkSize, true); _freeList.insert(_freeList.end(), _chunkSize, true);
_maxAvail += _chunkSize; _maxAvail += _chunkSize;
_freeList[_nextFree] = false; _freeList[_nextFree] = false;
obj = newChunk; // &newChunk[0]; obj = newChunk;
} }
else else
{ {
int chunkId = _nextFree / _chunkSize; int chunkId = _nextFree / _chunkSize;
int rank = _nextFree - chunkId * _chunkSize; int rank = _nextFree - chunkId * _chunkSize;
_freeList[_nextFree] = false; _freeList[_nextFree] = false;
obj = _chunkList[chunkId] + rank; // &_chunkList[chunkId][rank]; obj = _chunkList[chunkId] + rank;
} }
if (_nextFree < _maxOccupied) if (_nextFree <= _maxOccupied)
{ {
_nbHoles-=1; _nbHoles-=1;
} }
@ -122,7 +127,6 @@ public:
{ {
_maxOccupied = _nextFree; _maxOccupied = _nextFree;
} }
//obj->init();
return obj; return obj;
} }
@ -148,10 +152,10 @@ public:
if (toFree < _nextFree) if (toFree < _nextFree)
_nextFree = toFree; _nextFree = toFree;
if (toFree < _maxOccupied) if (toFree < _maxOccupied)
_nbHoles += 1; ++_nbHoles;
else
--_maxOccupied;
_lastDelChunk = i; _lastDelChunk = i;
//obj->clean();
//checkDelete(i); compactage non fait
} }
void clear() void clear()
@ -167,6 +171,37 @@ public:
clearVector( _freeList ); clearVector( _freeList );
} }
// nb allocated elements
size_t size() const
{
return _freeList.size();
}
// nb used elements
size_t nbElements() const
{
return _maxOccupied + 1 - _nbHoles;
}
// return an element w/o any check
const X* operator[]( size_t i ) const // i < size()
{
int chunkId = i / _chunkSize;
int rank = i - chunkId * _chunkSize;
return _chunkList[ chunkId ] + rank;
}
// return only being used element
const X* at( size_t i ) const // i < size()
{
if ( i >= size() || _freeList[ i ] )
return 0;
int chunkId = i / _chunkSize;
int rank = i - chunkId * _chunkSize;
return _chunkList[ chunkId ] + rank;
}
// void destroy(int toFree) // void destroy(int toFree)
// { // {
// // no control 0<= toFree < _freeList.size() // // no control 0<= toFree < _freeList.size()
@ -177,4 +212,41 @@ public:
}; };
template<class X> class ObjectPoolIterator : public SMDS_Iterator<const X*>
{
const ObjectPool<X>& _pool;
int _i, _nbFound;
public:
ObjectPoolIterator( const ObjectPool<X>& pool ) : _pool( pool ), _i( 0 ), _nbFound( 0 )
{
if ( more() && _pool._freeList[ _i ] == true )
{
next();
--_nbFound;
}
}
virtual bool more()
{
return ( _i <= _pool._maxOccupied && _nbFound < (int)_pool.nbElements() );
}
virtual const X* next()
{
const X* x = 0;
if ( more() )
{
x = _pool[ _i ];
++_nbFound;
for ( ++_i; _i <= _pool._maxOccupied; ++_i )
if ( _pool._freeList[ _i ] == false )
break;
}
return x;
}
};
#endif #endif

View File

@ -228,15 +228,15 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
SMDSAbs_ElementType elemType, SMDSAbs_ElementType elemType,
SMDS_ElemIteratorPtr theElemIt = SMDS_ElemIteratorPtr(), SMDS_ElemIteratorPtr theElemIt = SMDS_ElemIteratorPtr(),
double tolerance = NodeRadius ); double tolerance = NodeRadius );
void getElementsNearPoint( const gp_Pnt& point, TIDSortedElemSet& foundElems ); void prepare(); // !!!call it before calling the following methods!!!
void getElementsNearLine ( const gp_Ax1& line, TIDSortedElemSet& foundElems); void getElementsNearPoint( const gp_Pnt& point, vector<const SMDS_MeshElement*>& foundElems );
void getElementsInSphere ( const gp_XYZ& center, void getElementsNearLine ( const gp_Ax1& line, vector<const SMDS_MeshElement*>& foundElems);
const double radius, TIDSortedElemSet& foundElems); void getElementsInSphere ( const gp_XYZ& center,
size_t getSize() { return std::max( _size, _elements.size() ); } const double radius,
virtual ~ElementBndBoxTree(); vector<const SMDS_MeshElement*>& foundElems);
protected: protected:
ElementBndBoxTree():_size(0) {} ElementBndBoxTree() {}
SMESH_Octree* newChild() const { return new ElementBndBoxTree; } SMESH_Octree* newChild() const { return new ElementBndBoxTree; }
void buildChildrenData(); void buildChildrenData();
Bnd_B3d* buildRootBox(); Bnd_B3d* buildRootBox();
@ -245,11 +245,25 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
struct ElementBox : public Bnd_B3d struct ElementBox : public Bnd_B3d
{ {
const SMDS_MeshElement* _element; const SMDS_MeshElement* _element;
int _refCount; // an ElementBox can be included in several tree branches bool _isMarked;
ElementBox(const SMDS_MeshElement* elem, double tolerance); void init(const SMDS_MeshElement* elem, double tolerance);
}; };
vector< ElementBox* > _elements; vector< ElementBox* > _elements;
size_t _size;
typedef ObjectPool< ElementBox > TElementBoxPool;
//!< allocator of ElementBox's and SMESH_TreeLimit
struct LimitAndPool : public SMESH_TreeLimit
{
TElementBoxPool _elBoPool;
std::vector< ElementBox* > _markedElems;
LimitAndPool():SMESH_TreeLimit( MaxLevel, /*minSize=*/0. ) {}
};
LimitAndPool* getLimitAndPool() const
{
SMESH_TreeLimit* limitAndPool = const_cast< SMESH_TreeLimit* >( myLimit );
return static_cast< LimitAndPool* >( limitAndPool );
}
}; };
//================================================================================ //================================================================================
@ -258,32 +272,27 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
*/ */
//================================================================================ //================================================================================
ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh, SMDSAbs_ElementType elemType, SMDS_ElemIteratorPtr theElemIt, double tolerance) ElementBndBoxTree::ElementBndBoxTree(const SMDS_Mesh& mesh,
:SMESH_Octree( new SMESH_TreeLimit( MaxLevel, /*minSize=*/0. )) SMDSAbs_ElementType elemType,
SMDS_ElemIteratorPtr theElemIt,
double tolerance)
:SMESH_Octree( new LimitAndPool() )
{ {
int nbElems = mesh.GetMeshInfo().NbElements( elemType ); int nbElems = mesh.GetMeshInfo().NbElements( elemType );
_elements.reserve( nbElems ); _elements.reserve( nbElems );
TElementBoxPool& elBoPool = getLimitAndPool()->_elBoPool;
SMDS_ElemIteratorPtr elemIt = theElemIt ? theElemIt : mesh.elementsIterator( elemType ); SMDS_ElemIteratorPtr elemIt = theElemIt ? theElemIt : mesh.elementsIterator( elemType );
while ( elemIt->more() ) while ( elemIt->more() )
_elements.push_back( new ElementBox( elemIt->next(),tolerance )); {
ElementBox* eb = elBoPool.getNew();
eb->init( elemIt->next(), tolerance );
_elements.push_back( eb );
}
compute(); compute();
} }
//================================================================================
/*!
* \brief Destructor
*/
//================================================================================
ElementBndBoxTree::~ElementBndBoxTree()
{
for ( size_t i = 0; i < _elements.size(); ++i )
if ( --_elements[i]->_refCount <= 0 )
delete _elements[i];
}
//================================================================================ //================================================================================
/*! /*!
* \brief Return the maximal box * \brief Return the maximal box
@ -311,14 +320,10 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
{ {
if ( !_elements[i]->IsOut( *myChildren[j]->getBox() )) if ( !_elements[i]->IsOut( *myChildren[j]->getBox() ))
{
_elements[i]->_refCount++;
((ElementBndBoxTree*)myChildren[j])->_elements.push_back( _elements[i]); ((ElementBndBoxTree*)myChildren[j])->_elements.push_back( _elements[i]);
}
} }
_elements[i]->_refCount--;
} }
_size = _elements.size(); //_size = _elements.size();
SMESHUtils::FreeVector( _elements ); // = _elements.clear() + free memory SMESHUtils::FreeVector( _elements ); // = _elements.clear() + free memory
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
@ -327,33 +332,61 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
if ((int) child->_elements.size() <= MaxNbElemsInLeaf ) if ((int) child->_elements.size() <= MaxNbElemsInLeaf )
child->myIsLeaf = true; child->myIsLeaf = true;
if ( child->_elements.capacity() - child->_elements.size() > 1000 ) if ( child->isLeaf() && child->_elements.capacity() > child->_elements.size() )
SMESHUtils::CompactVector( child->_elements ); SMESHUtils::CompactVector( child->_elements );
} }
} }
//================================================================================
/*!
* \brief Un-mark all elements
*/
//================================================================================
void ElementBndBoxTree::prepare()
{
// TElementBoxPool& elBoPool = getElementBoxPool();
// for ( size_t i = 0; i < elBoPool.nbElements(); ++i )
// const_cast< ElementBox* >( elBoPool[ i ])->_isMarked = false;
}
//================================================================================ //================================================================================
/*! /*!
* \brief Return elements which can include the point * \brief Return elements which can include the point
*/ */
//================================================================================ //================================================================================
void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt& point, void ElementBndBoxTree::getElementsNearPoint( const gp_Pnt& point,
TIDSortedElemSet& foundElems) vector<const SMDS_MeshElement*>& foundElems)
{ {
if ( getBox()->IsOut( point.XYZ() )) if ( getBox()->IsOut( point.XYZ() ))
return; return;
if ( isLeaf() ) if ( isLeaf() )
{ {
LimitAndPool* pool = getLimitAndPool();
for ( size_t i = 0; i < _elements.size(); ++i ) for ( size_t i = 0; i < _elements.size(); ++i )
if ( !_elements[i]->IsOut( point.XYZ() )) if ( !_elements[i]->IsOut( point.XYZ() ) &&
foundElems.insert( _elements[i]->_element ); !_elements[i]->_isMarked )
{
foundElems.push_back( _elements[i]->_element );
_elements[i]->_isMarked = true;
pool->_markedElems.push_back( _elements[i] );
}
} }
else else
{ {
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
((ElementBndBoxTree*) myChildren[i])->getElementsNearPoint( point, foundElems ); ((ElementBndBoxTree*) myChildren[i])->getElementsNearPoint( point, foundElems );
if ( level() == 0 )
{
LimitAndPool* pool = getLimitAndPool();
for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
pool->_markedElems[i]->_isMarked = false;
pool->_markedElems.clear();
}
} }
} }
@ -363,22 +396,37 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
*/ */
//================================================================================ //================================================================================
void ElementBndBoxTree::getElementsNearLine( const gp_Ax1& line, void ElementBndBoxTree::getElementsNearLine( const gp_Ax1& line,
TIDSortedElemSet& foundElems) vector<const SMDS_MeshElement*>& foundElems)
{ {
if ( getBox()->IsOut( line )) if ( getBox()->IsOut( line ))
return; return;
if ( isLeaf() ) if ( isLeaf() )
{ {
LimitAndPool* pool = getLimitAndPool();
for ( size_t i = 0; i < _elements.size(); ++i ) for ( size_t i = 0; i < _elements.size(); ++i )
if ( !_elements[i]->IsOut( line )) if ( !_elements[i]->IsOut( line ) &&
foundElems.insert( _elements[i]->_element ); !_elements[i]->_isMarked )
{
foundElems.push_back( _elements[i]->_element );
_elements[i]->_isMarked = true;
pool->_markedElems.push_back( _elements[i] );
}
} }
else else
{ {
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
((ElementBndBoxTree*) myChildren[i])->getElementsNearLine( line, foundElems ); ((ElementBndBoxTree*) myChildren[i])->getElementsNearLine( line, foundElems );
if ( level() == 0 )
{
LimitAndPool* pool = getLimitAndPool();
for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
pool->_markedElems[i]->_isMarked = false;
pool->_markedElems.clear();
}
} }
} }
@ -388,23 +436,38 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
*/ */
//================================================================================ //================================================================================
void ElementBndBoxTree::getElementsInSphere ( const gp_XYZ& center, void ElementBndBoxTree::getElementsInSphere ( const gp_XYZ& center,
const double radius, const double radius,
TIDSortedElemSet& foundElems) vector<const SMDS_MeshElement*>& foundElems)
{ {
if ( getBox()->IsOut( center, radius )) if ( getBox()->IsOut( center, radius ))
return; return;
if ( isLeaf() ) if ( isLeaf() )
{ {
LimitAndPool* pool = getLimitAndPool();
for ( size_t i = 0; i < _elements.size(); ++i ) for ( size_t i = 0; i < _elements.size(); ++i )
if ( !_elements[i]->IsOut( center, radius )) if ( !_elements[i]->IsOut( center, radius ) &&
foundElems.insert( _elements[i]->_element ); !_elements[i]->_isMarked )
{
foundElems.push_back( _elements[i]->_element );
_elements[i]->_isMarked = true;
pool->_markedElems.push_back( _elements[i] );
}
} }
else else
{ {
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
((ElementBndBoxTree*) myChildren[i])->getElementsInSphere( center, radius, foundElems ); ((ElementBndBoxTree*) myChildren[i])->getElementsInSphere( center, radius, foundElems );
if ( level() == 0 )
{
LimitAndPool* pool = getLimitAndPool();
for ( size_t i = 0; i < pool->_markedElems.size(); ++i )
pool->_markedElems[i]->_isMarked = false;
pool->_markedElems.clear();
}
} }
} }
@ -414,13 +477,13 @@ namespace // Utils used in SMESH_ElementSearcherImpl::FindElementsByPoint()
*/ */
//================================================================================ //================================================================================
ElementBndBoxTree::ElementBox::ElementBox(const SMDS_MeshElement* elem, double tolerance) void ElementBndBoxTree::ElementBox::init(const SMDS_MeshElement* elem, double tolerance)
{ {
_element = elem; _element = elem;
_refCount = 1; _isMarked = false;
SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); SMDS_ElemIteratorPtr nIt = elem->nodesIterator();
while ( nIt->more() ) while ( nIt->more() )
Add( SMESH_TNodeXYZ( nIt->next() )); Add( SMESH_NodeXYZ( nIt->next() ));
Enlarge( tolerance ); Enlarge( tolerance );
} }
@ -771,9 +834,13 @@ FindElementsByPoint(const gp_Pnt& point,
{ {
_ebbTree[_elementType] = new ElementBndBoxTree( *_mesh, type, _meshPartIt, tolerance ); _ebbTree[_elementType] = new ElementBndBoxTree( *_mesh, type, _meshPartIt, tolerance );
} }
TIDSortedElemSet suspectElems; else
{
_ebbTree[ type ]->prepare();
}
vector< const SMDS_MeshElement* > suspectElems;
_ebbTree[ type ]->getElementsNearPoint( point, suspectElems ); _ebbTree[ type ]->getElementsNearPoint( point, suspectElems );
TIDSortedElemSet::iterator elem = suspectElems.begin(); vector< const SMDS_MeshElement* >::iterator elem = suspectElems.begin();
for ( ; elem != suspectElems.end(); ++elem ) for ( ; elem != suspectElems.end(); ++elem )
if ( !SMESH_MeshAlgos::IsOut( *elem, point, tolerance )) if ( !SMESH_MeshAlgos::IsOut( *elem, point, tolerance ))
foundElements.push_back( *elem ); foundElements.push_back( *elem );
@ -801,8 +868,10 @@ SMESH_ElementSearcherImpl::FindClosestTo( const gp_Pnt& point,
ElementBndBoxTree*& ebbTree = _ebbTree[ type ]; ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
if ( !ebbTree ) if ( !ebbTree )
ebbTree = new ElementBndBoxTree( *_mesh, type, _meshPartIt ); ebbTree = new ElementBndBoxTree( *_mesh, type, _meshPartIt );
else
ebbTree->prepare();
TIDSortedElemSet suspectElems; vector<const SMDS_MeshElement*> suspectElems;
ebbTree->getElementsNearPoint( point, suspectElems ); ebbTree->getElementsNearPoint( point, suspectElems );
if ( suspectElems.empty() && ebbTree->maxSize() > 0 ) if ( suspectElems.empty() && ebbTree->maxSize() > 0 )
@ -816,13 +885,14 @@ SMESH_ElementSearcherImpl::FindClosestTo( const gp_Pnt& point,
radius = ebbTree->maxSize() / pow( 2., getTreeHeight()) / 2; radius = ebbTree->maxSize() / pow( 2., getTreeHeight()) / 2;
while ( suspectElems.empty() ) while ( suspectElems.empty() )
{ {
ebbTree->prepare();
ebbTree->getElementsInSphere( point.XYZ(), radius, suspectElems ); ebbTree->getElementsInSphere( point.XYZ(), radius, suspectElems );
radius *= 1.1; radius *= 1.1;
} }
} }
double minDist = std::numeric_limits<double>::max(); double minDist = std::numeric_limits<double>::max();
multimap< double, const SMDS_MeshElement* > dist2face; multimap< double, const SMDS_MeshElement* > dist2face;
TIDSortedElemSet::iterator elem = suspectElems.begin(); vector<const SMDS_MeshElement*>::iterator elem = suspectElems.begin();
for ( ; elem != suspectElems.end(); ++elem ) for ( ; elem != suspectElems.end(); ++elem )
{ {
double dist = SMESH_MeshAlgos::GetDistance( *elem, point ); double dist = SMESH_MeshAlgos::GetDistance( *elem, point );
@ -886,6 +956,8 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point)
ElementBndBoxTree*& ebbTree = _ebbTree[ SMDSAbs_Face ]; ElementBndBoxTree*& ebbTree = _ebbTree[ SMDSAbs_Face ];
if ( !ebbTree ) if ( !ebbTree )
ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt ); ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
else
ebbTree->prepare();
// Algo: analyse transition of a line starting at the point through mesh boundary; // Algo: analyse transition of a line starting at the point through mesh boundary;
// try three lines parallel to axis of the coordinate system and perform rough // try three lines parallel to axis of the coordinate system and perform rough
@ -901,13 +973,14 @@ TopAbs_State SMESH_ElementSearcherImpl::GetPointState(const gp_Pnt& point)
gp_Ax1 lineAxis( point, axisDir[axis]); gp_Ax1 lineAxis( point, axisDir[axis]);
gp_Lin line ( lineAxis ); gp_Lin line ( lineAxis );
TIDSortedElemSet suspectFaces; // faces possibly intersecting the line vector<const SMDS_MeshElement*> suspectFaces; // faces possibly intersecting the line
if ( axis > 0 ) ebbTree->prepare();
ebbTree->getElementsNearLine( lineAxis, suspectFaces ); ebbTree->getElementsNearLine( lineAxis, suspectFaces );
// Intersect faces with the line // Intersect faces with the line
map< double, TInters > & u2inters = paramOnLine2TInters[ axis ]; map< double, TInters > & u2inters = paramOnLine2TInters[ axis ];
TIDSortedElemSet::iterator face = suspectFaces.begin(); vector<const SMDS_MeshElement*>::iterator face = suspectFaces.begin();
for ( ; face != suspectFaces.end(); ++face ) for ( ; face != suspectFaces.end(); ++face )
{ {
// get face plane // get face plane
@ -1114,10 +1187,10 @@ void SMESH_ElementSearcherImpl::GetElementsNearLine( const gp_Ax1&
ElementBndBoxTree*& ebbTree = _ebbTree[ type ]; ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
if ( !ebbTree ) if ( !ebbTree )
ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt ); ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
else
ebbTree->prepare();
TIDSortedElemSet suspectFaces; // elements possibly intersecting the line ebbTree->getElementsNearLine( line, foundElems );
ebbTree->getElementsNearLine( line, suspectFaces );
foundElems.assign( suspectFaces.begin(), suspectFaces.end());
} }
//======================================================================= //=======================================================================
@ -1135,10 +1208,10 @@ void SMESH_ElementSearcherImpl::GetElementsInSphere( const gp_XYZ&
ElementBndBoxTree*& ebbTree = _ebbTree[ type ]; ElementBndBoxTree*& ebbTree = _ebbTree[ type ];
if ( !ebbTree ) if ( !ebbTree )
ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt ); ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
else
ebbTree->prepare();
TIDSortedElemSet suspectFaces; // elements possibly intersecting the line ebbTree->getElementsInSphere( center, radius, foundElems );
ebbTree->getElementsInSphere( center, radius, suspectFaces );
foundElems.assign( suspectFaces.begin(), suspectFaces.end() );
} }
//======================================================================= //=======================================================================

View File

@ -2926,15 +2926,6 @@ bool _ViscousBuilder::findShapesToSmooth( _SolidData& data )
// define allowed thickness // define allowed thickness
computeGeomSize( data ); // compute data._geomSize and _LayerEdge::_maxLen computeGeomSize( data ); // compute data._geomSize and _LayerEdge::_maxLen
data._maxThickness = 0;
data._minThickness = 1e100;
list< const StdMeshers_ViscousLayers* >::iterator hyp = data._hyps.begin();
for ( ; hyp != data._hyps.end(); ++hyp )
{
data._maxThickness = Max( data._maxThickness, (*hyp)->GetTotalThickness() );
data._minThickness = Min( data._minThickness, (*hyp)->GetTotalThickness() );
}
//const double tgtThick = /*Min( 0.5 * data._geomSize, */data._maxThickness;
// Find shapes needing smoothing; such a shape has _LayerEdge._normal on it's // Find shapes needing smoothing; such a shape has _LayerEdge._normal on it's
// boundary inclined to the shape at a sharp angle // boundary inclined to the shape at a sharp angle
@ -4363,7 +4354,7 @@ void _ViscousBuilder::computeGeomSize( _SolidData& data )
_EdgesOnShape& eos = data._edgesOnShape[ iS ]; _EdgesOnShape& eos = data._edgesOnShape[ iS ];
if ( eos._edges.empty() ) if ( eos._edges.empty() )
continue; continue;
// get neighbor faces intersection with which should not be considered since // get neighbor faces, intersection with which should not be considered since
// collisions are avoided by means of smoothing // collisions are avoided by means of smoothing
set< TGeomID > neighborFaces; set< TGeomID > neighborFaces;
if ( eos._hyp.ToSmooth() ) if ( eos._hyp.ToSmooth() )
@ -4393,6 +4384,78 @@ void _ViscousBuilder::computeGeomSize( _SolidData& data )
} }
} }
} }
data._maxThickness = 0;
data._minThickness = 1e100;
list< const StdMeshers_ViscousLayers* >::iterator hyp = data._hyps.begin();
for ( ; hyp != data._hyps.end(); ++hyp )
{
data._maxThickness = Max( data._maxThickness, (*hyp)->GetTotalThickness() );
data._minThickness = Min( data._minThickness, (*hyp)->GetTotalThickness() );
}
// Limit inflation step size by geometry size found by intersecting
// normals of _LayerEdge's with mesh faces
if ( data._stepSize > 0.3 * data._geomSize )
limitStepSize( data, 0.3 * data._geomSize );
if ( data._stepSize > data._minThickness )
limitStepSize( data, data._minThickness );
// -------------------------------------------------------------------------
// Detect _LayerEdge which can't intersect with opposite or neighbor layer,
// so no need in detecting intersection at each inflation step
// -------------------------------------------------------------------------
int nbSteps = data._maxThickness / data._stepSize;
if ( nbSteps < 3 || nbSteps * data._n2eMap.size() < 100000 )
return;
vector< const SMDS_MeshElement* > closeFaces;
int nbDetected = 0;
for ( size_t iS = 0; iS < data._edgesOnShape.size(); ++iS )
{
_EdgesOnShape& eos = data._edgesOnShape[ iS ];
if ( eos._edges.empty() || eos.ShapeType() != TopAbs_FACE )
continue;
for ( size_t i = 0; i < eos.size(); ++i )
{
SMESH_NodeXYZ p( eos[i]->_nodes[0] );
double radius = data._maxThickness + 2 * eos[i]->_maxLen;
closeFaces.clear();
searcher->GetElementsInSphere( p, radius, SMDSAbs_Face, closeFaces );
bool toIgnore = true;
for ( size_t iF = 0; iF < closeFaces.size() && toIgnore; ++iF )
if ( !( toIgnore = ( closeFaces[ iF ]->getshapeId() == eos._shapeID ||
data._ignoreFaceIds.count( closeFaces[ iF ]->getshapeId() ))))
{
// check if a _LayerEdge will inflate in a direction opposite to a direction
// toward a close face
bool allBehind = true;
for ( int iN = 0; iN < closeFaces[ iF ]->NbCornerNodes() && allBehind; ++iN )
{
SMESH_NodeXYZ pi( closeFaces[ iF ]->GetNode( iN ));
allBehind = (( pi - p ) * eos[i]->_normal < 0.1 * data._stepSize );
}
toIgnore = allBehind;
}
if ( toIgnore ) // no need to detect intersection
{
eos[i]->Set( _LayerEdge::INTERSECTED );
++nbDetected;
}
}
}
debugMsg( "Nb LE to intersect " << data._n2eMap.size()-nbDetected << ", ignore " << nbDetected );
return;
} }
//================================================================================ //================================================================================
@ -4405,14 +4468,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
{ {
SMESH_MesherHelper helper( *_mesh ); SMESH_MesherHelper helper( *_mesh );
// Limit inflation step size by geometry size found by itersecting
// normals of _LayerEdge's with mesh faces
if ( data._stepSize > 0.3 * data._geomSize )
limitStepSize( data, 0.3 * data._geomSize );
const double tgtThick = data._maxThickness; const double tgtThick = data._maxThickness;
if ( data._stepSize > data._minThickness )
limitStepSize( data, data._minThickness );
if ( data._stepSize < 1. ) if ( data._stepSize < 1. )
data._epsilon = data._stepSize * 1e-7; data._epsilon = data._stepSize * 1e-7;
@ -4530,6 +4586,7 @@ bool _ViscousBuilder::inflate(_SolidData& data)
break; break;
} }
#endif #endif
// new step size // new step size
limitStepSize( data, 0.25 * distToIntersection ); limitStepSize( data, 0.25 * distToIntersection );
if ( data._stepSizeNodes[0] ) if ( data._stepSizeNodes[0] )
@ -5654,17 +5711,16 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData& data,
if ( iFrom >= iTo ) continue; if ( iFrom >= iTo ) continue;
_LayerEdge* e0 = _eos[iFrom]->_2neibors->_edges[0]; _LayerEdge* e0 = _eos[iFrom]->_2neibors->_edges[0];
_LayerEdge* e1 = _eos[iTo-1]->_2neibors->_edges[1]; _LayerEdge* e1 = _eos[iTo-1]->_2neibors->_edges[1];
gp_XY uv0 = ( e0 == eV0 ) ? uvV0 : e0->LastUV( F, _eos ); gp_XY uv0 = ( e0 == eV0 ) ? uvV0 : e0->LastUV( F, _eos );
gp_XY uv1 = ( e1 == eV1 ) ? uvV1 : e1->LastUV( F, _eos ); gp_XY uv1 = ( e1 == eV1 ) ? uvV1 : e1->LastUV( F, _eos );
double param0 = ( iFrom == 0 ) ? 0. : _leParams[ iFrom-1 ]; double param0 = ( iFrom == 0 ) ? 0. : _leParams[ iFrom-1 ];
double param1 = _leParams[ iTo ]; double param1 = _leParams[ iTo ];
const gp_XY rangeUV = uv1 - uv0; gp_XY rangeUV = uv1 - uv0;
for ( size_t i = iFrom; i < iTo; ++i ) for ( size_t i = iFrom; i < iTo; ++i )
{ {
if ( _eos[i]->Is( _LayerEdge::BLOCKED )) continue; if ( _eos[i]->Is( _LayerEdge::BLOCKED )) continue;
double param = ( _leParams[i] - param0 ) / ( param1 - param0 ); double param = ( _leParams[i] - param0 ) / ( param1 - param0 );
gp_XY newUV = uv0 + param * rangeUV; gp_XY newUV = uv0 + param * rangeUV;
_eos[i]->_pos.back().SetCoord( newUV.X(), newUV.Y(), 0 );
gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() ); gp_Pnt newPos = surface->Value( newUV.X(), newUV.Y() );
SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( _eos[i]->_nodes.back() ); SMDS_MeshNode* tgtNode = const_cast<SMDS_MeshNode*>( _eos[i]->_nodes.back() );
@ -5674,6 +5730,28 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData& data,
SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() ); SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
pos->SetUParameter( newUV.X() ); pos->SetUParameter( newUV.X() );
pos->SetVParameter( newUV.Y() ); pos->SetVParameter( newUV.Y() );
gp_XYZ newUV0( newUV.X(), newUV.Y(), 0 );
if ( !_eos[i]->Is( _LayerEdge::SMOOTHED ))
{
_eos[i]->Set( _LayerEdge::SMOOTHED ); // to check in refine() (IPAL54237)
if ( _eos[i]->_pos.size() > 2 )
{
// modify previous positions to make _LayerEdge less sharply bent
vector<gp_XYZ>& uvVec = _eos[i]->_pos;
const gp_XYZ uvShift = newUV0 - uvVec.back();
const double len2 = ( uvVec.back() - uvVec[ 0 ] ).SquareModulus();
int iPrev = uvVec.size() - 2;
while ( iPrev > 0 )
{
double r = ( uvVec[ iPrev ] - uvVec[0] ).SquareModulus() / len2;
uvVec[ iPrev ] += uvShift * r;
--iPrev;
}
}
}
_eos[i]->_pos.back() = newUV0;
} }
} }
} }
@ -5764,6 +5842,8 @@ bool _Smoother1D::smoothAnalyticEdge( _SolidData& data,
SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() ); SMDS_FacePosition* pos = static_cast<SMDS_FacePosition*>( tgtNode->GetPosition() );
pos->SetUParameter( newUV.X() ); pos->SetUParameter( newUV.X() );
pos->SetVParameter( newUV.Y() ); pos->SetVParameter( newUV.Y() );
_eos[i]->Set( _LayerEdge::SMOOTHED ); // to check in refine() (IPAL54237)
} }
} }
return true; return true;
@ -6011,8 +6091,8 @@ void _Smoother1D::prepare(_SolidData& data)
// divide E to have offset segments with low deflection // divide E to have offset segments with low deflection
BRepAdaptor_Curve c3dAdaptor( E ); BRepAdaptor_Curve c3dAdaptor( E );
const double curDeflect = 0.1; //0.3; // 0.01; // Curvature deflection const double curDeflect = 0.1; //0.01; // Curvature deflection == |p1p2]*sin(p1p2,p1pM)
const double angDeflect = 0.1; //0.2; // 0.09; // Angular deflection const double angDeflect = 0.1; //0.09; // Angular deflection == sin(p1pM,pMp2)
GCPnts_TangentialDeflection discret(c3dAdaptor, angDeflect, curDeflect); GCPnts_TangentialDeflection discret(c3dAdaptor, angDeflect, curDeflect);
if ( discret.NbPoints() <= 2 ) if ( discret.NbPoints() <= 2 )
{ {
@ -6022,14 +6102,39 @@ void _Smoother1D::prepare(_SolidData& data)
const double u0 = c3dAdaptor.FirstParameter(); const double u0 = c3dAdaptor.FirstParameter();
gp_Pnt p; gp_Vec tangent; gp_Pnt p; gp_Vec tangent;
_offPoints.resize( discret.NbPoints() ); if ( discret.NbPoints() >= (int) _eos.size() + 2 )
for ( size_t i = 0; i < _offPoints.size(); i++ )
{ {
double u = discret.Parameter( i+1 ); _offPoints.resize( discret.NbPoints() );
c3dAdaptor.D1( u, p, tangent ); for ( size_t i = 0; i < _offPoints.size(); i++ )
_offPoints[i]._xyz = p.XYZ(); {
_offPoints[i]._edgeDir = tangent.XYZ(); double u = discret.Parameter( i+1 );
_offPoints[i]._param = GCPnts_AbscissaPoint::Length( c3dAdaptor, u0, u ) / _curveLen; c3dAdaptor.D1( u, p, tangent );
_offPoints[i]._xyz = p.XYZ();
_offPoints[i]._edgeDir = tangent.XYZ();
_offPoints[i]._param = GCPnts_AbscissaPoint::Length( c3dAdaptor, u0, u ) / _curveLen;
}
}
else
{
std::vector< double > params( _eos.size() + 2 );
params[0] = data.GetHelper().GetNodeU( E, leOnV[0]->_nodes[0] );
params.back() = data.GetHelper().GetNodeU( E, leOnV[1]->_nodes[0] );
for ( size_t i = 0; i < _eos.size(); i++ )
params[i+1] = data.GetHelper().GetNodeU( E, _eos[i]->_nodes[0] );
if ( params[1] > params[ _eos.size() ] )
std::reverse( params.begin() + 1, params.end() - 1 );
_offPoints.resize( _eos.size() + 2 );
for ( size_t i = 0; i < _offPoints.size(); i++ )
{
const double u = params[i];
c3dAdaptor.D1( u, p, tangent );
_offPoints[i]._xyz = p.XYZ();
_offPoints[i]._edgeDir = tangent.XYZ();
_offPoints[i]._param = GCPnts_AbscissaPoint::Length( c3dAdaptor, u0, u ) / _curveLen;
}
} }
// set _2edges // set _2edges
@ -6069,8 +6174,14 @@ void _Smoother1D::prepare(_SolidData& data)
int iLBO = _offPoints.size() - 2; // last but one int iLBO = _offPoints.size() - 2; // last but one
_leOnV[ 0 ]._normal = getNormalNormal( leOnV[0]->_normal, _edgeDir[0] ); if ( leOnV[ 0 ]->Is( _LayerEdge::MULTI_NORMAL ))
_leOnV[ 1 ]._normal = getNormalNormal( leOnV[1]->_normal, _edgeDir[1] ); _leOnV[ 0 ]._normal = getNormalNormal( _eos._edges[1]->_normal, _edgeDir[0] );
else
_leOnV[ 0 ]._normal = getNormalNormal( leOnV[0]->_normal, _edgeDir[0] );
if ( leOnV[ 1 ]->Is( _LayerEdge::MULTI_NORMAL ))
_leOnV[ 1 ]._normal = getNormalNormal( _eos._edges.back()->_normal, _edgeDir[1] );
else
_leOnV[ 1 ]._normal = getNormalNormal( leOnV[1]->_normal, _edgeDir[1] );
_leOnV[ 0 ]._len = 0; _leOnV[ 0 ]._len = 0;
_leOnV[ 1 ]._len = 0; _leOnV[ 1 ]._len = 0;
_leOnV[ 0 ]._lenFactor = _offPoints[1 ]._2edges._edges[1]->_lenFactor; _leOnV[ 0 ]._lenFactor = _offPoints[1 ]._2edges._edges[1]->_lenFactor;
@ -6104,7 +6215,7 @@ void _Smoother1D::prepare(_SolidData& data)
//================================================================================ //================================================================================
/*! /*!
* \brief set _normal of _leOnV[is2nd] to be normal to the EDGE * \brief return _normal of _leOnV[is2nd] normal to the EDGE
*/ */
//================================================================================ //================================================================================
@ -6115,6 +6226,9 @@ gp_XYZ _Smoother1D::getNormalNormal( const gp_XYZ & normal,
gp_XYZ norm = edgeDir ^ cross; gp_XYZ norm = edgeDir ^ cross;
double size = norm.Modulus(); double size = norm.Modulus();
// if ( size == 0 ) // MULTI_NORMAL _LayerEdge
// return gp_XYZ( 1e-100, 1e-100, 1e-100 );
return norm / size; return norm / size;
} }
@ -6834,8 +6948,8 @@ bool _ViscousBuilder::updateNormals( _SolidData& data,
// compute new _normals // compute new _normals
for ( size_t i = 0; i < intEdgesDist.size(); ++i ) for ( size_t i = 0; i < intEdgesDist.size(); ++i )
{ {
_LayerEdge* edge2 = intEdgesDist[i].first; _LayerEdge* edge2 = intEdgesDist[i].first;
double distWgt = edge1->_len / intEdgesDist[i].second; double distWgt = edge1->_len / intEdgesDist[i].second;
// if ( edge1->Is( _LayerEdge::BLOCKED ) && // if ( edge1->Is( _LayerEdge::BLOCKED ) &&
// edge2->Is( _LayerEdge::BLOCKED )) continue; // edge2->Is( _LayerEdge::BLOCKED )) continue;
if ( edge2->Is( _LayerEdge::MARKED )) continue; if ( edge2->Is( _LayerEdge::MARKED )) continue;
@ -6876,9 +6990,14 @@ bool _ViscousBuilder::updateNormals( _SolidData& data,
e2neIt->second._maxLen = 0.7 * minIntDist / edge1->_lenFactor; e2neIt->second._maxLen = 0.7 * minIntDist / edge1->_lenFactor;
if ( iter > 0 && sgn1 * sgn2 < 0 && edge1->_cosin < 0 ) if ( iter > 0 && sgn1 * sgn2 < 0 && edge1->_cosin < 0 )
e2neIt->second._normal += dir2; e2neIt->second._normal += dir2;
e2neIt = edge2newEdge.insert( make_pair( edge2, zeroEdge )).first; e2neIt = edge2newEdge.insert( make_pair( edge2, zeroEdge )).first;
e2neIt->second._normal += distWgt * newNormal; e2neIt->second._normal += distWgt * newNormal;
e2neIt->second._cosin = edge2->_cosin; if ( Precision::IsInfinite( zeroEdge._maxLen ))
{
e2neIt->second._cosin = edge2->_cosin;
e2neIt->second._maxLen = 1.3 * minIntDist / edge1->_lenFactor;
}
if ( iter > 0 && sgn1 * sgn2 < 0 && edge2->_cosin < 0 ) if ( iter > 0 && sgn1 * sgn2 < 0 && edge2->_cosin < 0 )
e2neIt->second._normal += dir1; e2neIt->second._normal += dir1;
} }
@ -9710,8 +9829,20 @@ bool _ViscousBuilder::refine(_SolidData& data)
} }
else if ( eos._isRegularSWOL ) // usual SWOL else if ( eos._isRegularSWOL ) // usual SWOL
{ {
for ( size_t j = 1; j < edge._pos.size(); ++j ) if ( edge.Is( _LayerEdge::SMOOTHED ))
segLen[j] = segLen[j-1] + (edge._pos[j-1] - edge._pos[j] ).Modulus(); {
SMESH_NodeXYZ p0( edge._nodes[0] );
for ( size_t j = 1; j < edge._pos.size(); ++j )
{
gp_XYZ pj = surface->Value( edge._pos[j].X(), edge._pos[j].Y() ).XYZ();
segLen[j] = ( pj - p0 ) * edge._normal;
}
}
else
{
for ( size_t j = 1; j < edge._pos.size(); ++j )
segLen[j] = segLen[j-1] + (edge._pos[j-1] - edge._pos[j] ).Modulus();
}
} }
else if ( !surface.IsNull() ) // SWOL surface with singularities else if ( !surface.IsNull() ) // SWOL surface with singularities
{ {