Salome HOME
PAL11544 optimize a little
[modules/smesh.git] / src / SMESH / SMESH_subMesh.cxx
index 238bd22d92f547e07772855c49c8590e2de476ff..385bc08c0f85ad7439d66c8e9aee2f24fe0f8081 100644 (file)
@@ -32,6 +32,7 @@ using namespace std;
 #include "SMESH_Mesh.hxx"
 #include "SMESH_Hypothesis.hxx"
 #include "SMESH_Algo.hxx"
+#include "SMESH_HypoFilter.hxx"
 
 #include "utilities.h"
 #include "OpUtil.hxx"
@@ -45,14 +46,16 @@ using namespace std;
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 
-#include <TColStd_ListIteratorOfListOfInteger.hxx>
-
 #ifdef _DEBUG_
 #include <gp_Pnt.hxx>
 #include <BRep_Tool.hxx>
 #include <TopoDS.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
 #endif
 
+#include <Standard_Failure.hxx>
+#include <Standard_ErrorHandler.hxx>
+
 //=============================================================================
 /*!
  *  default constructor:
@@ -76,8 +79,8 @@ SMESH_subMesh::SMESH_subMesh(int Id, SMESH_Mesh * father, SMESHDS_Mesh * meshDS,
        }
        else
        {
-               _algoState = NO_ALGO;
-               _computeState = NOT_READY;
+          _algoState = NO_ALGO;
+          _computeState = NOT_READY;
        }
 }
 
@@ -89,8 +92,8 @@ SMESH_subMesh::SMESH_subMesh(int Id, SMESH_Mesh * father, SMESHDS_Mesh * meshDS,
 
 SMESH_subMesh::~SMESH_subMesh()
 {
-       MESSAGE("SMESH_subMesh::~SMESH_subMesh");
-       // ****
+  MESSAGE("SMESH_subMesh::~SMESH_subMesh");
+  // ****
 }
 
 //=============================================================================
@@ -101,8 +104,8 @@ SMESH_subMesh::~SMESH_subMesh()
 
 int SMESH_subMesh::GetId() const
 {
-       //MESSAGE("SMESH_subMesh::GetId");
-       return _Id;
+  //MESSAGE("SMESH_subMesh::GetId");
+  return _Id;
 }
 
 //=============================================================================
@@ -113,19 +116,16 @@ int SMESH_subMesh::GetId() const
 
 SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS()
 {
-       //MESSAGE("SMESH_subMesh::GetSubMeshDS");
-       if (_subMeshDS==NULL)
-       {
-               //MESSAGE("subMesh pointer still null, trying to get it...");
-               _subMeshDS = _meshDS->MeshElements(_subShape);  // may be null ...
-               if (_subMeshDS==NULL)
-               {
-                       MESSAGE("problem... subMesh still empty");
-                       //NRI   ASSERT(0);
-                       //NRI   throw SALOME_Exception(LOCALIZED(subMesh still empty));
-               }
-       }
-       return _subMeshDS;
+  // submesh appears in DS only when a mesher set nodes and elements on it
+  if (_subMeshDS==NULL)
+  {
+    _subMeshDS = _meshDS->MeshElements(_subShape);     // may be null ...
+//     if (_subMeshDS==NULL)
+//     {
+//       MESSAGE("problem... subMesh still empty");
+//     }
+  }
+  return _subMeshDS;
 }
 
 //=============================================================================
@@ -150,7 +150,6 @@ SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS()
 
 SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
 {
-  //MESSAGE("SMESH_subMesh::GetFirstToCompute");
   const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
   SMESH_subMesh *firstToCompute = 0;
 
@@ -158,13 +157,10 @@ SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
   for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
   {
     SMESH_subMesh *sm = (*itsub).second;
-    //       SCRUTE(sm->GetId());
-    //       SCRUTE(sm->GetComputeState());
     bool readyToCompute = (sm->GetComputeState() == READY_TO_COMPUTE);
     if (readyToCompute)
     {
       firstToCompute = sm;
-      //SCRUTE(sm->GetId());
       break;
     }
   }
@@ -195,12 +191,19 @@ bool SMESH_subMesh::SubMeshesComputed()
   for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
   {
     SMESH_subMesh *sm = (*itsub).second;
-
-    const TopoDS_Shape & ss = sm->GetSubShape();
-    int type = ss.ShapeType();
-    bool computeOk = (sm->GetComputeState() == COMPUTE_OK);
+    SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
+    // PAL10974.
+    // There are some tricks with compute states, e.g. Penta_3D leaves
+    // one face with READY_TO_COMPUTE state in order to be able to
+    // recompute 3D when a locale triangle hypo changes (see PAL7428).
+    // So we check if mesh is really present
+    //bool computeOk = (sm->GetComputeState() == COMPUTE_OK);
+    bool computeOk = ( ds && ( ds->GetNodes()->more() || ds->GetElements()->more() ));
     if (!computeOk)
     {
+      const TopoDS_Shape & ss = sm->GetSubShape();
+      int type = ss.ShapeType();
+
       subMeshesComputed = false;
 
       switch (type)
@@ -416,20 +419,12 @@ void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape)
   int ordType = 9 - type;               // 2 = Vertex, 8 = CompSolid
   int cle = aSubMesh->GetId();
   cle += 10000000 * ordType;    // sort map by ordType then index
-  if (_mapDepend.find(cle) == _mapDepend.end())
+  if ( _mapDepend.find( cle ) == _mapDepend.end())
   {
     _mapDepend[cle] = aSubMesh;
-    const map < int, SMESH_subMesh * >&subMap = aSubMesh->DependsOn();
-    map < int, SMESH_subMesh * >::const_iterator im;
-    for (im = subMap.begin(); im != subMap.end(); im++)
-    {
-      int clesub = (*im).first;
-      SMESH_subMesh *sm = (*im).second;
-      if (_mapDepend.find(clesub) == _mapDepend.end())
-        _mapDepend[clesub] = sm;
-    }
+    const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
+    _mapDepend.insert( subMap.begin(), subMap.end() );
   }
-
 }
 
 //=============================================================================
@@ -465,33 +460,28 @@ bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) cons
 
 //=======================================================================
 //function : IsApplicableHypotesis
-//purpose  : return true if theHypothesis can be used to mesh me:
-//           its shape type is checked
+//purpose  : 
 //=======================================================================
 
-bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis) const
+bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
+                                          const TopAbs_ShapeEnum  theShapeType)
 {
   if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
     // algorithm
-    return ( theHypothesis->GetShapeType() & (1<< _subShape.ShapeType()));
+    return ( theHypothesis->GetShapeType() & (1<< theShapeType));
 
   // hypothesis
-  switch ( _subShape.ShapeType() ) {
-  case TopAbs_EDGE:
-  case TopAbs_FACE:
+  switch ( theShapeType ) {
+  case TopAbs_EDGE: 
+  case TopAbs_FACE: 
   case TopAbs_SHELL:
-  case TopAbs_SOLID: {
-    int aHypDim   = theHypothesis->GetDim();
-    int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
-    return ( aHypDim == aShapeDim );
-  }
-//   case TopAbs_VERTEX:
+  case TopAbs_SOLID:
+    return SMESH_Gen::GetShapeDim( theShapeType ) == theHypothesis->GetDim();
 //   case TopAbs_WIRE:
 //   case TopAbs_COMPSOLID:
 //   case TopAbs_COMPOUND:
   default:;
   }
-
   return false;
 }
 
@@ -508,11 +498,12 @@ SMESH_Hypothesis::Hypothesis_Status
   //SCRUTE(_algoState);
   //SCRUTE(event);
 
-  SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
-
   // **** les retour des evenement shape sont significatifs
   // (add ou remove fait ou non)
   // le retour des evenement father n'indiquent pas que add ou remove fait
+
+  SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
+
   int dim = SMESH_Gen::GetShapeDim(_subShape);
 
   if (dim < 1)
@@ -561,27 +552,28 @@ SMESH_Hypothesis::Hypothesis_Status
       string hypName = anHyp->GetName();
 
       if (hypName == "Propagation") {
-        if (_subShape.ShapeType() == TopAbs_EDGE) {
-          isPropagationOk = _father->BuildPropagationChain(_subShape);
-        } else {
-          TopExp_Explorer exp (_subShape, TopAbs_EDGE);
-          TopTools_MapOfShape aMap;
-          for (; exp.More(); exp.Next()) {
-            if (aMap.Add(exp.Current())) {
-              if (!_father->BuildPropagationChain(exp.Current())) {
-                isPropagationOk = false;
-              }
+        TopExp_Explorer exp (_subShape, TopAbs_EDGE);
+        TopTools_MapOfShape aMap;
+        for (; exp.More(); exp.Next()) {
+          if (aMap.Add(exp.Current())) {
+            if (!_father->BuildPropagationChain(exp.Current())) {
+              isPropagationOk = false;
             }
           }
         }
-      } else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated
-        if (_subShape.ShapeType() == TopAbs_EDGE) {
-          TopoDS_Shape aMainEdge;
-          if (_father->IsPropagatedHypothesis(_subShape, aMainEdge)) {
-            isPropagationOk = _father->RebuildPropagationChains();
-          } else if (_father->IsPropagationHypothesis(_subShape)) {
-            isPropagationOk = _father->BuildPropagationChain(_subShape);
-          } else {
+      }
+      else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated
+        TopExp_Explorer exp (_subShape, TopAbs_EDGE);
+        TopTools_MapOfShape aMap;
+        for (; exp.More(); exp.Next()) {
+          if (aMap.Add(exp.Current())) {
+            TopoDS_Shape aMainEdge;
+            if (_father->IsPropagatedHypothesis(exp.Current(), aMainEdge)) {
+              isPropagationOk = _father->RebuildPropagationChains();
+            } else if (_father->IsPropagationHypothesis(exp.Current())) {
+              isPropagationOk = _father->BuildPropagationChain(exp.Current());
+            } else {
+            }
           }
         }
       } else {
@@ -602,43 +594,30 @@ SMESH_Hypothesis::Hypothesis_Status
       return SMESH_Hypothesis::HYP_OK; // nothing changes
 
     // Serve Propagation of 1D hypothesis
-    if (event == REMOVE_HYP) {
+    if (event == REMOVE_HYP)
+    {
       bool isPropagationOk = true;
-      string hypName = anHyp->GetName();
-
-      if (hypName == "Propagation") {
-        if (_subShape.ShapeType() == TopAbs_EDGE) {
-          if (!_father->RemovePropagationChain(_subShape)) {
-            return SMESH_Hypothesis::HYP_UNKNOWN_FATAL;
-          }
-          // rebuild propagation chains, because removing one
-          // chain can resolve concurention, existing before
-          isPropagationOk = _father->RebuildPropagationChains();
-        } else {
-          TopExp_Explorer exp (_subShape, TopAbs_EDGE);
-          TopTools_MapOfShape aMap;
-          for (; exp.More(); exp.Next()) {
-            if (aMap.Add(exp.Current())) {
-              if (!_father->RemovePropagationChain(exp.Current())) {
-                return SMESH_Hypothesis::HYP_UNKNOWN_FATAL;
-              }
+      SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" ));
+      if ( propagFilter.IsOk( anHyp, _subShape ))
+      {
+        TopExp_Explorer exp (_subShape, TopAbs_EDGE);
+        TopTools_MapOfShape aMap;
+        for (; exp.More(); exp.Next()) {
+          if (aMap.Add(exp.Current()) &&
+              !_father->GetHypothesis( exp.Current(), propagFilter, true )) {
+            // no more Propagation on the current edge
+            if (!_father->RemovePropagationChain(exp.Current())) {
+              return SMESH_Hypothesis::HYP_UNKNOWN_FATAL;
             }
           }
-          // rebuild propagation chains, because removing one
-          // chain can resolve concurention, existing before
-          if (!_father->RebuildPropagationChains()) {
-            isPropagationOk = false;
-          }
-        }
-      } else { // if (hypName == "Propagation")
-        if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated
-        {
-          if (_subShape.ShapeType() == TopAbs_EDGE) {
-            isPropagationOk = _father->RebuildPropagationChains();
-            if (!isPropagationOk && ret < SMESH_Hypothesis::HYP_CONCURENT)
-              ret = SMESH_Hypothesis::HYP_CONCURENT;
-          }
         }
+        // rebuild propagation chains, because removing one
+        // chain can resolve concurention, existing before
+        isPropagationOk = _father->RebuildPropagationChains();
+      }
+      else if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated
+      {
+        isPropagationOk = _father->RebuildPropagationChains();
       }
 
       if (!isPropagationOk && ret < SMESH_Hypothesis::HYP_CONCURENT) {
@@ -805,20 +784,17 @@ SMESH_Hypothesis::Hypothesis_Status
       ASSERT(algo);
       if (!algo->CheckHypothesis((*_father),_subShape, ret ))
       {
-        MESSAGE("two applying algo on the same shape not allowed");
-        _meshDS->RemoveHypothesis(_subShape, anHyp);
         if ( !SMESH_Hypothesis::IsStatusFatal( ret ))
           // ret should be fatal: anHyp was not added
           ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
       }
-      else if (SMESH_Hypothesis::IsStatusFatal( ret ))
-      {
-        _meshDS->RemoveHypothesis(_subShape, anHyp);
-      }
       else if (!_father->IsUsedHypothesis(  anHyp, _subShape ))
+        ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
+
+      if (SMESH_Hypothesis::IsStatusFatal( ret ))
       {
+        MESSAGE("do not add extra hypothesis");
         _meshDS->RemoveHypothesis(_subShape, anHyp);
-        ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
       }
       else
       {
@@ -828,11 +804,19 @@ SMESH_Hypothesis::Hypothesis_Status
     }
     case ADD_ALGO: {           //already existing algo : on father ?
       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
-      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
-        SetAlgoState(HYP_OK);
+      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+        // check if algo changes
+        SMESH_HypoFilter f;
+        f.Init(   SMESH_HypoFilter::IsAlgo() );
+        f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
+        f.AndNot( SMESH_HypoFilter::Is( algo ));
+        const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
+        if (prevAlgo && 
+            string(algo->GetName()) != string(prevAlgo->GetName()) )
+          modifiedHyp = true;
+      }
       else
         SetAlgoState(MISSING_HYP);
-      modifiedHyp = true;
       break;
     }
     case REMOVE_HYP: {
@@ -853,13 +837,13 @@ SMESH_Hypothesis::Hypothesis_Status
       }
       else
       {
-        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
-          SetAlgoState(HYP_OK);
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+          // check if algo remains
+          if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
+            modifiedHyp = true;
+        }
         else
           SetAlgoState(MISSING_HYP);
-        // check if same algo remains
-        if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
-          modifiedHyp = true;
       }
       break;
     }
@@ -868,7 +852,6 @@ SMESH_Hypothesis::Hypothesis_Status
       ASSERT(algo);
       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
       {
-        SetAlgoState(HYP_OK);
         if (_father->IsUsedHypothesis( anHyp, _subShape )) // new Hyp
           modifiedHyp = true;
       }
@@ -876,27 +859,35 @@ SMESH_Hypothesis::Hypothesis_Status
         SetAlgoState(MISSING_HYP);
       break;
     }
-    case ADD_FATHER_ALGO: {    // a new algo on father
+    case ADD_FATHER_ALGO: {
       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
-      if ( algo == anHyp ) {
-        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
-          SetAlgoState(HYP_OK);
+      if ( algo == anHyp ) { // a new algo on father
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+          // check if algo changes
+          SMESH_HypoFilter f;
+          f.Init(   SMESH_HypoFilter::IsAlgo() );
+          f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
+          f.AndNot( SMESH_HypoFilter::Is( algo ));
+          const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
+          if (prevAlgo && 
+              string(algo->GetName()) != string(prevAlgo->GetName()) )
+            modifiedHyp = true;
+        }
         else
           SetAlgoState(MISSING_HYP);
-        modifiedHyp = true;
       }
       break;
     }
     case REMOVE_FATHER_HYP: {
       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
       ASSERT(algo);
-      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
-        SetAlgoState(HYP_OK);
+      if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+        // is there the same local hyp or maybe a new father algo applied?
+        if ( !GetSimilarAttached( _subShape, anHyp ) )
+          modifiedHyp = true;
+      }
       else
         SetAlgoState(MISSING_HYP);
-      // is there the same local hyp or maybe a new father algo applied?
-      if ( !GetSimilarAttached( _subShape, anHyp ) )
-        modifiedHyp = true;
       break;
     }
     case REMOVE_FATHER_ALGO: {
@@ -907,13 +898,13 @@ SMESH_Hypothesis::Hypothesis_Status
       }
       else
       {
-        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
-          SetAlgoState(HYP_OK);
+        if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
+          // check if algo changes
+          if ( string(algo->GetName()) != string( anHyp->GetName()) )
+            modifiedHyp = true;
+        }
         else
           SetAlgoState(MISSING_HYP);
-        // is there the same local algo or maybe a new father algo applied?
-        if ( !GetSimilarAttached( _subShape, anHyp ))
-          modifiedHyp = true;
       }
       break;
     }
@@ -956,7 +947,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
   SMESH_Gen* gen =_father->GetGen();
 
   // only local algo is to be checked
-  if ( gen->IsGlobalAlgo( theAlgo, *_father ))
+  if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
     return true;
 
   // check algo attached to adjacent shapes
@@ -979,7 +970,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
       if (algo &&
           //algo != theAlgo &&
           !algo->NeedDescretBoundary() /*&&
-          !gen->IsGlobalAlgo( algo, *_father )*/)
+          !gen->IsGlobalHypothesis( algo, *_father )*/)
         return false; // NOT CONFORM MESH WILL BE PRODUCED
     }
   }
@@ -995,9 +986,7 @@ bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
 
 void SMESH_subMesh::SetAlgoState(int state)
 {
-//     if (state != _oldAlgoState)
-//     int retc = ComputeStateEngine(MODIF_ALGO_STATE);
-               _algoState = state;
+  _algoState = state;
 }
 
 //=============================================================================
@@ -1013,7 +1002,7 @@ SMESH_Hypothesis::Hypothesis_Status
   SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
   //EAP: a wire (dim==1) should notify edges (dim==1)
   //EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
-  if (/*EAP:dim > 1*/ _subShape.ShapeType() < TopAbs_EDGE )
+  if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
   {
     const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
 
@@ -1038,7 +1027,7 @@ SMESH_Hypothesis::Hypothesis_Status
 
 void SMESH_subMesh::CleanDependsOn()
 {
-       MESSAGE("SMESH_subMesh::CleanDependsOn");
+  //MESSAGE("SMESH_subMesh::CleanDependsOn");
        // **** parcourir les ancetres dans l'ordre de dépendance
 
        ComputeStateEngine(CLEAN);
@@ -1048,7 +1037,6 @@ void SMESH_subMesh::CleanDependsOn()
        for (its = dependson.begin(); its != dependson.end(); its++)
        {
                SMESH_subMesh *sm = (*its).second;
-               SCRUTE((*its).first);
                sm->ComputeStateEngine(CLEAN);
        }
 }
@@ -1105,6 +1093,37 @@ void SMESH_subMesh::DumpAlgoState(bool isMain)
        }
 }
 
+//================================================================================
+/*!
+ * \brief Remove nodes and elements bound to submesh
+  * \param subMesh - submesh containing nodes and elements
+ */
+//================================================================================
+
+static void cleanSubMesh( SMESH_subMesh * subMesh )
+{
+  if ( subMesh )
+    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);
+      }
+
+      SMDS_NodeIteratorPtr itn=subMeshDS->GetNodes();
+      while(itn->more())
+      {
+        const SMDS_MeshNode * node = itn->next();
+        //MESSAGE( " RM node: "<<node->GetID());
+        meshDS->RemoveNode(node);
+      }
+    }
+}
+
 //=============================================================================
 /*!
  *
@@ -1152,7 +1171,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
       break;
     case CLEAN:
       RemoveSubMeshElementsAndNodes();
-      break;
+      //break; submeshes dependent on me should be cleaned as well
     case CLEANDEP:
       CleanDependants();
       break;
@@ -1210,13 +1229,19 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
           _computeState = FAILED_TO_COMPUTE;
           break;
         }
-        RemoveSubMeshElementsAndNodes();
         // compute
-        if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
-          ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
-        else
-          ret = algo->Compute((*_father), _subShape);
-
+        CleanDependants();
+        RemoveSubMeshElementsAndNodes();
+        try {
+          if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
+            ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
+          else
+            ret = algo->Compute((*_father), _subShape);
+        }
+        catch (Standard_Failure) {
+          MESSAGE( "Exception in algo->Compute() ");
+          ret = false;
+        }
         if (!ret)
         {
           MESSAGE("problem in algo execution: failed to compute");
@@ -1226,9 +1251,10 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
 
 #ifdef _DEBUG_
           // Show vertices location of a failed shape
-          TopExp_Explorer exp( _subShape, TopAbs_VERTEX);
-          for ( ; exp.More(); exp.Next() ) {
-            gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( exp.Current() )));
+          TopTools_IndexedMapOfShape vMap;
+          TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
+          for ( int iv = 1; iv <= vMap.Extent(); ++iv ) {
+            gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
             cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
           }
 #endif
@@ -1253,7 +1279,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
         if (ret)
           _computeState = READY_TO_COMPUTE;
       }
-      break;
+      //break; submeshes dependent on me should be cleaned as well
     case CLEANDEP:
       CleanDependants();
       break;
@@ -1283,13 +1309,8 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
     switch (event)
     {
     case MODIF_HYP:
-      CleanDependants();        // recursive recall with event CLEANDEP
-      algo = gen->GetAlgo((*_father), _subShape);
-      if (algo && !algo->NeedDescretBoundary())
-        CleanDependsOn(); // remove sub-mesh with event CLEANDEP
-      break;
     case MODIF_ALGO_STATE:
-      CleanDependants();        // recursive recall with event CLEANDEP
+      ComputeStateEngine( CLEAN );
       algo = gen->GetAlgo((*_father), _subShape);
       if (algo && !algo->NeedDescretBoundary())
         CleanDependsOn(); // remove sub-mesh with event CLEANDEP
@@ -1306,7 +1327,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
         if (ret)
           _computeState = READY_TO_COMPUTE;
       }
-      break;
+      // break; submeshes dependent on me should be cleaned as well
     case CLEANDEP:
       CleanDependants();        // recursive recall with event CLEANDEP
       break;
@@ -1359,7 +1380,7 @@ bool SMESH_subMesh::ComputeStateEngine(int event)
         _computeState = READY_TO_COMPUTE;
       else
         _computeState = NOT_READY;
-      break;
+      // break; submeshes dependent on me should be cleaned as well
     case CLEANDEP:
       CleanDependants();
       break;
@@ -1498,46 +1519,20 @@ void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
 
 void SMESH_subMesh::CleanDependants()
 {
-  //MESSAGE("SMESH_subMesh::CleanDependants: shape type " << _subShape.ShapeType() );
+  int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
 
   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
   for (; it.More(); it.Next())
   {
     const TopoDS_Shape& ancestor = it.Value();
-    //MESSAGE("ancestor shape type " << ancestor.ShapeType() );
-    SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
-    if (aSubMesh)
-      aSubMesh->ComputeStateEngine(CLEANDEP);
-  }
-  ComputeStateEngine(CLEAN);
-}
-
-
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-
-static void removeSubMesh( SMESHDS_Mesh * meshDS, const TopoDS_Shape& subShape)
-{
-  SMESHDS_SubMesh * subMeshDS = meshDS->MeshElements(subShape);
-  if (subMeshDS!=NULL)
-  {
-    SMDS_ElemIteratorPtr ite=subMeshDS->GetElements();
-    while(ite->more())
-    {
-      const SMDS_MeshElement * elt = ite->next();
-      //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
-      meshDS->RemoveElement(elt);
-    }
-
-    SMDS_NodeIteratorPtr itn=subMeshDS->GetNodes();
-    while(itn->more())
-    {
-      const SMDS_MeshNode * node = itn->next();
-      //MESSAGE( " RM node: "<<node->GetID());
-      meshDS->RemoveNode(node);
+    if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
+      // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
+      // will erase mesh on other shapes in a compound
+      if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
+        SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
+        if (aSubMesh)
+          aSubMesh->ComputeStateEngine(CLEAN);
+      }
     }
   }
 }
@@ -1550,9 +1545,9 @@ static void removeSubMesh( SMESHDS_Mesh * meshDS, const TopoDS_Shape& subShape)
 
 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
 {
-  SCRUTE(_subShape.ShapeType());
+  //SCRUTE(_subShape.ShapeType());
 
-  removeSubMesh( _meshDS, _subShape );
+  cleanSubMesh( this );
 
   // algo may bind a submesh not to _subShape, eg 3D algo
   // sets nodes on SHELL while _subShape may be SOLID
@@ -1564,7 +1559,7 @@ void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
     {
       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
       for ( ; exp.More(); exp.Next() )
-        removeSubMesh( _meshDS, exp.Current() );
+        cleanSubMesh( _father->GetSubMeshContaining( exp.Current() ));
     }
     else
       break;
@@ -1659,28 +1654,16 @@ const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape&
                                                           const SMESH_Hypothesis * theHyp,
                                                           const int                theHypType)
 {
-  const list<const SMESHDS_Hypothesis*>& aHypList =
-    _father->GetHypothesisList( theShape );
-  list<const SMESHDS_Hypothesis*>::const_iterator it = aHypList.begin();
-  for ( ; it != aHypList.end(); it++ )
-  {
-    const SMESH_Hypothesis* hyp = static_cast< const SMESH_Hypothesis *>( *it );
-    if ( theHyp )
-    {
-      // find similar
-      if (hyp != theHyp &&
-          hyp->GetType() == theHyp->GetType() &&
-          hyp->GetDim()  == theHyp->GetDim())
-        return hyp;
-    }
-    else
-    {
-      if ( hyp->GetType() == theHypType && IsApplicableHypotesis( hyp ))
-        return hyp;
-    }
+  SMESH_HypoFilter filter;
+  filter.Init( SMESH_HypoFilter::HasType( theHyp ? theHyp->GetType() : theHypType ));
+  if ( theHyp ) {
+    filter.And( SMESH_HypoFilter::HasDim( theHyp->GetDim() ));
+    filter.AndNot( SMESH_HypoFilter::Is( theHyp ));
   }
+  else
+    filter.And( SMESH_HypoFilter::IsApplicableTo( theShape ));
 
-  return 0;
+  return _father->GetHypothesis( theShape, filter, false );
 }
 
 //=======================================================================