Salome HOME
#16648 [CEA] RadialQuadrangle algorithm hypothesis change requires a Clear Mesh Data...
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
index 4b3444adf88aac5c6ce8302169e94421adc00d10..7cc790b4442e2eaa9ff099aa3253a3b9f7842414 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2019  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
@@ -80,8 +80,6 @@
 #include <pthread.h>
 #endif
 
-using namespace std;
-
 // maximum stored group name length in MED file
 #define MAX_MED_GROUP_NAME_LENGTH 80
 
@@ -106,15 +104,13 @@ class SMESH_Mesh::SubMeshHolder : public SMESHDS_TSubMeshHolder< SMESH_subMesh >
 //=============================================================================
 
 SMESH_Mesh::SMESH_Mesh(int               theLocalId, 
-                       int               theStudyId, 
                        SMESH_Gen*        theGen,
                        bool              theIsEmbeddedMode,
                        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;
   _myDocument    = theDocument;
   _myMeshDS      = theDocument->NewMesh(theIsEmbeddedMode,theLocalId);
@@ -135,7 +131,6 @@ SMESH_Mesh::SMESH_Mesh(int               theLocalId,
 
 SMESH_Mesh::SMESH_Mesh():
   _id(-1),
-  _studyId(-1),
   _groupId( 0 ),
   _nbSubShapes( 0 ),
   _isShapeToMesh( false ),
@@ -179,7 +174,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();
@@ -192,7 +187,7 @@ SMESH_Mesh::~SMESH_Mesh()
     sm->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED );
 
   // delete groups
-  map < int, SMESH_Group * >::iterator itg;
+  std::map < int, SMESH_Group * >::iterator itg;
   for (itg = _mapGroup.begin(); itg != _mapGroup.end(); itg++) {
     SMESH_Group *aGroup = (*itg).second;
     delete aGroup;
@@ -208,7 +203,7 @@ SMESH_Mesh::~SMESH_Mesh()
   // remove self from studyContext
   if ( _gen )
   {
-    StudyContextStruct * studyContext = _gen->GetStudyContext( _studyId );
+    StudyContextStruct * studyContext = _gen->GetStudyContext();
     studyContext->mapMesh.erase( _id );
   }
   if ( _myDocument )
@@ -248,7 +243,7 @@ SMESH_Mesh* SMESH_Mesh::FindMesh( int meshId ) const
   if ( _id == meshId )
     return (SMESH_Mesh*) this;
 
-  if ( StudyContextStruct *aStudyContext = _gen->GetStudyContext( _studyId ))
+  if ( StudyContextStruct *aStudyContext = _gen->GetStudyContext())
   {
     std::map < int, SMESH_Mesh * >::iterator i_m = aStudyContext->mapMesh.find( meshId );
     if ( i_m != aStudyContext->mapMesh.end() )
@@ -279,7 +274,7 @@ void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
     // - sub-meshes
     _subMeshHolder->DeleteAll();
     //  - groups on geometry
-    map <int, SMESH_Group *>::iterator i_gr = _mapGroup.begin();
+    std::map <int, SMESH_Group *>::iterator i_gr = _mapGroup.begin();
     while ( i_gr != _mapGroup.end() ) {
       if ( dynamic_cast<SMESHDS_GroupOnGeom*>( i_gr->second->GetGroupDS() )) {
         _myMeshDS->RemoveGroup( i_gr->second->GetGroupDS() );
@@ -361,10 +356,20 @@ 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 {
+        OCC_CATCH_SIGNALS;
+        GEOMUtils::PreciseBoundingBox( aShape, Box );
+        isPrecise = true;
+      }
+      catch (...) {
+        isPrecise = false;
+      }
+    if ( !isPrecise )
+    {
+      BRepBndLib::Add( aShape, Box );
+    }
     if ( !Box.IsVoid() )
       return sqrt( Box.SquareExtent() );
   }
@@ -429,6 +434,7 @@ void SMESH_Mesh::Clear()
       sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
     }
   }
+  GetMeshDS()->Modified();
   _isModified = false;
 }
 
@@ -440,7 +446,7 @@ void SMESH_Mesh::Clear()
 
 void SMESH_Mesh::ClearSubMesh(const int theShapeId)
 {
-  // clear sub-meshes; get ready to re-compute as a side-effect 
+  // clear sub-meshes; get ready to re-compute as a side-effect
   if ( SMESH_subMesh *sm = GetSubMeshContaining( theShapeId ) )
   {
     SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
@@ -448,7 +454,7 @@ void SMESH_Mesh::ClearSubMesh(const int theShapeId)
     while ( smIt->more() )
     {
       sm = smIt->next();
-      TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();      
+      TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();
       if ( shapeType == TopAbs_VERTEX || shapeType < TopAbs_SOLID )
         // all other shapes depends on vertices so they are already cleaned
         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
@@ -460,92 +466,66 @@ void SMESH_Mesh::ClearSubMesh(const int theShapeId)
 
 //=======================================================================
 //function : UNVToMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 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) {
-    TGroupNamesMap aGroupNames = myReader.GetGroupNamesMap();
-    //const TGroupIdMap& aGroupId = myReader.GetGroupIdMap();
-    aGroup->InitSubGroupsIterator();
-    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);      
-        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);
-            }
-          }
-          if (aElement)
-            aGroupDS->SetType(aElement->GetType());
-        }
-      }
-    }
+
+  TGroupNamesMap& aGroupNames = myReader.GetGroupNamesMap();
+  TGroupNamesMap::iterator gr2names;
+  int anId = 1 + ( _mapGroup.empty() ? 0 : _mapGroup.rbegin()->first );
+  for ( gr2names = aGroupNames.begin(); gr2names != aGroupNames.end(); ++gr2names )
+  {
+    SMDS_MeshGroup*   aGroup = gr2names->first;
+    const std::string& aName = gr2names->second;
+    SMESHDS_Group* aGroupDS = new SMESHDS_Group( anId++, _myMeshDS, aGroup->GetType() );
+    aGroupDS->SMDSGroup() = std::move( *aGroup );
+    aGroupDS->SetStoreName( aName.c_str() );
+    AddGroup( aGroupDS );
   }
+
   return 1;
 }
 
 //=======================================================================
 //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() ) std::cout << er->myComment << std::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++ ) {
-    SMESH_Group* aGroup = AddGroup( name_type->second, name_type->first.c_str(), anId );
+  std::list<TNameAndType> aGroupNames = myReader.GetGroupNamesAndTypes();
+  std::list<TNameAndType>::iterator name_type = aGroupNames.begin();
+  for ( ; name_type != aGroupNames.end(); name_type++ )
+  {
+    SMESH_Group* aGroup = AddGroup( name_type->second, name_type->first.c_str() );
     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() );
@@ -553,32 +533,31 @@ int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
       }
     }
   }
+
+  _myMeshDS->Modified();
+  _myMeshDS->CompactMesh();
+
   return (int) status;
 }
 
 //=======================================================================
 //function : STLToMesh
-//purpose  : 
+//purpose  :
 //=======================================================================
 
-int SMESH_Mesh::STLToMesh(const char* theFileName)
+std::string 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;
+
+  return myReader.GetName();
 }
 
 //================================================================================
@@ -665,18 +644,18 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
     // NOTE: this is not a correct way to check a name of hypothesis,
     // there should be an attribute of hypothesis saying that it can/can't
     // be global/local
-    string hypName = anHyp->GetName();
+    std::string hypName = anHyp->GetName();
     if ( hypName == "NotConformAllowed" )
     {
-      if(MYDEBUG) MESSAGE( "Hypotesis <NotConformAllowed> can be only global" );
+      if(MYDEBUG) MESSAGE( "Hypothesis <NotConformAllowed> can be only global" );
       return SMESH_Hypothesis::HYP_INCOMPATIBLE;
     }
   }
 
   // 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);
 
@@ -704,14 +683,14 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
       }
     }
 
-    // check concurent hypotheses on ancestors
-    if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp )
+    // check concurrent hypotheses on ancestors
+    if (ret < SMESH_Hypothesis::HYP_CONCURRENT && !isGlobalHyp )
     {
       SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
       while ( smIt->more() ) {
         SMESH_subMesh* sm = smIt->next();
-        if ( sm->IsApplicableHypotesis( anHyp )) {
-          ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() );
+        if ( sm->IsApplicableHypothesis( anHyp )) {
+          ret2 = sm->CheckConcurrentHypothesis( anHyp->GetType() );
           if (ret2 > ret) {
             ret = ret2;
             break;
@@ -721,6 +700,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);
@@ -734,35 +714,33 @@ 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);
+
+  StudyContextStruct *sc = _gen->GetStudyContext();
   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);
 
   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
 
   // there may appear concurrent hyps that were covered by the removed hyp
-  if (ret < SMESH_Hypothesis::HYP_CONCURENT &&
-      subMesh->IsApplicableHypotesis( anHyp ) &&
-      subMesh->CheckConcurentHypothesis( anHyp->GetType() ) != SMESH_Hypothesis::HYP_OK)
-    ret = SMESH_Hypothesis::HYP_CONCURENT;
+  if (ret < SMESH_Hypothesis::HYP_CONCURRENT &&
+      subMesh->IsApplicableHypothesis( anHyp ) &&
+      subMesh->CheckConcurrentHypothesis( anHyp->GetType() ) != SMESH_Hypothesis::HYP_OK)
+    ret = SMESH_Hypothesis::HYP_CONCURRENT;
 
   // sub-shapes
   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
@@ -775,14 +753,14 @@ SMESH_Hypothesis::Hypothesis_Status
     if (ret2 > ret) // more severe
       ret = ret2;
 
-    // check concurent hypotheses on ancestors
-    if (ret < SMESH_Hypothesis::HYP_CONCURENT && !IsMainShape( aSubShape ) )
+    // check concurrent hypotheses on ancestors
+    if (ret < SMESH_Hypothesis::HYP_CONCURRENT && !IsMainShape( aSubShape ) )
     {
       SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
       while ( smIt->more() ) {
         SMESH_subMesh* sm = smIt->next();
-        if ( sm->IsApplicableHypotesis( anHyp )) {
-          ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() );
+        if ( sm->IsApplicableHypothesis( anHyp )) {
+          ret2 = sm->CheckConcurrentHypothesis( anHyp->GetType() );
           if (ret2 > ret) {
             ret = ret2;
             break;
@@ -793,6 +771,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);
@@ -805,7 +784,7 @@ SMESH_Hypothesis::Hypothesis_Status
  */
 //=============================================================================
 
-const list<const SMESHDS_Hypothesis*>&
+const std::list<const SMESHDS_Hypothesis*>&
 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
   throw(SALOME_Exception)
 {
@@ -852,8 +831,8 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const SMESH_subMesh *   aSubM
 
   {
     const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
-    const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
-    list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
+    const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
+    std::list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
     for ( ; hyp != hypList.end(); hyp++ ) {
       const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
       if ( aFilter.IsOk( h, aSubShape)) {
@@ -869,12 +848,12 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const SMESH_subMesh *   aSubM
       const_cast< std::vector< SMESH_subMesh * > & > ( aSubMesh->GetAncestors() );
     SortByMeshOrder( ancestors );
 
-    vector<SMESH_subMesh*>::const_iterator smIt = ancestors.begin(); 
+    std::vector<SMESH_subMesh*>::const_iterator smIt = ancestors.begin(); 
     for ( ; smIt != ancestors.end(); smIt++ )
     {
       const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
-      const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
-      list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
+      const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
+      std::list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
       for ( ; hyp != hypList.end(); hyp++ ) {
         const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
         if (aFilter.IsOk( h, curSh )) {
@@ -898,11 +877,11 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const SMESH_subMesh *   aSubM
  */
 //================================================================================
 
-int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
-                              const SMESH_HypoFilter&             aFilter,
-                              list <const SMESHDS_Hypothesis * >& aHypList,
-                              const bool                          andAncestors,
-                              list< TopoDS_Shape > *              assignedTo/*=0*/) const
+int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                     aSubShape,
+                              const SMESH_HypoFilter&                  aFilter,
+                              std::list <const SMESHDS_Hypothesis * >& aHypList,
+                              const bool                               andAncestors,
+                              std::list< TopoDS_Shape > *              assignedTo/*=0*/) const
 {
   return GetHypotheses( const_cast< SMESH_Mesh* >(this)->GetSubMesh( aSubShape ),
                         aFilter, aHypList, andAncestors, assignedTo );
@@ -919,22 +898,22 @@ int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
  */
 //================================================================================
 
-int SMESH_Mesh::GetHypotheses(const SMESH_subMesh *               aSubMesh,
-                              const SMESH_HypoFilter&             aFilter,
-                              list <const SMESHDS_Hypothesis * >& aHypList,
-                              const bool                          andAncestors,
-                              list< TopoDS_Shape > *              assignedTo/*=0*/) const
+int SMESH_Mesh::GetHypotheses(const SMESH_subMesh *                    aSubMesh,
+                              const SMESH_HypoFilter&                  aFilter,
+                              std::list <const SMESHDS_Hypothesis * >& aHypList,
+                              const bool                               andAncestors,
+                              std::list< TopoDS_Shape > *              assignedTo/*=0*/) const
 {
   if ( !aSubMesh ) return 0;
 
-  set<string> hypTypes; // to exclude same type hypos from the result list
+  std::set< std::string > hypTypes; // to exclude same type hypos from the result list
   int nbHyps = 0;
 
   // only one main hypothesis is allowed
   bool mainHypFound = false;
 
   // fill in hypTypes
-  list<const SMESHDS_Hypothesis*>::const_iterator hyp;
+  std::list<const SMESHDS_Hypothesis*>::const_iterator hyp;
   for ( hyp = aHypList.begin(); hyp != aHypList.end(); hyp++ ) {
     if ( hypTypes.insert( (*hyp)->GetName() ).second )
       nbHyps++;
@@ -945,7 +924,7 @@ int SMESH_Mesh::GetHypotheses(const SMESH_subMesh *               aSubMesh,
   // get hypos from aSubShape
   {
     const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
-    const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
+    const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
     for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
     {
       const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
@@ -970,11 +949,11 @@ int SMESH_Mesh::GetHypotheses(const SMESH_subMesh *               aSubMesh,
       const_cast< std::vector< SMESH_subMesh * > & > ( aSubMesh->GetAncestors() );
     SortByMeshOrder( ancestors );
 
-    vector<SMESH_subMesh*>::const_iterator smIt = ancestors.begin();
+    std::vector<SMESH_subMesh*>::const_iterator smIt = ancestors.begin();
     for ( ; smIt != ancestors.end(); smIt++ )
     {
       const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
-      const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
+      const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
       for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
       {
         const SMESH_Hypothesis* h = cSMESH_Hyp( *hyp );
@@ -1002,7 +981,7 @@ int SMESH_Mesh::GetHypotheses(const SMESH_subMesh *               aSubMesh,
 
 SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const int anHypId) const
 {
-  StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
+  StudyContextStruct *sc = _gen->GetStudyContext();
   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
     return NULL;
 
@@ -1016,10 +995,9 @@ SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const int anHypId) const
  */
 //=============================================================================
 
-const list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
+const std::list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
-  if(MYDEBUG) MESSAGE("SMESH_Mesh::GetLog");
   return _myMeshDS->GetScript()->GetCommands();
 }
 
@@ -1031,7 +1009,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();
 }
 
@@ -1041,7 +1018,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);
@@ -1049,7 +1026,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() )
     {
@@ -1088,7 +1066,7 @@ SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
 
 //=============================================================================
 /*!
- * Get the SMESH_subMesh object implementation. Dont create it, return null
+ * Get the SMESH_subMesh object implementation. Don't create it, return null
  * if it does not exist.
  */
 //=============================================================================
@@ -1102,7 +1080,7 @@ SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape)
 
 //=============================================================================
 /*!
- * Get the SMESH_subMesh object implementation. Dont create it, return null
+ * Get the SMESH_subMesh object implementation. Don't create it, return null
  * if it does not exist.
  */
 //=============================================================================
@@ -1117,22 +1095,22 @@ throw(SALOME_Exception)
 
 //================================================================================
 /*!
- * \brief Return submeshes of groups containing the given sub-shape
+ * \brief Return sub-meshes of groups containing the given sub-shape
  */
 //================================================================================
 
-list<SMESH_subMesh*>
+std::list<SMESH_subMesh*>
 SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
   throw(SALOME_Exception)
 {
-  list<SMESH_subMesh*> found;
+  std::list<SMESH_subMesh*> found;
 
   SMESH_subMesh * subMesh = GetSubMeshContaining(aSubShape);
   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();
@@ -1158,6 +1136,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;
 }
 //=======================================================================
@@ -1171,7 +1155,7 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
   SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
 
   // check if anHyp can be used to mesh aSubMesh
-  if ( !aSubMesh || !aSubMesh->IsApplicableHypotesis( hyp ))
+  if ( !aSubMesh || !aSubMesh->IsApplicableHypothesis( hyp ))
     return false;
 
   SMESH_Algo *algo = aSubMesh->GetAlgo();
@@ -1186,7 +1170,7 @@ bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
     // look trough hypotheses used by algo
     const SMESH_HypoFilter* hypoKind;
     if (( hypoKind = algo->GetCompatibleHypoFilter( !hyp->IsAuxiliary() ))) {
-      list <const SMESHDS_Hypothesis * > usedHyps;
+      std::list <const SMESHDS_Hypothesis * > usedHyps;
       if ( GetHypotheses( aSubMesh, *hypoKind, usedHyps, true ))
         return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
     }
@@ -1195,27 +1179,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
@@ -1228,57 +1191,82 @@ void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* h
   if ( !GetMeshDS()->IsUsedHypothesis( hyp ))
     return;
 
-  if (_callUp)
-    _callUp->HypothesisModified();
+  bool toCallBack = true;
+  if ( _callUp && hyp && NbNodes() == 0 ) // for not loaded mesh
+  {
+    _callUp->HypothesisModified( hyp->GetID() );
+    toCallBack = ( NbNodes() > 0 );
+  }
 
   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;
+  std::list <const SMESHDS_Hypothesis * > usedHyps;
+  std::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->IsApplicableHypothesis( 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();
+
+  if ( _callUp && hyp && toCallBack )
+    _callUp->HypothesisModified( hyp->GetID() );
 }
 
 //=============================================================================
@@ -1328,7 +1316,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();
@@ -1343,6 +1331,8 @@ SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
         hasNotComputed = true;
       if ( hasComputed && hasNotComputed)
         return true;
+
+    default:;
     }
   }
   if ( NbNodes() < 1 )
@@ -1351,6 +1341,41 @@ SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
   return false;
 }
 
+//=============================================================================
+/*!
+ * \brief Return true if all sub-meshes are computed OK - to update an icon
+ */
+//=============================================================================
+
+bool SMESH_Mesh::IsComputedOK()
+{
+  if ( NbNodes() == 0 )
+    return false;
+
+  // if ( !HasShapeToMesh() )
+  //   return true;
+
+  if ( SMESH_subMesh* mainSM = GetSubMeshContaining( 1 ))
+  {
+    SMESH_subMeshIteratorPtr smIt = mainSM->getDependsOnIterator(/*includeSelf=*/true);
+    while ( smIt->more() )
+    {
+      const SMESH_subMesh* sm = smIt->next();
+      if ( !sm->IsAlwaysComputed() )
+        switch ( sm->GetComputeState() )
+        {
+        case SMESH_subMesh::NOT_READY:
+        case SMESH_subMesh::COMPUTE_OK:
+          continue; // ok
+        case SMESH_subMesh::FAILED_TO_COMPUTE:
+        case SMESH_subMesh::READY_TO_COMPUTE:
+          return false;
+        }
+    }
+  }
+  return true;
+}
+
 //================================================================================
 /*!
  * \brief Check if any groups of the same type have equal names
@@ -1359,15 +1384,15 @@ SMESH_subMeshIteratorPtr smIt( _subMeshHolder->GetIterator() );
 
 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
 {
-  //set<string> aGroupNames; // Corrected for Mantis issue 0020028
-  map< SMDSAbs_ElementType, set<string> > aGroupNames;
-  for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
+  // Corrected for Mantis issue 0020028
+  std::map< SMDSAbs_ElementType, std::set< std::string > > aGroupNames;
+  for ( std::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)
+    std::string    aGroupName = aGroup->GetName();
+    aGroupName.resize( MAX_MED_GROUP_NAME_LENGTH );
+    if ( !aGroupNames[aType].insert(aGroupName).second )
       return true;
   }
 
@@ -1382,34 +1407,46 @@ bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
  *  \param [in] theAutoGroups - boolean parameter for creating/not creating
  *              the groups Group_On_All_Nodes, Group_On_All_Faces, ... ;
  *              the typical use is auto_groups=false.
- *  \param [in] theVersion - defines the version of format of MED file, that will be created
+ *  \param [in] theMinor - define the minor version (y, where version is x.y.z) of MED file format.
+ *              The theMinor must be between 0 and the current minor version of MED file library.
+ *              If theMinor is equal to -1, the minor version is not changed (default).
+ *              The major version (x, where version is x.y.z) cannot be changed.
  *  \param [in] meshPart - mesh data to export
  *  \param [in] theAutoDimension - if \c true, a space dimension of a MED mesh can be either
-     *         - 1D if all mesh nodes lie on OX coordinate axis, or
-     *         - 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.
+ *              - 1D if all mesh nodes lie on OX coordinate axis, or
+ *              - 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)
+ *  \param [in] ZTolerance - tolerance in Z direction. If Z coordinate of a node is close to zero
+ *              within a given tolerance, the coordinate is set to zero.
+ *              If \a ZTolerance is negative, the node coordinates are kept as is.
  *  \return int - mesh index in the file
  */
 //================================================================================
 
-void SMESH_Mesh::ExportMED(const char *        file, 
-                           const char*         theMeshName, 
+void SMESH_Mesh::ExportMED(const char *        file,
+                           const char*         theMeshName,
                            bool                theAutoGroups,
                            int                 theVersion,
                            const SMESHDS_Mesh* meshPart,
                            bool                theAutoDimension,
-                           bool                theAddODOnVertices)
-  throw(SALOME_Exception)
+                           bool                theAddODOnVertices,
+                           double              theZTolerance,
+                           bool                theAllElemsToGroup)
+throw(SALOME_Exception)
 {
+  MESSAGE("MED_VERSION:"<< theVersion);
   SMESH_TRY;
 
   DriverMED_W_SMESHDS_Mesh myWriter;
-  myWriter.SetFile         ( file, MED::EVersion(theVersion) );
+  myWriter.SetFile         ( file , theVersion);
   myWriter.SetMesh         ( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS   );
   myWriter.SetAutoDimension( theAutoDimension );
   myWriter.AddODOnVertices ( theAddODOnVertices );
-  if ( !theMeshName ) 
+  myWriter.SetZTolerance   ( theZTolerance );
+  if ( !theMeshName )
     myWriter.SetMeshId     ( _id         );
   else {
     myWriter.SetMeshId     ( -1          );
@@ -1421,23 +1458,29 @@ void SMESH_Mesh::ExportMED(const char *        file,
     myWriter.AddGroupOfEdges();
     myWriter.AddGroupOfFaces();
     myWriter.AddGroupOfVolumes();
+    myWriter.AddGroupOf0DElems();
+    myWriter.AddGroupOfBalls();
   }
+  if ( theAllElemsToGroup )
+    myWriter.AddAllToGroup();
 
   // Pass groups to writer. Provide unique group names.
   //set<string> aGroupNames; // Corrected for Mantis issue 0020028
   if ( !meshPart )
   {
-    map< SMDSAbs_ElementType, set<string> > aGroupNames;
+    std::map< SMDSAbs_ElementType, std::set<std::string> > aGroupNames;
     char aString [256];
     int maxNbIter = 10000; // to guarantee cycle finish
-    for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
+    for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin();
+          it != _mapGroup.end();
+          it++ ) {
       SMESH_Group*       aGroup   = it->second;
       SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
       if ( aGroupDS ) {
         SMDSAbs_ElementType aType = aGroupDS->GetType();
-        string aGroupName0 = aGroup->GetName();
+        std::string aGroupName0 = aGroup->GetName();
         aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
-        string aGroupName = aGroupName0;
+        std::string aGroupName = aGroupName0;
         for (int i = 1; !aGroupNames[aType].insert(aGroupName).second && i < maxNbIter; i++) {
           sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
           aGroupName = aString;
@@ -1471,17 +1514,19 @@ void SMESH_Mesh::ExportSAUV(const char *file,
 #ifdef WIN32
   cmd = "%PYTHONBIN% ";
 #else
-  cmd = "python ";
+  cmd = "python3 ";
 #endif
   cmd += "-c \"";
   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, /*minor=*/-1,
+            /*meshPart=*/NULL, /*theAutoDimension=*/false, /*theAddODOnVertices=*/false,
+            /*zTol=*/-1, /*theAllElemsToGroup=*/true ); // theAllElemsToGroup is for PAL0023413
 #ifdef WIN32
   cmd = "%PYTHONBIN% ";
 #else
-  cmd = "python ";
+  cmd = "python3 ";
 #endif
   cmd += "-c \"";
   cmd += "from medutilities import convert ; convert(r'" + medfilename + "', 'MED', 'GIBI', 1, r'" + file + "')";
@@ -1490,7 +1535,7 @@ void SMESH_Mesh::ExportSAUV(const char *file,
 #ifdef WIN32
   cmd = "%PYTHONBIN% ";
 #else
-  cmd = "python ";
+  cmd = "python3 ";
 #endif
   cmd += "-c \"";
   cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
@@ -1531,13 +1576,15 @@ void SMESH_Mesh::ExportUNV(const char *        file,
   myWriter.SetMeshId(_id);
   //  myWriter.SetGroups(_mapGroup);
 
+  // pass group names to SMESHDS
   if ( !meshPart )
   {
-    for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
+    std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin();
+    for ( ; it != _mapGroup.end(); it++ ) {
       SMESH_Group*       aGroup   = it->second;
       SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
       if ( aGroupDS ) {
-        string aGroupName = aGroup->GetName();
+        std::string aGroupName = aGroup->GetName();
         aGroupDS->SetStoreName( aGroupName.c_str() );
         myWriter.AddGroup( aGroupDS );
       }
@@ -1554,6 +1601,7 @@ void SMESH_Mesh::ExportUNV(const char *        file,
 
 void SMESH_Mesh::ExportSTL(const char *        file,
                            const bool          isascii,
+                           const char *        name,
                            const SMESHDS_Mesh* meshPart) throw(SALOME_Exception)
 {
   Unexpect aCatch(SalomeException);
@@ -1562,6 +1610,7 @@ void SMESH_Mesh::ExportSTL(const char *        file,
   myWriter.SetIsAscii( isascii );
   myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS);
   myWriter.SetMeshId(_id);
+  if ( name ) myWriter.SetName( name );
   myWriter.Perform();
 }
 
@@ -1573,17 +1622,38 @@ void SMESH_Mesh::ExportSTL(const char *        file,
 
 void SMESH_Mesh::ExportCGNS(const char *        file,
                             const SMESHDS_Mesh* meshDS,
-                            const char *        meshName)
+                            const char *        meshName,
+                            const bool          groupElemsByType)
 {
   int res = Driver_Mesh::DRS_FAIL;
+
+  // pass group names to SMESHDS
+  std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin();
+  for ( ; it != _mapGroup.end(); it++ ) {
+    SMESH_Group*       group   = it->second;
+    SMESHDS_GroupBase* groupDS = group->GetGroupDS();
+    if ( groupDS ) {
+      std::string groupName = group->GetName();
+      groupDS->SetStoreName( groupName.c_str() );
+    }
+  }
 #ifdef WITH_CGNS
+
   DriverCGNS_Write myWriter;
   myWriter.SetFile( file );
   myWriter.SetMesh( const_cast<SMESHDS_Mesh*>( meshDS ));
   myWriter.SetMeshName( SMESH_Comment("Mesh_") << meshDS->GetPersistentId());
   if ( meshName && meshName[0] )
     myWriter.SetMeshName( meshName );
+  myWriter.SetElementsByType( groupElemsByType );
   res = myWriter.Perform();
+  if ( res != Driver_Mesh::DRS_OK )
+  {
+    SMESH_ComputeErrorPtr err = myWriter.GetError();
+    if ( err && !err->IsOK() && !err->myComment.empty() )
+      throw SALOME_Exception(("Export failed: " + err->myComment ).c_str() );
+  }
+
 #endif
   if ( res != Driver_Mesh::DRS_OK )
     throw SALOME_Exception("Export failed");
@@ -1628,7 +1698,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();
@@ -1642,7 +1712,7 @@ double SMESH_Mesh::GetComputeProgress() const
       }
       catch (...) {
 #ifdef _DEBUG_
-        cerr << "Exception in " << algo->GetName() << "::GetProgress()" << endl;
+        std::cerr << "Exception in " << algo->GetName() << "::GetProgress()" << std::endl;
 #endif
       }
       if ( 0. < rate && rate < 1.001 )
@@ -1783,10 +1853,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);
 }
 
 //================================================================================
@@ -1861,6 +1931,19 @@ int SMESH_Mesh::NbPrisms(SMDSAbs_ElementOrder order) const throw(SALOME_Exceptio
   return _myMeshDS->GetMeshInfo().NbPrisms(order);
 }
 
+int SMESH_Mesh::NbQuadPrisms() const throw (SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  return _myMeshDS->GetMeshInfo().NbQuadPrisms();
+}
+
+int SMESH_Mesh::NbBiQuadPrisms() const throw (SALOME_Exception)
+{
+  Unexpect aCatch(SalomeException);
+  return _myMeshDS->GetMeshInfo().NbBiQuadPrisms();
+}
+
+
 //================================================================================
 /*!
  * \brief  Return number of hexagonal prisms in the mesh
@@ -1923,7 +2006,7 @@ int SMESH_Mesh::NbMeshes() const // nb meshes in the Study
 
 //=======================================================================
 //function : IsNotConformAllowed
-//purpose  : check if a hypothesis alowing notconform mesh is present
+//purpose  : check if a hypothesis allowing notconform mesh is present
 //=======================================================================
 
 bool SMESH_Mesh::IsNotConformAllowed() const
@@ -1952,16 +2035,17 @@ bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
 
 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
                                    const char*               theName,
-                                   int&                      theId,
+                                   const int                 theId,
                                    const TopoDS_Shape&       theShape,
                                    const SMESH_PredicatePtr& thePredicate)
 {
-  if (_mapGroup.count(_groupId))
+  if ( _mapGroup.count( theId ))
     return NULL;
-  theId = _groupId;
-  SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape, thePredicate);
+  int id = ( theId < 0 ) ? _groupId : theId;
+  SMESH_Group* aGroup = new SMESH_Group ( id, this, theType, theName, theShape, thePredicate );
   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
-  _mapGroup[_groupId++] = aGroup;
+  _mapGroup[ id ] = aGroup;
+  _groupId = 1 + _mapGroup.rbegin()->first;
   return aGroup;
 }
 
@@ -1973,10 +2057,10 @@ SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
 
 SMESH_Group* SMESH_Mesh::AddGroup (SMESHDS_GroupBase* groupDS) throw(SALOME_Exception)
 {
-  if ( !groupDS ) 
+  if ( !groupDS )
     throw SALOME_Exception(LOCALIZED ("SMESH_Mesh::AddGroup(): NULL SMESHDS_GroupBase"));
 
-  map <int, SMESH_Group*>::iterator i_g = _mapGroup.find( groupDS->GetID() );
+  std::map <int, SMESH_Group*>::iterator i_g = _mapGroup.find( groupDS->GetID() );
   if ( i_g != _mapGroup.end() && i_g->second )
   {
     if ( i_g->second->GetGroupDS() == groupDS )
@@ -1998,15 +2082,15 @@ SMESH_Group* SMESH_Mesh::AddGroup (SMESHDS_GroupBase* groupDS) throw(SALOME_Exce
 /*!
  * \brief Creates SMESH_Groups for not wrapped SMESHDS_Groups
  *  \retval bool - true if new SMESH_Groups have been created
- * 
+ *
  */
 //================================================================================
 
 bool SMESH_Mesh::SynchronizeGroups()
 {
-  int nbGroups = _mapGroup.size();
-  const set<SMESHDS_GroupBase*>& groups = _myMeshDS->GetGroups();
-  set<SMESHDS_GroupBase*>::const_iterator gIt = groups.begin();
+  const size_t                            nbGroups = _mapGroup.size();
+  const std::set<SMESHDS_GroupBase*>&       groups = _myMeshDS->GetGroups();
+  std::set<SMESHDS_GroupBase*>::const_iterator gIt = groups.begin();
   for ( ; gIt != groups.end(); ++gIt )
   {
     SMESHDS_GroupBase* groupDS = (SMESHDS_GroupBase*) *gIt;
@@ -2015,7 +2099,7 @@ bool SMESH_Mesh::SynchronizeGroups()
       _mapGroup[_groupId] = new SMESH_Group( groupDS );
   }
   if ( !_mapGroup.empty() )
-    _groupId = _mapGroup.rbegin()->first + 1;
+    _groupId = 1 + _mapGroup.rbegin()->first;
 
   return nbGroups < _mapGroup.size();
 }
@@ -2028,7 +2112,7 @@ bool SMESH_Mesh::SynchronizeGroups()
 
 SMESH_Mesh::GroupIteratorPtr SMESH_Mesh::GetGroups() const
 {
-  typedef map <int, SMESH_Group *> TMap;
+  typedef std::map <int, SMESH_Group *> TMap;
   return GroupIteratorPtr( new SMDS_mapIterator<TMap>( _mapGroup ));
 }
 
@@ -2038,11 +2122,12 @@ SMESH_Mesh::GroupIteratorPtr SMESH_Mesh::GetGroups() const
  */
 //=============================================================================
 
-SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
+SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID) const
 {
-  if (_mapGroup.find(theGroupID) == _mapGroup.end())
+  std::map <int, SMESH_Group*>::const_iterator id_grp = _mapGroup.find( theGroupID );
+  if ( id_grp == _mapGroup.end() )
     return NULL;
-  return _mapGroup[theGroupID];
+  return id_grp->second;
 }
 
 
@@ -2052,10 +2137,11 @@ SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
  */
 //=============================================================================
 
-list<int> SMESH_Mesh::GetGroupIds() const
+std::list<int> SMESH_Mesh::GetGroupIds() const
 {
-  list<int> anIds;
-  for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
+  std::list<int> anIds;
+  std::map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin();
+  for ( ; it != _mapGroup.end(); it++ )
     anIds.push_back( it->first );
   
   return anIds;
@@ -2080,7 +2166,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;
@@ -2095,7 +2181,7 @@ bool SMESH_Mesh::RemoveGroup (const int theGroupID)
 //=======================================================================
 //function : GetAncestors
 //purpose  : return list of ancestors of theSubShape in the order
-//           that lower dimention shapes come first.
+//           that lower dimension shapes come first.
 //=======================================================================
 
 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
@@ -2124,7 +2210,7 @@ ostream& SMESH_Mesh::Dump(ostream& save)
   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
   {
-    string orderStr = isQuadratic ? "quadratic" : "linear";
+    std::string orderStr = isQuadratic ? "quadratic" : "linear";
     SMDSAbs_ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
 
     save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
@@ -2135,7 +2221,7 @@ ostream& SMESH_Mesh::Dump(ostream& save)
       save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
       save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
       if ( nb3 + nb4 !=  NbFaces(order) ) {
-        map<int,int> myFaceMap;
+        std::map<int,int> myFaceMap;
         SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
         while( itFaces->more( ) ) {
           int nbNodes = itFaces->next()->NbNodes();
@@ -2144,9 +2230,9 @@ ostream& SMESH_Mesh::Dump(ostream& save)
           myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
         }
         save << clause << ".3) Faces in detail: " << endl;
-        map <int,int>::iterator itF;
+        std::map <int,int>::iterator itF;
         for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
-          save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
+          save << "--> nb nodes: " << itF->first << " - nb elements:\t" << itF->second << endl;
       }
     }
     save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
@@ -2160,7 +2246,7 @@ ostream& SMESH_Mesh::Dump(ostream& save)
       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
       save << clause << ".4) Number of " << orderStr << " pyramids:    \t" << nb5 << endl;
       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
-        map<int,int> myVolumesMap;
+        std::map<int,int> myVolumesMap;
         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
         while( itVolumes->more( ) ) {
           int nbNodes = itVolumes->next()->NbNodes();
@@ -2169,9 +2255,9 @@ ostream& SMESH_Mesh::Dump(ostream& save)
           myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
         }
         save << clause << ".5) Volumes in detail: " << endl;
-        map <int,int>::iterator itV;
+        std::map <int,int>::iterator itV;
         for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
-          save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
+          save << "--> nb nodes: " << itV->first << " - nb elements:\t" << itV->second << endl;
       }
     }
     save << endl;
@@ -2199,7 +2285,7 @@ SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem
 SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID )
 {
   SMESH_Group* aGroup = 0;
-  map < int, SMESH_Group * >::iterator itg = _mapGroup.find( theGroupID );
+  std::map < int, SMESH_Group * >::iterator itg = _mapGroup.find( theGroupID );
   if ( itg == _mapGroup.end() )
     return aGroup;
 
@@ -2319,27 +2405,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;
+  std::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;
+  typedef std::vector<SMESH_subMesh*>::iterator TPosInList;
+  std::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();
@@ -2350,10 +2440,6 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
               smVec.push_back( sm );
           }
         }
-        else
-        {
-          smVec.push_back( sm );
-        }
       }
     }
     // find smVec items in theListToSort
@@ -2361,8 +2447,9 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
     {
       TPosInList smPos = find( smBeg, smEnd, smVec[i] );
       if ( smPos != smEnd ) {
-        onlyOrderedList.push_back( smVec[i] );
-        sortedPos[ distance( smBeg, smPos )] = smPos;
+        sortedPos[ std::distance( smBeg, smPos )] = smPos;
+        if ( sortedPos.size() > onlyOrderedList.size() )
+          onlyOrderedList.push_back( smVec[i] );
       }
     }
   }
@@ -2370,11 +2457,11 @@ void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
     return res;
   res = true;
 
-  vector<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
-  vector<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
+  std::vector<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
+  std::vector<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
 
-  // iterate on ordered submeshes and insert them in detected positions
-  map< int, TPosInList >::iterator i_pos = sortedPos.begin();
+  // iterate on ordered sub-meshes and insert them in detected positions
+  std::map< int, TPosInList >::iterator i_pos = sortedPos.begin();
   for ( ; onlyBIt != onlyEIt; ++onlyBIt, ++i_pos )
     *(i_pos->second) = *onlyBIt;
 
@@ -2391,18 +2478,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
 } 
 
 //=============================================================================