Salome HOME
22874: [CEA 1425] Performance SMESH Module
authoreap <eap@opencascade.com>
Fri, 27 Mar 2015 16:41:20 +0000 (19:41 +0300)
committereap <eap@opencascade.com>
Fri, 27 Mar 2015 16:41:20 +0000 (19:41 +0300)
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()

12 files changed:
doc/salome/gui/SMESH/images/quad_mesh_invalid.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/quad_meshes.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/about_hypo.doc
doc/salome/gui/SMESH/input/about_meshes.doc
doc/salome/gui/SMESH/input/basic_meshing_algos.doc
doc/salome/gui/SMESH/input/constructing_submeshes.doc
doc/salome/gui/SMESH/input/editing_meshes.doc
doc/salome/gui/SMESH/input/quad_ijk_algo.doc [new file with mode: 0644]
src/SMESH/SMESH_Mesh.cxx
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_Mesh_i.cxx

diff --git a/doc/salome/gui/SMESH/images/quad_mesh_invalid.png b/doc/salome/gui/SMESH/images/quad_mesh_invalid.png
new file mode 100644 (file)
index 0000000..cce9980
Binary files /dev/null and b/doc/salome/gui/SMESH/images/quad_mesh_invalid.png differ
diff --git a/doc/salome/gui/SMESH/images/quad_meshes.png b/doc/salome/gui/SMESH/images/quad_meshes.png
new file mode 100644 (file)
index 0000000..c6cbd0c
Binary files /dev/null and b/doc/salome/gui/SMESH/images/quad_meshes.png differ
index 3c38fb7db650d1170c1d807dad7e9c54f3bf2616..b2dab5dbf1e511d1247fb25733cee87fddacb52d 100644 (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.
-
 */
index 60ad290a8f51f30fc4869b180ae94c2de1c737fa..470cb854da57d380967edefe89f8c359763639fb 100644 (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
index bdf730b677ea4a8cde939ca9587cf728061ec6c0..f494926d121296e3f70871c733611b07cca01242 100644 (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"
index 8e750f6a25579c5b85d29b8e197cc1972d19d548..9da2e4f7f841b74f84681122e5531b299287bff4 100644 (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.
+in \ref constructing_meshes_page "Create mesh" dialog. 
+
+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.
 
-\par
 \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 
index 4cc70553fe34336561b80b37fd85f2a9704e67e3..a4602e6c48089e2a4b0963fb070cfa670d2f2adc 100644 (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"
 
diff --git a/doc/salome/gui/SMESH/input/quad_ijk_algo.doc b/doc/salome/gui/SMESH/input/quad_ijk_algo.doc
new file mode 100644 (file)
index 0000000..dfdb2d5
--- /dev/null
@@ -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.
+
+*/
index 20deb04a6c678e1684b8ad5387a530c350463cef..992e317351bb767b9400786990889eed35f050a9 100644 (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>
 #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() );
   }
index 715d6656ad1c35832a17193bfc58d0039457d6bf..468352968e03ec71b83755db7110619a2317a752 100644 (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 );
index d233bb63fa7c62b3ae7ce33c9692b70955526da9..519478d300bd5126f75585304eb9676c955fc84c 100644 (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();
 
index cc209d3798da0482d4eec217273dd70721a1a7a7..7649c27dec4e750f89380c9992c21de2b4c63c64 100644 (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 );