Salome HOME
23418: [OCC] Mesh: Minimization of memory usage of SMESH
[modules/smesh.git] / src / SMESH / SMESH_Gen.cxx
index d009d077ad899f51582fc3b465f87d0c4d80c659..f87162e45de947a63c8c93497a4f68bead3d03e5 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -20,7 +20,7 @@
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-//  SMESH SMESH : implementaion of SMESH idl descriptions
+//  SMESH SMESH : implementation of SMESH idl descriptions
 //  File   : SMESH_Gen.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
@@ -35,6 +35,7 @@
 #include "SMDS_MeshNode.hxx"
 #include "SMESHDS_Document.hxx"
 #include "SMESH_HypoFilter.hxx"
+#include "SMESH_Mesh.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 
@@ -53,9 +54,6 @@
 
 using namespace std;
 
-//#include <vtkDebugLeaks.h>
-
-
 //=============================================================================
 /*!
  *  Constructor
@@ -64,15 +62,23 @@ using namespace std;
 
 SMESH_Gen::SMESH_Gen()
 {
-  MESSAGE("SMESH_Gen::SMESH_Gen");
   _localId = 0;
   _hypId   = 0;
   _segmentation = _nbSegments = 10;
-  SMDS_Mesh::_meshList.clear();
-  MESSAGE(SMDS_Mesh::_meshList.size());
   _compute_canceled = false;
-  _sm_current = NULL;
-  //vtkDebugLeaks::SetExitError(0);
+}
+
+namespace
+{
+  // a structure used to nullify SMESH_Gen field of SMESH_Hypothesis,
+  // which is needed for SMESH_Hypothesis not deleted before ~SMESH_Gen()
+  struct _Hyp : public SMESH_Hypothesis
+  {
+    void NullifyGen()
+    {
+      _gen = 0;
+    }
+  };
 }
 
 //=============================================================================
@@ -83,13 +89,19 @@ SMESH_Gen::SMESH_Gen()
 
 SMESH_Gen::~SMESH_Gen()
 {
-  MESSAGE("SMESH_Gen::~SMESH_Gen");
   std::map < int, StudyContextStruct * >::iterator i_sc = _mapStudyContext.begin();
   for ( ; i_sc != _mapStudyContext.end(); ++i_sc )
   {
-    delete i_sc->second->myDocument;
-    delete i_sc->second;
-  }  
+    StudyContextStruct* context = i_sc->second;
+    std::map < int, SMESH_Hypothesis * >::iterator i_hyp = context->mapHypothesis.begin();
+    for ( ; i_hyp != context->mapHypothesis.end(); ++i_hyp )
+    {
+      if ( _Hyp* h = static_cast< _Hyp*>( i_hyp->second ))
+        h->NullifyGen();
+    }
+    delete context->myDocument;
+    delete context;
+  }
 }
 
 //=============================================================================
@@ -103,9 +115,8 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(int theStudyId, bool theIsEmbeddedMode)
   throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  MESSAGE("SMESH_Gen::CreateMesh");
 
-  // Get studyContext, create it if it does'nt exist, with a SMESHDS_Document
+  // Get studyContext, create it if it doesn't exist, with a SMESHDS_Document
   StudyContextStruct *aStudyContext = GetStudyContext(theStudyId);
 
   // create a new SMESH_mesh object
@@ -127,14 +138,16 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(int theStudyId, bool theIsEmbeddedMode)
 
 bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
                         const TopoDS_Shape &  aShape,
-                        const bool            aShapeOnly /*=false*/,
-                        const bool            anUpward /*=false*/,
+                        const int             aFlags /*= COMPACT_MESH*/,
                         const ::MeshDimension aDim /*=::MeshDim_3D*/,
                         TSetOfInt*            aShapesId /*=0*/)
 {
-  MESSAGE("SMESH_Gen::Compute");
   MEMOSTAT;
 
+  const bool   aShapeOnly = aFlags & SHAPE_ONLY;
+  const bool     anUpward = aFlags & UPWARD;
+  const bool aCompactMesh = aFlags & COMPACT_MESH;
+
   bool ret = true;
 
   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
@@ -146,10 +159,12 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
   SMESH_subMeshIteratorPtr smIt;
 
   // Fix of Issue 22150. Due to !BLSURF->OnlyUnaryInput(), BLSURF computes edges
-  // that must be computed by Projection 1D-2D when Projection asks to compute
+  // that must be computed by Projection 1D-2D while the Projection asks to compute
   // one face only.
   SMESH_subMesh::compute_event computeEvent =
     aShapeOnly ? SMESH_subMesh::COMPUTE_SUBMESH : SMESH_subMesh::COMPUTE;
+  if ( !aMesh.HasShapeToMesh() )
+    computeEvent = SMESH_subMesh::COMPUTE_NOGEOM; // if several algos and no geometry
 
   if ( anUpward ) // is called from the below code in this method
   {
@@ -181,9 +196,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       {
         if (_compute_canceled)
           return false;
-        _sm_current = smToCompute;
+        setCurrentSubMesh( smToCompute );
         smToCompute->ComputeStateEngine( computeEvent );
-        _sm_current = NULL;
+        setCurrentSubMesh( NULL );
       }
 
       // we check all the sub-meshes here and detect if any of them failed to compute
@@ -268,9 +283,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
         {
           if (_compute_canceled)
             return false;
-          _sm_current = smToCompute;
+          setCurrentSubMesh( smToCompute );
           smToCompute->ComputeStateEngine( computeEvent );
-          _sm_current = NULL;
+          setCurrentSubMesh( NULL );
           if ( aShapesId )
             aShapesId->insert( smToCompute->GetId() );
         }
@@ -336,7 +351,8 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
             SMESH_Hypothesis::Hypothesis_Status status;
             if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
               // mesh a lower smToCompute starting from vertices
-              Compute( aMesh, aSubShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId );
+              Compute( aMesh, aSubShape, aFlags | SHAPE_ONLY_UPWARD, aDim, aShapesId );
+              // Compute( aMesh, aSubShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId );
           }
         }
       }
@@ -355,9 +371,9 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
 
           if (_compute_canceled)
             return false;
-          _sm_current = sm;
+          setCurrentSubMesh( sm );
           sm->ComputeStateEngine( computeEvent );
-          _sm_current = NULL;
+          setCurrentSubMesh( NULL );
           if ( aShapesId )
             aShapesId->insert( sm->GetId() );
         }
@@ -367,18 +383,14 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
     // -----------------------------------------------
     // mesh the rest sub-shapes starting from vertices
     // -----------------------------------------------
-    ret = Compute( aMesh, aShape, aShapeOnly, /*anUpward=*/true, aDim, aShapesId );
+    ret = Compute( aMesh, aShape, aFlags | UPWARD, aDim, aShapesId );
   }
 
-  MESSAGE( "VSR - SMESH_Gen::Compute() finished, OK = " << ret);
   MEMOSTAT;
 
-  SMESHDS_Mesh *myMesh = aMesh.GetMeshDS();
-  MESSAGE("*** compactMesh after compute");
-  myMesh->compactMesh();
-
   // fix quadratic mesh by bending iternal links near concave boundary
-  if ( aShape.IsSame( aMesh.GetShapeToMesh() ) &&
+  if ( aCompactMesh && // a final compute
+       aShape.IsSame( aMesh.GetShapeToMesh() ) &&
        !aShapesId && // not preview
        ret ) // everything is OK
   {
@@ -388,6 +400,12 @@ bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
       aHelper.FixQuadraticElements( sm->GetComputeError() );
     }
   }
+
+  if ( aCompactMesh )
+  {
+    aMesh.GetMeshDS()->Modified();
+    aMesh.GetMeshDS()->CompactMesh();
+  }
   return ret;
 }
 
@@ -400,8 +418,9 @@ void SMESH_Gen::PrepareCompute(SMESH_Mesh &          aMesh,
                                const TopoDS_Shape &  aShape)
 {
   _compute_canceled = false;
-  _sm_current = NULL;
+  resetCurrentSubMesh();
 }
+
 //=============================================================================
 /*!
  * Cancel Compute a mesh
@@ -411,10 +430,44 @@ void SMESH_Gen::CancelCompute(SMESH_Mesh &          aMesh,
                               const TopoDS_Shape &  aShape)
 {
   _compute_canceled = true;
-  if(_sm_current)
-    {
-      _sm_current->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
-    }
+  if ( const SMESH_subMesh* sm = GetCurrentSubMesh() )
+  {
+    const_cast< SMESH_subMesh* >( sm )->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
+  }
+  resetCurrentSubMesh();
+}
+
+//================================================================================
+/*!
+ * \brief Returns a sub-mesh being currently computed
+ */
+//================================================================================
+
+const SMESH_subMesh* SMESH_Gen::GetCurrentSubMesh() const
+{
+  return _sm_current.empty() ? 0 : _sm_current.back();
+}
+
+//================================================================================
+/*!
+ * \brief Sets a sub-mesh being currently computed.
+ *
+ * An algorithm can call Compute() for a sub-shape, hence we keep a stack of sub-meshes
+ */
+//================================================================================
+
+void SMESH_Gen::setCurrentSubMesh(SMESH_subMesh* sm)
+{
+  if ( sm )
+    _sm_current.push_back( sm );
+
+  else if ( !_sm_current.empty() )
+    _sm_current.pop_back();
+}
+
+void SMESH_Gen::resetCurrentSubMesh()
+{
+  _sm_current.clear();
 }
 
 //=============================================================================
@@ -429,8 +482,6 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
                          const bool            anUpward,
                          TSetOfInt*            aShapesId)
 {
-  MESSAGE("SMESH_Gen::Evaluate");
-
   bool ret = true;
 
   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
@@ -552,7 +603,6 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
     ret = Evaluate( aMesh, aShape, aResMap, /*anUpward=*/true, aShapesId );
   }
 
-  MESSAGE( "VSR - SMESH_Gen::Evaluate() finished, OK = " << ret);
   return ret;
 }
 
@@ -622,7 +672,7 @@ static bool checkConformIgnoredAlgos(SMESH_Mesh&               aMesh,
           checkConform = false; // no more check conformity
           INFOS( "ERROR: Local <" << algo->GetName() <<
                 "> would produce not conform mesh: "
-                "<Not Conform Mesh Allowed> hypotesis is missing");
+                "<Not Conform Mesh Allowed> hypothesis is missing");
           theErrors.push_back( SMESH_Gen::TAlgoStateError() );
           theErrors.back().Set( SMESH_Hypothesis::HYP_NOTCONFORM, algo, false );
         }
@@ -673,8 +723,6 @@ static bool checkMissing(SMESH_Gen*                aGen,
   if ( aCheckedMap.count( aSubMesh ))
     return true;
 
-  //MESSAGE("=====checkMissing");
-
   int ret = true;
   SMESH_Algo* algo = 0;
 
@@ -795,8 +843,6 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh&               theMesh,
                              const TopoDS_Shape&       theShape,
                              list< TAlgoStateError > & theErrors)
 {
-  //MESSAGE("SMESH_Gen::CheckAlgoState");
-
   bool ret = true;
   bool hasAlgo = false;
 
@@ -874,8 +920,6 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh&               theMesh,
   // well defined
   // ----------------------------------------------------------------
 
-  //MESSAGE( "---info on missing hypothesis and find out if all needed algos are");
-
   // find max dim of global algo
   int aTopAlgoDim = 0;
   for (dim = 3; dim > 0; dim--)
@@ -910,7 +954,7 @@ bool SMESH_Gen::GetAlgoState(SMESH_Mesh&               theMesh,
   if ( !hasAlgo ) {
     ret = false;
     theErrors.push_back( TAlgoStateError() );
-    theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, 1, true );
+    theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, theMesh.HasShapeToMesh() ? 1 : 3, true );
   }
 
   return ret;
@@ -1032,7 +1076,8 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_subMesh * aSubMesh,
   SMESH_Mesh&          aMesh  = *aSubMesh->GetFather();
 
   SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
-  filter.And( filter.IsApplicableTo( aShape ));
+  if ( aMesh.HasShapeToMesh() )
+    filter.And( filter.IsApplicableTo( aShape ));
 
   typedef SMESH_Algo::Features AlgoData;
 
@@ -1103,7 +1148,7 @@ SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_subMesh * aSubMesh,
 
 StudyContextStruct *SMESH_Gen::GetStudyContext(int studyId)
 {
-  // Get studyContext, create it if it does'nt exist, with a SMESHDS_Document
+  // Get studyContext, create it if it doesn't exist, with a SMESHDS_Document
 
   if (_mapStudyContext.find(studyId) == _mapStudyContext.end())
   {
@@ -1140,7 +1185,7 @@ int SMESH_Gen::GetShapeDim(const TopAbs_ShapeEnum & aShapeType)
 
 //=============================================================================
 /*!
- * Genarate a new id unique withing this Gen
+ * Genarate a new id unique within this Gen
  */
 //=============================================================================