Salome HOME
23413: [CEA 2025] bug SMESH orientation
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
index 49446080fa25794004ca7f9c81952eedf4b3d7e6..eac04a4d1604fda010e7e467e0897f81f132a8b7 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
@@ -112,7 +112,7 @@ SMESH_Mesh::SMESH_Mesh(int               theLocalId,
                        SMESHDS_Document* theDocument):
   _groupId( 0 ), _nbSubShapes( 0 )
 {
-  MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)");
+  if(MYDEBUG) MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)");
   _id            = theLocalId;
   _studyId       = theStudyId;
   _gen           = theGen;
@@ -179,7 +179,7 @@ namespace
 
 SMESH_Mesh::~SMESH_Mesh()
 {
-  MESSAGE("SMESH_Mesh::~SMESH_Mesh");
+  if(MYDEBUG) MESSAGE("SMESH_Mesh::~SMESH_Mesh");
 
   // avoid usual removal of elements while processing RemoveHypothesis( algo ) event
   SMESHDS_SubMeshIteratorPtr smIt = _myMeshDS->SubMeshes();
@@ -237,6 +237,26 @@ bool SMESH_Mesh::MeshExists( int meshId ) const
   return _myDocument ? bool( _myDocument->GetMesh( meshId )) : false;
 }
 
+//================================================================================
+/*!
+ * \brief Return a mesh by id
+ */
+//================================================================================
+
+SMESH_Mesh* SMESH_Mesh::FindMesh( int meshId ) const
+{
+  if ( _id == meshId )
+    return (SMESH_Mesh*) this;
+
+  if ( StudyContextStruct *aStudyContext = _gen->GetStudyContext( _studyId ))
+  {
+    std::map < int, SMESH_Mesh * >::iterator i_m = aStudyContext->mapMesh.find( meshId );
+    if ( i_m != aStudyContext->mapMesh.end() )
+      return i_m->second;
+  }
+  return NULL;
+}
+
 //=============================================================================
 /*!
  * \brief Set geometry to be meshed
@@ -341,10 +361,19 @@ double SMESH_Mesh::GetShapeDiagonalSize(const TopoDS_Shape & aShape)
     int nbFaces = 0;
     for ( TopExp_Explorer f( aShape, TopAbs_FACE ); f.More() && nbFaces < maxNbFaces; f.Next() )
       ++nbFaces;
+    bool isPrecise = false;
     if ( nbFaces < maxNbFaces )
-      GEOMUtils::PreciseBoundingBox(aShape, Box);
-    else
-      BRepBndLib::Add( aShape, Box);
+      try {
+        GEOMUtils::PreciseBoundingBox( aShape, Box );
+        isPrecise = true;
+      }
+      catch (...) {
+        isPrecise = false;
+      }
+    if ( !isPrecise )
+    {
+      BRepBndLib::Add( aShape, Box );
+    }
     if ( !Box.IsVoid() )
       return sqrt( Box.SquareExtent() );
   }
@@ -409,6 +438,7 @@ void SMESH_Mesh::Clear()
       sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
     }
   }
+  GetMeshDS()->Modified();
   _isModified = false;
 }
 
@@ -445,47 +475,38 @@ void SMESH_Mesh::ClearSubMesh(const int theShapeId)
 
 int SMESH_Mesh::UNVToMesh(const char* theFileName)
 {
-  if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<<theFileName);
-  if(_isShapeToMesh)
+  if ( _isShapeToMesh )
     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
   _isShapeToMesh = false;
+
   DriverUNV_R_SMDS_Mesh myReader;
   myReader.SetMesh(_myMeshDS);
   myReader.SetFile(theFileName);
   myReader.SetMeshId(-1);
   myReader.Perform();
-  if(MYDEBUG){
-    MESSAGE("UNVToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
-    MESSAGE("UNVToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
-    MESSAGE("UNVToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
-    MESSAGE("UNVToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
-  }
-  SMDS_MeshGroup* aGroup = (SMDS_MeshGroup*) myReader.GetGroup();
-  if (aGroup != 0) {
+
+  if ( SMDS_MeshGroup* aGroup = (SMDS_MeshGroup*) myReader.GetGroup() )
+  {
     TGroupNamesMap aGroupNames = myReader.GetGroupNamesMap();
-    //const TGroupIdMap& aGroupId = myReader.GetGroupIdMap();
     aGroup->InitSubGroupsIterator();
-    while (aGroup->MoreSubGroups()) {
+    while (aGroup->MoreSubGroups())
+    {
       SMDS_MeshGroup* aSubGroup = (SMDS_MeshGroup*) aGroup->NextSubGroup();
       string aName = aGroupNames[aSubGroup];
       int aId;
-
-      SMESH_Group* aSMESHGroup = AddGroup( aSubGroup->GetType(), aName.c_str(), aId );
-      if ( aSMESHGroup ) {
-        if(MYDEBUG) MESSAGE("UNVToMesh - group added: "<<aName);      
+      if ( SMESH_Group* aSMESHGroup = AddGroup( aSubGroup->GetType(), aName.c_str(), aId ))
+      {
         SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aSMESHGroup->GetGroupDS() );
         if ( aGroupDS ) {
           aGroupDS->SetStoreName(aName.c_str());
           aSubGroup->InitIterator();
           const SMDS_MeshElement* aElement = 0;
-          while (aSubGroup->More()) {
-            aElement = aSubGroup->Next();
-            if (aElement) {
-              aGroupDS->SMDSGroup().Add(aElement);
-            }
-          }
+          while ( aSubGroup->More() )
+            if (( aElement = aSubGroup->Next() ))
+              aGroupDS->SMDSGroup().Add( aElement );
+
           if (aElement)
-            aGroupDS->SetType(aElement->GetType());
+            aGroupDS->SetType( aElement->GetType() );
         }
       }
     }
@@ -495,37 +516,34 @@ int SMESH_Mesh::UNVToMesh(const char* theFileName)
 
 //=======================================================================
 //function : MEDToMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
 {
-  if(MYDEBUG) MESSAGE("MEDToMesh - theFileName = "<<theFileName<<", mesh name = "<<theMeshName);
-  if(_isShapeToMesh)
+  if ( _isShapeToMesh )
     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
   _isShapeToMesh = false;
+
   DriverMED_R_SMESHDS_Mesh myReader;
   myReader.SetMesh(_myMeshDS);
   myReader.SetMeshId(-1);
   myReader.SetFile(theFileName);
   myReader.SetMeshName(theMeshName);
   Driver_Mesh::Status status = myReader.Perform();
-  if(MYDEBUG){
-    MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
-    MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
-    MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
-    MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
-  }
+#ifdef _DEBUG_
+  SMESH_ComputeErrorPtr er = myReader.GetError();
+  if ( er && !er->IsOK() ) cout << er->myComment << endl;
+#endif
 
   // Reading groups (sub-meshes are out of scope of MED import functionality)
   list<TNameAndType> aGroupNames = myReader.GetGroupNamesAndTypes();
-  if(MYDEBUG) MESSAGE("MEDToMesh - Nb groups = "<<aGroupNames.size()); 
   int anId;
   list<TNameAndType>::iterator name_type = aGroupNames.begin();
-  for ( ; name_type != aGroupNames.end(); name_type++ ) {
+  for ( ; name_type != aGroupNames.end(); name_type++ )
+  {
     SMESH_Group* aGroup = AddGroup( name_type->second, name_type->first.c_str(), anId );
     if ( aGroup ) {
-      if(MYDEBUG) MESSAGE("MEDToMesh - group added: "<<name_type->first.c_str());      
       SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
       if ( aGroupDS ) {
         aGroupDS->SetStoreName( name_type->first.c_str() );
@@ -543,21 +561,16 @@ int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
 
 int SMESH_Mesh::STLToMesh(const char* theFileName)
 {
-  if(MYDEBUG) MESSAGE("STLToMesh - theFileName = "<<theFileName);
   if(_isShapeToMesh)
     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
   _isShapeToMesh = false;
+
   DriverSTL_R_SMDS_Mesh myReader;
   myReader.SetMesh(_myMeshDS);
   myReader.SetFile(theFileName);
   myReader.SetMeshId(-1);
   myReader.Perform();
-  if(MYDEBUG){
-    MESSAGE("STLToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
-    MESSAGE("STLToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
-    MESSAGE("STLToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
-    MESSAGE("STLToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
-  }
+
   return 1;
 }
 
@@ -655,8 +668,8 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
 
   // shape
 
-  bool isAlgo = ( anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
-  int   event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
+  bool                     isAlgo = ( anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO );
+  SMESH_subMesh::algo_event event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
 
   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
 
@@ -701,6 +714,7 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
     }
   }
   HasModificationsToDiscard(); // to reset _isModified flag if a mesh becomes empty
+  GetMeshDS()->Modified();
 
   if(MYDEBUG) subMesh->DumpAlgoState(true);
   if(MYDEBUG) SCRUTE(ret);
@@ -714,25 +728,23 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
 //=============================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
-                               int anHypId)throw(SALOME_Exception)
+SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
+                             int                    anHypId) throw( SALOME_Exception )
 {
   Unexpect aCatch(SalomeException);
   if(MYDEBUG) MESSAGE("SMESH_Mesh::RemoveHypothesis");
-  
+
   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
-  
+
   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
-  if(MYDEBUG) {
-    SCRUTE(anHyp->GetType());
-  }
-  
+  if(MYDEBUG) { SCRUTE(anHyp->GetType()); }
+
   // shape 
-  
-  bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
-  int event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
+
+  bool                     isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
+  SMESH_subMesh::algo_event event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
 
   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
 
@@ -773,6 +785,7 @@ SMESH_Hypothesis::Hypothesis_Status
   }
 
   HasModificationsToDiscard(); // to reset _isModified flag if mesh become empty
+  GetMeshDS()->Modified();
 
   if(MYDEBUG) subMesh->DumpAlgoState(true);
   if(MYDEBUG) SCRUTE(ret);
@@ -999,7 +1012,6 @@ SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const int anHypId) const
 const list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  if(MYDEBUG) MESSAGE("SMESH_Mesh::GetLog");
   return _myMeshDS->GetScript()->GetCommands();
 }
 
@@ -1011,7 +1023,6 @@ const list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
 void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  if(MYDEBUG) MESSAGE("SMESH_Mesh::ClearLog");
   _myMeshDS->GetScript()->Clear();
 }
 
@@ -1021,7 +1032,7 @@ void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
  */
 //=============================================================================
 
-SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
+SMESH_subMesh * SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
   throw(SALOME_Exception)
 {
   int index = _myMeshDS->ShapeToIndex(aSubShape);
@@ -1029,7 +1040,8 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
     return 0;
 
   // for submeshes on GEOM Group
-  if (( !index || index > _nbSubShapes ) && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
+  if (( !index || index > _nbSubShapes ) && aSubShape.ShapeType() == TopAbs_COMPOUND )
+  {
     TopoDS_Iterator it( aSubShape );
     if ( it.More() )
     {
@@ -1097,7 +1109,7 @@ throw(SALOME_Exception)
 
 //================================================================================
 /*!
- * \brief Return submeshes of groups containing the given sub-shape
+ * \brief Return sub-meshes of groups containing the given sub-shape
  */
 //================================================================================
 
@@ -1111,8 +1123,8 @@ SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
   if ( !subMesh )
     return found;
 
-  // submeshes of groups have max IDs, so search from the map end
-SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator( /*reverse=*/true ) );
+  // sub-meshes of groups have max IDs, so search from the map end
+  SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator( /*reverse=*/true ) );
   while ( smIt->more() ) {
     SMESH_subMesh*    sm = smIt->next();
     SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
@@ -1138,6 +1150,12 @@ SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator( /*reverse=*/true ) )
           found.push_back( mainSM );
       }
   }
+  else // issue 0023068
+  {
+    if ( SMESH_subMesh * mainSM = GetSubMeshContaining(1) )
+      if ( mainSM->GetSubShape().ShapeType() == TopAbs_COMPOUND )
+        found.push_back( mainSM );
+  }
   return found;
 }
 //=======================================================================
@@ -1175,27 +1193,6 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
   return false;
 }
 
-//=============================================================================
-/*!
- *
- */
-//=============================================================================
-
-// const list < SMESH_subMesh * >&
-// SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
-//   throw(SALOME_Exception)
-// {
-//   _subMeshesUsingHypothesisList.clear();
-//   SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
-//   while ( smIt->more() )
-//   {
-//     SMESH_subMesh* aSubMesh = smIt->next();
-//     if ( IsUsedHypothesis ( anHyp, aSubMesh ))
-//       _subMeshesUsingHypothesisList.push_back( aSubMesh );
-//   }
-//   return _subMeshesUsingHypothesisList;
-// }
-
 //=======================================================================
 //function : NotifySubMeshesHypothesisModification
 //purpose  : Say all submeshes using theChangedHyp that it has been modified
@@ -1214,49 +1211,67 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
   SMESH_Algo *algo;
   const SMESH_HypoFilter* compatibleHypoKind;
   list <const SMESHDS_Hypothesis * > usedHyps;
-
-  // keep sub-meshes not to miss ones whose state can change due to notifying others
   vector< SMESH_subMesh* > smToNotify;
+  bool allMeshedEdgesNotified = true;
 
   SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
   while ( smIt->more() )
   {
     SMESH_subMesh* aSubMesh = smIt->next();
+    bool toNotify = false;
 
     // if aSubMesh meshing depends on hyp,
     // we call aSubMesh->AlgoStateEngine( MODIF_HYP, hyp ) that causes either
-    // 1) clearing of already computed aSubMesh or
+    // 1) clearing already computed aSubMesh or
     // 2) changing algo_state from MISSING_HYP to HYP_OK when parameters of hyp becomes valid,
     // other possible changes are not interesting. (IPAL0052457 - assigning hyp performance pb)
-    if ( aSubMesh->GetComputeState() != SMESH_subMesh::COMPUTE_OK &&
-         aSubMesh->GetComputeState() != SMESH_subMesh::FAILED_TO_COMPUTE &&
-         aSubMesh->GetAlgoState()    != SMESH_subMesh::MISSING_HYP &&
-         !hyp->DataDependOnParams() )
-      continue;
-
-    const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
-
-    if (( aSubMesh->IsApplicableHypotesis( hyp )) &&
-        ( algo = aSubMesh->GetAlgo() )            &&
-        ( compatibleHypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() )) &&
-        ( compatibleHypoKind->IsOk( hyp, aSubShape )))
+    if ( aSubMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK ||
+         aSubMesh->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE ||
+         aSubMesh->GetAlgoState()    == SMESH_subMesh::MISSING_HYP ||
+         hyp->DataDependOnParams() )
     {
-      // check if hyp is used by algo
-      usedHyps.clear();
-      if ( GetHypotheses( aSubMesh, *compatibleHypoKind, usedHyps, true ) &&
-           find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
+      const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
+
+      if (( aSubMesh->IsApplicableHypotesis( hyp )) &&
+          ( algo = aSubMesh->GetAlgo() )            &&
+          ( compatibleHypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() )) &&
+          ( compatibleHypoKind->IsOk( hyp, aSubShape )))
       {
-        smToNotify.push_back( aSubMesh );
+        // check if hyp is used by algo
+        usedHyps.clear();
+        toNotify = ( GetHypotheses( aSubMesh, *compatibleHypoKind, usedHyps, true ) &&
+                     std::find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() );
       }
     }
+    if ( toNotify )
+    {
+      smToNotify.push_back( aSubMesh );
+      if ( aSubMesh->GetAlgoState() == SMESH_subMesh::MISSING_HYP )
+        allMeshedEdgesNotified = false; //  update of algo state needed, not mesh clearing
+    }
+    else
+    {
+      if ( !aSubMesh->IsEmpty() &&
+           aSubMesh->GetSubShape().ShapeType() == TopAbs_EDGE )
+        allMeshedEdgesNotified = false;
+    }
   }
+  if ( smToNotify.empty() )
+    return;
 
-  for ( size_t i = 0; i < smToNotify.size(); ++i )
+  // if all meshed EDGEs will be notified then the notification is equivalent
+  // to the whole mesh clearing, which is usually faster
+  if ( allMeshedEdgesNotified && NbNodes() > 0 )
   {
-    smToNotify[i]->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
-                                   const_cast< SMESH_Hypothesis*>( hyp ));
+    Clear();
+  }
+  else
+  {
+    // notify in reverse order to avoid filling the pool of IDs
+    for ( int i = smToNotify.size()-1; i >= 0; --i )
+      smToNotify[i]->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
+                                     const_cast< SMESH_Hypothesis*>( hyp ));
   }
-
   HasModificationsToDiscard(); // to reset _isModified flag if mesh becomes empty
   GetMeshDS()->Modified();
 }
@@ -1308,7 +1323,7 @@ bool SMESH_Mesh::HasModificationsToDiscard() const
   // return true if the next Compute() will be partial and
   // existing but changed elements may prevent successful re-compute
   bool hasComputed = false, hasNotComputed = false;
-SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
+  SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
   while ( smIt->more() )
   {
     const SMESH_subMesh* aSubMesh = smIt->next();
@@ -1323,6 +1338,8 @@ SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
         hasNotComputed = true;
       if ( hasComputed && hasNotComputed)
         return true;
+
+    default:;
     }
   }
   if ( NbNodes() < 1 )
@@ -1339,15 +1356,15 @@ SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
 
 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
 {
-  //set<string> aGroupNames; // Corrected for Mantis issue 0020028
+  // Corrected for Mantis issue 0020028
   map< SMDSAbs_ElementType, set<string> > aGroupNames;
   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
   {
-    SMESH_Group* aGroup = it->second;
+    SMESH_Group*       aGroup = it->second;
     SMDSAbs_ElementType aType = aGroup->GetGroupDS()->GetType();
-    string aGroupName = aGroup->GetName();
-    aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
-    if (!aGroupNames[aType].insert(aGroupName).second)
+    string         aGroupName = aGroup->GetName();
+    aGroupName.resize( MAX_MED_GROUP_NAME_LENGTH );
+    if ( !aGroupNames[aType].insert(aGroupName).second )
       return true;
   }
 
@@ -1369,6 +1386,8 @@ bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
      *         - 2D if all mesh nodes lie on XOY coordinate plane, or
      *         - 3D in the rest cases.
      *         If \a theAutoDimension is \c false, the space dimension is always 3.
+ *  \param [in] theAddODOnVertices - to create 0D elements on all vertices
+ *  \param [in] theAllElemsToGroup - to make every element to belong to any group (PAL23413)
  *  \return int - mesh index in the file
  */
 //================================================================================
@@ -1379,7 +1398,8 @@ void SMESH_Mesh::ExportMED(const char *        file,
                            int                 theVersion,
                            const SMESHDS_Mesh* meshPart,
                            bool                theAutoDimension,
-                           bool                theAddODOnVertices)
+                           bool                theAddODOnVertices,
+                           bool                theAllElemsToGroup)
   throw(SALOME_Exception)
 {
   SMESH_TRY;
@@ -1402,6 +1422,8 @@ void SMESH_Mesh::ExportMED(const char *        file,
     myWriter.AddGroupOfFaces();
     myWriter.AddGroupOfVolumes();
   }
+  if ( theAllElemsToGroup )
+    myWriter.AddAllToGroup();
 
   // Pass groups to writer. Provide unique group names.
   //set<string> aGroupNames; // Corrected for Mantis issue 0020028
@@ -1457,7 +1479,9 @@ void SMESH_Mesh::ExportSAUV(const char *file,
   cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
   cmd += "\"";
   system(cmd.c_str());
-  ExportMED(medfilename.c_str(), theMeshName, theAutoGroups, 1);
+  ExportMED(medfilename.c_str(), theMeshName, theAutoGroups, /*theVersion=*/1,
+            /*meshPart=*/NULL, /*theAutoDimension=*/false, /*theAddODOnVertices=*/false,
+            /*theAllElemsToGroup=*/true ); // theAllElemsToGroup is for PAL0023413
 #ifdef WIN32
   cmd = "%PYTHONBIN% ";
 #else
@@ -1608,7 +1632,7 @@ double SMESH_Mesh::GetComputeProgress() const
       const std::vector<SMESH_subMesh*>& smToCompute = algo->SubMeshesToCompute();
       for ( size_t i = 0; i < smToCompute.size(); ++i )
       {
-        if ( smToCompute[i]->IsEmpty() )
+        if ( smToCompute[i]->IsEmpty() || smToCompute.size() == 1 )
           algoNotDoneCost += smToCompute[i]->GetComputeCost();
         else
           algoDoneCost += smToCompute[i]->GetComputeCost();
@@ -1763,10 +1787,10 @@ int SMESH_Mesh::NbBiQuadQuadrangles() const throw(SALOME_Exception)
  */
 //================================================================================
 
-int SMESH_Mesh::NbPolygons() const throw(SALOME_Exception)
+int SMESH_Mesh::NbPolygons(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  return _myMeshDS->GetMeshInfo().NbPolygons();
+  return _myMeshDS->GetMeshInfo().NbPolygons(order);
 }
 
 //================================================================================
@@ -1984,8 +2008,8 @@ SMESH_Group* SMESH_Mesh::AddGroup (SMESHDS_GroupBase* groupDS) throw(SALOME_Exce
 
 bool SMESH_Mesh::SynchronizeGroups()
 {
-  int nbGroups = _mapGroup.size();
-  const set<SMESHDS_GroupBase*>& groups = _myMeshDS->GetGroups();
+  const size_t                       nbGroups = _mapGroup.size();
+  const set<SMESHDS_GroupBase*>&       groups = _myMeshDS->GetGroups();
   set<SMESHDS_GroupBase*>::const_iterator gIt = groups.begin();
   for ( ; gIt != groups.end(); ++gIt )
   {
@@ -2060,7 +2084,7 @@ void SMESH_Mesh::SetCallUp( TCallUp* upCaller )
  */
 //=============================================================================
 
-bool SMESH_Mesh::RemoveGroup (const int theGroupID)
+bool SMESH_Mesh::RemoveGroup( const int theGroupID )
 {
   if (_mapGroup.find(theGroupID) == _mapGroup.end())
     return false;
@@ -2096,11 +2120,11 @@ ostream& SMESH_Mesh::Dump(ostream& save)
 {
   int clause = 0;
   save << "========================== Dump contents of mesh ==========================" << endl << endl;
-  save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
-  save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
-  save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
-  save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
-  save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
+  save << ++clause << ") Total number of nodes:      \t" << NbNodes() << endl;
+  save << ++clause << ") Total number of edges:      \t" << NbEdges() << endl;
+  save << ++clause << ") Total number of faces:      \t" << NbFaces() << endl;
+  save << ++clause << ") Total number of polygons:   \t" << NbPolygons() << endl;
+  save << ++clause << ") Total number of volumes:    \t" << NbVolumes() << endl;
   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
   {
@@ -2135,10 +2159,10 @@ ostream& SMESH_Mesh::Dump(ostream& save)
       int nb4 = NbTetras(order);
       int nb5 = NbPyramids(order);
       int nb6 = NbPrisms(order);
-      save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
+      save << clause << ".1) Number of " << orderStr << " hexahedrons: \t" << nb8 << endl;
       save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
-      save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
+      save << clause << ".4) Number of " << orderStr << " pyramids:    \t" << nb5 << endl;
       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
         map<int,int> myVolumesMap;
         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
@@ -2299,27 +2323,31 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
  */
 //=============================================================================
 
- bool SMESH_Mesh::SortByMeshOrder(std::vector<SMESH_subMesh*>& theListToSort) const
+bool SMESH_Mesh::SortByMeshOrder(std::vector<SMESH_subMesh*>& theListToSort) const
 {
   if ( !_mySubMeshOrder.size() || theListToSort.size() < 2)
     return true;
   
   bool res = false;
-  vector<SMESH_subMesh*> onlyOrderedList;
+  vector<SMESH_subMesh*> onlyOrderedList, smVec;
+
   // collect all ordered submeshes in one list as pointers
   // and get their positions within theListToSort
   typedef vector<SMESH_subMesh*>::iterator TPosInList;
   map< int, TPosInList > sortedPos;
   TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end();
-  TListOfListOfInt::const_iterator listIdsIt = _mySubMeshOrder.begin();
+  TListOfListOfInt::const_iterator      listIdsIt = _mySubMeshOrder.begin();
   for( ; listIdsIt != _mySubMeshOrder.end(); listIdsIt++)
   {
     const TListOfInt& listOfId = *listIdsIt;
     // convert sm ids to sm's
-    vector<SMESH_subMesh*> smVec;
+    smVec.clear();
     TListOfInt::const_iterator idIt = listOfId.begin();
-    for ( ; idIt != listOfId.end(); idIt++ ) {
-      if ( SMESH_subMesh * sm = GetSubMeshContaining( *idIt )) {
+    for ( ; idIt != listOfId.end(); idIt++ )
+    {
+      if ( SMESH_subMesh * sm = GetSubMeshContaining( *idIt ))
+      {
+        smVec.push_back( sm );
         if ( sm->GetSubMeshDS() && sm->GetSubMeshDS()->IsComplexSubmesh() )
         {
           SMESHDS_SubMeshIteratorPtr smdsIt = sm->GetSubMeshDS()->GetSubMeshIterator();
@@ -2330,10 +2358,6 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
               smVec.push_back( sm );
           }
         }
-        else
-        {
-          smVec.push_back( sm );
-        }
       }
     }
     // find smVec items in theListToSort
@@ -2353,7 +2377,7 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
   vector<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
   vector<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
 
-  // iterate on ordered submeshes and insert them in detected positions
+  // iterate on ordered sub-meshes and insert them in detected positions
   map< int, TPosInList >::iterator i_pos = sortedPos.begin();
   for ( ; onlyBIt != onlyEIt; ++onlyBIt, ++i_pos )
     *(i_pos->second) = *onlyBIt;
@@ -2371,18 +2395,27 @@ bool SMESH_Mesh::IsOrderOK( const SMESH_subMesh* smBefore,
                             const SMESH_subMesh* smAfter ) const
 {
   TListOfListOfInt::const_iterator listIdsIt = _mySubMeshOrder.begin();
-  TListOfInt::const_iterator idBef, idAft;
   for( ; listIdsIt != _mySubMeshOrder.end(); listIdsIt++)
   {
     const TListOfInt& listOfId = *listIdsIt;
-    idBef = std::find( listOfId.begin(), listOfId.end(), smBefore->GetId() );
-    if ( idBef != listOfId.end() )
-      idAft = std::find( listOfId.begin(), listOfId.end(), smAfter->GetId() );
-    if ( idAft != listOfId.end () )
-      return ( std::distance( listOfId.begin(), idBef ) <
-               std::distance( listOfId.begin(), idAft )   );
+    int iB = -1, iA = -1, i = 0;
+    for ( TListOfInt::const_iterator id = listOfId.begin(); id != listOfId.end(); ++id, ++i )
+    {
+      if ( *id == smBefore->GetId() )
+      {
+        iB = i;
+        if ( iA > -1 )
+          return iB < iA;
+      }
+      else if ( *id == smAfter->GetId() )
+      {
+        iA = i;
+        if ( iB > -1 )
+          return iB < iA;
+      }
+    }
   }
-  return true; // no order imposed to given submeshes
+  return true; // no order imposed to given sub-meshes
 } 
 
 //=============================================================================