22874: [CEA 1425] Performance SMESH Module

Fix a leak of PropagationMgrData

+ Do not use volumes for preview of Extrusion
+ Fix a regression: empty groups are not removed with contents
+ avoid too long waiting at creation of hypotheses due to use of
  GEOMUtils::PreciseBoundingBox() in SMESH_Mesh::GetShapeDiagonalSize()
This commit is contained in:
eap 2015-03-27 19:41:20 +03:00
parent bbca2cb797
commit 0921263864
12 changed files with 155 additions and 31 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -10,6 +10,22 @@ with different parameters you can preset the quantity or size of
elements which will compose your mesh. So, it will be possible to
generate a coarse or a more refined mesh.
The choice of a hypothesis depends on the selected algorithm.
Hypotheses are created during creation and edition of
\ref constructing_meshes_page "meshes" and
\ref constructing_submeshes_page "sub-mesh".
Once created a hypotheses can be reused during creation and
edition of other meshes and sub-meshes. All created hypotheses and
algorithms are present in the Object Browser in \a Hypotheses and
\a Algorithms folders correspondingly. From the context menu of the
hypothesis you can invoke a dialog for modification of its parameters,
and \b Unassign command that will unassign the hypothesis from all
the meshes and sub-meshes using it.
Modification of any hypothesis parameter and unassignment of a
hypothesis leads to automatic removal of elements generated with use
of this hypothesis.
In \b MESH there are the following Basic Hypotheses:
<ul>
<li>\subpage a1d_meshing_hypo_page "1D Hypotheses" (for meshing of
@ -39,8 +55,7 @@ In \b MESH there are the following Basic Hypotheses:
</ul>
There also exist
\subpage additional_hypo_page "Additional Hypotheses" that can be used together
with main hypotheses:
\subpage additional_hypo_page "Additional Hypotheses":
<ul>
<li>\ref propagation_anchor "Propagation of 1D Hypothesis on opposite edges"</li>
<li>\ref propagofdistribution_anchor "Propagation of Node Distribution on Opposite Edges"</li>
@ -49,6 +64,4 @@ with main hypotheses:
<li>\ref quadrangle_preference_anchor "Quadrangle preference"</li>
</ul>
The choice of a hypothesis depends on the selected algorithm.
*/

View File

@ -18,7 +18,7 @@ Mesh module provides several ways to create the mesh:
objects).
Construction of \subpage constructing_submeshes_page "sub-meshes"
allows to mesh some sub-shapes of the main shape, for example a face,
allows to discretize some sub-shapes of the main shape, for example a face,
using different meshing parameters than other sub-shapes.<br>
Meshing parameters of meshes and sub-meshes can be
\subpage editing_meshes_page "edited". (Upon edition only mesh entities
@ -58,6 +58,12 @@ Mesh module provides several ways to create the mesh:
Meshes can be edited using the MESH functions destined for
\ref modifying_meshes_page "modification" of meshes.
Attractive meshing capabilities include:
- 3D and 2D \ref viscous_layers_anchor "Viscous Layers" (boundary
layers of highly stretched elements beneficial for high quality
viscous computations);
- automatic conformal transition between tetrahedral and hexahedral
sub-meshes.
The \b structure of a SALOME mesh is described by nodes and elements based on
these nodes. Geometry of the element is defined by the sequence of

View File

@ -28,8 +28,8 @@ number of mesh segments following an 1D hypothesis.
<ul>
<li><em>Triangle (Mefisto)</em> meshing algorithm - splits faces
into triangular elements.</li>
<li><em>Quadrangle (Mapping)</em> meshing algorithm - splits faces
into quadrangular elements.</li>
<li>\subpage quad_ijk_algo_page "Quadrangle (Mapping)" meshing
algorithm - splits faces into quadrangular elements.</li>
</ul>
\image html image123.gif "Example of a triangular 2D mesh"

View File

@ -89,13 +89,15 @@ The following dialog box will appear:
\par
\image html createmesh-inv2.png
\par
It allows to define the \b Name, the parent \b Mesh and the \b
Geometry (e.g. a face if the parent mesh has been built on box) of the
sub-mesh. You can define meshing algorithms and hypotheses in the same way as
in \ref constructing_meshes_page "Create mesh" dialog.
\par
Later you can change applied hypotheses or their parameters in
\ref editing_meshes_page "Edit mesh/sub-mesh" dialog. Mesh entities
generated using changed hypotheses are automatically removed.
\anchor subshape_by_mesh_elem
If the parent mesh is already computed, then you can define the
\b Geometry by picking mesh elements computed on a sub-shape of interest
@ -106,18 +108,14 @@ already down, then click it to release and then click it again. The
following pop-up menu allowing to choose a way of geometry definition will
appear.
\par
\image html choose_geom_selection_way.png
\par
<b>Direct geometry selection</b> enables selecting the sub-shape in the Object
Browser.
<b>Find geometry by mesh element selection</b> activates the following dialog.
\par
\image html find_geom_by_mesh_elem.png
\par
In this dialog, <b> Element Type </b> defines a kind of element to pick in the
Viewer.
Instead of picking an element in the Viewer, you can type its
@ -126,22 +124,20 @@ ID in <b> Element ID</b> field.
with which the sub-shape will appear in the Object Browser (if not yet
there).
\par
In the Object Browser the structure of the new sub-mesh will be
displayed as follows:
\image html image10.jpg
\par
It contains:
<ul>
<li>a sub-mesh name (\a SubMeshFace1)
<li>a reference to the geometrical object on the basis of which the
sub-mesh has been constructed (<em>Cylindrical Face_1</em>);</li>
<li><b>Applied hypotheses</b> folder containing the references to the
hypotheses selected at the construction of the sub-mesh;</li>
<li><b>Applied algorithms</b> folder containing the references to the
algorithms selected at the construction of the sub-mesh.</li>
<li><em>Applied hypotheses</em> folder containing the references to the
hypotheses assigned to the sub-mesh;</li>
<li><em>Applied algorithms</em> folder containing the references to the
algorithms assigned to the sub-mesh.</li>
</ul>
<br><b>See Also</b> a sample TUI Script of a

View File

@ -16,10 +16,13 @@ You can also change values for the current hypothesis by clicking the
\image html image122.png
<center><em>"Edit Hypothesis" button</em></center>
Mesh entities generated before using changed hypotheses are automatically removed.
See how the mesh constructed on a geometrical object
changes if we apply different algorithms to it.
changes if we apply different meshing parameters to it.
\image html edit_mesh1.png "Example of a mesh with Max. Element area 2D hypothesis roughly corresponding to 1D hypotheses on edges"
<br>
\image html edit_mesh_change_value_hyp.png "And now the Max Element area is greatly reduced"

View File

@ -0,0 +1,49 @@
/*!
\page quad_ijk_algo_page Quadrangle (Mapping) meshing algorithm
<b>Quadrangle (Mapping)</b> meshing algorithm is intended for creating
all-quadrangle and quad-dominant meshes on faces with no holes and
bound by at least three edges.
The algorithm can create mesh on any face but mesh quality and
validity depends on two factors:
- face shape (number of edges and concavity of boundary);
- discretization of edges.
\image html quad_mesh_invalid.png "Invalid mesh on quadrilateral concave faces"
The algorithm uses <em>Transfinite Interpolation</em> technic in
parametric space of a face to locate nodes inside the face.
The algorithm treats any face as a quadrangle. If a face is bound by
more than four edges, four most sharp vertices are considered as
corners of the quadrangle and all edges between these vertices are
treated as quadrangle sides. In the case of three edges, the vertex
specified by the user is considered as a degenerated side of the
quadrangle.
\image html quad_meshes.png "Algorithm generates a structured mesh on complex faces provided that edges are properly discretized"
To get an all-quadrangle mesh you have to carefully define 1D
hypotheses on edges of a face. To get a \b structured mesh you have to assure
equal number of segments on opposite sides of the quadrangle. If this
condition is not respected, the algorithm by default (with no
hypothesis) creates \b quad-dominant mesh with triangles located near a
side with maximal number of segments. But you can get an
\b all-quadrangle mesh in this case by using
\ref hypo_quad_params_anchor "Quadrangle Parameters"
hypothesis to specify how to make transition mesh between opposite
sides with different number of segments, provided that certain
conditions are respected. In any case total number of segments must be
even. To use \a Reduced transition method there must be equal number
of segments on one pair of opposite sides.
The following hypotheses help in creation of quadrangle meshes.
- \ref propagation_anchor "Propagation" additional 1D hypotheses
help to get equal number of segments on opposite sides of the
quadrilateral face.
- \ref a1d_algos_anchor "Composite Side Discretization" algorithm is useful
to discretize several C1 continues edges as one quadrangle side.
*/

View File

@ -58,7 +58,7 @@
#include <GEOMUtils.hxx>
#undef _Precision_HeaderFile
//#include <BRepBndLib.hxx>
#include <BRepBndLib.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <Bnd_Box.hxx>
#include <TColStd_MapOfInteger.hxx>
@ -72,11 +72,12 @@
#include "SMESH_TryCatch.hxx" // include after OCCT headers!
#include "Utils_ExceptHandlers.hxx"
#ifndef WIN32
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#else
#include <pthread.h>
include <pthread.h>
#endif
using namespace std;
@ -180,6 +181,23 @@ SMESH_Mesh::~SMESH_Mesh()
{
MESSAGE("SMESH_Mesh::~SMESH_Mesh");
// Unassign algorithms in order to have all SMESH_subMeshEventListenerData deleted (22874)
SMESHDS_SubMeshIteratorPtr smIt = _myMeshDS->SubMeshes();
while ( smIt->more() ) {
// avoid usual removal of elements while processing RemoveHypothesis( algo ) event
const_cast<SMESHDS_SubMesh*>( smIt->next() )->Clear();
}
const ShapeToHypothesis & hyps = _myMeshDS->GetHypotheses();
for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
{
const TopoDS_Shape& s = s2hyps.Key();
THypList hyps = s2hyps.ChangeValue(); // copy
THypList::const_iterator h = hyps.begin();
for ( ; h != hyps.end(); ++h )
if ( (*h)->GetType() != SMESHDS_Hypothesis::PARAM_ALGO )
RemoveHypothesis( s, (*h)->GetID() );
}
// issue 0020340: EDF 1022 SMESH : Crash with FindNodeClosestTo in a second new study
// Notify event listeners at least that something happens
if ( SMESH_subMesh * sm = GetSubMeshContaining(1))
@ -329,7 +347,16 @@ double SMESH_Mesh::GetShapeDiagonalSize(const TopoDS_Shape & aShape)
{
if ( !aShape.IsNull() ) {
Bnd_Box Box;
GEOMUtils::PreciseBoundingBox(aShape, Box);
// avoid too long waiting on large shapes. PreciseBoundingBox() was added
// to assure same result which else depends on presence of triangulation (IPAL52557).
const int maxNbFaces = 4000;
int nbFaces = 0;
for ( TopExp_Explorer f( aShape, TopAbs_FACE ); f.More() && nbFaces < maxNbFaces; f.Next() )
++nbFaces;
if ( nbFaces < maxNbFaces )
GEOMUtils::PreciseBoundingBox(aShape, Box);
else
BRepBndLib::Add( aShape, Box);
if ( !Box.IsVoid() )
return sqrt( Box.SquareExtent() );
}

View File

@ -747,7 +747,7 @@ SMESH_Gen_i::GetHypothesisParameterValues (const char* theHypType,
return SMESH::SMESH_Hypothesis::_nil();
::SMESH_Mesh* mesh = meshServant ? &meshServant->GetImpl() : (::SMESH_Mesh*)0;
// create a temporary hypothesis to know its dimention
// create a temporary hypothesis to know its dimension
SMESH::SMESH_Hypothesis_var tmpHyp = this->createHypothesis( theHypType, theLibName );
SMESH_Hypothesis_i* hypServant = SMESH::DownCast<SMESH_Hypothesis_i*>( tmpHyp );
if ( !hypServant )
@ -2427,6 +2427,7 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
// loop on sub-meshes
for ( int i = 0; i < theMeshesArray.length(); i++)
{
if ( CORBA::is_nil( theMeshesArray[i] )) continue;
SMESH::SMESH_Mesh_var anInitMesh = theMeshesArray[i]->GetMesh();
if ( anInitMesh->_is_nil() ) continue;
SMESH_Mesh_i* anInitImpl = SMESH::DownCast<SMESH_Mesh_i*>( anInitMesh );

View File

@ -182,6 +182,12 @@ namespace MeshEditor_I {
{
GetMeshDS()->ClearMesh();
}
void Remove( SMDSAbs_ElementType type )
{
SMDS_ElemIteratorPtr eIt = GetMeshDS()->elementsIterator( type );
while ( eIt->more() )
GetMeshDS()->RemoveFreeElement( eIt->next(), /*sm=*/0, /*fromGroups=*/false );
}
};// struct TPreviewMesh
static SMESH_NodeSearcher * theNodeSearcher = 0;
@ -2398,6 +2404,10 @@ SMESH_MeshEditor_i::RotationSweepObjects(const SMESH::ListOfIDSources & theNodes
<< TVar( theTolerance ) << ", "
<< theMakeGroups << " )";
}
else
{
getPreviewMesh()->Remove( SMDSAbs_Volume );
}
return aGroups ? aGroups : new SMESH::ListOfGroups;
@ -2551,6 +2561,10 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode
<< TVar( theNbOfSteps ) << ", "
<< theToMakeGroups << " )";
}
else
{
getPreviewMesh()->Remove( SMDSAbs_Volume );
}
return aGroups ? aGroups : new SMESH::ListOfGroups;
@ -2623,6 +2637,10 @@ SMESH_MeshEditor_i::ExtrusionByNormal(const SMESH::ListOfIDSources& objects,
<< ", " << dim
<< " )";
}
else
{
getPreviewMesh()->Remove( SMDSAbs_Volume );
}
declareMeshModified( /*isReComputeSafe=*/true ); // does not influence Compute()
@ -2675,6 +2693,10 @@ SMESH_MeshEditor_i::AdvancedExtrusion(const SMESH::long_array & theIDsOfElements
<< theSewTolerance << ", "
<< theMakeGroups << " )";
}
else
{
getPreviewMesh()->Remove( SMDSAbs_Volume );
}
return aGroups ? aGroups : new SMESH::ListOfGroups;
@ -2844,6 +2866,10 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
<< ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
<< theMakeGroups << " )";
}
else
{
getPreviewMesh()->Remove( SMDSAbs_Volume );
}
return aGroups._retn();

View File

@ -105,7 +105,7 @@ int SMESH_Mesh_i::_idGenerator = 0;
SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
SMESH_Gen_i* gen_i,
CORBA::Long studyId )
CORBA::Long studyId )
: SALOME::GenericObj_i( thePOA )
{
MESSAGE("SMESH_Mesh_i");
@ -1077,14 +1077,17 @@ void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup
if ( _preMeshInfo )
_preMeshInfo->FullLoadFromFile();
if ( theGroup->_is_nil() || theGroup->IsEmpty() )
if ( theGroup->_is_nil() )
return;
vector<int> nodeIds; // to remove nodes becoming free
CORBA::Long elemID = theGroup->GetID( 1 );
int nbElemNodes = GetElemNbNodes( elemID );
if ( nbElemNodes > 0 )
nodeIds.reserve( theGroup->Size() * nbElemNodes );
if ( !theGroup->IsEmpty() )
{
CORBA::Long elemID = theGroup->GetID( 1 );
int nbElemNodes = GetElemNbNodes( elemID );
if ( nbElemNodes > 0 )
nodeIds.reserve( theGroup->Size() * nbElemNodes );
}
// Remove contents
SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );