Salome HOME
Regression revealed after restoring mesh data destruction at study closing
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index be6345c937f7697ebf36eb3284fc3be398e69f03..7bab8d9e74cba84dc539cbfe16bb52fe83383501 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  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
 // 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_subMesh.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
 
 #include "SMESH_subMesh.hxx"
 
+#include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Mesh.hxx"
 #include "SMESH_Algo.hxx"
+#include "SMESH_Comment.hxx"
 #include "SMESH_Gen.hxx"
 #include "SMESH_HypoFilter.hxx"
 #include "SMESH_Hypothesis.hxx"
 #include "SMESH_Mesh.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMeshEventListener.hxx"
-#include "SMESH_Comment.hxx"
-#include "SMDS_SetIterator.hxx"
-#include "SMDSAbs_ElementType.hxx"
-
-#include <Basics_OCCTVersion.hxx>
 
 #include "utilities.h"
 #include "OpUtil.hxx"
 
 using namespace std;
 
+#ifdef _DEBUG_
+// enable printing algo + shape id + hypo used while meshing
+//#define PRINT_WHO_COMPUTE_WHAT
+#endif
+
 //=============================================================================
 /*!
  * \brief Allocate some memory at construction and release it at destruction.
@@ -241,7 +244,7 @@ bool SMESH_subMesh::IsMeshComputed() const
 {
   if ( _alwaysComputed )
     return true;
-  // algo may bind a submesh not to _subShape, eg 3D algo
+  // algo may bind a sub-mesh not to _subShape, eg 3D algo
   // sets nodes on SHELL while _subShape may be SOLID
 
   SMESHDS_Mesh* meshDS = _father->GetMeshDS();
@@ -280,7 +283,7 @@ bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const
   int dimToCheck = myDim - 1;
   bool subMeshesComputed = true;
   if ( isFailedToCompute ) *isFailedToCompute = false;
-  // check subMeshes with upper dimension => reverse iteration
+  // check sub-meshes with upper dimension => reverse iteration
   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
   while ( smIt->more() )
   {
@@ -291,67 +294,22 @@ bool SMESH_subMesh::SubMeshesComputed(bool * isFailedToCompute/*=0*/) const
 
     // MSV 07.04.2006: restrict checking to myDim-1 only. Ex., there is no sense
     // in checking of existence of edges if the algo needs only faces. Moreover,
-    // degenerated edges may have no submesh, as after computing NETGEN_2D.
+    // degenerated edges may have no sub-mesh, as after computing NETGEN_2D.
     if ( !_algo || _algo->NeedDiscreteBoundary() ) {
       int dim = SMESH_Gen::GetShapeDim( ss );
       if (dim < dimToCheck)
-        break; // the rest subMeshes are all of less dimension
+        break; // the rest sub-meshes are all of less dimension
     }
     SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
-    bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
-                      (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes()  )));
+    bool computeOk = ((sm->GetComputeState() == COMPUTE_OK ) ||
+                      (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes() )));
     if (!computeOk)
     {
       subMeshesComputed = false;
+
       if ( isFailedToCompute && !(*isFailedToCompute) )
         *isFailedToCompute = ( sm->GetComputeState() == FAILED_TO_COMPUTE );
 
-      // int type = ss.ShapeType();
-
-      // switch (type)
-      // {
-      // case TopAbs_COMPOUND:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a COMPOUND");
-      //     break;
-      //   }
-      // case TopAbs_COMPSOLID:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a COMPSOLID");
-      //     break;
-      //   }
-      // case TopAbs_SHELL:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a SHEL");
-      //     break;
-      //   }
-      // case TopAbs_WIRE:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a WIRE");
-      //     break;
-      //   }
-      // case TopAbs_SOLID:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a SOLID");
-      //     break;
-      //   }
-      // case TopAbs_FACE:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a FACE");
-      //     break;
-      //   }
-      // case TopAbs_EDGE:
-      //   {
-      //     MESSAGE("The not computed sub mesh is a EDGE");
-      //     break;
-      //   }
-      // default:
-      //   {
-      //     MESSAGE("The not computed sub mesh is of unknown type");
-      //     break;
-      //   }
-      // }
-
       if ( !isFailedToCompute )
         break;
     }
@@ -438,7 +396,8 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
   }
   break;
   case TopAbs_COMPSOLID: insertDependence( _subShape, TopAbs_SOLID ); break;
-  case TopAbs_SOLID:     insertDependence( _subShape, TopAbs_FACE ); break;
+  case TopAbs_SOLID:     insertDependence( _subShape, TopAbs_FACE );
+  { /*internal EDGE*/    insertDependence( _subShape, TopAbs_EDGE, TopAbs_WIRE ); break; }
   case TopAbs_SHELL:     insertDependence( _subShape, TopAbs_FACE ); break;
   case TopAbs_FACE:      insertDependence( _subShape, TopAbs_EDGE ); break;
   case TopAbs_WIRE:      insertDependence( _subShape, TopAbs_EDGE ); break;
@@ -457,14 +416,17 @@ const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
 
 namespace
 {
-  int dependsOnMapKey( const SMESH_subMesh* sm )
+  int dependsOnMapKey( TopAbs_ShapeEnum type, int shapeID )
   {
-    int type = sm->GetSubShape().ShapeType();
-    int ordType = 9 - type;               // 2 = Vertex, 8 = CompSolid
-    int cle = sm->GetId();
+    int ordType = 9 - int(type);               // 2 = Vertex, 8 = CompSolid
+    int     cle = shapeID;
     cle += 10000000 * ordType;    // sort map by ordType then index
     return cle;
   }
+  int dependsOnMapKey( const SMESH_subMesh* sm )
+  {
+    return dependsOnMapKey( sm->GetSubShape().ShapeType(), sm->GetId() );
+  }
 }
 
 //=============================================================================
@@ -474,9 +436,10 @@ namespace
 //=============================================================================
 
 void SMESH_subMesh::insertDependence(const TopoDS_Shape aShape,
-                                     TopAbs_ShapeEnum   aSubType)
+                                     TopAbs_ShapeEnum   aSubType,
+                                     TopAbs_ShapeEnum   avoidType)
 {
-  TopExp_Explorer sub( aShape, aSubType );
+  TopExp_Explorer sub( aShape, aSubType, avoidType );
   for ( ; sub.More(); sub.Next() )
   {
     SMESH_subMesh *aSubMesh = _father->GetSubMesh( sub.Current() );
@@ -503,6 +466,17 @@ bool SMESH_subMesh::DependsOn( const SMESH_subMesh* other ) const
   return other ? _mapDepend.count( dependsOnMapKey( other )) : false;
 }
 
+//================================================================================
+/*!
+ * \brief Return \c true if \a this sub-mesh depends on a \a shape
+ */
+//================================================================================
+
+bool SMESH_subMesh::DependsOn( const int shapeID ) const
+{
+  return DependsOn( _father->GetSubMeshContaining( shapeID ));
+}
+
 //=============================================================================
 /*!
  * Return a shape of \a this sub-mesh
@@ -517,7 +491,7 @@ const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
 //=======================================================================
 //function : CanAddHypothesis
 //purpose  : return true if theHypothesis can be attached to me:
-//           its dimention is checked
+//           its dimension is checked
 //=======================================================================
 
 bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const
@@ -538,12 +512,25 @@ bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) cons
 }
 
 //=======================================================================
-//function : IsApplicableHypotesis
-//purpose  :
+//function : IsApplicableHypothesis
+//purpose  : check if this sub-mesh can be computed using a hypothesis
 //=======================================================================
 
-bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
-                                          const TopAbs_ShapeEnum  theShapeType)
+bool SMESH_subMesh::IsApplicableHypothesis(const SMESH_Hypothesis* theHypothesis) const
+{
+  if ( !_father->HasShapeToMesh() && _subShape.ShapeType() == TopAbs_SOLID )
+    return true; // true for the PseudoShape
+
+  return IsApplicableHypothesis( theHypothesis, _subShape.ShapeType() );
+}
+
+//=======================================================================
+//function : IsApplicableHypothesis
+//purpose  : compare shape type and hypothesis type
+//=======================================================================
+
+bool SMESH_subMesh::IsApplicableHypothesis(const SMESH_Hypothesis* theHypothesis,
+                                           const TopAbs_ShapeEnum  theShapeType)
 {
   if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
   {
@@ -593,7 +580,7 @@ bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
 //================================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
+  SMESH_subMesh::AlgoStateEngine(algo_event event, SMESH_Hypothesis * anHyp)
 {
   // **** les retour des evenement shape sont significatifs
   // (add ou remove fait ou non)
@@ -635,7 +622,7 @@ SMESH_Hypothesis::Hypothesis_Status
   bool modifiedHyp = (event == MODIF_HYP);  // if set to true, force event MODIF_ALGO_STATE
   SMESH_Algo* algoRequiringCleaning = 0;
 
-  bool isApplicableHyp = IsApplicableHypotesis( anHyp );
+  bool isApplicableHyp = IsApplicableHypothesis( anHyp );
 
   if (event == ADD_ALGO || event == ADD_FATHER_ALGO)
   {
@@ -657,7 +644,7 @@ SMESH_Hypothesis::Hypothesis_Status
       filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 ));
       filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 ));
       if ( SMESH_Algo * curAlgo = (SMESH_Algo*)_father->GetHypothesis( this, filter, true ))
-        if ( !curAlgo->NeedDiscreteBoundary() )
+        if ( !curAlgo->NeedDiscreteBoundary() && curAlgo != anHyp )
           algoRequiringCleaning = curAlgo;
     }
   }
@@ -1085,7 +1072,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
   if ( !theAlgo ) return false;
 
   // Suppose that theAlgo is applicable to _subShape, do not check it here
-  //if ( !IsApplicableHypotesis( theAlgo )) return false;
+  //if ( !IsApplicableHypothesis( theAlgo )) return false;
 
   // check only algo that doesn't NeedDiscreteBoundary(): because mesh made
   // on a sub-shape will be ignored by theAlgo
@@ -1093,8 +1080,6 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
        !theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo?
     return true;
 
-  SMESH_Gen* gen =_father->GetGen();
-
   // only local algo is to be checked
   //if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
   if ( _subShape.ShapeType() == _father->GetMeshDS()->ShapeToMesh().ShapeType() )
@@ -1153,7 +1138,7 @@ void SMESH_subMesh::setAlgoState(algo_state state)
 //================================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_subMesh::SubMeshesAlgoStateEngine(int                event,
+  SMESH_subMesh::SubMeshesAlgoStateEngine(algo_event         event,
                                           SMESH_Hypothesis * anHyp,
                                           bool               exitOnFatal)
 {
@@ -1203,8 +1188,6 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
   }
   else if ( algoRequiringCleaning && algoRequiringCleaning->SupportSubmeshes() )
   {
-    SMESHDS_Mesh* meshDS = _father->GetMeshDS();
-
     // find sub-meshes to keep elements on
     set< SMESH_subMesh* > smToKeep;
     TopAbs_ShapeEnum prevShapeType = TopAbs_SHAPE;
@@ -1220,26 +1203,29 @@ void SMESH_subMesh::cleanDependsOn( SMESH_Algo* algoRequiringCleaning/*=0*/ )
         if ( !sameShapeType )
         {
           // check if the algo allows presence of global algos of dimension the algo
-          // can generate it-self
+          // can generate it-self;
+          // always keep a node on VERTEX, as this node can be shared by segments
+          // lying on EDGEs not shared by the VERTEX of sm, due to MergeNodes (PAL23068)
           int  shapeDim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
-          keepSubMeshes = algoRequiringCleaning->NeedLowerHyps( shapeDim );
+          keepSubMeshes = ( algoRequiringCleaning->NeedLowerHyps( shapeDim ) || shapeDim == 0 );
           prevShapeType = sm->GetSubShape().ShapeType();
           toKeepPrevShapeType = keepSubMeshes;
         }
         if ( !keepSubMeshes )
         {
-          // look for an algo assigned to sm
-          bool algoFound = false;
-          const list<const SMESHDS_Hypothesis*>& hyps = meshDS->GetHypothesis( sm->_subShape );
-          list<const SMESHDS_Hypothesis*>::const_iterator h = hyps.begin();
-          for ( ; ( !algoFound && h != hyps.end() ); ++h )
-            algoFound = ((*h)->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
-          keepSubMeshes = algoFound;
+          // look for a local algo used to mesh sm
+          TopoDS_Shape algoShape = SMESH_MesherHelper::GetShapeOfHypothesis
+            ( algoRequiringCleaning, _subShape, _father );
+          SMESH_HypoFilter moreLocalAlgo;
+          moreLocalAlgo.Init( SMESH_HypoFilter::IsMoreLocalThan( algoShape, *_father ));
+          moreLocalAlgo.And ( SMESH_HypoFilter::IsAlgo() );
+          bool localAlgoFound = _father->GetHypothesis( sm->_subShape, moreLocalAlgo, true );
+          keepSubMeshes = localAlgoFound;
         }
         // remember all sub-meshes of sm
         if ( keepSubMeshes )
         {
-          SMESH_subMeshIteratorPtr smIt2 = getDependsOnIterator(false);
+          SMESH_subMeshIteratorPtr smIt2 = sm->getDependsOnIterator(true);
           while ( smIt2->more() )
             smToKeep.insert( smIt2->next() );
         }
@@ -1302,25 +1288,24 @@ void SMESH_subMesh::DumpAlgoState(bool isMain)
 static void cleanSubMesh( SMESH_subMesh * subMesh )
 {
   if (subMesh) {
-    if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) {
+    if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS())
+    {
       SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS();
-      SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
-      while (ite->more()) {
-        const SMDS_MeshElement * elt = ite->next();
-        //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
-        //meshDS->RemoveElement(elt);
-        meshDS->RemoveFreeElement(elt, 0);
-      }
-
-      SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
-      while (itn->more()) {
-        const SMDS_MeshNode * node = itn->next();
-        //MESSAGE( " RM node: "<<node->GetID());
-        if ( node->NbInverseElements() == 0 )
-          meshDS->RemoveFreeNode(node, 0);
-        else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
-          meshDS->RemoveNode(node);
-      }
+      int nbElems = subMeshDS->NbElements();
+      if ( nbElems > 0 )
+        for ( SMDS_ElemIteratorPtr ite = subMeshDS->GetElements(); ite->more(); )
+          meshDS->RemoveFreeElement( ite->next(), subMeshDS );
+
+      int nbNodes = subMeshDS->NbNodes();
+      if ( nbNodes > 0 )
+        for ( SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes(); itn->more() ; )
+        {
+          const SMDS_MeshNode * node = itn->next();
+          if ( node->NbInverseElements() == 0 )
+            meshDS->RemoveFreeNode( node, subMeshDS );
+          else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
+            meshDS->RemoveNode( node );
+        }
       subMeshDS->Clear();
     }
   }
@@ -1332,7 +1317,7 @@ static void cleanSubMesh( SMESH_subMesh * subMesh )
  */
 //=============================================================================
 
-bool SMESH_subMesh::ComputeStateEngine(int event)
+bool SMESH_subMesh::ComputeStateEngine(compute_event event)
 {
   switch ( event ) {
   case MODIF_ALGO_STATE:
@@ -1446,6 +1431,31 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           _computeState = READY_TO_COMPUTE;
       }
       break;
+
+    case COMPUTE_NOGEOM:  // no geometry; can be several algos
+      if ( !_father->HasShapeToMesh() )
+      {
+        algo = GetAlgo(); // current algo
+        if ( algo )
+        {
+          // apply algos in the order of increasing dimension
+          std::list< const SMESHDS_Hypothesis * > algos = _father->GetHypothesisList( _subShape );
+          for ( int t = SMESHDS_Hypothesis::ALGO_1D; t <= SMESHDS_Hypothesis::ALGO_3D; ++t )
+          {
+            std::list<const SMESHDS_Hypothesis *>::iterator al = algos.begin();
+            for ( ; al != algos.end(); ++al )
+              if ( (*al)->GetType() == t )
+              {
+                _algo = (SMESH_Algo*) *al;
+                _computeState = READY_TO_COMPUTE;
+                if ( !ComputeStateEngine( COMPUTE ))
+                  break;
+              }
+          }
+          _algo = algo; // restore
+        }
+        break;
+      }
     case COMPUTE:
     case COMPUTE_SUBMESH:
       {
@@ -1529,7 +1539,6 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           MESSAGE("std::bad_alloc thrown inside algo->Compute()");
           if ( _computeError ) {
             _computeError->myName = COMPERR_MEMORY_PB;
-            //_computeError->myComment = exc.what();
           }
           cleanSubMesh( this );
           throw exc;
@@ -1538,7 +1547,6 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()");
           if ( _computeError ) {
             _computeError->myName = COMPERR_MEMORY_PB;
-            //_computeError->myComment = exc.what();
           }
           cleanSubMesh( this );
           throw std::bad_alloc();
@@ -1579,7 +1587,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           ret = false;
         // check if anything was built
         TopExp_Explorer subS(shape, _subShape.ShapeType());
-        if (ret)
+        if ( ret )
         {
           for (; ret && subS.More(); subS.Next())
             if ( !_father->GetSubMesh( subS.Current() )->IsMeshComputed() &&
@@ -1587,10 +1595,27 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
                    !algo->isDegenerated( TopoDS::Edge( subS.Current() ))))
               ret = false;
         }
+#ifdef PRINT_WHO_COMPUTE_WHAT
+        for (subS.ReInit(); subS.More(); subS.Next())
+        {
+          const std::list <const SMESHDS_Hypothesis *> & hyps =
+            _algo->GetUsedHypothesis( *_father, _subShape );
+          SMESH_Comment hypStr;
+          if ( !hyps.empty() )
+          {
+            hypStr << hyps.front()->GetName() << " ";
+            ((SMESHDS_Hypothesis*)hyps.front())->SaveTo( hypStr.Stream() );
+            hypStr << " ";
+          }
+          cout << _algo->GetName()
+               << " " << _father->GetSubMesh( subS.Current() )->GetId()
+               << " " << hypStr << endl;
+        }
+#endif
         // Set _computeError
-        if (!ret && !isComputeErrorSet)
+        if ( !ret && !isComputeErrorSet )
         {
-          for (subS.ReInit(); subS.More(); subS.Next())
+          for ( subS.ReInit(); subS.More(); subS.Next() )
           {
             SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
             if ( !sm->IsMeshComputed() )
@@ -1604,11 +1629,41 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
             }
           }
         }
-        if (ret && _computeError && _computeError->myName != COMPERR_WARNING )
+        if ( ret && _computeError && _computeError->myName != COMPERR_WARNING )
         {
           _computeError.reset();
         }
 
+        // transform errors into warnings if it is caused by mesh edition (imp 0023068)
+        if (!ret && _father->GetIsModified() )
+        {
+          for (subS.ReInit(); subS.More(); subS.Next())
+          {
+            SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
+            if ( !sm->IsMeshComputed() && sm->_computeError )
+            {
+              // check if there is a VERTEX w/o nodes
+              // with READY_TO_COMPUTE state (after MergeNodes())
+              SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(false,false);
+              while ( smIt->more() )
+              {
+                SMESH_subMesh * vertSM = smIt->next();
+                if ( vertSM->_subShape.ShapeType() != TopAbs_VERTEX ) break;
+                if ( vertSM->GetComputeState() == READY_TO_COMPUTE )
+                {
+                  SMESHDS_SubMesh * ds = vertSM->GetSubMeshDS();
+                  if ( !ds || ds->NbNodes() == 0 )
+                  {
+                    sm->_computeState = READY_TO_COMPUTE;
+                    sm->_computeError->myName = COMPERR_WARNING;
+                    break;
+                  }
+                }
+              }
+            }
+          }
+        }
+
         // send event SUBMESH_COMPUTED
         if ( ret ) {
           if ( !algo->NeedDiscreteBoundary() )
@@ -1628,6 +1683,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           else
             updateDependantsState( SUBMESH_COMPUTED );
         }
+        // let algo clear its data gathered while algo->Compute()
+        algo->CheckHypothesis((*_father), _subShape, hyp_status);
       }
       break;
     case COMPUTE_CANCELED:               // nothing to do
@@ -1690,7 +1747,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
     case COMPUTE_CANCELED:      // nothing to do
       break;
     case CLEAN:
-      cleanDependants();  // clean sub-meshes, dependant on this one, with event CLEAN
+      cleanDependants();  // clean sub-meshes, dependent on this one, with event CLEAN
       removeSubMeshElementsAndNodes();
       _computeState = NOT_READY;
       if ( _algoState == HYP_OK )
@@ -1969,7 +2026,7 @@ void SMESH_subMesh::updateSubMeshState(const compute_state theState)
 //purpose  :
 //=======================================================================
 
-void SMESH_subMesh::ComputeSubMeshStateEngine(int event, const bool includeSelf)
+void SMESH_subMesh::ComputeSubMeshStateEngine(compute_event event, const bool includeSelf)
 {
   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(includeSelf,false);
   while ( smIt->more() )
@@ -2079,10 +2136,10 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
     const TopoDS_Shape&  S = subMesh->_subShape;
     if ( S.ShapeType() != this->_subShape.ShapeType() )
       continue;
-    theSubs.push_back( subMesh );
     if ( subMesh == this )
     {
       aBuilder.Add( aCompound, S );
+      theSubs.push_back( subMesh );
     }
     else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
     {
@@ -2093,6 +2150,7 @@ TopoDS_Shape SMESH_subMesh::getCollection(SMESH_Gen * theGen,
         aBuilder.Add( aCompound, S );
         if ( !subMesh->SubMeshesComputed() )
           theSubComputed = false;
+        theSubs.push_back( subMesh );
       }
     }
   }
@@ -2130,16 +2188,14 @@ const SMESH_Hypothesis* SMESH_subMesh::getSimilarAttached(const TopoDS_Shape&
 }
 
 //=======================================================================
-//function : CheckConcurentHypothesis
+//function : CheckConcurrentHypothesis
 //purpose  : check if there are several applicable hypothesis attached to
 //           ancestors
 //=======================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
+  SMESH_subMesh::CheckConcurrentHypothesis (const int theHypType)
 {
-  MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
-
   // is there local hypothesis on me?
   if ( getSimilarAttached( _subShape, 0, theHypType ) )
     return SMESH_Hypothesis::HYP_OK;
@@ -2160,7 +2216,7 @@ SMESH_Hypothesis::Hypothesis_Status
         aPrevHyp     = hyp;
       }
       else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
-        return SMESH_Hypothesis::HYP_CONCURENT;
+        return SMESH_Hypothesis::HYP_CONCURRENT;
       else
         return SMESH_Hypothesis::HYP_OK;
     }
@@ -2222,9 +2278,9 @@ void SMESH_subMesh::setEventListener(EventListener*     listener,
     _eventListeners.find( listener );
   if ( l_d != _eventListeners.end() ) {
     EventListenerData* curData = l_d->second;
+    l_d->second = data;
     if ( curData && curData != data && curData->IsDeletable() )
       delete curData;
-    l_d->second = data;
   }
   else
   {
@@ -2232,6 +2288,7 @@ void SMESH_subMesh::setEventListener(EventListener*     listener,
       if ( listener->GetName() == l_d->first->GetName() )
       {
         EventListenerData* curData = l_d->second;
+        l_d->second = 0;
         if ( curData && curData != data && curData->IsDeletable() )
           delete curData;
         if ( l_d->first != listener && l_d->first->IsDeletable() )
@@ -2309,7 +2366,7 @@ EventListenerData* SMESH_subMesh::GetEventListenerData(const string& listenerNam
 
 //================================================================================
 /*!
- * \brief Notify stored event listeners on the occured event
+ * \brief Notify stored event listeners on the occurred event
  * \param event - algo_event or compute_event itself
  * \param eventType - algo_event or compute_event
  * \param hyp - hypothesis, if eventType is algo_event
@@ -2415,7 +2472,7 @@ void SMESH_subMesh::loadDependentMeshes()
  * \brief Do something on a certain event
  * \param event - algo_event or compute_event itself
  * \param eventType - algo_event or compute_event
- * \param subMesh - the submesh where the event occures
+ * \param subMesh - the submesh where the event occurs
  * \param data - listener data stored in the subMesh
  * \param hyp - hypothesis, if eventType is algo_event
  * 
@@ -2440,7 +2497,7 @@ void SMESH_subMeshEventListener::ProcessEvent(const int          event,
     switch ( event ) {
     case SMESH_subMesh::CLEAN:
       for ( ; smIt != smEnd; ++ smIt)
-        (*smIt)->ComputeStateEngine( event );
+        (*smIt)->ComputeStateEngine( SMESH_subMesh::compute_event( event ));
       break;
     case SMESH_subMesh::COMPUTE:
     case SMESH_subMesh::COMPUTE_SUBMESH:
@@ -2465,7 +2522,7 @@ namespace {
   {
     _Iterator(SMDS_Iterator<SMESH_subMesh*>* subIt,
               SMESH_subMesh*                 prepend,
-              SMESH_subMesh*                 append): myIt(subIt),myAppend(append)
+              SMESH_subMesh*                 append): myAppend(append), myIt(subIt)
     {
       myCur = prepend ? prepend : myIt->more() ? myIt->next() : append;
       if ( myCur == append ) append = 0;
@@ -2494,9 +2551,9 @@ namespace {
 
 //================================================================================
 /*!
- * \brief  Return iterator on the submeshes this one depends on
 * \param includeSelf - this submesh to be returned also
 * \param reverse - if true, complex shape submeshes go first
+ * \brief Return iterator on the submeshes this one depends on
 \param includeSelf - this submesh to be returned also
 \param reverse - if true, complex shape submeshes go first
  */
 //================================================================================
 
@@ -2537,8 +2594,13 @@ const std::vector< SMESH_subMesh * > & SMESH_subMesh::GetAncestors() const
     SMESH_subMesh* me = const_cast< SMESH_subMesh* >( this );
     me->_ancestors.reserve( ancShapes.Extent() );
 
+    // assure that all sub-meshes exist
+    TopoDS_Shape mainShape = _father->GetShapeToMesh();
+    if ( !mainShape.IsNull() )
+      _father->GetSubMesh( mainShape )->DependsOn();
+
     TopTools_MapOfShape map;
-   
+
     for ( TopTools_ListIteratorOfListOfShape it( ancShapes ); it.More(); it.Next() )
       if ( SMESH_subMesh* sm = _father->GetSubMeshContaining( it.Value() ))
         if ( map.Add( it.Value() ))
@@ -2570,7 +2632,7 @@ void SMESH_subMesh::ClearAncestors()
 bool SMESH_subMesh::FindIntersection(const SMESH_subMesh*            theOther,
                                      std::set<const SMESH_subMesh*>& theSetOfCommon ) const
 {
-  int oldNb = theSetOfCommon.size();
+  size_t oldNb = theSetOfCommon.size();
 
   // check main submeshes
   const map <int, SMESH_subMesh*>::const_iterator otherEnd = theOther->_mapDepend.end();