Salome HOME
bos #26523 EDF 24234 - Viscous Layer
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
index f6877fa472404c875366b9c7cd7887e1adbeaa95..9fce23337f80410db0b0cc76714487d90492dd25 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2021  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
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
 
+#include <BRepPrimAPI_MakeBox.hxx>
+#include <BRepPrimAPI_MakeCylinder.hxx>
+#include <BRepPrimAPI_MakeSphere.hxx>
+#include <BRep_Tool.hxx>
+#include <OSD.hxx>
+#include <TColStd_MapOfAsciiString.hxx>
+#include <TCollection_AsciiString.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <TopoDS.hxx>
-#include <TopoDS_Iterator.hxx>
-#include <TopoDS_Compound.hxx>
 #include <TopoDS_CompSolid.hxx>
-#include <TopoDS_Solid.hxx>
-#include <TopoDS_Shell.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Wire.hxx>
+#include <TopoDS_Compound.hxx>
 #include <TopoDS_Edge.hxx>
-#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Iterator.hxx>
 #include <TopoDS_Shape.hxx>
-#include <TopTools_MapOfShape.hxx>
-#include <TopTools_IndexedMapOfShape.hxx>
-#include <TopTools_ListOfShape.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Solid.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
 #include <gp_Pnt.hxx>
-#include <BRep_Tool.hxx>
-#include <TCollection_AsciiString.hxx>
-#include <OSD.hxx>
-#include <BRepPrimAPI_MakeSphere.hxx>
-#include <BRepPrimAPI_MakeCylinder.hxx>
-#include <BRepPrimAPI_MakeBox.hxx>
-
 
 #ifdef WIN32
  #include <windows.h>
@@ -84,7 +84,6 @@
 #include "MED_Factory.hxx"
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_FacePosition.hxx"
-#include "SMDS_PolyhedralVolumeOfNodes.hxx"
 #include "SMDS_SetIterator.hxx"
 #include "SMDS_SpacePosition.hxx"
 #include "SMDS_VertexPosition.hxx"
 #include "SMESH_PreMeshInfo.hxx"
 #include "SMESH_PythonDump.hxx"
 #include "SMESH_ControlsDef.hxx"
+#include <SMESH_BoostTxtArchive.hxx>
+
+// to pass CORBA exception through SMESH_TRY
+#define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
 #include "SMESH_TryCatch.hxx" // to include after OCC headers!
 
 #include CORBA_SERVER_HEADER(SMESH_Group)
 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
 
 
+#include <GEOMImpl_Types.hxx>
 #include <GEOM_Client.hxx>
 
 #include <Basics_Utils.hxx>
 
 #include <map>
 #include <fstream>
+#include <sstream>
 #include <cstdio>
 #include <cstdlib>
+#include <memory>
+
+#include <boost/archive/text_oarchive.hpp>
+#include <boost/serialization/list.hpp>
+#include <boost/serialization/string.hpp>
 
 using namespace std;
 using SMESH::TPythonDump;
@@ -151,12 +161,12 @@ static int MYDEBUG = 0;
 #endif
 
 // Static variables definition
-GEOM::GEOM_Gen_var      SMESH_Gen_i::myGeomGen = GEOM::GEOM_Gen::_nil();
+GEOM::GEOM_Gen_var      SMESH_Gen_i::myGeomGen;
 CORBA::ORB_var          SMESH_Gen_i::myOrb;
 PortableServer::POA_var SMESH_Gen_i::myPoa;
-SALOME_NamingService*   SMESH_Gen_i::myNS  = NULL;
-SALOME_LifeCycleCORBA*  SMESH_Gen_i::myLCC = NULL;
-SMESH_Gen_i*            SMESH_Gen_i::mySMESHGen = NULL;
+SALOME_NamingService_Abstract*   SMESH_Gen_i::myNS  = nullptr;
+SALOME_LifeCycleCORBA*  SMESH_Gen_i::myLCC = nullptr;
+SMESH_Gen_i*            SMESH_Gen_i::mySMESHGen = nullptr;
 
 
 const int nbElemPerDiagonal = 10;
@@ -177,8 +187,24 @@ PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theOb
     PortableServer::Servant aServant = GetPOA()->reference_to_servant( theObject );
     return aServant;
   }
-  catch (...) {
-    INFOS( "GetServant - Unknown exception was caught!!!" );
+  catch (PortableServer::POA::ObjectNotActive &ex)
+  {
+    MESSAGE("GetServant: ObjectNotActive");
+    return NULL;
+  }
+  catch (PortableServer::POA::WrongAdapter &ex)
+  {
+    MESSAGE("GetServant: WrongAdapter: OK when several servants used to build several mesh in parallel...");
+    return NULL;
+  }
+  catch (PortableServer::POA::WrongPolicy &ex)
+  {
+    MESSAGE("GetServant: WrongPolicy");
+    return NULL;
+  }
+  catch (...)
+  {
+    MESSAGE( "GetServant - Unknown exception was caught!!!" );
     return NULL;
   }
 }
@@ -211,6 +237,14 @@ CORBA::Object_var SMESH_Gen_i::SObjectToObject( SALOMEDS::SObject_ptr theSObject
   return anObj;
 }
 
+// Set Naming Service object
+void SMESH_Gen_i::SetNS(SALOME_NamingService_Abstract *ns)
+{
+  if(myNS)
+    delete myNS;
+  myNS = ns;
+}
+
 //=============================================================================
 /*!
  *  GetNS [ static ]
@@ -219,9 +253,9 @@ CORBA::Object_var SMESH_Gen_i::SObjectToObject( SALOMEDS::SObject_ptr theSObject
  */
 //=============================================================================
 
-SALOME_NamingService* SMESH_Gen_i::GetNS()
+SALOME_NamingService_Abstract* SMESH_Gen_i::GetNS()
 {
-  if ( myNS == NULL ) {
+  if ( !myNS ) {
     myNS = SINGLETON_<SALOME_NamingService>::Instance();
     ASSERT(SINGLETON_<SALOME_NamingService>::IsAlreadyExisting());
     myNS->init_orb( GetORB() );
@@ -236,14 +270,15 @@ SALOME_NamingService* SMESH_Gen_i::GetNS()
  *  Get SALOME_LifeCycleCORBA object
  */
 //=============================================================================
-SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC() {
+
+SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC()
+{
   if ( myLCC == NULL ) {
     myLCC = new SALOME_LifeCycleCORBA( GetNS() );
   }
   return myLCC;
 }
 
-
 //=============================================================================
 /*!
  *  GetGeomEngine [ static ]
@@ -251,16 +286,13 @@ SALOME_LifeCycleCORBA*  SMESH_Gen_i::GetLCC() {
  *  Get GEOM::GEOM_Gen reference
  */
 //=============================================================================
-GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine() {
-  //CCRT GEOM::GEOM_Gen_var aGeomEngine =
-  //CCRT   GEOM::GEOM_Gen::_narrow( GetLCC()->FindOrLoad_Component("FactoryServer","GEOM") );
-  //CCRT return aGeomEngine._retn();
-  if(CORBA::is_nil(myGeomGen))
-  {
-    Engines::EngineComponent_ptr temp=GetLCC()->FindOrLoad_Component("FactoryServer","GEOM");
-    myGeomGen=GEOM::GEOM_Gen::_narrow(temp);
-  }
-  return myGeomGen;
+
+GEOM::GEOM_Gen_var SMESH_Gen_i::GetGeomEngine( GEOM::GEOM_Object_ptr go )
+{
+  GEOM::GEOM_Gen_ptr gen = GEOM::GEOM_Gen::_nil();
+  if ( !CORBA::is_nil( go ))
+    gen = go->GetGen();
+  return gen;
 }
 
 //=============================================================================
@@ -287,8 +319,9 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
                           PortableServer::POA_ptr   poa,
                           PortableServer::ObjectId* contId,
                           const char*               instanceName,
-                          const char*               interfaceName )
-  : Engines_Component_i( orb, poa, contId, instanceName, interfaceName )
+                          const char*               interfaceName,
+                          bool                      checkNS)
+  : Engines_Component_i( orb, poa, contId, instanceName, interfaceName, false, checkNS )
 {
 
   myOrb = CORBA::ORB::_duplicate(orb);
@@ -297,7 +330,10 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
   _thisObj = this ;
   _id = myPoa->activate_object( _thisObj );
 
+  myStudyContext = new StudyContext;
+
   myIsEmbeddedMode = false;
+  myIsEnablePublish = true;
   myShapeReader = NULL;  // shape reader
   mySMESHGen = this;
   myIsHistoricalPythonDump = true;
@@ -310,21 +346,24 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
   // find out mode (embedded or standalone) here else
   // meshes created before calling SMESH_Client::GetSMESHGen(), which calls
   // SMESH_Gen_i::SetEmbeddedMode(), have wrong IsEmbeddedMode flag
-  if ( SALOME_NamingService* ns = GetNS() )
+  if(checkNS)
   {
-    CORBA::Object_var obj = ns->Resolve( "/Kernel/Session" );
-    SALOME::Session_var session = SALOME::Session::_narrow( obj ) ;
-    if ( !session->_is_nil() )
+    if ( SALOME_NamingService_Abstract* ns = GetNS() )
     {
-      CORBA::String_var str_host = session->getHostname();
-      CORBA::Long        s_pid = session->getPID();
-      string my_host = Kernel_Utils::GetHostname();
+      CORBA::Object_var obj = ns->Resolve( "/Kernel/Session" );
+      SALOME::Session_var session = SALOME::Session::_narrow( obj ) ;
+      if ( !session->_is_nil() )
+      {
+        CORBA::String_var str_host = session->getHostname();
+        CORBA::Long        s_pid = session->getPID();
+        string my_host = Kernel_Utils::GetHostname();
 #ifdef WIN32
-      long    my_pid = (long)_getpid();
+        long    my_pid = (long)_getpid();
 #else
-      long    my_pid = (long) getpid();
+        long    my_pid = (long) getpid();
 #endif
-      SetEmbeddedMode( s_pid == my_pid && my_host == str_host.in() );
+        SetEmbeddedMode( s_pid == my_pid && my_host == str_host.in() );
+      }
     }
   }
 }
@@ -355,15 +394,13 @@ SMESH_Gen_i::~SMESH_Gen_i()
   myHypCreatorMap.clear();
 
   // Clear study contexts data
-  map<int, StudyContext*>::iterator it;
-  for ( it = myStudyContextMap.begin(); it != myStudyContextMap.end(); ++it ) {
-    delete it->second;
-  }
-  myStudyContextMap.clear();
+  delete myStudyContext;
+
   // delete shape reader
   if ( myShapeReader )
     delete myShapeReader;
 }
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::getHypothesisCreator
@@ -371,13 +408,13 @@ SMESH_Gen_i::~SMESH_Gen_i()
  *  Get hypothesis creator
  */
 //=============================================================================
+
 GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHypName,
                                                               const char* theLibName,
                                                               std::string& thePlatformLibName)
-  throw (SALOME::SALOME_Exception)
 {
   std::string aPlatformLibName;
-  /* It's Need to tranlate lib name for WIN32 or X platform */
+  /* It's Need to translate lib name for WIN32 or X platform */
   if ( theLibName && theLibName[0] != '\0'  )
   {
     int libNameLen = strlen(theLibName);
@@ -422,15 +459,27 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
     {
       // load plugin library
       if(MYDEBUG) MESSAGE("Loading server meshers plugin library ...");
-      LibHandle libHandle = LoadLib( aPlatformLibName.c_str() );
+#ifdef WIN32
+#  ifdef UNICODE
+      const wchar_t* path = Kernel_Utils::decode_s(aPlatformLibName);
+      SMESHUtils::ArrayDeleter<const wchar_t> deleter( path );
+#  else
+      const char* path = aPlatformLibName.c_str();
+#  endif
+#else
+      const char* path = aPlatformLibName.c_str();
+#endif
+      LibHandle libHandle = LoadLib( path );
+
       if (!libHandle)
       {
         // report any error, if occurred
 #ifndef WIN32
         const char* anError = dlerror();
-        throw(SALOME_Exception(anError));
+        throw(SALOME_Exception( anError ));
 #else
-        throw(SALOME_Exception(LOCALIZED( "Can't load server meshers plugin library" )));
+        throw(SALOME_Exception ( SMESH_Comment("Can't load meshers plugin library " )
+                                 << aPlatformLibName));
 #endif
       }
 
@@ -440,7 +489,8 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
         (GetHypothesisCreator)GetProc( libHandle, "GetHypothesisCreator" );
       if (!procHandle)
       {
-        throw(SALOME_Exception(LOCALIZED("bad hypothesis plugin library")));
+        throw(SALOME_Exception(SMESH_Comment("bad hypothesis plugin library")
+                               << aPlatformLibName ));
         UnLoadLib(libHandle);
       }
 
@@ -449,7 +499,8 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
       aCreator = procHandle(theHypName);
       if (!aCreator)
       {
-        throw(SALOME_Exception(LOCALIZED("no such a hypothesis in this plugin")));
+        throw(SALOME_Exception( SMESH_Comment( theHypName ) << " is missing from "
+                                << aPlatformLibName));
       }
       // map hypothesis creator to a hypothesis name
       myHypCreatorMap[string(theHypName)] = aCreator;
@@ -474,6 +525,7 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
  *  Create hypothesis of given type
  */
 //=============================================================================
+
 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName,
                                                           const char* theLibName)
 {
@@ -484,7 +536,7 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
     getHypothesisCreator(theHypName, theLibName, aPlatformLibName);
 
   // create a new hypothesis object, store its ref. in studyContext
-  myHypothesis_i = aCreator->Create(myPoa, GetCurrentStudyID(), &myGen);
+  myHypothesis_i = aCreator->Create(myPoa, &myGen);
   if (myHypothesis_i)
   {
     myHypothesis_i->SetLibName( aPlatformLibName.c_str() ); // for persistency assurance
@@ -495,7 +547,7 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
     hypothesis_i = myHypothesis_i->_this();
     int nextId = RegisterObject( hypothesis_i );
     if(MYDEBUG) { MESSAGE( "Add hypo to map with id = "<< nextId ); }
-    else        { nextId = 0; } // avoid "unused variable" warning in release mode
+    else        { (void)nextId; } // avoid "unused variable" warning in release mode
   }
   return hypothesis_i._retn();
 }
@@ -507,8 +559,8 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
  *  Create empty mesh on shape
  */
 //=============================================================================
+
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::createMesh" );
@@ -516,16 +568,16 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
   // Get or create the GEOM_Client instance
   try {
     // create a new mesh object servant, store it in a map in study context
-    SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this, GetCurrentStudyID() );
+    SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this );
     // create a new mesh object
     if(MYDEBUG) MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
-    meshServant->SetImpl( myGen.CreateMesh( GetCurrentStudyID(), myIsEmbeddedMode ));
+    meshServant->SetImpl( myGen.CreateMesh( myIsEmbeddedMode ));
 
     // activate the CORBA servant of Mesh
     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( meshServant->_this() );
     int nextId = RegisterObject( mesh );
     if(MYDEBUG) { MESSAGE( "Add mesh to map with id = "<< nextId); }
-    else        { nextId = 0; } // avoid "unused variable" warning in release mode
+    else        { (void)nextId; } // avoid "unused variable" warning in release mode
     return mesh._retn();
   }
   catch (SALOME_Exception& S_ex) {
@@ -541,6 +593,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
  *  Get shape reader
  */
 //=============================================================================
+
 GEOM_Client* SMESH_Gen_i::GetShapeReader()
 {
   // create shape reader if necessary
@@ -557,13 +610,10 @@ GEOM_Client* SMESH_Gen_i::GetShapeReader()
  *  Set GEOM::GEOM_Gen reference
  */
 //=============================================================================
-//GEOM::GEOM_Gen_ptr SMESH_Gen_i::SetGeomEngine( const char* containerLoc )
+
 void SMESH_Gen_i::SetGeomEngine( GEOM::GEOM_Gen_ptr geomcompo )
 {
-  //Engines::Component_ptr temp=GetLCC()->FindOrLoad_Component(containerLoc,"GEOM");
-  //myGeomGen=GEOM::GEOM_Gen::_narrow(temp);
-  myGeomGen=GEOM::GEOM_Gen::_duplicate(geomcompo);
-  //return myGeomGen;
+  myGeomGen = GEOM::GEOM_Gen::_duplicate( geomcompo );
 }
 
 //=============================================================================
@@ -613,95 +663,152 @@ CORBA::Boolean SMESH_Gen_i::IsEmbeddedMode()
 
 //=============================================================================
 /*!
- *  SMESH_Gen_i::SetCurrentStudy
+ *  SMESH_Gen_i::SetEnablePublish
+ *
+ *  Set enable publishing in the study
+ */
+//=============================================================================
+
+void SMESH_Gen_i::SetEnablePublish( CORBA::Boolean theIsEnablePublish )
+{
+  myIsEnablePublish = theIsEnablePublish;
+}
+
+//=============================================================================
+/*!
+ *  SMESH_Gen_i::IsEnablePublish
  *
- *  Set current study
+ *  Check enable publishing
  */
 //=============================================================================
 
-void SMESH_Gen_i::SetCurrentStudy( SALOMEDS::Study_ptr theStudy )
+CORBA::Boolean SMESH_Gen_i::IsEnablePublish()
 {
-  setCurrentStudy( theStudy );
+  return myIsEnablePublish;
 }
 
-void SMESH_Gen_i::setCurrentStudy( SALOMEDS::Study_ptr theStudy,
-                                   bool                theStudyIsBeingClosed)
+//=============================================================================
+/*!
+ *  SMESH_Gen_i::UpdateStudy
+ *
+ *  Update study (needed at switching GEOM->SMESH)
+ */
+//=============================================================================
+
+void SMESH_Gen_i::UpdateStudy()
 {
-  int curStudyId = GetCurrentStudyID();
-  myCurrentStudy = SALOMEDS::Study::_duplicate( theStudy );
-  // create study context, if it doesn't exist and set current study
-  int studyId = GetCurrentStudyID();
-  if ( myStudyContextMap.find( studyId ) == myStudyContextMap.end() )
-    myStudyContextMap[ studyId ] = new StudyContext;
-
-  // myCurrentStudy may be nil
-  if ( !theStudyIsBeingClosed && !CORBA::is_nil( myCurrentStudy ) ) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
-    SALOMEDS::SComponent_wrap GEOM_var = myCurrentStudy->FindComponent( "GEOM" );
+  if ( !myStudyContext )
+    myStudyContext = new StudyContext;
+
+  SALOMEDS::Study_var aStudy = getStudyServant();
+  if ( !CORBA::is_nil( aStudy ) )
+  {
+    SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
+
+    SALOMEDS::SComponent_wrap GEOM_var = aStudy->FindComponent( "GEOM" );
+    if( !GEOM_var->_is_nil() )
+      aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine( /*isShaper=*/false ) );
+
+    GEOM_var = aStudy->FindComponent( "SHAPERSTUDY" );
     if( !GEOM_var->_is_nil() )
-      aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine() );
+      aStudyBuilder->LoadWith( GEOM_var, GetGeomEngine( /*isShaper=*/true ) );
+
     // NPAL16168, issue 0020210
     // Let meshes update their data depending on GEOM groups that could change
-    if ( curStudyId != studyId )
-    {
-      CORBA::String_var compDataType = ComponentDataType();
-      SALOMEDS::SComponent_wrap me = myCurrentStudy->FindComponent( compDataType.in() );
-      if ( !me->_is_nil() ) {
-        SALOMEDS::ChildIterator_wrap anIter = myCurrentStudy->NewChildIterator( me );
-        for ( ; anIter->More(); anIter->Next() ) {
-          SALOMEDS::SObject_wrap so = anIter->Value();
-          CORBA::Object_var     ior = SObjectToObject( so );
-          if ( SMESH_Mesh_i*   mesh = SMESH::DownCast<SMESH_Mesh_i*>( ior ))
-            mesh->CheckGeomModif();
-        }
+    CORBA::String_var compDataType = ComponentDataType();
+    SALOMEDS::SComponent_wrap me = aStudy->FindComponent( compDataType.in() );
+    if ( !me->_is_nil() ) {
+      SALOMEDS::ChildIterator_wrap anIter = aStudy->NewChildIterator( me );
+      for ( ; anIter->More(); anIter->Next() ) {
+        SALOMEDS::SObject_wrap so = anIter->Value();
+        CORBA::Object_var     ior = SObjectToObject( so );
+        if ( SMESH_Mesh_i*   mesh = SMESH::DownCast<SMESH_Mesh_i*>( ior ))
+          mesh->CheckGeomModif();
       }
     }
   }
 }
 
-//=============================================================================
+//================================================================================
 /*!
- *  SMESH_Gen_i::GetCurrentStudy
- *
- *  Get current study
+ * \brief Return true if mesh has ICON_SMESH_TREE_GEOM_MODIF icon
  */
-//=============================================================================
+//================================================================================
+
+bool SMESH_Gen_i::isGeomModifIcon( SMESH::SMESH_Mesh_ptr mesh )
+{
+  SALOMEDS::SObject_wrap so = ObjectToSObject( mesh );
+  SALOMEDS::GenericAttribute_wrap attr;
+  if ( ! so->_is_nil() && so->FindAttribute( attr.inout(), "AttributePixMap" ))
+  {
+    SALOMEDS::AttributePixMap_wrap pm = attr;
+    CORBA::String_var             ico = pm->GetPixMap();
+    return ( strcmp( ico.in(), "ICON_SMESH_TREE_GEOM_MODIF" ) == 0 );
+  }
+  return false;
+}
+
+//=================================================================================
+// function : hasObjectInfo()
+// purpose  : shows if module provides information for its objects
+//=================================================================================
+
+bool SMESH_Gen_i::hasObjectInfo()
+{
+  return true;
+}
+
+//=================================================================================
+// function : getObjectInfo()
+// purpose  : returns an information for a given object by its entry
+//=================================================================================
 
-SALOMEDS::Study_ptr SMESH_Gen_i::GetCurrentStudy()
+char* SMESH_Gen_i::getObjectInfo( const char* entry )
 {
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetCurrentStudy: study Id = " << GetCurrentStudyID() );
-  if ( GetCurrentStudyID() < 0 )
-    return SALOMEDS::Study::_nil();
-  return SALOMEDS::Study::_duplicate( myCurrentStudy );
+  // for a mesh with icon == ICON_SMESH_TREE_GEOM_MODIF show a warning;
+  // for the rest, "module 'SMESH', ID=0:1:2:*"
+
+  SMESH_Comment txt;
+
+  SALOMEDS::SObject_wrap  so = getStudyServant()->FindObjectID( entry );
+  CORBA::Object_var      obj = SObjectToObject( so );
+  SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( obj );
+  if ( isGeomModifIcon( mesh ))
+  {
+    txt << "The geometry was changed and the mesh needs to be recomputed";
+  }
+
+  if ( txt.empty() )
+  {
+    CORBA::String_var compType = ComponentDataType();
+    txt << "module '" << compType << "', ID=" << entry;
+  }
+  return CORBA::string_dup( txt );
 }
 
 //=============================================================================
 /*!
- *  SMESH_Gen_i::GetCurrentStudyContext
+ *  SMESH_Gen_i::GetStudyContext
  *
- *  Get current study context
+ *  Get study context
  */
 //=============================================================================
-StudyContext* SMESH_Gen_i::GetCurrentStudyContext()
+
+StudyContext* SMESH_Gen_i::GetStudyContext()
 {
-  if ( !CORBA::is_nil( myCurrentStudy ) &&
-       myStudyContextMap.find( GetCurrentStudyID() ) != myStudyContextMap.end() )
-    return myStudyContextMap[ myCurrentStudy->StudyId() ];
-  else
-    return 0;
+  return myStudyContext;
 }
 
 //=============================================================================
 /*!
  *  SMESH_Gen_i::CreateHypothesis
  *
- *  Create hypothesis/algorothm of given type and publish it in the study
+ *  Create hypothesis/algorithm of given type and publish it in the study
  */
 //=============================================================================
 
 SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypName,
                                                            const char* theLibName )
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   // Create hypothesis/algorithm
@@ -709,10 +816,10 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam
 
   // Publish hypothesis/algorithm in the study
   if ( CanPublishInStudy( hyp ) ) {
-    SALOMEDS::SObject_wrap aSO = PublishHypothesis( myCurrentStudy, hyp );
+    SALOMEDS::SObject_wrap aSO = PublishHypothesis( hyp );
     if ( !aSO->_is_nil() ) {
       // Update Python script
-      TPythonDump() << aSO << " = " << this << ".CreateHypothesis('"
+      TPythonDump(this) << aSO << " = " << this << ".CreateHypothesis('"
                     << theHypName << "', '" << theLibName << "')";
     }
   }
@@ -720,6 +827,42 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam
   return hyp._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Return a hypothesis initialized by given average length.
+ *  \param theHypType - hypothesis type name
+ *  \param theLibName - plugin library name
+ *  \param theAverageLength - average length
+ *  \param theQuadDominated - is quad-dominated flag
+ *  \retval SMESH::SMESH_Hypothesis_ptr - the new hypothesis
+ */
+//================================================================================
+
+SMESH::SMESH_Hypothesis_ptr
+SMESH_Gen_i::CreateHypothesisByAverageLength( const char*    theHypType,
+                                              const char*    theLibName,
+                                              CORBA::Double  theAverageLength,
+                                              CORBA::Boolean theQuadDominated)
+{
+  SMESH::HypInitParams initParams = { ::SMESH_Hypothesis::BY_AVERAGE_LENGTH,
+                                      theAverageLength, theQuadDominated };
+
+  SMESH::SMESH_Hypothesis_var hyp =
+    GetHypothesisParameterValues( theHypType, theLibName,
+                                  SMESH::SMESH_Mesh::_nil(),
+                                  GEOM::GEOM_Object::_nil(),
+                                  initParams );
+  SALOMEDS::SObject_wrap so = PublishHypothesis( hyp );
+
+  TPythonDump(this) << hyp << " = " << this << ".CreateHypothesisByAverageLength( '"
+                << theHypType << "', '"
+                << theLibName << "', "
+                << theAverageLength << ", "
+                << theQuadDominated << " )";
+
+  return hyp._retn();
+}
+
 //================================================================================
 /*!
  * \brief Return a hypothesis holding parameter values corresponding either to the mesh
@@ -735,14 +878,15 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::CreateHypothesis( const char* theHypNam
 //================================================================================
 
 SMESH::SMESH_Hypothesis_ptr
-SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
-                                           const char*           theLibName,
-                                           SMESH::SMESH_Mesh_ptr theMesh,
-                                           GEOM::GEOM_Object_ptr theGeom,
-                                           CORBA::Boolean        byMesh)
-  throw ( SALOME::SALOME_Exception )
+SMESH_Gen_i::GetHypothesisParameterValues( const char*                 theHypType,
+                                           const char*                 theLibName,
+                                           SMESH::SMESH_Mesh_ptr       theMesh,
+                                           GEOM::GEOM_Object_ptr       theGeom,
+                                           const SMESH::HypInitParams& theParams)
 {
   Unexpect aCatch(SALOME_SalomeException);
+
+  const bool byMesh = ( theParams.way == ::SMESH_Hypothesis::BY_MESH );
   if ( byMesh && CORBA::is_nil( theMesh ) )
     return SMESH::SMESH_Hypothesis::_nil();
   if ( byMesh && CORBA::is_nil( theGeom ) )
@@ -797,17 +941,24 @@ SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
     if ( hyp->SetParametersByMesh( mesh, shape ))
       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
   }
-  else {
-    double diagonal = 0;
-    if ( mesh )
-      diagonal = mesh->GetShapeDiagonalSize();
-    else
-      diagonal = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
+  else
+  {
     ::SMESH_Hypothesis::TDefaults dflts;
-    dflts._elemLength = diagonal / myGen.GetBoundaryBoxSegmentation();
-    dflts._nbSegments = myGen.GetDefaultNbSegments();
-    dflts._shape      = &shape;
-    // let the temporary hypothesis initialize it's values
+    dflts._way           = ( ::SMESH_Hypothesis::InitWay) theParams.way;
+    dflts._nbSegments    = myGen.GetDefaultNbSegments();
+    dflts._elemLength    = theParams.averageLength;
+    dflts._quadDominated = theParams.quadDominated;
+    if ( theParams.way == ::SMESH_Hypothesis::BY_GEOM )
+    {
+      if ( mesh )
+        dflts._diagonal  = mesh->GetShapeDiagonalSize();
+      else
+        dflts._diagonal  = ::SMESH_Mesh::GetShapeDiagonalSize( shape );
+      dflts._elemLength  = dflts._diagonal / myGen.GetBoundaryBoxSegmentation();
+      dflts._shape       = &shape;
+    }
+
+    // let the hypothesis initialize it's values
     if ( hyp->SetParametersByDefaults( dflts, mesh ))
       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
   }
@@ -834,12 +985,12 @@ CORBA::Boolean SMESH_Gen_i::GetSoleSubMeshUsingHyp( SMESH::SMESH_Hypothesis_ptr
                                                     SMESH::SMESH_Mesh_out       theMesh,
                                                     GEOM::GEOM_Object_out       theShape)
 {
-  if ( GetCurrentStudyID() < 0 || CORBA::is_nil( theHyp ))
+  if ( CORBA::is_nil( theHyp ))
     return false;
 
   // get Mesh component SO
   CORBA::String_var compDataType = ComponentDataType();
-  SALOMEDS::SComponent_wrap comp = myCurrentStudy->FindComponent( compDataType.in() );
+  SALOMEDS::SComponent_wrap comp = getStudyServant()->FindComponent( compDataType.in() );
   if ( CORBA::is_nil( comp ))
     return false;
 
@@ -847,7 +998,7 @@ CORBA::Boolean SMESH_Gen_i::GetSoleSubMeshUsingHyp( SMESH::SMESH_Hypothesis_ptr
   SMESH::SMESH_Mesh_var foundMesh;
   TopoDS_Shape          foundShape;
   bool                  isSole = true;
-  SALOMEDS::ChildIterator_wrap meshIter = myCurrentStudy->NewChildIterator( comp );
+  SALOMEDS::ChildIterator_wrap meshIter = getStudyServant()->NewChildIterator( comp );
   for ( ; meshIter->More() && isSole; meshIter->Next() )
   {
     SALOMEDS::SObject_wrap curSO = meshIter->Value();
@@ -915,26 +1066,26 @@ CORBA::Boolean SMESH_Gen_i::GetSoleSubMeshUsingHyp( SMESH::SMESH_Hypothesis_ptr
 
 //=============================================================================
 /*!
- * Sets number of segments per diagonal of boundary box of geometry by which
+ * Set number of segments per diagonal of boundary box of geometry by which
  * default segment length of appropriate 1D hypotheses is defined
  */
 //=============================================================================
 
 void SMESH_Gen_i::SetBoundaryBoxSegmentation( CORBA::Long theNbSegments )
-  throw ( SALOME::SALOME_Exception )
 {
   if ( theNbSegments > 0 )
     myGen.SetBoundaryBoxSegmentation( int( theNbSegments ));
   else
     THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM );
 }
+
 //=============================================================================
-  /*!
  * \brief Sets default number of segments per edge
  */
+/*!
* \brief Set default number of segments per edge
+ */
 //=============================================================================
+
 void SMESH_Gen_i::SetDefaultNbSegments(CORBA::Long theNbSegments)
-  throw ( SALOME::SALOME_Exception )
 {
   if ( theNbSegments > 0 )
     myGen.SetDefaultNbSegments( int(theNbSegments) );
@@ -944,8 +1095,8 @@ void SMESH_Gen_i::SetDefaultNbSegments(CORBA::Long theNbSegments)
 
 //=============================================================================
 /*!
-  Set an option value
-*/
* Set an option value
+ */
 //=============================================================================
 
 void SMESH_Gen_i::SetOption(const char* name, const char* value)
@@ -1007,8 +1158,8 @@ void SMESH_Gen_i::SetOption(const char* name, const char* value)
 
 //=============================================================================
 /*!
-  Return an option value
-*/
 Return an option value
+ */
 //=============================================================================
 
 char* SMESH_Gen_i::GetOption(const char* name)
@@ -1040,7 +1191,6 @@ char* SMESH_Gen_i::GetOption(const char* name)
 //=============================================================================
 
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObject )
-     throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
@@ -1053,13 +1203,13 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObj
 
   // publish mesh in the study
   if ( CanPublishInStudy( mesh ) ) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
+    SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
     aStudyBuilder->NewCommand();  // There is a transaction
-    SALOMEDS::SObject_wrap aSO = PublishMesh( myCurrentStudy, mesh.in() );
+    SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() );
     aStudyBuilder->CommitCommand();
     if ( !aSO->_is_nil() ) {
       // Update Python script
-      TPythonDump() << aSO << " = " << this << ".CreateMesh(" << theShapeObject << ")";
+      TPythonDump(this) << aSO << " = " << this << ".CreateMesh(" << theShapeObject << ")";
     }
   }
 
@@ -1075,7 +1225,6 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObj
 //=============================================================================
 
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateEmptyMesh()
-     throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
@@ -1084,13 +1233,13 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateEmptyMesh()
 
   // publish mesh in the study
   if ( CanPublishInStudy( mesh ) ) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
+    SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
     aStudyBuilder->NewCommand();  // There is a transaction
-    SALOMEDS::SObject_wrap aSO = PublishMesh( myCurrentStudy, mesh.in() );
+    SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() );
     aStudyBuilder->CommitCommand();
     if ( !aSO->_is_nil() ) {
       // Update Python script
-      TPythonDump() << aSO << " = " << this << ".CreateEmptyMesh()";
+      TPythonDump(this) << aSO << " = " << this << ".CreateEmptyMesh()";
     }
   }
 
@@ -1101,11 +1250,11 @@ namespace
 {
   //================================================================================
   /*!
-   * \brief Throws an exception in case if the file can't be read
+   * \brief Throw an exception in case if the file can't be read
    */
   //================================================================================
 
-  void checkFileReadable( const char* theFileName ) throw ( SALOME::SALOME_Exception )
+  void checkFileReadable( const char* theFileName )
   {
     SMESH_File f ( theFileName );
     if ( !f )
@@ -1129,7 +1278,6 @@ namespace
 //=============================================================================
 
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName )
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
 
@@ -1139,13 +1287,13 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName
   string aFileName;
   // publish mesh in the study
   if ( CanPublishInStudy( aMesh ) ) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
+    SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
     aStudyBuilder->NewCommand();  // There is a transaction
-    SALOMEDS::SObject_wrap aSO = PublishMesh( myCurrentStudy, aMesh.in(), aFileName.c_str() );
+    SALOMEDS::SObject_wrap aSO = PublishMesh( aMesh.in(), aFileName.c_str() );
     aStudyBuilder->CommitCommand();
     if ( !aSO->_is_nil() ) {
       // Update Python script
-      TPythonDump() << aSO << " = " << this << ".CreateMeshesFromUNV(r'" << theFileName << "')";
+      TPythonDump(this) << aSO << " = " << this << ".CreateMeshesFromUNV(r'" << theFileName << "')";
     }
   }
 
@@ -1168,17 +1316,17 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName
  */
 //=============================================================================
 
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileName,
-                                                           SMESH::DriverMED_ReadStatus& theStatus,
-                                                           const char* theCommandNameForPython,
-                                                           const char* theFileNameForPython)
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char*                  theFileName,
+                                                     SMESH::DriverMED_ReadStatus& theStatus )
 {
+  checkFileReadable( theFileName );
+
 #ifdef WIN32
   char bname[ _MAX_FNAME ];
-  _splitpath( theFileNameForPython, NULL, NULL, bname, NULL );
+  _splitpath( theFileName, NULL, NULL, bname, NULL );
   string aFileName = bname;
 #else
-  string aFileName = basename( const_cast<char *>(theFileNameForPython) );
+  string aFileName = basename( const_cast<char *>( theFileName ));
 #endif
   // Retrieve mesh names from the file
   DriverMED_R_SMESHDS_Mesh myReader;
@@ -1191,61 +1339,57 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileNa
 
   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
 
-  // Python Dump
-  TPythonDump aPythonDump;
-  aPythonDump << "([";
+    // Python Dump
+    TPythonDump aPythonDump(this);
+    aPythonDump << "([";
 
-  if (theStatus == SMESH::DRS_OK) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder;
-    if ( GetCurrentStudyID() > -1 )
+    if (theStatus == SMESH::DRS_OK)
     {
-      aStudyBuilder = myCurrentStudy->NewBuilder();
+      SALOMEDS::StudyBuilder_var aStudyBuilder;
+      aStudyBuilder = getStudyServant()->NewBuilder();
       aStudyBuilder->NewCommand();  // There is a transaction
-    }
-    aResult->length( aNames.size() );
-    int i = 0;
 
-    // Iterate through all meshes and create mesh objects
-    for ( list<string>::iterator it = aNames.begin(); it != aNames.end(); it++ )
-    {
-      // Python Dump
-      if (i > 0) aPythonDump << ", ";
-
-      // create mesh
-      SMESH::SMESH_Mesh_var mesh = createMesh();
-
-      // publish mesh in the study
-      SALOMEDS::SObject_wrap aSO;
-      if ( CanPublishInStudy( mesh ) )
-        // little trick: for MED file theFileName and theFileNameForPython are the same, but they are different for SAUV
-        // - as names of meshes are stored in MED file, we use them for data publishing
-        // - as mesh name is not stored in UNV file, we use file name as name of mesh when publishing data
-        aSO = PublishMesh( myCurrentStudy, mesh.in(), ( theFileName == theFileNameForPython ) ? (*it).c_str() : aFileName.c_str() );
-
-      // Python Dump
-      if ( !aSO->_is_nil() ) {
-        aPythonDump << aSO;
-      } else {
-        aPythonDump << "mesh_" << i;
-      }
+      aResult->length( aNames.size() );
+      int i = 0;
+
+      // Iterate through all meshes and create mesh objects
+      for ( const std::string & meshName : aNames )
+      {
+        // Python Dump
+        if (i > 0) aPythonDump << ", ";
+
+        // create mesh
+        SMESH::SMESH_Mesh_var mesh = createMesh();
+
+        // publish mesh in the study
+        SALOMEDS::SObject_wrap aSO;
+        if ( CanPublishInStudy( mesh ) )
+          aSO = PublishMesh( mesh.in(), meshName.c_str() );
+
+        // Python Dump
+        if ( !aSO->_is_nil() ) {
+          aPythonDump << aSO;
+        } else {
+          aPythonDump << "mesh_" << i;
+        }
 
-      // Read mesh data (groups are published automatically by ImportMEDFile())
-      SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
-      ASSERT( meshServant );
-      SMESH::DriverMED_ReadStatus status1 =
-        meshServant->ImportMEDFile( theFileName, (*it).c_str() );
-      if (status1 > theStatus)
-        theStatus = status1;
+        // Read mesh data (groups are published automatically by ImportMEDFile())
+        SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
+        ASSERT( meshServant );
+        SMESH::DriverMED_ReadStatus status1 =
+          meshServant->ImportMEDFile( theFileName, meshName.c_str() );
+        if (status1 > theStatus)
+          theStatus = status1;
 
-      aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
-      meshServant->GetImpl().GetMeshDS()->Modified();
+        aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
+        meshServant->GetImpl().GetMeshDS()->Modified();
+      }
+      if ( !aStudyBuilder->_is_nil() )
+        aStudyBuilder->CommitCommand();
     }
-    if ( !aStudyBuilder->_is_nil() )
-      aStudyBuilder->CommitCommand();
-  }
 
-  // Update Python script
-  aPythonDump << "], status) = " << this << "." << theCommandNameForPython << "(r'" << theFileNameForPython << "')";
+    // Update Python script
+    aPythonDump << "], status) = " << this << ".CreateMeshesFromMED( r'" << theFileName << "' )";
   }
   // Dump creation of groups
   for ( CORBA::ULong  i = 0; i < aResult->length(); ++i )
@@ -1254,58 +1398,6 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileNa
   return aResult._retn();
 }
 
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName,
-                                                     SMESH::DriverMED_ReadStatus& theStatus)
-  throw ( SALOME::SALOME_Exception )
-{
-  Unexpect aCatch(SALOME_SalomeException);
-  checkFileReadable( theFileName );
-
-  SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(theFileName, theStatus, "CreateMeshesFromMED", theFileName);
-  return result;
-}
-
-//=============================================================================
-/*!
- *  SMESH_Gen_i::CreateMeshFromSAUV
- *
- *  Create mesh and import data from SAUV file
- */
-//=============================================================================
-
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromSAUV( const char* theFileName,
-                                                      SMESH::DriverMED_ReadStatus& theStatus)
-     throw ( SALOME::SALOME_Exception )
-{
-  Unexpect aCatch(SALOME_SalomeException);
-  checkFileReadable( theFileName );
-
-  std::string sauvfilename(theFileName);
-  std::string medfilename(theFileName);
-  medfilename += ".med";
-  std::string cmd;
-#ifdef WIN32
-  cmd = "%PYTHONBIN% ";
-#else
-  cmd = "python ";
-#endif
-  cmd += "-c \"";
-  cmd += "from medutilities import convert ; convert(r'" + sauvfilename + "', 'GIBI', 'MED', 1, r'" + medfilename + "')";
-  cmd += "\"";
-  system(cmd.c_str());
-  SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(medfilename.c_str(), theStatus, "CreateMeshesFromSAUV", sauvfilename.c_str());
-#ifdef WIN32
-  cmd = "%PYTHONBIN% ";
-#else
-  cmd = "python ";
-#endif
-  cmd += "-c \"";
-  cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
-  cmd += "\"";
-  system(cmd.c_str());
-  return result;
-}
-
 //=============================================================================
 /*!
  *  SMESH_Gen_i::CreateMeshFromSTL
@@ -1315,7 +1407,6 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromSAUV( const char* theFileName,
 //=============================================================================
 
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName )
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   checkFileReadable( theFileName );
@@ -1331,14 +1422,13 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName
 #endif
   // publish mesh in the study
   if ( CanPublishInStudy( aMesh ) ) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
+    SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
     aStudyBuilder->NewCommand();  // There is a transaction
-    SALOMEDS::SObject_wrap aSO = PublishInStudy
-      ( myCurrentStudy, SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
+    SALOMEDS::SObject_wrap aSO = PublishInStudy( SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
     aStudyBuilder->CommitCommand();
     if ( !aSO->_is_nil() ) {
       // Update Python script
-      TPythonDump() << aSO << " = " << this << ".CreateMeshesFromSTL(r'" << theFileName << "')";
+      TPythonDump(this) << aSO << " = " << this << ".CreateMeshesFromSTL(r'" << theFileName << "')";
     }
   }
 
@@ -1355,9 +1445,8 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName
  */
 //================================================================================
 
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char* theFileName,
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char*                  theFileName,
                                                       SMESH::DriverMED_ReadStatus& theStatus)
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   checkFileReadable( theFileName );
@@ -1377,12 +1466,12 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char* theFileName,
   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
 
     // Python Dump
-    TPythonDump aPythonDump;
+    TPythonDump aPythonDump(this);
     aPythonDump << "([";
 
     if (theStatus == SMESH::DRS_OK)
     {
-      SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
+      SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
       aStudyBuilder->NewCommand();  // There is a transaction
 
       int i = 0;
@@ -1410,7 +1499,7 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char* theFileName,
         // publish mesh in the study
         SALOMEDS::SObject_wrap aSO;
         if ( CanPublishInStudy( mesh ) )
-          aSO = PublishMesh( myCurrentStudy, mesh.in(), meshName.c_str() );
+          aSO = PublishMesh( mesh.in(), meshName.c_str() );
 
         // Python Dump
         if ( !aSO->_is_nil() ) {
@@ -1445,7 +1534,6 @@ SMESH::SMESH_Mesh_ptr
 SMESH_Gen_i::CreateMeshesFromGMF( const char*             theFileName,
                                   CORBA::Boolean          theMakeRequiredGroups,
                                   SMESH::ComputeError_out theError)
-    throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   checkFileReadable( theFileName );
@@ -1460,14 +1548,13 @@ SMESH_Gen_i::CreateMeshesFromGMF( const char*             theFileName,
 #endif
   // publish mesh in the study
   if ( CanPublishInStudy( aMesh ) ) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
+    SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
     aStudyBuilder->NewCommand();  // There is a transaction
-    SALOMEDS::SObject_wrap aSO = PublishInStudy
-      ( myCurrentStudy, SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
+    SALOMEDS::SObject_wrap aSO = PublishInStudy( SALOMEDS::SObject::_nil(), aMesh.in(), aFileName.c_str() );
     aStudyBuilder->CommitCommand();
     if ( !aSO->_is_nil() ) {
       // Update Python script
-      TPythonDump() << "("<< aSO << ", error) = " << this << ".CreateMeshesFromGMF(r'"
+      TPythonDump(this) << "("<< aSO << ", error) = " << this << ".CreateMeshesFromGMF(r'"
                     << theFileName << "', "
                     << theMakeRequiredGroups << " )";
     }
@@ -1484,13 +1571,12 @@ SMESH_Gen_i::CreateMeshesFromGMF( const char*             theFileName,
 /*!
  *  SMESH_Gen_i::IsReadyToCompute
  *
- *  Returns true if mesh contains enough data to be computed
+ *  Return true if mesh contains enough data to be computed
  */
 //=============================================================================
 
 CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh,
                                               GEOM::GEOM_Object_ptr theShapeObject )
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IsReadyToCompute" );
@@ -1498,11 +1584,9 @@ CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh,
   if ( CORBA::is_nil( theShapeObject ) )
     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
                                   SALOME::BAD_PARAM );
-
   if ( CORBA::is_nil( theMesh ) )
     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
                                   SALOME::BAD_PARAM );
-
   try {
     // get mesh servant
     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
@@ -1530,16 +1614,17 @@ CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh,
 SALOMEDS::SObject_ptr SMESH_Gen_i::GetAlgoSO(const ::SMESH_Algo* algo)
 {
   if ( algo ) {
-    if ( !myCurrentStudy->_is_nil() ) {
+    SALOMEDS::Study_var aStudy = getStudyServant();
+    if ( !aStudy->_is_nil() ) {
       // find algo in the study
       CORBA::String_var compDataType  = ComponentDataType();
-      SALOMEDS::SComponent_wrap father = myCurrentStudy->FindComponent( compDataType.in() );
+      SALOMEDS::SComponent_wrap father = aStudy->FindComponent( compDataType.in() );
       if ( !father->_is_nil() ) {
-        SALOMEDS::ChildIterator_wrap itBig = myCurrentStudy->NewChildIterator( father );
+        SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( father );
         for ( ; itBig->More(); itBig->Next() ) {
           SALOMEDS::SObject_wrap gotBranch = itBig->Value();
           if ( gotBranch->Tag() == GetAlgorithmsRootTag() ) {
-            SALOMEDS::ChildIterator_wrap algoIt = myCurrentStudy->NewChildIterator( gotBranch );
+            SALOMEDS::ChildIterator_wrap algoIt = aStudy->NewChildIterator( gotBranch );
             for ( ; algoIt->More(); algoIt->Next() ) {
               SALOMEDS::SObject_wrap algoSO = algoIt->Value();
               CORBA::Object_var     algoIOR = SObjectToObject( algoSO );
@@ -1566,7 +1651,6 @@ SALOMEDS::SObject_ptr SMESH_Gen_i::GetAlgoSO(const ::SMESH_Algo* algo)
 
 SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr theMesh,
                                                            GEOM::GEOM_Object_ptr theSubObject )
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetComputeErrors()" );
@@ -1619,7 +1703,7 @@ SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr
           else {
             errStruct.algoName = error->myAlgo->GetName();
           }
-          errStruct.hasBadMesh = !error->myBadElements.empty();
+          errStruct.hasBadMesh = error->HasBadElems();
         }
       }
       error_array->length( nbErr );
@@ -1641,7 +1725,6 @@ SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr
 SMESH::MeshPreviewStruct*
 SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
                                   CORBA::Short          theSubShapeID )
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetBadInputElements()" );
@@ -1661,7 +1744,7 @@ SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
       {
         // compute error
         SMESH_ComputeErrorPtr error = sm->GetComputeError();
-        if ( error && !error->myBadElements.empty())
+        if ( error && error->HasBadElems() )
         {
           typedef map<const SMDS_MeshElement*, int > TNode2LocalIDMap;
           typedef TNode2LocalIDMap::iterator         TNodeLocalID;
@@ -1671,8 +1754,10 @@ SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
           list< TNodeLocalID > connectivity;
           int i, nbElements = 0, nbConnNodes = 0;
 
-          list<const SMDS_MeshElement*>::iterator elemIt  = error->myBadElements.begin();
-          list<const SMDS_MeshElement*>::iterator elemEnd = error->myBadElements.end();
+          const list<const SMDS_MeshElement*>& badElems =
+            static_cast<SMESH_BadInputElements*>( error.get() )->myBadElements;
+          list<const SMDS_MeshElement*>::const_iterator elemIt  = badElems.begin();
+          list<const SMDS_MeshElement*>::const_iterator elemEnd = badElems.end();
           for ( ; elemIt != elemEnd; ++elemIt, ++nbElements )
           {
             SMDS_ElemIteratorPtr nIt = (*elemIt)->nodesIterator();
@@ -1699,7 +1784,7 @@ SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
           }
           // fill element types
           result->elementTypes.length( nbElements );
-          for ( i = 0, elemIt = error->myBadElements.begin(); i <nbElements; ++i, ++elemIt )
+          for ( i = 0, elemIt = badElems.begin(); i <nbElements; ++i, ++elemIt )
           {
             const SMDS_MeshElement* elem = *elemIt;
             result->elementTypes[i].SMDS_ElementType = (SMESH::ElementType) elem->GetType();
@@ -1727,7 +1812,6 @@ SMESH::ListOfGroups*
 SMESH_Gen_i::MakeGroupsOfBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
                                            CORBA::Short          theSubShapeID,
                                            const char*           theGroupName )
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
 
@@ -1740,7 +1824,7 @@ SMESH_Gen_i::MakeGroupsOfBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
     if ( SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh ))
     {
       groups = meshServant->MakeGroupsOfBadInputElements( theSubShapeID, theGroupName );
-      TPythonDump() << groups << " = " << this
+      TPythonDump(this) << groups << " = " << this
                     << ".MakeGroupsOfBadInputElements( "
                     << theMesh << ", " << theSubShapeID << ", '" << theGroupName << "' )";
     }
@@ -1753,16 +1837,15 @@ SMESH_Gen_i::MakeGroupsOfBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
 
 //================================================================================
 /*!
- * \brief Returns errors of hypotheses definintion
- * \param theMesh - the mesh
- * \param theSubObject - the main or sub- shape
- * \retval SMESH::algo_error_array* - sequence of errors
+ * \brief Returns errors of hypotheses definition
+ *  \param theMesh - the mesh
+ *  \param theSubObject - the main or sub- shape
+ *  \retval SMESH::algo_error_array* - sequence of errors
  */
 //================================================================================
 
 SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMesh,
                                                     GEOM::GEOM_Object_ptr theSubObject )
-      throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetAlgoState()" );
@@ -1824,7 +1907,6 @@ SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMes
 SMESH::long_array*
 SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr      theMainShapeObject,
                              const SMESH::object_array& theListOfSubShapeObject )
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetSubShapesId" );
@@ -1898,7 +1980,6 @@ SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr      theMainShapeObject,
 
 CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
                                      GEOM::GEOM_Object_ptr theShapeObject )
-     throw ( SALOME::SALOME_Exception )
 {
   //MEMOSTAT;
   Unexpect aCatch(SALOME_SalomeException);
@@ -1913,16 +1994,19 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
                                   SALOME::BAD_PARAM );
 
   // Update Python script
-  TPythonDump() << "isDone = " << this << ".Compute( "
+  TPythonDump(this) << "isDone = " << this << ".Compute( "
                 << theMesh << ", " << theShapeObject << ")";
 
   try {
     // get mesh servant
-    SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
+    SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
     ASSERT( meshServant );
     if ( meshServant ) {
-      meshServant->Load();
-      // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
+      if ( isGeomModifIcon( theMesh ))
+        meshServant->Clear();
+      else
+        meshServant->Load();
+      // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
       meshServant->CheckGeomModif();
       // get local TopoDS_Shape
       TopoDS_Shape myLocShape;
@@ -1939,10 +2023,13 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
       bool ok = myGen.Compute( myLocMesh, myLocShape, how );
       meshServant->CreateGroupServants(); // algos can create groups (issue 0020918)
       myLocMesh.GetMeshDS()->Modified();
+      UpdateIcons( theMesh );
+      if ( ok )
+        HighLightInvalid( theMesh, /*isInvalid=*/false );
       return ok;
     }
   }
-  catch ( std::bad_alloc ) {
+  catch ( std::bad_alloc& ) {
     INFOS( "Compute(): lack of memory" );
   }
   catch ( SALOME_Exception& S_ex ) {
@@ -1965,14 +2052,16 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
 void SMESH_Gen_i::CancelCompute( SMESH::SMESH_Mesh_ptr theMesh,
                                  GEOM::GEOM_Object_ptr theShapeObject )
 {
-  SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
-  ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
-  TopoDS_Shape myLocShape;
-  if(theMesh->HasShapeToMesh())
-    myLocShape = GeomObjectToShape( theShapeObject );
-  else
-    myLocShape = SMESH_Mesh::PseudoShape();
-  myGen.CancelCompute( myLocMesh, myLocShape);
+  if ( SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() ))
+  {
+    ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
+    TopoDS_Shape myLocShape;
+    if(theMesh->HasShapeToMesh())
+      myLocShape = GeomObjectToShape( theShapeObject );
+    else
+      myLocShape = SMESH_Mesh::PseudoShape();
+    myGen.CancelCompute( myLocMesh, myLocShape);
+  }
 }
 
 //=============================================================================
@@ -1987,7 +2076,6 @@ SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh
                                                    GEOM::GEOM_Object_ptr theShapeObject,
                                                    SMESH::Dimension      theDimension,
                                                    SMESH::long_array&    theShapesId)
-     throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Precompute" );
@@ -2007,14 +2095,14 @@ SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh
     meshServant->Load();
     ASSERT( meshServant );
     if ( meshServant ) {
-      // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
+      // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
       meshServant->CheckGeomModif();
       // get local TopoDS_Shape
       TopoDS_Shape myLocShape;
       if(theMesh->HasShapeToMesh())
         myLocShape = GeomObjectToShape( theShapeObject );
       else
-        return result._retn();;
+        return result._retn();
 
       // call implementation compute
       ::SMESH_Mesh& myLocMesh = meshServant->GetImpl();
@@ -2151,7 +2239,7 @@ SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh
       }
     }
   }
-  catch ( std::bad_alloc ) {
+  catch ( std::bad_alloc& ) {
     INFOS( "Precompute(): lack of memory" );
   }
   catch ( SALOME_Exception& S_ex ) {
@@ -2172,30 +2260,26 @@ SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh
  */
 //=============================================================================
 
-SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
-                                         GEOM::GEOM_Object_ptr theShapeObject)
-//                                     SMESH::long_array& theNbElems)
-     throw ( SALOME::SALOME_Exception )
+SMESH::smIdType_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
+                                             GEOM::GEOM_Object_ptr theShapeObject)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Evaluate" );
 
   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
-    THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
-                                  SALOME::BAD_PARAM );
+    THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
 
   if ( CORBA::is_nil( theMesh ) )
-    THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",
-                                  SALOME::BAD_PARAM );
+    THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
 
-  SMESH::long_array_var nbels = new SMESH::long_array;
+  SMESH::smIdType_array_var nbels = new SMESH::smIdType_array;
   nbels->length(SMESH::Entity_Last);
   int i = SMESH::Entity_Node;
   for (; i < SMESH::Entity_Last; i++)
     nbels[i] = 0;
 
   // Update Python script
-  TPythonDump() << "theNbElems = " << this << ".Evaluate( "
+  TPythonDump(this) << "theNbElems = " << this << ".Evaluate( "
                 << theMesh << ", " << theShapeObject << ")";
 
   try {
@@ -2204,7 +2288,7 @@ SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
     ASSERT( meshServant );
     if ( meshServant ) {
       meshServant->Load();
-      // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
+      // NPAL16168: "geometrical group edition from a submesh don't modify mesh computation"
       meshServant->CheckGeomModif();
       // get local TopoDS_Shape
       TopoDS_Shape myLocShape;
@@ -2218,9 +2302,9 @@ SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
       /*CORBA::Boolean ret =*/ myGen.Evaluate( myLocMesh, myLocShape, aResMap);
       MapShapeNbElemsItr anIt = aResMap.begin();
       for(; anIt!=aResMap.end(); anIt++) {
-        const vector<int>& aVec = (*anIt).second;
+        const vector<smIdType>& aVec = (*anIt).second;
         for ( i = SMESH::Entity_Node; i < (int)aVec.size(); i++ ) {
-          int nbElem = aVec[i];
+          smIdType nbElem = aVec[i];
           if ( nbElem < 0 ) // algo failed, check that it has reported a message
           {
             SMESH_subMesh*            sm = anIt->first;
@@ -2238,7 +2322,7 @@ SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
       return nbels._retn();
     }
   }
-  catch ( std::bad_alloc ) {
+  catch ( std::bad_alloc& ) {
     INFOS( "Evaluate(): lack of memory" );
   }
   catch ( SALOME_Exception& S_ex ) {
@@ -2263,28 +2347,27 @@ SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
 
 GEOM::GEOM_Object_ptr
 SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
-                                       CORBA::Long            theElementID,
+                                       SMESH::smIdType        theElementID,
                                        const char*            theGeomName)
-  throw ( SALOME::SALOME_Exception )
 {
   Unexpect aCatch(SALOME_SalomeException);
 
   GEOM::GEOM_Object_wrap geom = FindGeometryByMeshElement(theMesh, theElementID);
   if ( !geom->_is_nil() ) {
     GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
-    GEOM::GEOM_Gen_ptr    geomGen   = GetGeomEngine();
+    GEOM::GEOM_Gen_var    geomGen   = GetGeomEngine( geom );
 
     // try to find the corresponding SObject
-    SALOMEDS::SObject_wrap SObj = ObjectToSObject( myCurrentStudy, geom.in() );
+    SALOMEDS::SObject_wrap SObj = ObjectToSObject( geom.in() );
     if ( SObj->_is_nil() ) // submesh can be not found even if published
     {
       // try to find published submesh
       GEOM::ListOfLong_var list = geom->GetSubShapeIndices();
       if ( !geom->IsMainShape() && list->length() == 1 ) {
-        SALOMEDS::SObject_wrap mainSO = ObjectToSObject( myCurrentStudy, mainShape );
+        SALOMEDS::SObject_wrap mainSO = ObjectToSObject( mainShape );
         SALOMEDS::ChildIterator_wrap it;
         if ( !mainSO->_is_nil() ) {
-          it = myCurrentStudy->NewChildIterator( mainSO );
+          it = getStudyServant()->NewChildIterator( mainSO );
         }
         if ( !it->_is_nil() ) {
           for ( it->InitEx(true); it->More(); it->Next() ) {
@@ -2303,8 +2386,8 @@ SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
         }
       }
     }
-    if ( SObj->_is_nil() ) // publish a new subshape
-      SObj = geomGen->AddInStudy( myCurrentStudy, geom, theGeomName, mainShape );
+    if ( SObj->_is_nil() && !geomGen->_is_nil() ) // publish a new subshape
+      SObj = geomGen->AddInStudy( geom, theGeomName, mainShape );
 
     // return only published geometry
     if ( !SObj->_is_nil() ) {
@@ -2328,15 +2411,14 @@ SMESH_Gen_i::GetGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
 
 GEOM::GEOM_Object_ptr
 SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
-                                        CORBA::Long            theElementID)
-  throw ( SALOME::SALOME_Exception )
+                                        SMESH::smIdType            theElementID)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( CORBA::is_nil( theMesh ) )
     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", SALOME::BAD_PARAM );
 
   GEOM::GEOM_Object_var mainShape = theMesh->GetShapeToMesh();
-  GEOM::GEOM_Gen_ptr    geomGen   = GetGeomEngine();
+  GEOM::GEOM_Gen_var    geomGen   = GetGeomEngine( mainShape );
 
   // get a core mesh DS
   SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( theMesh );
@@ -2352,14 +2434,14 @@ SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
         GEOM::GEOM_Object_var geom = ShapeToGeomObject( meshDS->IndexToShape( shapeID ));
         if ( geom->_is_nil() ) {
           // try to find a published sub-shape
-          SALOMEDS::SObject_wrap mainSO = ObjectToSObject( myCurrentStudy, mainShape );
+          SALOMEDS::SObject_wrap mainSO = ObjectToSObject( mainShape );
           SALOMEDS::ChildIterator_wrap it;
           if ( !mainSO->_is_nil() ) {
-            it = myCurrentStudy->NewChildIterator( mainSO );
+            it = getStudyServant()->NewChildIterator( mainSO );
           }
           if ( !it->_is_nil() ) {
             for ( it->InitEx(true); it->More(); it->Next() ) {
-              SALOMEDS::SObject_wrap      so = it->Value();
+              SALOMEDS::SObject_wrap     so = it->Value();
               CORBA::Object_var         obj = SObjectToObject( so );
               GEOM::GEOM_Object_var subGeom = GEOM::GEOM_Object::_narrow( obj );
               if ( !subGeom->_is_nil() ) {
@@ -2374,8 +2456,7 @@ SMESH_Gen_i::FindGeometryByMeshElement( SMESH::SMESH_Mesh_ptr  theMesh,
         }
         if ( geom->_is_nil() ) {
           // explode
-          GEOM::GEOM_IShapesOperations_wrap op =
-            geomGen->GetIShapesOperations( GetCurrentStudyID() );
+          GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
           if ( !op->_is_nil() )
             geom = op->GetSubShape( mainShape, shapeID );
         }
@@ -2404,14 +2485,15 @@ SMESH::SMESH_Mesh_ptr
 SMESH_Gen_i::Concatenate(const SMESH::ListOfIDSources& theMeshesArray,
                          CORBA::Boolean                theUniteIdenticalGroups,
                          CORBA::Boolean                theMergeNodesAndElements,
-                         CORBA::Double                 theMergeTolerance)
-  throw ( SALOME::SALOME_Exception )
+                         CORBA::Double                 theMergeTolerance,
+                         SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
 {
   return ConcatenateCommon(theMeshesArray,
                            theUniteIdenticalGroups,
                            theMergeNodesAndElements,
                            theMergeTolerance,
-                           false);
+                           false,
+                           theMeshToAppendTo);
 }
 
 //================================================================================
@@ -2427,14 +2509,15 @@ SMESH::SMESH_Mesh_ptr
 SMESH_Gen_i::ConcatenateWithGroups(const SMESH::ListOfIDSources& theMeshesArray,
                                    CORBA::Boolean                theUniteIdenticalGroups,
                                    CORBA::Boolean                theMergeNodesAndElements,
-                                   CORBA::Double                 theMergeTolerance)
-  throw ( SALOME::SALOME_Exception )
+                                   CORBA::Double                 theMergeTolerance,
+                                   SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
 {
   return ConcatenateCommon(theMeshesArray,
                            theUniteIdenticalGroups,
                            theMergeNodesAndElements,
                            theMergeTolerance,
-                           true);
+                           true,
+                           theMeshToAppendTo);
 }
 
 //================================================================================
@@ -2450,284 +2533,270 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
                                CORBA::Boolean                theUniteIdenticalGroups,
                                CORBA::Boolean                theMergeNodesAndElements,
                                CORBA::Double                 theMergeTolerance,
-                               CORBA::Boolean                theCommonGroups)
-  throw ( SALOME::SALOME_Exception )
+                               CORBA::Boolean                theCommonGroups,
+                               SMESH::SMESH_Mesh_ptr         theMeshToAppendTo)
 {
-  typedef list<SMESH::SMESH_Group_var> TListOfNewGroups;
-  typedef map< pair<string, SMESH::ElementType>, TListOfNewGroups > TGroupsMap;
+  std::unique_ptr< TPythonDump > pPythonDump( new TPythonDump(this) );
+  TPythonDump& pythonDump = *pPythonDump; // prevent dump of called methods
 
-  TPythonDump* pPythonDump = new TPythonDump;
-  TPythonDump& aPythonDump = *pPythonDump; // prevent dump of called methods
-
-  // create mesh
-  SMESH::SMESH_Mesh_var aNewMesh = CreateEmptyMesh();
-
-  if ( aNewMesh->_is_nil() )
-    return aNewMesh._retn();
+  // create mesh if theMeshToAppendTo not provided
+  SMESH::SMESH_Mesh_var newMesh;
+  if ( CORBA::is_nil( theMeshToAppendTo ))
+    newMesh = CreateEmptyMesh();
+  else
+    newMesh = SMESH::SMESH_Mesh::_duplicate( theMeshToAppendTo );
+  SMESH_Mesh_i* newImpl = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
+  if ( !newImpl ) return newMesh._retn();
+  newImpl->Load();
 
-  SMESH_Mesh_i* aNewImpl = SMESH::DownCast<SMESH_Mesh_i*>( aNewMesh );
-  if ( !aNewImpl )
-    return aNewMesh._retn();
+  ::SMESH_Mesh&   locMesh = newImpl->GetImpl();
+  SMESHDS_Mesh* newMeshDS = locMesh.GetMeshDS();
 
-  ::SMESH_Mesh& aLocMesh = aNewImpl->GetImpl();
-  SMESHDS_Mesh* aNewMeshDS = aLocMesh.GetMeshDS();
+  typedef std::list<SMESH::SMESH_Group_var>          TListOfNewGroups;
+  typedef std::pair<string, SMESH::ElementType >     TNameAndType;
+  typedef std::map< TNameAndType, TListOfNewGroups > TGroupsMap;
+  TGroupsMap       groupsMap;
+  TListOfNewGroups listOfNewGroups;
 
-  TGroupsMap aGroupsMap;
-  TListOfNewGroups aListOfNewGroups;
-  ::SMESH_MeshEditor aNewEditor(&aLocMesh);
-  SMESH::ListOfGroups_var aListOfGroups;
+  if ( !CORBA::is_nil( theMeshToAppendTo ))
+  {
+    // fill groupsMap with existing groups
+    SMESH::ListOfGroups_var groups = theMeshToAppendTo->GetGroups();
+    for ( CORBA::ULong i = 0; i < groups->length(); ++i )
+    {
+      SMESH::SMESH_Group_var group = SMESH::SMESH_Group::_narrow( groups[ i ]);
+      if ( !group->_is_nil() )
+      {
+        CORBA::String_var  name = group->GetName();
+        SMESH::ElementType type = group->GetType();
+        groupsMap[ TNameAndType( name.in(), type ) ].push_back( group );
+      }
+    }
+  }
 
-  ::SMESH_MeshEditor::ElemFeatures  elemType;
-  std::vector<const SMDS_MeshNode*> aNodesArray;
+  ::SMESH_MeshEditor               newEditor( &locMesh );
+  ::SMESH_MeshEditor::ElemFeatures elemType;
 
   // loop on sub-meshes
-  for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++)
+  for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++ )
   {
     if ( CORBA::is_nil( theMeshesArray[i] )) continue;
-    SMESH::SMESH_Mesh_var anInitMesh = theMeshesArray[i]->GetMesh();
-    if ( anInitMesh->_is_nil() ) continue;
-    SMESH_Mesh_i* anInitImpl = SMESH::DownCast<SMESH_Mesh_i*>( anInitMesh );
-    if ( !anInitImpl ) continue;
-    anInitImpl->Load();
+    SMESH::SMESH_Mesh_var initMesh = theMeshesArray[i]->GetMesh();
+    SMESH_Mesh_i*         initImpl = SMESH::DownCast<SMESH_Mesh_i*>( initMesh );
+    if ( !initImpl ) continue;
+    if ( initMesh->_is_equivalent( theMeshToAppendTo ))
+      continue;
+    initImpl->Load();
 
-    //::SMESH_Mesh& aInitLocMesh = anInitImpl->GetImpl();
-    //SMESHDS_Mesh* anInitMeshDS = aInitLocMesh.GetMeshDS();
+    // assure that IDs increment by one during iteration
+    ::SMESH_Mesh& initLocMesh = initImpl->GetImpl();
+    SMESHDS_Mesh*  initMeshDS = initLocMesh.GetMeshDS();
+    if ( initMeshDS->MaxNodeID()    > initMeshDS->NbNodes() ||
+         initMeshDS->MaxElementID() > initMeshDS->NbElements() )
+    {
+      initMeshDS->Modified();
+      initMeshDS->CompactMesh();
+    }
 
     // remember nb of elements before filling in
-    SMESH::long_array_var prevState =  aNewMesh->GetNbElementsByType();
+    SMESH::smIdType_array_var prevState =  newMesh->GetNbElementsByType();
 
-    typedef std::map<const SMDS_MeshElement*, const SMDS_MeshElement*, TIDCompare > TEEMap;
-    TEEMap elemsMap, nodesMap;
+    // copy nodes
+
+    std::vector< const SMDS_MeshElement* > newNodes( initMeshDS->NbNodes() + 1, 0 );
+    SMDS_ElemIteratorPtr elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::NODE );
+    while ( elemIt->more() )
+    {
+      SMESH_NodeXYZ node = elemIt->next();
+      newNodes[ node->GetID() ] = newMeshDS->AddNode( node.X(), node.Y(), node.Z() );
+    }
 
-    // loop on elements of a sub-mesh
-    SMDS_ElemIteratorPtr itElems = anInitImpl->GetElements( theMeshesArray[i], SMESH::ALL );
-    const SMDS_MeshElement* anElem;
-    const SMDS_MeshElement* aNewElem;
-    const SMDS_MeshNode*    aNode;
-    const SMDS_MeshNode*    aNewNode;
-    int anElemNbNodes;
+    // copy elements
 
-    while ( itElems->more() )
+    SMESH::array_of_ElementType_var srcElemTypes = theMeshesArray[i]->GetTypes();
+    if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
+      continue;
+    std::vector< const SMDS_MeshElement* > newElems( initMeshDS->NbElements() + 1, 0 );
+    elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
+    while ( elemIt->more() )
     {
-      anElem = itElems->next();
-      anElemNbNodes = anElem->NbNodes();
-      aNodesArray.resize( anElemNbNodes );
+      const SMDS_MeshElement* elem = elemIt->next();
+      elemType.myNodes.resize( elem->NbNodes() );
 
-      // loop on nodes of an element
-      SMDS_ElemIteratorPtr itNodes = anElem->nodesIterator();
+      SMDS_NodeIteratorPtr itNodes = elem->nodeIterator();
       for ( int k = 0; itNodes->more(); k++)
       {
-        aNode = static_cast<const SMDS_MeshNode*>( itNodes->next() );
-        TEEMap::iterator n2nnIt = nodesMap.find( aNode );
-        if ( n2nnIt == nodesMap.end() )
-        {
-          aNewNode = aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z());
-          nodesMap.insert( make_pair( aNode, aNewNode ));
-        }
-        else
-        {
-          aNewNode = static_cast<const SMDS_MeshNode*>( n2nnIt->second );
-        }
-        aNodesArray[k] = aNewNode;
+        const SMDS_MeshNode* node = itNodes->next();
+        elemType.myNodes[ k ] = static_cast< const SMDS_MeshNode*> ( newNodes[ node->GetID() ]);
       }
 
       // creates a corresponding element on existent nodes in new mesh
-      if ( anElem->GetType() == SMDSAbs_Node )
-        aNewElem = 0;
-      else
-        aNewElem =
-          aNewEditor.AddElement( aNodesArray, elemType.Init( anElem, /*basicOnly=*/false ));
-
-      if ( aNewElem )
-        elemsMap.insert( make_pair( anElem, aNewElem ));
-
-    } //elems loop
-
-    aNewEditor.ClearLastCreated(); // forget the history
+      newElems[ elem->GetID() ] =
+        newEditor.AddElement( elemType.myNodes, elemType.Init( elem, /*basicOnly=*/false ));
+    }
+    newEditor.ClearLastCreated(); // forget the history
 
 
     // create groups of just added elements
-    SMESH::SMESH_Group_var aNewGroup;
-    SMESH::ElementType aGroupType;
+    SMESH::SMESH_Group_var newGroup;
+    SMESH::ElementType     groupType;
     if ( theCommonGroups )
     {
-      SMESH::long_array_var curState = aNewMesh->GetNbElementsByType();
+      // type names
+      const char* typeNames[] = { "All","Nodes","Edges","Faces","Volumes","0DElems","Balls" };
+
+      // check of typeNames: compilation failure mains that NB_ELEMENT_TYPES changed:
+      static_assert( sizeof(typeNames) / sizeof(const char*) ==SMESH::NB_ELEMENT_TYPES,
+                     "Update names of ElementType's!!!" );
+
+      SMESH::smIdType_array_var curState = newMesh->GetNbElementsByType();
 
-      for( aGroupType = SMESH::NODE;
-           aGroupType < SMESH::NB_ELEMENT_TYPES;
-           aGroupType = (SMESH::ElementType)( aGroupType + 1 ))
+      for( groupType = SMESH::NODE;
+           groupType < SMESH::NB_ELEMENT_TYPES;
+           groupType = (SMESH::ElementType)( groupType + 1 ))
       {
-        if ( curState[ aGroupType ] <= prevState[ aGroupType ])
-          continue;
+        if ( curState[ groupType ] <= prevState[ groupType ])
+          continue; // no elements of groupType added from the i-th mesh
 
         // make a group name
-        const char* typeNames[] = { "All","Nodes","Edges","Faces","Volumes","0DElems","Balls" };
-        { // check of typeNames: compilation failure mains that NB_ELEMENT_TYPES changed:
-          const int nbNames = sizeof(typeNames) / sizeof(const char*);
-          int _assert[( nbNames == SMESH::NB_ELEMENT_TYPES ) ? 2 : -1 ]; _assert[0]=_assert[1]=0;
-        }
-        string groupName = "Gr";
-        SALOMEDS::SObject_wrap aMeshSObj = ObjectToSObject( myCurrentStudy, theMeshesArray[i] );
-        if ( aMeshSObj ) {
-          CORBA::String_var name = aMeshSObj->GetName();
+        std::string groupName = "Gr";
+        SALOMEDS::SObject_wrap meshSO = ObjectToSObject( theMeshesArray[i] );
+        if ( meshSO ) {
+          CORBA::String_var name = meshSO->GetName();
           groupName += name;
         }
         groupName += "_";
-        groupName += typeNames[ aGroupType ];
+        groupName += typeNames[ groupType ];
 
         // make and fill a group
-        TEEMap & e2neMap = ( aGroupType == SMESH::NODE ) ? nodesMap : elemsMap;
-        aNewGroup = aNewImpl->CreateGroup( aGroupType, groupName.c_str() );
-        if ( SMESH_Group_i* grp_i = SMESH::DownCast<SMESH_Group_i*>( aNewGroup ))
+        newGroup = newImpl->CreateGroup( groupType, groupName.c_str() );
+        std::vector< const SMDS_MeshElement* > & elemVec =
+          ( groupType == SMESH::NODE ) ? newNodes : newElems;
+        if ( SMESH_Group_i* grp_i = SMESH::DownCast<SMESH_Group_i*>( newGroup ))
         {
           if ( SMESHDS_Group* grpDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() ))
           {
-            TEEMap::iterator e2neIt = e2neMap.begin();
-            for ( ; e2neIt != e2neMap.end(); ++e2neIt )
+            for ( size_t j = 0; j < elemVec.size(); ++j )
             {
-              aNewElem = e2neIt->second;
-              if ( aNewElem->GetType() == grpDS->GetType() )
-              {
-                grpDS->Add( aNewElem );
-
-                if ( prevState[ aGroupType ]++ >= curState[ aGroupType ] )
-                  break;
-              }
+              if ( elemVec[j] && elemVec[j]->GetType() == grpDS->GetType() )
+                grpDS->Add( elemVec[j] );
             }
           }
         }
-        aListOfNewGroups.clear();
-        aListOfNewGroups.push_back(aNewGroup);
-        aGroupsMap.insert(make_pair( make_pair(groupName, aGroupType), aListOfNewGroups ));
+        listOfNewGroups.clear();
+        listOfNewGroups.push_back( newGroup );
+        groupsMap.insert( std::make_pair( TNameAndType( groupName, groupType ),
+                                          listOfNewGroups ));
       }
     }
 
-    if ( SMESH_Mesh_i* anSrcImpl = SMESH::DownCast<SMESH_Mesh_i*>( theMeshesArray[i] ))
+    if ( SMESH_Mesh_i* initImpl = SMESH::DownCast<SMESH_Mesh_i*>( theMeshesArray[i] ))
     {
-      // copy orphan nodes
-      if ( anSrcImpl->NbNodes() > (int)nodesMap.size() )
-      {
-        SMDS_ElemIteratorPtr itNodes = anInitImpl->GetElements( theMeshesArray[i], SMESH::NODE );
-        while ( itNodes->more() )
-        {
-          const SMDS_MeshNode* aNode = static_cast< const SMDS_MeshNode* >( itNodes->next() );
-          if ( aNode->NbInverseElements() == 0 )
-          {
-            aNewNode = aNewMeshDS->AddNode(aNode->X(), aNode->Y(), aNode->Z());
-            nodesMap.insert( make_pair( aNode, aNewNode ));
-          }
-        }
-      }
-
       // copy groups
 
-      SMESH::SMESH_GroupBase_ptr aGroup;
-      CORBA::String_var aGroupName;
-      SMESH::long_array_var anNewIDs = new SMESH::long_array();
+      SMESH::SMESH_GroupBase_ptr group;
+      CORBA::String_var          groupName;
+      SMESH::smIdType_array_var newIDs = new SMESH::smIdType_array();
 
       // loop on groups of a source mesh
-      aListOfGroups = anSrcImpl->GetGroups();
-      for ( CORBA::ULong iG = 0; iG < aListOfGroups->length(); iG++ )
+      SMESH::ListOfGroups_var listOfGroups = initImpl->GetGroups();
+      for ( CORBA::ULong iG = 0; iG < listOfGroups->length(); iG++ )
       {
-        aGroup = aListOfGroups[iG];
-        aGroupType = aGroup->GetType();
-        aGroupName = aGroup->GetName();
-        string aName = aGroupName.in();
+        group     = listOfGroups[iG];
+        groupType = group->GetType();
+        groupName = group->GetName();
+        std::string name = groupName.in();
 
         // convert a list of IDs
-        anNewIDs->length( aGroup->Size() );
-        TEEMap & e2neMap = ( aGroupType == SMESH::NODE ) ? nodesMap : elemsMap;
-        SMDS_ElemIteratorPtr itGrElems = anSrcImpl->GetElements( aGroup, SMESH::ALL );
-        int iElem = 0;
+        newIDs->length( group->Size() );
+        std::vector< const SMDS_MeshElement* > & elemVec =
+          ( groupType == SMESH::NODE ) ? newNodes : newElems;
+        SMDS_ElemIteratorPtr itGrElems = initImpl->GetElements( group, SMESH::ALL );
+        int nbElems = 0;
         while ( itGrElems->more() )
         {
-          anElem = itGrElems->next();
-          TEEMap::iterator e2neIt = e2neMap.find( anElem );
-          if ( e2neIt != e2neMap.end() )
-            anNewIDs[ iElem++ ] = e2neIt->second->GetID();
+          const SMDS_MeshElement*    elem = itGrElems->next();
+          const SMDS_MeshElement* newElem = elemVec[ elem->GetID() ];
+          if ( newElem )
+            newIDs[ nbElems++ ] = newElem->GetID();
         }
-        anNewIDs->length( iElem );
+        newIDs->length( nbElems );
 
-        // check a current group name and type don't have identical ones in final mesh
-        aListOfNewGroups.clear();
-        TGroupsMap::iterator anIter = aGroupsMap.find( make_pair( aName, aGroupType ));
-        if ( anIter == aGroupsMap.end() ) {
+        // check that a current group name and type don't have identical ones in final mesh
+        listOfNewGroups.clear();
+        TNameAndType nameAndType( name, groupType );
+        TGroupsMap::iterator anIter = groupsMap.find( nameAndType );
+        if ( anIter == groupsMap.end() )
+        {
           // add a new group in the mesh
-          aNewGroup = aNewImpl->CreateGroup( aGroupType, aGroupName.in() );
-          // add elements into new group
-          aNewGroup->Add( anNewIDs );
+          newGroup = newImpl->CreateGroup( groupType, groupName.in() );
+          newGroup->Add( newIDs );
 
-          aListOfNewGroups.push_back(aNewGroup);
-          aGroupsMap.insert(make_pair( make_pair(aName, aGroupType), aListOfNewGroups ));
+          listOfNewGroups.push_back( newGroup );
+          groupsMap.insert( std::make_pair( nameAndType, listOfNewGroups ));
         }
-
-        else if ( theUniteIdenticalGroups ) {
+        else if ( theUniteIdenticalGroups )
+        {
           // unite identical groups
           TListOfNewGroups& aNewGroups = anIter->second;
-          aNewGroups.front()->Add( anNewIDs );
+          aNewGroups.front()->Add( newIDs );
         }
-
-        else {
+        else
+        {
           // rename identical groups
-          aNewGroup = aNewImpl->CreateGroup(aGroupType, aGroupName.in());
-          aNewGroup->Add( anNewIDs );
+          newGroup = newImpl->CreateGroup( groupType, groupName );
+          newGroup->Add( newIDs );
 
-          TListOfNewGroups& aNewGroups = anIter->second;
-          string aNewGroupName;
-          if (aNewGroups.size() == 1) {
-            aNewGroupName = aName + "_1";
-            aNewGroups.front()->SetName(aNewGroupName.c_str());
+          TListOfNewGroups& newGroups = anIter->second;
+          std::string newGroupName;
+          if ( newGroups.size() == 1 )
+          {
+            newGroupName = name + "_1";
+            newGroups.front()->SetName( newGroupName.c_str() );
           }
-          char aGroupNum[128];
-          sprintf(aGroupNum, "%u", (unsigned int)aNewGroups.size()+1);
-          aNewGroupName = aName + "_" + string(aGroupNum);
-          aNewGroup->SetName(aNewGroupName.c_str());
-          aNewGroups.push_back(aNewGroup);
+          newGroupName = name + "_" + SMESH_Comment( newGroups.size() + 1 );
+          newGroup->SetName( newGroupName.c_str() );
+          newGroups.push_back( newGroup );
         }
-      } //groups loop
+      } // loop on groups
     } // if an IDSource is a mesh
   } //meshes loop
 
-  if (theMergeNodesAndElements) // merge nodes
+  if ( theMergeNodesAndElements ) // merge nodes
   {
-    TIDSortedNodeSet aMeshNodes; // no input nodes
-    SMESH_MeshEditor::TListOfListOfNodes aGroupsOfNodes;
-    aNewEditor.FindCoincidentNodes( aMeshNodes, theMergeTolerance, aGroupsOfNodes,
-                                    /*SeparateCornersAndMedium=*/ false );
-    aNewEditor.MergeNodes( aGroupsOfNodes );
+    TIDSortedNodeSet meshNodes; // no input nodes == treat all
+    SMESH_MeshEditor::TListOfListOfNodes groupsOfNodes;
+    newEditor.FindCoincidentNodes( meshNodes, theMergeTolerance, groupsOfNodes,
+                                   /*SeparateCornersAndMedium=*/ false );
+    newEditor.MergeNodes( groupsOfNodes );
     // merge elements
-    aNewEditor.MergeEqualElements();
+    newEditor.MergeEqualElements();
   }
 
   // Update Python script
-  aPythonDump << aNewMesh << " = " << this << "."
-              << ( theCommonGroups ? "ConcatenateWithGroups" : "Concatenate" )
-              << "([";
-  for ( CORBA::ULong i = 0; i < theMeshesArray.length(); i++) {
-    if (i > 0) aPythonDump << ", ";
-    aPythonDump << theMeshesArray[i];
-  }
-  aPythonDump << "], ";
-  aPythonDump << theUniteIdenticalGroups << ", "
-              << theMergeNodesAndElements << ", "
-              << TVar( theMergeTolerance ) << ")";
+  pythonDump << newMesh << " = " << this
+             << "." << ( theCommonGroups ? "ConcatenateWithGroups" : "Concatenate" ) << "( "
+             << theMeshesArray << ", "
+             << theUniteIdenticalGroups << ", "
+             << theMergeNodesAndElements << ", "
+             << TVar( theMergeTolerance ) << ", "
+             << theMeshToAppendTo << " )";
 
-  delete pPythonDump; // enable python dump from GetGroups()
+  pPythonDump.reset(); // enable python dump from GetGroups()
 
   // 0020577: EDF 1164 SMESH: Bad dump of concatenate with create common groups
-  if ( !aNewMesh->_is_nil() )
+  if ( !newMesh->_is_nil() )
   {
-    SMESH::ListOfGroups_var groups = aNewMesh->GetGroups();
+    SMESH::ListOfGroups_var groups = newMesh->GetGroups();
   }
 
   // IPAL21468 Change icon of compound because it need not be computed.
-  SALOMEDS::SObject_wrap aMeshSObj = ObjectToSObject( myCurrentStudy, aNewMesh );
-  SetPixMap( aMeshSObj, "ICON_SMESH_TREE_MESH" );
+  SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
+  SetPixMap( meshSO, "ICON_SMESH_TREE_MESH" );
 
-  if (aNewMeshDS)
-    aNewMeshDS->Modified();
+  newMeshDS->Modified();
 
-  return aNewMesh._retn();
+  return newMesh._retn();
 }
 
 //================================================================================
@@ -2748,7 +2817,8 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
 {
   Unexpect aCatch(SALOME_SalomeException);
 
-  TPythonDump* pyDump = new TPythonDump; // prevent dump from CreateMesh()
+  TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh()
+  std::unique_ptr<TPythonDump> pyDumpDeleter( pyDump );
 
   // 1. Get source mesh
 
@@ -2768,7 +2838,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
   SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
   if ( !newMesh_i )
     THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
-  SALOMEDS::SObject_wrap meshSO = ObjectToSObject(myCurrentStudy, newMesh );
+  SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
   if ( !meshSO->_is_nil() )
   {
     SetName( meshSO, meshName, "Mesh" );
@@ -2791,7 +2861,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
   }
   else
   {
-    SMESH::long_array_var ids = meshPart->GetIDs();
+    SMESH::smIdType_array_var ids = meshPart->GetIDs();
     if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
     {
       for ( CORBA::ULong i=0; i < ids->length(); i++ )
@@ -2874,89 +2944,1065 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
     }
   }
 
-  // 5. Copy groups
+  // 5. Copy groups
+
+  int nbNewGroups = 0;
+  if ( toCopyGroups )
+  {
+    SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups();
+    while ( gIt->more() )
+    {
+      SMESH_Group* group = gIt->next();
+      const SMESHDS_GroupBase* groupDS = group->GetGroupDS();
+
+      // Check group type. We copy nodal groups containing nodes of copied element
+      SMDSAbs_ElementType groupType = groupDS->GetType();
+      if ( groupType != SMDSAbs_Node &&
+           newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 )
+        continue; // group type differs from types of meshPart
+
+      // Find copied elements in the group
+      vector< const SMDS_MeshElement* > groupElems;
+      SMDS_ElemIteratorPtr eIt = groupDS->GetElements();
+      if ( toKeepIDs )
+      {
+        const SMDS_MeshElement* foundElem;
+        if ( groupType == SMDSAbs_Node )
+        {
+          while ( eIt->more() )
+            if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() )))
+              groupElems.push_back( foundElem );
+        }
+        else
+        {
+          while ( eIt->more() )
+            if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() )))
+              groupElems.push_back( foundElem );
+        }
+      }
+      else
+      {
+        TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ];
+        if ( e2eMap.empty() ) continue;
+        smIdType minID = e2eMap.begin()->first->GetID();
+        smIdType maxID = e2eMap.rbegin()->first->GetID();
+        TE2EMap::iterator e2e;
+        while ( eIt->more() && groupElems.size() < e2eMap.size())
+        {
+          const SMDS_MeshElement* e = eIt->next();
+          if ( e->GetID() < minID || e->GetID() > maxID ) continue;
+          if ((e2e = e2eMap.find( e )) != e2eMap.end())
+            groupElems.push_back( e2e->second );
+        }
+      }
+      // Make a new group
+      if ( !groupElems.empty() )
+      {
+        SMESH::SMESH_Group_var newGroupObj =
+          newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() );
+        if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast<SMESH_GroupBase_i*>( newGroupObj))
+        {
+          SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS();
+          SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup();
+          for ( unsigned i = 0; i < groupElems.size(); ++i )
+            smdsGroup.Add( groupElems[i] );
+
+          nbNewGroups++;
+        }
+      }
+    }
+  }
+
+  newMeshDS->Modified();
+
+  *pyDump << newMesh << " = " << this
+          << ".CopyMesh( " << meshPart << ", "
+          << "'" << meshName << "', "
+          << toCopyGroups << ", "
+          << toKeepIDs << ")";
+
+  pyDumpDeleter.reset(); // allow dump in GetGroups()
+
+  if ( nbNewGroups > 0 ) // dump created groups
+    SMESH::ListOfGroups_var groups = newMesh->GetGroups();
+
+  return newMesh._retn();
+}
+
+
+namespace // utils for CopyMeshWithGeom()
+{
+  typedef std::map< std::string, std::string >             TStr2StrMap;
+  typedef std::map< std::string, std::set< std::string > > TStr2StrSetMap;
+  typedef std::map< std::set<int>, int >                   TIdSet2IndexMap;
+  typedef std::map< std::string, int >                     TName2IndexMap;
+
+  //================================================================================
+  /*!
+   * \brief Return a new sub-shape corresponding to an old one
+   */
+  //================================================================================
+
+  struct ShapeMapper
+  {
+    SMESH_Mesh_i* mySrcMesh_i;
+    SMESH_Mesh_i* myNewMesh_i;
+    SMESH_Gen_i*  myGen_i;
+    bool          myToPublish;
+    bool          myIsSameGeom;
+
+    TStr2StrMap   myOld2NewEntryMap; // map of study entries
+
+    GEOM::ListOfGO_var         mySubshapes; // sub-shapes existing in the new geometry
+    TIdSet2IndexMap            myIds2SubshapeIndex; // to find an existing sub-shape
+    TName2IndexMap             myName2SubshapeIndex; // to find an existing sub-shape by name
+
+    bool                       myGIPMapDone;
+    GEOM::ListOfListOfLong_var myGIPMap; // filled by GetInPlaceMap()
+
+    // not directly relating to shape search
+    TStr2StrSetMap myInvalidMap; // blame shape -> invalid objects
+
+    //================================================================================
+    /*!
+     * \brief Constructor
+     */
+    ShapeMapper( SMESH_Mesh_i* srcMesh_i,
+                 SMESH_Mesh_i* newMesh_i,
+                 SMESH_Gen_i*  smeshGen_i )
+      : mySrcMesh_i( srcMesh_i ),
+        myNewMesh_i( newMesh_i ),
+        myGen_i    ( smeshGen_i ),
+        myToPublish( smeshGen_i->IsEnablePublish() ),
+        myGIPMapDone( false )
+    {
+      // retrieve from the study shape mapping made thanks to
+      // "Set presentation parameters and sub-shapes from arguments" option
+
+      GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh();
+      GEOM::GEOM_Object_var mainShapeOld = mySrcMesh_i->GetShapeToMesh();
+      SALOMEDS::SObject_wrap oldSO = myGen_i->ObjectToSObject( mainShapeOld );
+      SALOMEDS::SObject_wrap newSO = myGen_i->ObjectToSObject( mainShapeNew );
+      if ( newSO->_is_nil() )
+      {
+        myToPublish = false;
+        return;
+      }
+      if (( myIsSameGeom = mainShapeNew->_is_equivalent( mainShapeOld )))
+        return;
+      CORBA::String_var oldEntry = oldSO->GetID();
+      CORBA::String_var newEntry = newSO->GetID();
+      myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
+                                                std::string( newEntry.in() )));
+      std::string  newMainEntry = newEntry.in();
+
+      SALOMEDS::Study_var            study = myGen_i->getStudyServant();
+      GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
+      GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
+      mySubshapes                          = op->GetExistingSubObjects( mainShapeNew,
+                                                                        /*groupsOnly=*/false );
+      for ( CORBA::ULong i = 0; i < mySubshapes->length(); ++i )
+      {
+        newSO = myGen_i->ObjectToSObject( mySubshapes[ i ]);
+        SALOMEDS::ChildIterator_wrap anIter = study->NewChildIterator( newSO );
+        bool refFound = false;
+        for ( ; anIter->More(); anIter->Next() )
+        {
+          SALOMEDS::SObject_wrap so = anIter->Value();
+          if ( so->ReferencedObject( oldSO.inout() ))
+          {
+            oldEntry = oldSO->GetID();
+            newEntry = newSO->GetID();
+            if (( refFound = ( newMainEntry != oldEntry.in() )))
+              myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
+                                                        std::string( newEntry.in() )));
+          }
+        }
+        if ( !refFound )
+        {
+          GEOM::GEOM_Object_var father = mySubshapes[ i ]->GetMainShape();
+          if ( father->_is_equivalent( mainShapeNew ))
+          {
+            GEOM::ListOfLong_var ids = mySubshapes[ i ]->GetSubShapeIndices();
+            std::set< int > idSet( &ids[0] , &ids[0] + ids->length() );
+            myIds2SubshapeIndex.insert( std::make_pair( idSet, i ));
+            CORBA::String_var name = newSO->GetName();
+            if ( name.in()[0] )
+              myName2SubshapeIndex.insert( std::make_pair( name.in(), i ));
+          }
+        }
+      }
+    }
+
+    //================================================================================
+    /*!
+     * \brief Find a new sub-shape corresponding to an old one
+     */
+    GEOM::GEOM_Object_ptr FindNew( GEOM::GEOM_Object_ptr oldShape )
+    {
+      if ( myIsSameGeom )
+        return GEOM::GEOM_Object::_duplicate( oldShape );
+
+      GEOM::GEOM_Object_var newShape;
+
+      if ( CORBA::is_nil( oldShape ))
+        return newShape._retn();
+
+      if ( !isChildOfOld( oldShape ))
+        return GEOM::GEOM_Object::_duplicate( oldShape ); // shape independent of the old shape
+
+      GEOM::GEOM_Object_var mainShapeNew = myNewMesh_i->GetShapeToMesh();
+      GEOM::GEOM_Gen_var         geomGen = myGen_i->GetGeomEngine( mainShapeNew );
+
+      // try to find by entry or name
+      if ( myToPublish )
+      {
+        CORBA::String_var  oldEntry = oldShape->GetStudyEntry();
+        TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry.in() );
+        if ( o2nID != myOld2NewEntryMap.end() )
+        {
+          newShape = getShapeByEntry( o2nID->second );
+        }
+        if ( newShape->_is_nil() )
+        {
+          CORBA::String_var name = oldShape->GetName();
+          TName2IndexMap::iterator n2ind = myName2SubshapeIndex.find( name.in() );
+          if ( n2ind != myName2SubshapeIndex.end() )
+          {
+            newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ n2ind->second ]);
+            GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices();
+            GEOM::ListOfLong_var newIndices = newShape->GetSubShapeIndices();
+            if ( oldIndices->length() == 0 ||
+                 newIndices->length() == 0 ||
+                 getShapeType( myNewMesh_i, newIndices[0] ) !=
+                 getShapeType( mySrcMesh_i, oldIndices[0] ))
+              newShape = GEOM::GEOM_Object::_nil();
+          }
+        }
+      }
+
+      if ( newShape->_is_nil() )
+      {
+        // try to construct a new sub-shape using myGIPMap
+        buildGIPMap();
+        std::vector< int >   newIndices;
+        GEOM::ListOfLong_var oldIndices = oldShape->GetSubShapeIndices();
+        for ( CORBA::ULong i = 0; i < oldIndices->length(); ++i )
+        {
+          findNewIDs( oldIndices[i], newIndices );
+        }
+        if ( newIndices.size() < oldIndices->length() ) // issue #17096
+        {
+          newIndices.clear();
+          newShape = getInPlace( oldShape );
+        }
+        if ( !newIndices.empty() && newShape->_is_nil() )
+        {
+          // search for a sub-shape with same ids
+          std::set< int > idSet( newIndices.begin(), newIndices.end() );
+          TIdSet2IndexMap::iterator ids2ind = myIds2SubshapeIndex.find( idSet );
+          if ( ids2ind != myIds2SubshapeIndex.end() ) {
+            newShape = GEOM::GEOM_Object::_duplicate( mySubshapes[ ids2ind->second ]);
+          }
+          if ( newShape->_is_nil() )
+            try
+            {
+              // create a new shape
+              if ( newIndices.size() > 1 || oldShape->GetType() == GEOM_GROUP )
+              {
+                int groupType = getShapeType( myNewMesh_i, newIndices[0] );
+
+                GEOM::GEOM_IGroupOperations_wrap grOp = geomGen->GetIGroupOperations();
+                newShape = grOp->CreateGroup( mainShapeNew, groupType );
+
+                GEOM::ListOfLong_var  newIndicesList = new GEOM::ListOfLong();
+                newIndicesList->length( newIndices.size() );
+                for ( size_t i = 0; i < newIndices.size(); ++i )
+                  newIndicesList[ i ] = newIndices[ i ];
+                grOp->UnionIDs( newShape, newIndicesList );
+              }
+              else
+              {
+                GEOM::GEOM_IShapesOperations_wrap shOp = geomGen->GetIShapesOperations();
+                newShape = shOp->GetSubShape( mainShapeNew, newIndices[0] );
+              }
+            }
+            catch (...)
+            {
+            }
+        }
+      }
+
+      if ( !newShape->_is_nil() && myToPublish )
+      {
+        CORBA::String_var oldEntry, newEntry = newShape->GetStudyEntry();
+        if ( !newEntry.in() || !newEntry.in()[0] )
+        {
+          CORBA::String_var    name = oldShape->GetName();
+          SALOMEDS::SObject_wrap so = geomGen->AddInStudy( newShape, name, mainShapeNew );
+          newEntry = newShape->GetStudyEntry();
+          oldEntry = oldShape->GetStudyEntry();
+          myOld2NewEntryMap.insert( std::make_pair( std::string( oldEntry.in() ),
+                                                    std::string( newEntry.in() )));
+        }
+      }
+
+      return newShape._retn();
+    }
+
+    //================================================================================
+    /*!
+     * \brief Return a study entry of a new shape by study entry of the old one
+     */
+    std::string FindNew( const std::string & oldEntry )
+    {
+      if ( myIsSameGeom )
+        return oldEntry;
+
+      TStr2StrMap::iterator o2nID = myOld2NewEntryMap.find( oldEntry );
+      if ( o2nID != myOld2NewEntryMap.end() )
+        return o2nID->second;
+
+      GEOM::GEOM_Object_var oldShape = getShapeByEntry( oldEntry );
+      if ( oldShape->_is_nil() || !isChildOfOld( oldShape ))
+        return oldEntry;
+
+      GEOM::GEOM_Object_ptr newShape = FindNew( oldShape );
+      if ( newShape->_is_nil() )
+        return std::string();
+
+      CORBA::String_var newEntry = newShape->GetStudyEntry();
+      return newEntry.in();
+    }
+
+    //================================================================================
+    /*!
+     * \brief Return a sub-shape ID of a new shape by a sub-shape ID of the old one.
+     *        Return zero if not found or there are more than one new ID
+     */
+    int FindNew( int oldID )
+    {
+      if ( myIsSameGeom )
+        return oldID;
+
+      buildGIPMap();
+
+      int newID = 0;
+
+      if ( 0 < oldID && oldID < (int)myGIPMap->length() )
+      {
+        if ( myGIPMap[ oldID ].length() == 1 )
+        {
+          newID = myGIPMap[ oldID ][ 0 ];
+        }
+        else if ( myGIPMap[ oldID ].length() > 1 &&
+                  getShapeType( mySrcMesh_i, oldID ) == TopAbs_VERTEX )
+        {
+          // select a meshed VERTEX
+          SMESH_subMesh* newSM;
+          for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length() && !newID; ++i )
+            if (( newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( myGIPMap[ oldID ][ i ] )) &&
+                ( !newSM->IsEmpty() ))
+              newID = myGIPMap[ oldID ][ i ];
+        }
+      }
+      return newID;
+    }
+
+    //================================================================================
+    /*!
+     * \brief Return a sub-shape ID of a new shape by an old sub-mesh.
+     *        Return zero if the old shape is not kept as is in the new shape.
+     */
+    int FindNewNotChanged( SMESH_subMesh* oldSM )
+    {
+      if ( myIsSameGeom )
+        return oldSM->GetId();
+
+      int newID = FindNew( oldSM->GetId() );
+      if ( !newID )
+        return 0;
+
+      SMESH_subMesh* newSM = myNewMesh_i->GetImpl().GetSubMeshContaining( newID );
+      if ( !newSM )
+        return 0;
+
+      // consider a sub-shape as not changed if all its sub-shapes are mapped into
+      // one new sub-shape of the same type.
+
+      if ( oldSM->DependsOn().size() !=
+           newSM->DependsOn().size() )
+        return 0;
+
+      SMESH_subMeshIteratorPtr srcSMIt = oldSM->getDependsOnIterator( /*includeSelf=*/true );
+      while ( srcSMIt->more() )
+      {
+        oldSM = srcSMIt->next();
+        int newSubID = FindNew( oldSM->GetId() );
+        if ( getShapeType( myNewMesh_i, newSubID ) !=
+             getShapeType( mySrcMesh_i, oldSM->GetId() ))
+          return 0;
+      }
+      return newID;
+    }
+
+    //================================================================================
+    /*!
+     * \brief Return shape by study entry
+     */
+    GEOM::GEOM_Object_ptr getShapeByEntry( const std::string & entry )
+    {
+      GEOM::GEOM_Object_var shape;
+      SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry.c_str() );
+      if ( !so->_is_nil() )
+      {
+        CORBA::Object_var obj = so->GetObject();
+        shape = GEOM::GEOM_Object::_narrow( obj );
+      }
+      return shape._retn();
+    }
+
+    //================================================================================
+    /*!
+     * \brief Fill myGIPMap by calling GetInPlaceMap()
+     */
+    void buildGIPMap()
+    {
+      if ( !myGIPMapDone )
+      {
+        myGIPMapDone = true;
+
+        GEOM::GEOM_Object_var   mainShapeNew = myNewMesh_i->GetShapeToMesh();
+        GEOM::GEOM_Object_var   mainShapeOld = mySrcMesh_i->GetShapeToMesh();
+        GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
+        GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
+        try
+        {
+          myGIPMap = op->GetInPlaceMap( mainShapeNew, mainShapeOld );
+        }
+        catch( ... )
+        {
+          myGIPMap = new GEOM::ListOfListOfLong();
+        }
+      }
+    }
+
+    //================================================================================
+    /*!
+     * \brief Get new sub-shape by calling GetInPlace()
+     */
+    GEOM::GEOM_Object_ptr getInPlace( GEOM::GEOM_Object_ptr oldShape )
+    {
+      GEOM::GEOM_Object_var newShape;
+
+      GEOM::GEOM_Object_var   mainShapeNew = myNewMesh_i->GetShapeToMesh();
+      GEOM::GEOM_Gen_var           geomGen = myGen_i->GetGeomEngine( mainShapeNew );
+      GEOM::GEOM_IShapesOperations_wrap op = geomGen->GetIShapesOperations();
+      try
+      {
+        newShape = op->GetInPlace( mainShapeNew, oldShape );
+      }
+      catch( ... )
+      {
+      }
+      return newShape._retn();
+    }
+
+    //================================================================================
+    /*!
+     * \brief Find a new sub-shape indices by an old one in myGIPMap. Return
+     *        number of found IDs
+     */
+    int findNewIDs( int oldID, std::vector< int >& newIDs  )
+    {
+      size_t prevNbIDs = newIDs.size();
+
+      if ( 0 < oldID && oldID < (int) myGIPMap->length() )
+      {
+        for ( CORBA::ULong i = 0; i < myGIPMap[ oldID ].length(); ++i )
+          newIDs.push_back( myGIPMap[ oldID ][ i ]);
+      }
+      return newIDs.size() - prevNbIDs;
+    }
+
+    //================================================================================
+    /*!
+     * \brief Check if an object relates to the old shape
+     */
+    bool isChildOfOld( GEOM::GEOM_Object_ptr oldShape )
+    {
+      if ( CORBA::is_nil( oldShape ))
+        return false;
+      GEOM::GEOM_Object_var mainShapeOld1 = mySrcMesh_i->GetShapeToMesh();
+      GEOM::GEOM_Object_var mainShapeOld2 = oldShape->GetMainShape();
+      return ( mainShapeOld1->_is_equivalent( mainShapeOld2 ) ||
+               mainShapeOld1->_is_equivalent( oldShape ));
+    }
+
+    //================================================================================
+    /*!
+     * \brief Return shape type by shape ID
+     */
+    TopAbs_ShapeEnum getShapeType( SMESH_Mesh_i* mesh_i, int shapeID )
+    {
+      SMESHDS_Mesh* meshDS = mesh_i->GetImpl().GetMeshDS();
+      const TopoDS_Shape& shape = meshDS->IndexToShape( shapeID );
+      return shape.IsNull() ? TopAbs_SHAPE : shape.ShapeType();
+    }
+
+    //================================================================================
+    /*!
+     * \brief Store a source sub-shape for which a counterpart not found and
+     *        a smesh object invalid due to that
+     */
+    void AddInvalid( GEOM::GEOM_Object_var  srcShape,
+                     SALOMEDS::SObject_wrap smeshSO )
+    {
+      CORBA::String_var geomEntry = srcShape->GetStudyEntry();
+      if ( geomEntry.in()[0] && !smeshSO->_is_nil() )
+      {
+        CORBA::String_var smeshEntry = smeshSO->GetID();
+        myInvalidMap[ geomEntry.in() ].insert( smeshEntry.in() );
+      }
+    }
+
+    //================================================================================
+    /*!
+     * \brief Store a source sub-shape for which a counterpart not found and
+     *        a smesh object invalid due to that
+     */
+    void AddInvalid( std::string            geomEntry,
+                     SALOMEDS::SObject_wrap smeshSO )
+    {
+      if ( !geomEntry.empty() )
+      {
+        CORBA::String_var smeshEntry = smeshSO->GetID();
+        myInvalidMap[ geomEntry ].insert( smeshEntry.in() );
+      }
+    }
+
+    //================================================================================
+    /*!
+     * \brief Store a source sub-shape for which a counterpart not found and
+     *        a smesh object invalid due to that
+     */
+    void AddInvalid( int                    oldGeomID,
+                     SALOMEDS::SObject_wrap smeshSO )
+    {
+      int shapeType = getShapeType( mySrcMesh_i, oldGeomID );
+      if ( shapeType < 0 || shapeType > TopAbs_SHAPE )
+        return;
+
+      const char* typeName[] = { "COMPOUND","COMPSOLID","SOLID","SHELL",
+                                 "FACE","WIRE","EDGE","VERTEX","SHAPE" };
+
+      SMESH_Comment geomName( typeName[ shapeType ]);
+      geomName << " #" << oldGeomID;
+
+      CORBA::String_var smeshEntry = smeshSO->GetID();
+      myInvalidMap[ geomName ].insert( smeshEntry.in() );
+    }
+
+    //================================================================================
+    /*!
+     * \brief Return entries of a source sub-shape for which a counterpart not found and
+     *        of smesh objects invalid due to that
+     */
+    void GetInvalid( SMESH::string_array_out &               theInvalidEntries,
+                     std::vector< SALOMEDS::SObject_wrap > & theInvalidMeshSObjects)
+    {
+      int nbSO = 0;
+      TStr2StrSetMap::iterator entry2entrySet = myInvalidMap.begin();
+      for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet )
+      {
+        nbSO += 1 + entry2entrySet->second.size();
+      }
+      int iSO = theInvalidMeshSObjects.size(), iEntry = 0;
+      theInvalidEntries->length  ( nbSO );
+      theInvalidMeshSObjects.resize( theInvalidMeshSObjects.size() + nbSO - myInvalidMap.size() );
+
+      entry2entrySet = myInvalidMap.begin();
+      for ( ; entry2entrySet != myInvalidMap.end(); ++entry2entrySet )
+      {
+        theInvalidEntries[ iEntry++ ] = entry2entrySet->first.c_str();
+
+        std::set< std::string > & entrySet = entry2entrySet->second;
+        std::set< std::string >::iterator entry = entrySet.begin();
+        for ( ; entry != entrySet.end(); ++entry )
+        {
+          theInvalidEntries[ iEntry++ ] = entry->c_str();
+
+          SALOMEDS::SObject_wrap so = myGen_i->getStudyServant()->FindObjectID( entry->c_str() );
+          if ( !so->_is_nil() )
+            theInvalidMeshSObjects[ iSO++ ] = so;
+        }
+      }
+    }
+
+  }; // struct ShapeMapper
+
+  //================================================================================
+  /*!
+   * \brief Append an item to a CORBA sequence
+   */
+  template < class CORBA_seq, class ITEM >
+  void append( CORBA_seq& seq, ITEM item )
+  {
+    if ( !CORBA::is_nil( item ))
+    {
+      seq->length( 1 + seq->length() );
+      seq[ seq->length() - 1 ] = item;
+    }
+  }
+} // namespace // utils for CopyMeshWithGeom()
+
+//================================================================================
+/*!
+ * \brief Create a mesh by copying definitions of another mesh to a given geometry
+ *  \param [in] sourceMesh - a mesh to copy
+ *  \param [in] newGeometry - a new geometry
+ *  \param [in] toCopyGroups - to create groups in the new mesh
+ *  \param [in] toReuseHypotheses - if True, existing hypothesis will be used by the new mesh,
+ *         otherwise new hypotheses with the same parameters will be created for the new mesh.
+ *  \param [in] toCopyElements - to copy mesh elements of same sub-shapes of the two geometries
+ *  \param [out] newMesh - return a new mesh
+ *  \param [out] newGroups - return new groups
+ *  \param [out] newSubmeshes - return new sub-meshes
+ *  \param [out] newHypotheses - return new algorithms and hypotheses
+ *  \param [out] invalidEntries - return study entries of objects whose
+ *         counterparts are not found in the newGeometry, followed by entries
+ *         of mesh sub-objects that are invalid because they depend on a not found
+ *         preceding sub-shape
+ *  \return CORBA::Boolean - is a success
+ */
+//================================================================================
+
+CORBA::Boolean SMESH_Gen_i::CopyMeshWithGeom( SMESH::SMESH_Mesh_ptr       theSourceMesh,
+                                              GEOM::GEOM_Object_ptr       theNewGeometry,
+                                              const char*                 theMeshName,
+                                              CORBA::Boolean              theToCopyGroups,
+                                              CORBA::Boolean              theToReuseHypotheses,
+                                              CORBA::Boolean              theToCopyElements,
+                                              SMESH::SMESH_Mesh_out       theNewMesh,
+                                              SMESH::ListOfGroups_out     theNewGroups,
+                                              SMESH::submesh_array_out    theNewSubmeshes,
+                                              SMESH::ListOfHypothesis_out theNewHypotheses,
+                                              SMESH::string_array_out     theInvalidEntries)
+{
+  if ( CORBA::is_nil( theSourceMesh ) ||
+       CORBA::is_nil( theNewGeometry ))
+    THROW_SALOME_CORBA_EXCEPTION( "NULL arguments", SALOME::BAD_PARAM );
+
+  if ( !theSourceMesh->HasShapeToMesh() )
+    THROW_SALOME_CORBA_EXCEPTION( "Source mesh not on geometry", SALOME::BAD_PARAM );
+
+  bool ok = true;
+  SMESH_TRY;
+
+  TPythonDump pyDump(this); // prevent dump from CreateMesh()
+
+  theNewMesh        = CreateMesh( theNewGeometry );
+  theNewGroups      = new SMESH::ListOfGroups();
+  theNewSubmeshes   = new SMESH::submesh_array();
+  theNewHypotheses  = new SMESH::ListOfHypothesis();
+  theInvalidEntries = new SMESH::string_array();
+
+  std::vector< SALOMEDS::SObject_wrap > invalidSObjects;
+
+  GEOM::GEOM_Object_var srcGeom = theSourceMesh->GetShapeToMesh();
+  GEOM::GEOM_Object_var geom, newGeom;
+  SALOMEDS::SObject_wrap so;
+
+  SMESH_Mesh_i* srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theSourceMesh );
+  SMESH_Mesh_i* newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( theNewMesh );
+  srcMesh_i->Load();
+
+  ShapeMapper shapeMapper( srcMesh_i, newMesh_i, this );
+
+  // treat hypotheses of mesh and sub-meshes
+  SMESH::submesh_array_var smList = theSourceMesh->GetSubMeshes();
+  for ( CORBA::ULong iSM = 0; iSM <= smList->length(); ++iSM )
+  {
+    bool isSubMesh = ( iSM < smList->length() );
+    if ( isSubMesh )
+    {
+      // create a new sub-mesh
+      SMESH::SMESH_subMesh_var newSM;
+      geom = smList[iSM]->GetSubShape();
+      so   = ObjectToSObject( smList[iSM] );
+      CORBA::String_var name;
+      if ( !so->_is_nil() )
+        name = so->GetName();
+      newGeom = shapeMapper.FindNew( geom );
+      if ( newGeom->_is_nil() )
+      {
+        newSM = createInvalidSubMesh( theNewMesh, geom, name.in() );
+        shapeMapper.AddInvalid( geom, ObjectToSObject( newSM ));
+        ok = false;
+      }
+      else
+      {
+        newSM = theNewMesh->GetSubMesh( newGeom, name.in() );
+      }
+      append( theNewSubmeshes, newSM );
+
+      if ( newGeom->_is_nil() )
+        continue; // don't assign hypotheses
+    }
+    else
+    {
+      newGeom = GEOM::GEOM_Object::_duplicate( theNewGeometry );
+      geom    = srcGeom;
+      so      = ObjectToSObject( theNewMesh );
+      SetName( so, theMeshName, "Mesh" );
+    }
+
+    // assign hypotheses
+    SMESH::ListOfHypothesis_var hypList = theSourceMesh->GetHypothesisList( geom );
+    for ( CORBA::ULong iHyp = 0; iHyp < hypList->length(); ++iHyp )
+    {
+      SMESH::SMESH_Hypothesis_var hyp = hypList[ iHyp ];
+      SMESH_Hypothesis_i*       hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp );
+
+      // get geometry hyp depends on
+      std::vector< std::string > entryArray;
+      std::vector< int >         subIDArray;
+      bool dependsOnGeom = hyp_i->getObjectsDependOn( entryArray, subIDArray );
+
+      if ( !theToReuseHypotheses || dependsOnGeom )
+      {
+        // create a new hypothesis
+        CORBA::String_var type = hyp->GetName();
+        CORBA::String_var lib  = hyp->GetLibName();
+        CORBA::String_var data = hyp_i->SaveTo();
+        if ( data.in()[0] )
+        {
+          hyp   = CreateHypothesis( type, lib );
+          hyp_i = SMESH::DownCast< SMESH_Hypothesis_i* >( hyp );
+          hyp_i->LoadFrom( data.in() );
+          append( theNewHypotheses, hyp );
+        }
+      }
+
+      // update geometry hyp depends on
+      if ( dependsOnGeom )
+      {
+        for ( size_t iGeo = 0; iGeo < entryArray.size(); ++iGeo )
+        {
+          if ( !entryArray[ iGeo ].empty() )
+          {
+            std::string newEntry = shapeMapper.FindNew( entryArray[ iGeo ]);
+            if ( newEntry.empty() )
+            {
+              ok = false;
+              shapeMapper.AddInvalid( entryArray[ iGeo ], ObjectToSObject( hyp ));
+              shapeMapper.AddInvalid( entryArray[ iGeo ], so ); // sub-mesh
+            }
+            entryArray[ iGeo ] = newEntry;
+          }
+        }
+        for ( size_t iGeo = 0; iGeo < subIDArray.size(); ++iGeo )
+        {
+          if ( subIDArray[ iGeo ] > 0 )
+          {
+            int newID = shapeMapper.FindNew( subIDArray[ iGeo ]);
+            if ( newID < 1 )
+            {
+              ok = false;
+              shapeMapper.AddInvalid( subIDArray[ iGeo ], ObjectToSObject( hyp ));
+              shapeMapper.AddInvalid( subIDArray[ iGeo ], so ); // sub-mesh
+            }
+            subIDArray[ iGeo ] = newID;
+          }
+        }
+        if ( !hyp_i->setObjectsDependOn( entryArray, subIDArray ))
+          ok = false;
+      }
+
+      CORBA::String_var errorText;
+      theNewMesh->AddHypothesis( newGeom, hyp, errorText.out() );
+      if ( errorText.in()[0] )
+        ok = false;
+
+    } // loop on hypotheses
+  } // loop on sub-meshes and mesh
+
+
+  // copy mesh elements, keeping IDs
+  SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
+  if ( theToCopyElements && theSourceMesh->NbNodes() > 0 )
+  {
+    ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() );
+    ::SMESH_MeshEditor::ElemFeatures elemData;
+
+    SMESH_subMesh*         srcMainSM = srcMesh_i->GetImpl().GetSubMeshContaining( 1 );
+    SMESH_subMeshIteratorPtr srcSMIt = srcMainSM->getDependsOnIterator( /*includeSelf=*/true,
+                                                                        /*vertexLast=*/false);
+    while ( srcSMIt->more() )
+    {
+      SMESH_subMesh* srcSM = srcSMIt->next();
+      if ( srcSM->IsEmpty() )
+        continue; // not yet computed
+      int newID = shapeMapper.FindNewNotChanged( srcSM );
+      if ( newID < 1 )
+        continue;
+
+      SMESHDS_SubMesh* srcSMDS = srcSM->GetSubMeshDS();
+      SMDS_NodeIteratorPtr nIt = srcSMDS->GetNodes();
+      while ( nIt->more() )
+      {
+        SMESH_NodeXYZ node( nIt->next() );
+        const SMDS_MeshNode* newNode = newMeshDS->AddNodeWithID( node.X(), node.Y(), node.Z(),
+                                                                 node->GetID() );
+        const SMDS_PositionPtr pos = node->GetPosition();
+        const double*           uv = pos->GetParameters();
+        switch ( pos->GetTypeOfPosition() )
+        {
+        case SMDS_TOP_3DSPACE: newMeshDS->SetNodeInVolume( newNode, newID );               break;
+        case SMDS_TOP_FACE:    newMeshDS->SetNodeOnFace  ( newNode, newID, uv[0], uv[1] ); break;
+        case SMDS_TOP_EDGE:    newMeshDS->SetNodeOnEdge  ( newNode, newID, uv[0] );        break;
+        case SMDS_TOP_VERTEX:  newMeshDS->SetNodeOnVertex( newNode, newID );               break;
+        default: ;
+        }
+      }
+      SMDS_ElemIteratorPtr eIt = srcSMDS->GetElements();
+      while( eIt->more() )
+      {
+        const SMDS_MeshElement* e = eIt->next();
+        elemData.Init( e, /*basicOnly=*/false );
+        elemData.SetID( e->GetID() );
+        elemData.myNodes.resize( e->NbNodes() );
+        SMDS_NodeIteratorPtr nnIt = e->nodeIterator();
+        size_t iN;
+        for ( iN = 0; nnIt->more(); ++iN )
+        {
+          const SMDS_MeshNode* srcNode = nnIt->next();
+          elemData.myNodes[ iN ] = newMeshDS->FindNode( srcNode->GetID() );
+          if ( !elemData.myNodes[ iN ])
+            break;
+        }
+        if ( iN == elemData.myNodes.size() )
+          if ( const SMDS_MeshElement * newElem = editor.AddElement( elemData.myNodes, elemData ))
+            newMeshDS->SetMeshElementOnShape( newElem, newID );
+      }
+      if ( SMESH_subMesh* newSM = newMesh_i->GetImpl().GetSubMeshContaining( newID ))
+        newSM->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
+    }
+
+    newMeshDS->Modified();
+  }
+
 
-  int nbNewGroups = 0;
-  if ( toCopyGroups )
+  // treat groups
+
+  TStr2StrMap old2newGroupMap;
+
+  SALOME::GenericObj_wrap< SMESH::FilterManager > filterMgr = CreateFilterManager();
+
+  SMESH::ListOfGroups_var groups = theSourceMesh->GetGroups();
+  CORBA::ULong nbGroups = theToCopyGroups ? groups->length() : 0, nbAddedGroups = 0;
+  for ( CORBA::ULong i = 0; i < nbGroups + nbAddedGroups; ++i )
   {
-    SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups();
-    while ( gIt->more() )
-    {
-      SMESH_Group* group = gIt->next();
-      const SMESHDS_GroupBase* groupDS = group->GetGroupDS();
+    SMESH::SMESH_Group_var         stdlGroup = SMESH::SMESH_Group::_narrow        ( groups[ i ]);
+    SMESH::SMESH_GroupOnGeom_var   geomGroup = SMESH::SMESH_GroupOnGeom::_narrow  ( groups[ i ]);
+    SMESH::SMESH_GroupOnFilter_var fltrGroup = SMESH::SMESH_GroupOnFilter::_narrow( groups[ i ]);
 
-      // Check group type. We copy nodal groups containing nodes of copied element
-      SMDSAbs_ElementType groupType = groupDS->GetType();
-      if ( groupType != SMDSAbs_Node &&
-           newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 )
-        continue; // group type differs from types of meshPart
+    CORBA::String_var      name = groups[ i ]->GetName();
+    SMESH::ElementType elemType = groups[ i ]->GetType();
 
-      // Find copied elements in the group
-      vector< const SMDS_MeshElement* > groupElems;
-      SMDS_ElemIteratorPtr eIt = groupDS->GetElements();
-      if ( toKeepIDs )
+    SMESH::SMESH_GroupBase_var newGroup;
+
+    if ( !stdlGroup->_is_nil() )
+    {
+      if ( newMeshDS->GetMeshInfo().NbElements( SMDSAbs_ElementType( elemType )) > 0 )
       {
-        const SMDS_MeshElement* foundElem;
-        if ( groupType == SMDSAbs_Node )
-        {
-          while ( eIt->more() )
-            if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() )))
-              groupElems.push_back( foundElem );
-        }
-        else
+        SMESH::smIdType_array_var elemIDs = stdlGroup->GetIDs();
+        const bool isElem = ( elemType != SMESH::NODE );
+        CORBA::ULong iE = 0;
+        for ( ; iE < elemIDs->length(); ++iE ) // check if any element has been copied
+          if ( newMeshDS->GetElementType( elemIDs[ iE ], isElem ) != SMDSAbs_All )
+            break;
+        if ( iE < elemIDs->length() )
         {
-          while ( eIt->more() )
-            if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() )))
-              groupElems.push_back( foundElem );
+          stdlGroup = theNewMesh->CreateGroup( elemType, name );
+          stdlGroup->Add( elemIDs );
+          newGroup = SMESH::SMESH_GroupBase::_narrow( stdlGroup );
         }
       }
+    }
+    else if ( !geomGroup->_is_nil() )
+    {
+      GEOM::GEOM_Object_var    geom = geomGroup->GetShape();
+      GEOM::GEOM_Object_var newGeom = shapeMapper.FindNew( geom );
+      if ( newGeom->_is_nil() )
+      {
+        newGroup = theNewMesh->CreateGroup( elemType, name ); // just to notify the user
+        shapeMapper.AddInvalid( geom, ObjectToSObject( newGroup ));
+        ok = false;
+      }
       else
       {
-        TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ];
-        if ( e2eMap.empty() ) continue;
-        int minID = e2eMap.begin()->first->GetID();
-        int maxID = e2eMap.rbegin()->first->GetID();
-        TE2EMap::iterator e2e;
-        while ( eIt->more() && groupElems.size() < e2eMap.size())
-        {
-          const SMDS_MeshElement* e = eIt->next();
-          if ( e->GetID() < minID || e->GetID() > maxID ) continue;
-          if ((e2e = e2eMap.find( e )) != e2eMap.end())
-            groupElems.push_back( e2e->second );
-        }
+        newGroup = theNewMesh->CreateGroupFromGEOM( elemType, name, newGeom );
       }
-      // Make a new group
-      if ( !groupElems.empty() )
+    }
+    else if ( !fltrGroup->_is_nil() )
+    {
+      // replace geometry in a filter
+      SMESH::Filter_var filter = fltrGroup->GetFilter();
+      SMESH::Filter::Criteria_var criteria;
+      filter->GetCriteria( criteria.out() );
+
+      bool isMissingGroup = false;
+      std::vector< std::string > badEntries;
+
+      for ( CORBA::ULong iCr = 0; iCr < criteria->length(); ++iCr )
       {
-        SMESH::SMESH_Group_var newGroupObj =
-          newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() );
-        if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast<SMESH_GroupBase_i*>( newGroupObj))
+        const char* thresholdID = criteria[ iCr ].ThresholdID.in();
+        switch ( criteria[ iCr ].Type )
         {
-          SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS();
-          SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup();
-          for ( unsigned i = 0; i < groupElems.size(); ++i )
-            smdsGroup.Add( groupElems[i] );
+        case SMESH::FT_BelongToMeshGroup:
+        {
+          SALOME::GenericObj_wrap< SMESH::BelongToMeshGroup > btgg = filterMgr->CreateBelongToMeshGroup();
+          btgg->SetGroupID( thresholdID );
+          SMESH::SMESH_GroupBase_ptr refGroup = btgg->GetGroup();
+          SALOMEDS::SObject_wrap   refGroupSO = ObjectToSObject( refGroup );
+          if ( refGroupSO->_is_nil() )
+            break;
+          CORBA::String_var     refID = refGroupSO->GetID();
+          TStr2StrMap::iterator o2nID = old2newGroupMap.find( refID.in() );
+          if ( o2nID == old2newGroupMap.end() )
+          {
+            isMissingGroup = true; // corresponding new group not yet created
+            break;
+          }
+          criteria[ iCr ].ThresholdID = o2nID->second.c_str();
 
-          nbNewGroups++;
+          if ( o2nID->second.empty() ) // new referred group is invalid
+            badEntries.push_back( refID.in() );
+          break;
+        }
+        case SMESH::FT_BelongToGeom:
+        case SMESH::FT_BelongToPlane:
+        case SMESH::FT_BelongToCylinder:
+        case SMESH::FT_BelongToGenSurface:
+        case SMESH::FT_LyingOnGeom:
+        {
+          std::string newID = shapeMapper.FindNew( thresholdID );
+          criteria[ iCr ].ThresholdID = newID.c_str();
+          if ( newID.empty() )
+            badEntries.push_back( thresholdID );
+          break;
+        }
+        case SMESH::FT_ConnectedElements:
+        {
+          if ( thresholdID && thresholdID[0] )
+          {
+            std::string newID = shapeMapper.FindNew( thresholdID );
+            criteria[ iCr ].ThresholdID = newID.c_str();
+            if ( newID.empty() )
+              badEntries.push_back( thresholdID );
+          }
+          break;
+        }
+        default:;
         }
+      } // loop on criteria
+
+      if ( isMissingGroup && i < nbGroups )
+      {
+        // to treat the group again
+        append( groups, SMESH::SMESH_GroupBase::_duplicate( groups[ i ]));
+        ++nbAddedGroups;
+        continue;
+      }
+      SMESH::Filter_var newFilter = filterMgr->CreateFilter();
+      newFilter->SetCriteria( criteria );
+
+      newGroup = theNewMesh->CreateGroupFromFilter( elemType, name, newFilter );
+      newFilter->UnRegister();
+
+      SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup );
+      for ( size_t iEnt = 0; iEnt < badEntries.size(); ++iEnt )
+        shapeMapper.AddInvalid( badEntries[ iEnt ], newSO );
+
+      if ( isMissingGroup ) // all groups treated but a referred groups still not found
+      {
+        invalidSObjects.push_back( ObjectToSObject( newGroup ));
+        ok = false;
       }
+      if ( !badEntries.empty() )
+        ok = false;
+
+    } // treat a group on filter
+
+    append( theNewGroups, newGroup );
+
+    // fill old2newGroupMap
+    SALOMEDS::SObject_wrap srcSO = ObjectToSObject( groups[i] );
+    SALOMEDS::SObject_wrap newSO = ObjectToSObject( newGroup );
+    if ( !srcSO->_is_nil() )
+    {
+      CORBA::String_var srcID, newID("");
+      srcID = srcSO->GetID();
+      if ( !newSO->_is_nil() )
+        newID = newSO->GetID();
+      old2newGroupMap.insert( std::make_pair( std::string( srcID.in() ),
+                                              std::string( newID.in() )));
     }
-  }
 
-  newMeshDS->Modified();
+    if ( newGroup->_is_nil() )
+      ok = false;
 
-  *pyDump << newMesh << " = " << this
-          << ".CopyMesh( " << meshPart << ", "
-          << "'" << meshName << "', "
-          << toCopyGroups << ", "
-          << toKeepIDs << ")";
+  } // loop on groups
 
-  delete pyDump; pyDump = 0; // allow dump in GetGroups()
+  newMeshDS->CompactMesh();
 
-  if ( nbNewGroups > 0 ) // dump created groups
-    SMESH::ListOfGroups_var groups = newMesh->GetGroups();
+  // set mesh name
+  if ( !theMeshName || !theMeshName[0] )
+  {
+    SALOMEDS::SObject_wrap soNew = ObjectToSObject( theNewMesh );
+    SALOMEDS::SObject_wrap soOld = ObjectToSObject( theSourceMesh );
+    CORBA::String_var oldName = soOld->GetName();
+    SetName( soNew, oldName.in(), "Mesh" );
+  }
+  // mark invalid objects
+  shapeMapper.GetInvalid( theInvalidEntries, invalidSObjects );
+
+  for ( size_t i = 0; i < invalidSObjects.size(); ++i )
+    highLightInvalid( invalidSObjects[i].in(), true );
+
+  pyDump << "ok, "
+         << theNewMesh << ", "
+         << theNewGroups << ", "
+         << *theNewSubmeshes.ptr() << ", "
+         << *theNewHypotheses.ptr() << ", "
+         << "invalidEntries = " << this << ".CopyMeshWithGeom( "
+         << theSourceMesh << ", "
+         << theNewGeometry << ", "
+         << "'" << theMeshName << "', "
+         << theToCopyGroups << ", "
+         << theToReuseHypotheses << ", "
+         << theToCopyElements << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return ok;
+}
 
-  return newMesh._retn();
+//================================================================================
+/*!
+ * \brief Get version of MED format being used.
+ */
+//================================================================================
+
+char* SMESH_Gen_i::GetMEDFileVersion()
+{
+  MED::TInt majeur, mineur, release;
+  majeur =  mineur = release = 0;
+  MED::GetVersionRelease(majeur, mineur, release);
+  std::ostringstream version;
+  version << majeur << "." << mineur << "." << release;
+  return CORBA::string_dup( version.str().c_str() );
 }
 
 //================================================================================
@@ -2966,28 +4012,37 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
  *  Get MED version of the file by its name
  */
 //================================================================================
-CORBA::Boolean SMESH_Gen_i::GetMEDVersion(const char* theFileName,
-                                          SMESH::MED_VERSION& theVersion)
+
+char* SMESH_Gen_i::GetMEDVersion(const char* theFileName)
 {
-  theVersion = SMESH::MED_V2_1;
-  MED::EVersion aVersion = MED::GetVersionId( theFileName );
-  switch( aVersion ) {
-    case MED::eV2_1     : theVersion = SMESH::MED_V2_1;    return true;
-    case MED::eV2_2     : theVersion = SMESH::MED_V2_2;    return true;
-    case MED::eLATEST   : theVersion = SMESH::MED_LATEST;  return true;
-    case MED::eMINOR_0  : theVersion = SMESH::MED_MINOR_0; return true;
-    case MED::eMINOR_1  : theVersion = SMESH::MED_MINOR_1; return true;
-    case MED::eMINOR_2  : theVersion = SMESH::MED_MINOR_2; return true;
-    case MED::eMINOR_3  : theVersion = SMESH::MED_MINOR_3; return true;
-    case MED::eMINOR_4  : theVersion = SMESH::MED_MINOR_4; return true;
-    case MED::eMINOR_5  : theVersion = SMESH::MED_MINOR_5; return true;
-    case MED::eMINOR_6  : theVersion = SMESH::MED_MINOR_6; return true;
-    case MED::eMINOR_7  : theVersion = SMESH::MED_MINOR_7; return true;
-    case MED::eMINOR_8  : theVersion = SMESH::MED_MINOR_8; return true;
-    case MED::eMINOR_9  : theVersion = SMESH::MED_MINOR_9; return true;
-    case MED::eVUnknown : return false;
-  }
-  return false;
+  std::string version = MED::GetMEDVersion( theFileName );
+  return CORBA::string_dup( version.c_str() );
+}
+
+//================================================================================
+/*!
+ *  SMESH_Gen_i::CheckCompatibility
+ *
+ *  Check compatibility of file with MED format being used, read only.
+ */
+//================================================================================
+
+CORBA::Boolean SMESH_Gen_i::CheckCompatibility(const char* theFileName)
+{
+  return MED::CheckCompatibility( theFileName );
+}
+
+//================================================================================
+/*!
+ *  SMESH_Gen_i::CheckWriteCompatibility
+ *
+ *  Check compatibility of file with MED format being used, for append on write.
+ */
+//================================================================================
+
+CORBA::Boolean SMESH_Gen_i::CheckWriteCompatibility(const char* theFileName)
+{
+  return MED::CheckCompatibility( theFileName, true );
 }
 
 //================================================================================
@@ -2998,9 +4053,10 @@ CORBA::Boolean SMESH_Gen_i::GetMEDVersion(const char* theFileName,
  */
 //================================================================================
 SMESH::string_array* SMESH_Gen_i::GetMeshNames(const char* theFileName)
+
 {
   SMESH::string_array_var aResult = new SMESH::string_array();
-  MED::PWrapper aMed = MED::CrWrapper( theFileName );
+  MED::PWrapper aMed = MED::CrWrapperR( theFileName );
   MED::TErr anErr;
   MED::TInt aNbMeshes = aMed->GetNbMeshes( &anErr );
   if( anErr >= 0 ) {
@@ -3020,20 +4076,21 @@ SMESH::string_array* SMESH_Gen_i::GetMeshNames(const char* theFileName)
  *  Save SMESH module's data
  */
 //=============================================================================
+
 SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                                       const char*              theURL,
                                       bool                     isMultiFile )
 {
-  //  ASSERT( theComponent->GetStudy()->StudyId() == myCurrentStudy->StudyId() )
-  // san -- in case <myCurrentStudy> differs from theComponent's study,
-  // use that of the component
-  if ( theComponent->GetStudy()->StudyId() != GetCurrentStudyID() )
-    SetCurrentStudy( theComponent->GetStudy() );
+  // localizing
+  Kernel_Utils::Localizer loc;
+
+  if (!myStudyContext)
+    UpdateStudy();
 
   // Store study contents as a set of python commands
-  SavePython(myCurrentStudy);
+  SavePython();
 
-  StudyContext* myStudyContext = GetCurrentStudyContext();
+  SALOMEDS::Study_var aStudy = getStudyServant();
 
   // Declare a byte stream
   SALOMEDS::TMPFile_var aStreamFile;
@@ -3043,20 +4100,20 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
     ( isMultiFile ) ? TCollection_AsciiString( ( char* )theURL ) : ( char* )SALOMEDS_Tool::GetTmpDir().c_str();
 
   // Create a sequence of files processed
-  SALOMEDS::ListOfFileNames_var aFileSeq = new SALOMEDS::ListOfFileNames;
-  aFileSeq->length( NUM_TMP_FILES );
+  SALOMEDS_Tool::ListOfFiles aFileSeq;
+  aFileSeq.reserve( NUM_TMP_FILES );
 
   TCollection_AsciiString aStudyName( "" );
   if ( isMultiFile )
-    aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( myCurrentStudy->URL() ).c_str() );
+    aStudyName = ( (char*)SALOMEDS_Tool::GetNameFromPath( Kernel_Utils::encode(aStudy->URL()) ).c_str() );
 
   // Set names of temporary files
   TCollection_AsciiString filename =
     aStudyName + TCollection_AsciiString( "_SMESH.hdf" );        // for SMESH data itself
   TCollection_AsciiString meshfile =
     aStudyName + TCollection_AsciiString( "_SMESH_Mesh.med" );   // for mesh data to be stored in MED file
-  aFileSeq[ 0 ] = CORBA::string_dup( filename.ToCString() );
-  aFileSeq[ 1 ] = CORBA::string_dup( meshfile.ToCString() );
+  aFileSeq.push_back(CORBA::string_dup( filename.ToCString() ));
+  aFileSeq.push_back(CORBA::string_dup( meshfile.ToCString() ));
   filename = tmpDir + filename;
   meshfile = tmpDir + meshfile;
 
@@ -3080,17 +4137,21 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
   cmd+="\" \"";
   cmd+=meshfile;
   cmd+="\"";
+#ifdef WIN32
+  cmd+=" 2>NUL";
+#endif
   system(cmd.ToCString());
 
   // MED writer to be used by storage process
-  DriverMED_W_SMESHDS_Mesh myWriter;
-  myWriter.SetFile( meshfile.ToCString() );
+  DriverMED_W_SMESHDS_Mesh writer;
+  writer.SetFile( meshfile.ToCString() );
+  //writer.SetSaveNumbers( false ); // bos #24400 -- it leads to change of element IDs
 
   // IMP issue 20918
   // SetStoreName() to groups before storing hypotheses to let them refer to
   // groups using "store name", which is "Group <group_persistent_id>"
   {
-    SALOMEDS::ChildIterator_wrap itBig = myCurrentStudy->NewChildIterator( theComponent );
+    SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( theComponent );
     for ( ; itBig->More(); itBig->Next() ) {
       SALOMEDS::SObject_wrap gotBranch = itBig->Value();
       if ( gotBranch->Tag() > GetAlgorithmsRootTag() ) {
@@ -3099,9 +4160,8 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
           SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
           if ( !myMesh->_is_nil() ) {
             myMesh->Load(); // load from study file if not yet done
-            TPythonDump pd; // not to dump GetGroups()
+            TPythonDump pd(this); // not to dump GetGroups()
             SMESH::ListOfGroups_var groups = myMesh->GetGroups();
-            pd << ""; // to avoid optimizing pd out
             for ( CORBA::ULong i = 0; i < groups->length(); ++i )
             {
               SMESH_GroupBase_i* grImpl = SMESH::DownCast<SMESH_GroupBase_i*>( groups[i]);
@@ -3110,7 +4170,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 CORBA::String_var objStr = GetORB()->object_to_string( grImpl->_this() );
                 int anId = myStudyContext->findId( string( objStr.in() ) );
                 char grpName[ 30 ];
-                sprintf( grpName, "Group %d", anId );
+                sprintf( grpName, "Group %d %d", anId, grImpl->GetLocalID() );
                 SMESHDS_GroupBase* aGrpBaseDS = grImpl->GetGroupDS();
                 aGrpBaseDS->SetStoreName( grpName );
               }
@@ -3127,7 +4187,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
   aFile->CreateOnDisk();
 
   // --> iterator for top-level objects
-  SALOMEDS::ChildIterator_wrap itBig = myCurrentStudy->NewChildIterator( theComponent );
+  SALOMEDS::ChildIterator_wrap itBig = aStudy->NewChildIterator( theComponent );
   for ( ; itBig->More(); itBig->Next() ) {
     SALOMEDS::SObject_wrap gotBranch = itBig->Value();
 
@@ -3138,7 +4198,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
       aTopGroup->CreateOnDisk();
 
       // iterator for all hypotheses
-      SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( gotBranch );
+      SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( gotBranch );
       for ( ; it->More(); it->Next() ) {
         SALOMEDS::SObject_wrap mySObject = it->Value();
         CORBA::Object_var anObject = SObjectToObject( mySObject );
@@ -3147,8 +4207,9 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
           if ( !myHyp->_is_nil() ) {
             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
             if ( myImpl ) {
-              string hypname = string( myHyp->GetName() );
-              string libname = string( myHyp->GetLibName() );
+              CORBA::String_var hn = myHyp->GetName(), ln = myHyp->GetLibName();
+              std::string hypname = hn.in();
+              std::string libname = ln.in();
               // BUG SWP13062
               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
               // WIN32 and ".so" for X-system) must be deleted
@@ -3159,14 +4220,12 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
 #else
               // PAL17753 (Regression: missing hypothesis in restored study)
               // "lib" also should be removed from the beginning
-              //if( libname_len > 3 )
-                //libname.resize( libname_len - 3 );
               if( libname_len > 6 )
                 libname = libname.substr( 3, libname_len - 3 - 3 );
 #endif
-              CORBA::String_var objStr = GetORB()->object_to_string( anObject );
-              int    id      = myStudyContext->findId( string( objStr.in() ) );
-              string hypdata = string( myImpl->SaveTo() );
+              CORBA::String_var  objStr = GetORB()->object_to_string( anObject );
+              CORBA::String_var hypdata = myImpl->SaveTo();
+              int                    id = myStudyContext->findId( string( objStr.in() ));
 
               // for each hypothesis create HDF group basing on its id
               char hypGrpName[30];
@@ -3186,10 +4245,10 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
               aDataset->CloseOnDisk();
               // --> persistent data of hypothesis
-              aSize[ 0 ] = hypdata.length() + 1;
+              aSize[ 0 ] = strlen( hypdata.in() ) + 1;
               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
               aDataset->CreateOnDisk();
-              aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
+              aDataset->WriteOnDisk( ( char* )( hypdata.in() ) );
               aDataset->CloseOnDisk();
               // close hypothesis HDF group
               aGroup->CloseOnDisk();
@@ -3207,7 +4266,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
       aTopGroup->CreateOnDisk();
 
       // iterator for all algorithms
-      SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( gotBranch );
+      SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( gotBranch );
       for ( ; it->More(); it->Next() ) {
         SALOMEDS::SObject_wrap mySObject = it->Value();
         CORBA::Object_var anObject = SObjectToObject( mySObject );
@@ -3216,8 +4275,9 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
           if ( !myHyp->_is_nil() ) {
             SMESH_Hypothesis_i* myImpl = dynamic_cast<SMESH_Hypothesis_i*>( GetServant( myHyp ).in() );
             if ( myImpl ) {
-              string hypname = string( myHyp->GetName() );
-              string libname = string( myHyp->GetLibName() );
+              CORBA::String_var hn = myHyp->GetName(), ln = myHyp->GetLibName();
+              std::string hypname = hn.in();
+              std::string libname = ln.in();
               // BUG SWP13062
               // Needs for save crossplatform libname, i.e. parth of name ( ".dll" for
               // WIN32 and ".so" for X-system) must be deleted
@@ -3228,14 +4288,12 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
 #else
               // PAL17753 (Regression: missing hypothesis in restored study)
               // "lib" also should be removed from the beginning
-              //if( libname_len > 3 )
-                //libname.resize( libname_len - 3 );
               if( libname_len > 6 )
                 libname = libname.substr( 3, libname_len - 3 - 3 );
 #endif
-              CORBA::String_var objStr = GetORB()->object_to_string( anObject );
-              int    id      = myStudyContext->findId( string( objStr.in() ) );
-              string hypdata = string( myImpl->SaveTo() );
+              CORBA::String_var  objStr = GetORB()->object_to_string( anObject );
+              CORBA::String_var hypdata = myImpl->SaveTo();
+              int                    id = myStudyContext->findId( string( objStr.in() ) );
 
               // for each algorithm create HDF group basing on its id
               char hypGrpName[30];
@@ -3255,10 +4313,10 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
               aDataset->WriteOnDisk( ( char* )( libname.c_str() ) );
               aDataset->CloseOnDisk();
               // --> persistent data of algorithm
-              aSize[0] = hypdata.length() + 1;
+              aSize[0] = strlen( hypdata.in() ) + 1;
               aDataset = new HDFdataset( "Data", aGroup, HDF_STRING, aSize, 1 );
               aDataset->CreateOnDisk();
-              aDataset->WriteOnDisk( ( char* )( hypdata.c_str() ) );
+              aDataset->WriteOnDisk( ( char* )( hypdata.in() ));
               aDataset->CloseOnDisk();
               // close algorithm HDF group
               aGroup->CloseOnDisk();
@@ -3294,8 +4352,8 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
             // check if the mesh is not empty
             if ( mySMESHDSMesh->NbNodes() > 0 ) {
               // write mesh data to med file
-              myWriter.SetMesh( mySMESHDSMesh );
-              myWriter.SetMeshId( id );
+              writer.SetMesh( mySMESHDSMesh );
+              writer.SetMeshId( id );
               strHasData = "1";
             }
             aSize[ 0 ] = strHasData.length() + 1;
@@ -3332,37 +4390,57 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
             aDataset->WriteOnDisk( &meshPersistentId );
             aDataset->CloseOnDisk();
 
+            // Store SMESH_Mesh_i::_mainShapeTick
+            int shapeTick = myImpl->MainShapeTick();
+            aSize[ 0 ] = 1;
+            aDataset = new HDFdataset( "shapeTick", aTopGroup, HDF_INT32, aSize, 1 );
+            aDataset->CreateOnDisk();
+            aDataset->WriteOnDisk( &shapeTick );
+            aDataset->CloseOnDisk();
+
             // write reference on a shape if exists
             SALOMEDS::SObject_wrap myRef;
             bool shapeRefFound = false;
-            bool found = gotBranch->FindSubObject( GetRefOnShapeTag(), myRef.inout() );
+            bool found = gotBranch->FindSubObject( (CORBA::Long)GetRefOnShapeTag(), myRef.inout() );
             if ( found ) {
               SALOMEDS::SObject_wrap myShape;
               bool ok = myRef->ReferencedObject( myShape.inout() );
               if ( ok ) {
-                shapeRefFound = (! CORBA::is_nil( myShape->GetObject() ));
-                string myRefOnObject = myShape->GetID();
-                if ( shapeRefFound && myRefOnObject.length() > 0 ) {
-                  aSize[ 0 ] = myRefOnObject.length() + 1;
+                CORBA::Object_var shapeObj = myShape->GetObject();
+                shapeRefFound = (! CORBA::is_nil( shapeObj ));
+                CORBA::String_var myRefOnObject = myShape->GetID();
+                if ( shapeRefFound && myRefOnObject.in()[0] ) {
+                  aSize[ 0 ] = strlen( myRefOnObject.in() ) + 1;
                   aDataset = new HDFdataset( "Ref on shape", aTopGroup, HDF_STRING, aSize, 1 );
                   aDataset->CreateOnDisk();
-                  aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
+                  aDataset->WriteOnDisk( ( char* )( myRefOnObject.in() ) );
                   aDataset->CloseOnDisk();
                 }
               }
             }
 
+            // Store file info
+            std::string info = myImpl->FileInfoToString();
+            if ( !info.empty() )
+            {
+              aSize[ 0 ] = info.size();
+              aDataset = new HDFdataset( "file info", aTopGroup, HDF_STRING, aSize, 1 );
+              aDataset->CreateOnDisk();
+              aDataset->WriteOnDisk( (char*) info.data() );
+              aDataset->CloseOnDisk();
+            }
+
             // write applied hypotheses if exist
             SALOMEDS::SObject_wrap myHypBranch;
-            found = gotBranch->FindSubObject( GetRefOnAppliedHypothesisTag(), myHypBranch.inout() );
-            if ( found && !shapeRefFound && hasShape) { // remove applied hyps
-              myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch );
+            found = gotBranch->FindSubObject( (CORBA::Long)GetRefOnAppliedHypothesisTag(), myHypBranch.inout() );
+            if ( found && !shapeRefFound && hasShape ) { // remove applied hyps
+              aStudy->NewBuilder()->RemoveObjectWithChildren( myHypBranch );
             }
             if ( found && (shapeRefFound || !hasShape) ) {
               aGroup = new HDFgroup( "Applied Hypotheses", aTopGroup );
               aGroup->CreateOnDisk();
 
-              SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( myHypBranch );
+              SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myHypBranch );
               int hypNb = 0;
               for ( ; it->More(); it->Next() ) {
                 SALOMEDS::SObject_wrap mySObject = it->Value();
@@ -3400,13 +4478,13 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
             found = gotBranch->FindSubObject( GetRefOnAppliedAlgorithmsTag(),
                                               myAlgoBranch.inout() );
             if ( found && !shapeRefFound && hasShape) { // remove applied algos
-              myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch );
+              aStudy->NewBuilder()->RemoveObjectWithChildren( myAlgoBranch );
             }
             if ( found && (shapeRefFound || !hasShape)) {
               aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
               aGroup->CreateOnDisk();
 
-              SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( myAlgoBranch );
+              SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myAlgoBranch );
               int algoNb = 0;
               for ( ; it->More(); it->Next() ) {
                 SALOMEDS::SObject_wrap mySObject = it->Value();
@@ -3449,7 +4527,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
               {
                 bool hasShapeRef = false;
                 SALOMEDS::ChildIterator_wrap itSM =
-                  myCurrentStudy->NewChildIterator( mySubmeshBranch );
+                  aStudy->NewChildIterator( mySubmeshBranch );
                 for ( ; itSM->More(); itSM->Next() ) {
                   SALOMEDS::SObject_wrap mySubRef, myShape, mySObject = itSM->Value();
                   if ( mySObject->FindSubObject( GetRefOnShapeTag(), mySubRef.inout() ))
@@ -3474,11 +4552,11 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                         }
                       }
                     }
-                    myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySObject );
+                    aStudy->NewBuilder()->RemoveObjectWithChildren( mySObject );
                   }
                 } // loop on submeshes of a type
                 if ( !shapeRefFound || !hasShapeRef ) { // remove the whole submeshes branch
-                  myCurrentStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch );
+                  aStudy->NewBuilder()->RemoveObjectWithChildren( mySubmeshBranch );
                   found = false;
                 }
               }  // end check if there is shape reference in submeshes
@@ -3504,7 +4582,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 aGroup->CreateOnDisk();
 
                 // iterator for all submeshes of given type
-                SALOMEDS::ChildIterator_wrap itSM = myCurrentStudy->NewChildIterator( mySubmeshBranch );
+                SALOMEDS::ChildIterator_wrap itSM = aStudy->NewChildIterator( mySubmeshBranch );
                 for ( ; itSM->More(); itSM->Next() ) {
                   SALOMEDS::SObject_wrap mySObject = itSM->Value();
                   CORBA::Object_var anSubObject = SObjectToObject( mySObject );
@@ -3541,7 +4619,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                       aSubSubGroup = new HDFgroup( "Applied Hypotheses", aSubGroup );
                       aSubSubGroup->CreateOnDisk();
 
-                      SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( mySubHypBranch );
+                      SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( mySubHypBranch );
                       int hypNb = 0;
                       for ( ; it->More(); it->Next() ) {
                         SALOMEDS::SObject_wrap mySubSObject = it->Value();
@@ -3578,7 +4656,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                       aSubSubGroup->CreateOnDisk();
 
                       SALOMEDS::ChildIterator_wrap it =
-                        myCurrentStudy->NewChildIterator( mySubAlgoBranch );
+                        aStudy->NewChildIterator( mySubAlgoBranch );
                       int algoNb = 0;
                       for ( ; it->More(); it->Next() ) {
                         SALOMEDS::SObject_wrap mySubSObject = it->Value();
@@ -3613,14 +4691,11 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 aGroup->CloseOnDisk();
               }
             }
-            // All sub-meshes will be stored in MED file
-            // .. will NOT (PAL 12992)
-            //if ( shapeRefFound )
-            //myWriter.AddAllSubMeshes();
 
             // store submesh order if any
             const TListOfListOfInt& theOrderIds = myLocMesh.GetMeshOrder();
-            if ( theOrderIds.size() ) {
+            const bool isNewOrederVersion = true; // old version saves ids, new one, entries
+            if ( !theOrderIds.empty() && !isNewOrederVersion ) { // keep old version for reference
               char order_list[ 30 ];
               strcpy( order_list, "Mesh Order" );
               // count number of submesh ids
@@ -3651,6 +4726,38 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
               //
               delete[] smIDs;
             }
+            if ( !theOrderIds.empty() && isNewOrederVersion )
+            {
+              // convert ids to entries
+              std::list< std::list< std::string > > orderEntryLists;
+              for ( const TListOfInt& idList : theOrderIds )
+              {
+                orderEntryLists.emplace_back();
+                std::list< std::string > & entryList = orderEntryLists.back();
+                for ( const int& id : idList )
+                {
+                  const TopoDS_Shape& shape = mySMESHDSMesh->IndexToShape( id );
+                  GEOM::GEOM_Object_var  go = ShapeToGeomObject( shape );
+                  SALOMEDS::SObject_var  so = ObjectToSObject( go );
+                  if ( !so->_is_nil() )
+                  {
+                    CORBA::String_var entry = so->GetID();
+                    entryList.emplace_back( entry.in() );
+                  }
+                }
+              }
+              // convert orderEntryLists to string
+              std::ostringstream ostream;
+              boost::archive::text_oarchive( ostream ) << orderEntryLists;
+              std::string orderEntryString = ostream.str();
+
+              // write HDF group
+              aSize[ 0 ] = orderEntryString.size() + 1;
+              aDataset = new HDFdataset( "MeshOrder_new", aTopGroup, HDF_STRING, aSize, 1 );
+              aDataset->CreateOnDisk();
+              aDataset->WriteOnDisk((char*) orderEntryString.data() );
+              aDataset->CloseOnDisk();
+            }
 
             // groups root sub-branch
             SALOMEDS::SObject_wrap myGroupsBranch;
@@ -3674,7 +4781,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 aGroup = new HDFgroup( name_group, aTopGroup );
                 aGroup->CreateOnDisk();
 
-                SALOMEDS::ChildIterator_wrap it = myCurrentStudy->NewChildIterator( myGroupsBranch );
+                SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( myGroupsBranch );
                 for ( ; it->More(); it->Next() ) {
                   SALOMEDS::SObject_wrap mySObject = it->Value();
                   CORBA::Object_var aSubObject = SObjectToObject( mySObject );
@@ -3692,8 +4799,8 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
 
                     // For each group, create a dataset named "Group <group_persistent_id>"
                     // and store the group's user name into it
-                    const char* grpName = aGrpBaseDS->GetStoreName();
-                    char* aUserName = myGroupImpl->GetName();
+                    const char*         grpName = aGrpBaseDS->GetStoreName();
+                    CORBA::String_var aUserName = myGroupImpl->GetName();
                     aSize[ 0 ] = strlen( aUserName ) + 1;
 
                     aDataset = new HDFdataset( grpName, aGroup, HDF_STRING, aSize, 1 );
@@ -3720,7 +4827,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                     // Pass SMESHDS_Group to MED writer
                     SMESHDS_Group* aGrpDS = dynamic_cast<SMESHDS_Group*>( aGrpBaseDS );
                     if ( aGrpDS )
-                      myWriter.AddGroup( aGrpDS );
+                      writer.AddGroup( aGrpDS );
 
                     // write reference on a shape if exists
                     SMESHDS_GroupOnGeom* aGeomGrp =
@@ -3731,21 +4838,21 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                           mySubRef->ReferencedObject( myShape.inout() ) &&
                           !CORBA::is_nil( myShape->GetObject() ))
                       {
-                        string myRefOnObject = myShape->GetID();
-                        if ( myRefOnObject.length() > 0 ) {
+                        CORBA::String_var myRefOnObject = myShape->GetID();
+                        if ( myRefOnObject.in()[0] ) {
                           char aRefName[ 30 ];
                           sprintf( aRefName, "Ref on shape %d", anId);
-                          aSize[ 0 ] = myRefOnObject.length() + 1;
+                          aSize[ 0 ] = strlen( myRefOnObject.in() ) + 1;
                           aDataset = new HDFdataset(aRefName, aGroup, HDF_STRING, aSize, 1);
                           aDataset->CreateOnDisk();
-                          aDataset->WriteOnDisk( ( char* )( myRefOnObject.c_str() ) );
+                          aDataset->WriteOnDisk( ( char* )( myRefOnObject.in() ));
                           aDataset->CloseOnDisk();
                         }
                       }
                       else // shape ref is invalid:
                       {
                         // save a group on geometry as ordinary group
-                        myWriter.AddGroup( aGeomGrp );
+                        writer.AddGroup( aGeomGrp );
                       }
                     }
                     else if ( SMESH_GroupOnFilter_i* aFilterGrp_i =
@@ -3768,7 +4875,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
             if ( strcmp( strHasData.c_str(), "1" ) == 0 )
             {
               // Flush current mesh information into MED file
-              myWriter.Perform();
+              writer.Perform();
 
               // save info on nb of elements
               SMESH_PreMeshInfo::SaveToFile( myImpl, id, aFile );
@@ -3795,7 +4902,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 {
                   SMDS_ElemIteratorPtr eIt =
                     mySMESHDSMesh->elementsIterator( isNode ? SMDSAbs_Node : SMDSAbs_All );
-                  int nbElems = isNode ? mySMESHDSMesh->NbNodes() : mySMESHDSMesh->GetMeshInfo().NbElements();
+                  smIdType nbElems = isNode ? mySMESHDSMesh->NbNodes() : mySMESHDSMesh->GetMeshInfo().NbElements();
                   if ( nbElems < 1 )
                     continue;
                   std::vector<int> smIDs; smIDs.reserve( nbElems );
@@ -3827,7 +4934,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                 // "Face V positions" - V parameter of node on face
 
                 // Find out nb of nodes on edges and faces
-                // Collect corresponing sub-meshes
+                // Collect corresponding sub-meshes
                 int nbEdgeNodes = 0, nbFaceNodes = 0;
                 list<SMESHDS_SubMesh*> aEdgeSM, aFaceSM;
                 // loop on SMESHDS_SubMesh'es
@@ -3836,7 +4943,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                   SMESHDS_SubMesh* aSubMesh = const_cast< SMESHDS_SubMesh* >( smIt->next() );
                   if ( aSubMesh->IsComplexSubmesh() )
                     continue; // submesh containing other submeshs
-                  int nbNodes = aSubMesh->NbNodes();
+                  smIdType nbNodes = aSubMesh->NbNodes();
                   if ( nbNodes == 0 ) continue;
 
                   int aShapeID = aSubMesh->GetID();
@@ -3886,8 +4993,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                       // Position
                       const SMDS_PositionPtr pos = node->GetPosition();
                       if ( onFace ) { // on FACE
-                        const SMDS_FacePosition* fPos =
-                          dynamic_cast<const SMDS_FacePosition*>( pos );
+                        SMDS_FacePositionPtr fPos = pos;
                         if ( fPos ) {
                           aUPos[ iNode ] = fPos->GetUParameter();
                           aVPos[ iNode ] = fPos->GetVParameter();
@@ -3897,8 +5003,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                           nbNodes--;
                       }
                       else { // on EDGE
-                        const SMDS_EdgePosition* ePos =
-                          dynamic_cast<const SMDS_EdgePosition*>( pos );
+                        SMDS_EdgePositionPtr ePos = pos;
                         if ( ePos ) {
                           aUPos[ iNode ] = ePos->GetUParameter();
                           iNode++;
@@ -3959,11 +5064,11 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
   delete aFile;
 
   // Convert temporary files to stream
-  aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq.in(), isMultiFile );
+  aStreamFile = SALOMEDS_Tool::PutFilesToStream( tmpDir.ToCString(), aFileSeq, isMultiFile );
 
   // Remove temporary files and directory
   if ( !isMultiFile )
-    SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
+    SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq, true );
 
   return aStreamFile._retn();
 }
@@ -3997,27 +5102,6 @@ SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent
   return anAsciiStreamFile._retn();
 }
 
-//=============================================================================
-/*!
- *  SMESH_Gen_i::loadGeomData
- *
- *  Load GEOM module data
- */
-//=============================================================================
-
-void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot )
-{
-  if ( theCompRoot->_is_nil() )
-    return;
-
-  SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theCompRoot->GetStudy() );
-  if ( aStudy->_is_nil() )
-    return;
-
-  SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
-  aStudyBuilder->LoadWith( theCompRoot, GetGeomEngine() );
-}
-
 //=============================================================================
 /*!
  *  SMESH_Gen_i::Load
@@ -4031,30 +5115,24 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                         const char*              theURL,
                         bool                     isMultiFile )
 {
-  if ( theComponent->GetStudy()->StudyId() != GetCurrentStudyID() )
-    SetCurrentStudy( theComponent->GetStudy() );
+  UpdateStudy(); // load geom data
+  Kernel_Utils::Localizer loc;
 
-  /*  if( !theComponent->_is_nil() )
-      {
-      //SALOMEDS::Study_var aStudy = SALOMEDS::Study::_narrow( theComponent->GetStudy() );
-      if( !myCurrentStudy->FindComponent( "GEOM" )->_is_nil() )
-      loadGeomData( myCurrentStudy->FindComponent( "GEOM" ) );
-      }*/
-
-  StudyContext* myStudyContext = GetCurrentStudyContext();
+  SALOMEDS::Study_var aStudy = getStudyServant();
 
   // Get temporary files location
   TCollection_AsciiString tmpDir =
     ( char* )( isMultiFile ? theURL : SALOMEDS_Tool::GetTmpDir().c_str() );
 
   // Convert the stream into sequence of files to process
-  SALOMEDS::ListOfFileNames_var aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
-                                                                            tmpDir.ToCString(),
-                                                                            isMultiFile );
+  SALOMEDS_Tool::ListOfFiles aFileSeq = SALOMEDS_Tool::PutStreamToFiles( theStream,
+                                                                         tmpDir.ToCString(),
+                                                                         isMultiFile );
   TCollection_AsciiString aStudyName( "" );
   if ( isMultiFile ) {
-    CORBA::String_var url = myCurrentStudy->URL();
-    aStudyName = (char*)SALOMEDS_Tool::GetNameFromPath( url.in() ).c_str();
+    CORBA::WString_var url = aStudy->URL();
+    SMESHUtils::ArrayDeleter<const char> urlMulibyte( Kernel_Utils::encode( url.in()) );
+    aStudyName = (char*)SALOMEDS_Tool::GetNameFromPath( urlMulibyte.get() ).c_str();
   }
   // Set names of temporary files
   TCollection_AsciiString filename = tmpDir + aStudyName + "_SMESH.hdf";
@@ -4079,10 +5157,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
     return false;
   }
 
-  TPythonDump pd; // prevent dump during loading
-
-  // DriverMED_R_SMESHDS_Mesh myReader;
-  // myReader.SetFile( meshfile.ToCString() );
+  TPythonDump pd(this); // prevent dump during loading
 
   // For PAL13473 ("Repetitive mesh") implementation.
   // New dependencies between SMESH objects are established:
@@ -4278,6 +5353,10 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             try { // protect persistence mechanism against exceptions
               myHyp = this->createHypothesis( hypname.c_str(), libname.c_str() );
             }
+            catch( SALOME::SALOME_Exception& ex )
+            {
+              INFOS( "Exception during hypothesis creation: " << ex.details.text );
+            }
             catch (...) {
               INFOS( "Exception during hypothesis creation" );
             }
@@ -4358,12 +5437,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             aDataset->ReadFromDisk( refFromFile );
             aDataset->CloseOnDisk();
             if ( strlen( refFromFile ) > 0 ) {
-              SALOMEDS::SObject_wrap shapeSO = myCurrentStudy->FindObjectID( refFromFile );
-
-              // Make sure GEOM data are loaded first
-              //loadGeomData( shapeSO->GetFatherComponent() );
-
-              CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
+              SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile );
+              CORBA::Object_var  shapeObject = SObjectToObject( shapeSO );
               if ( !CORBA::is_nil( shapeObject ) ) {
                 aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
                 if ( !aShapeObject->_is_nil() )
@@ -4374,7 +5449,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
           }
 
           // issue 20918. Restore Persistent Id of SMESHDS_Mesh
-          if( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
+          if ( aTopGroup->ExistInternalObject( "meshPersistentId" ) )
           {
             aDataset = new HDFdataset( "meshPersistentId", aTopGroup );
             aDataset->OpenOnDisk();
@@ -4385,11 +5460,33 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             myNewMeshImpl->GetImpl().GetMeshDS()->SetPersistentId( *meshPersistentId );
             delete [] meshPersistentId;
           }
+
+          // Restore SMESH_Mesh_i::_mainShapeTick
+          if ( aTopGroup->ExistInternalObject( "shapeTick" ))
+          {
+            aDataset = new HDFdataset( "shapeTick", aTopGroup );
+            aDataset->OpenOnDisk();
+            int* shapeTick = & myNewMeshImpl->MainShapeTick();
+            aDataset->ReadFromDisk( shapeTick );
+            aDataset->CloseOnDisk();
+          }
+
+          // Restore file info
+          if ( aTopGroup->ExistInternalObject( "file info" ))
+          {
+            aDataset = new HDFdataset( "file info", aTopGroup );
+            aDataset->OpenOnDisk();
+            size = aDataset->GetSize();
+            std::string info( size, ' ');
+            aDataset->ReadFromDisk( (char*) info.data() );
+            aDataset->CloseOnDisk();
+            myNewMeshImpl->FileInfoFromString( info );
+          }
         }
       }
     } // reading MESHes
 
-    // As all object that can be referred by hypothesis are created,
+    // As all objects that can be referred by hypothesis are created,
     // we can restore hypothesis data
 
     list< pair< SMESH_Hypothesis_i*, string > >::iterator hyp_data;
@@ -4407,8 +5504,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
     {
       aTopGroup                   = meshi_group->second;
       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
-      //::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
-      //SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
 
       GEOM::GEOM_Object_var aShapeObject = myNewMeshImpl->GetShapeToMesh();
       bool hasData = false;
@@ -4416,7 +5511,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
       // get mesh old id
       CORBA::String_var iorString = GetORB()->object_to_string( myNewMeshImpl->_this() );
       int newId = myStudyContext->findId( iorString.in() );
-      int id = myStudyContext->getOldId( newId );
+      int meshOldId = myStudyContext->getOldId( newId );
 
       // try to find mesh data dataset
       if ( aTopGroup->ExistInternalObject( "Has data" ) ) {
@@ -4428,10 +5523,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         aDataset->ReadFromDisk( strHasData );
         aDataset->CloseOnDisk();
         if ( strcmp( strHasData, "1") == 0 ) {
-          // read mesh data from MED file
-          // myReader.SetMesh( mySMESHDSMesh );
-          // myReader.SetMeshId( id );
-          // myReader.Perform();
           hasData = true;
         }
         delete [] strHasData;
@@ -4457,8 +5548,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             aDataset->ReadFromDisk( refFromFile );
             aDataset->CloseOnDisk();
             // san - it is impossible to recover applied algorithms using their entries within Load() method
-            //SALOMEDS::SObject_wrap hypSO = myCurrentStudy->FindObjectID( refFromFile );
-            //CORBA::Object_var hypObject = SObjectToObject( hypSO );
             int id = atoi( refFromFile );
             delete [] refFromFile;
             string anIOR = myStudyContext->getIORbyOldId( id );
@@ -4494,8 +5583,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             aDataset->ReadFromDisk( refFromFile );
             aDataset->CloseOnDisk();
             // san - it is impossible to recover applied hypotheses using their entries within Load() method
-            //SALOMEDS::SObject_wrap hypSO = myCurrentStudy->FindObjectID( refFromFile );
-            //CORBA::Object_var hypObject = SObjectToObject( hypSO );
             int id = atoi( refFromFile );
             delete [] refFromFile;
             string anIOR = myStudyContext->getIORbyOldId( id );
@@ -4565,7 +5652,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                 aDataset->ReadFromDisk( refFromFile );
                 aDataset->CloseOnDisk();
                 if ( strlen( refFromFile ) > 0 ) {
-                  SALOMEDS::SObject_wrap subShapeSO = myCurrentStudy->FindObjectID( refFromFile );
+                  SALOMEDS::SObject_wrap subShapeSO = aStudy->FindObjectID( refFromFile );
                   CORBA::Object_var subShapeObject = SObjectToObject( subShapeSO );
                   if ( !CORBA::is_nil( subShapeObject ) ) {
                     aSubShapeObject = GEOM::GEOM_Object::_narrow( subShapeObject );
@@ -4575,10 +5662,11 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                     if ( aSubMesh->_is_nil() )
                       continue;
                     string iorSubString = GetORB()->object_to_string( aSubMesh );
-                    int newSubId = myStudyContext->findId( iorSubString );
+                    int        newSubId = myStudyContext->findId( iorSubString );
                     myStudyContext->mapOldToNew( subid, newSubId );
                   }
                 }
+                delete [] refFromFile;
               }
 
               if ( aSubMesh->_is_nil() )
@@ -4613,6 +5701,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
                       }
                     }
+                    delete [] refFromFile;
                   }
                 }
                 // close "applied algorithms" HDF group
@@ -4648,6 +5737,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                           myNewMeshImpl->addHypothesis( aSubShapeObject, anHyp );
                       }
                     }
+                    delete [] refFromFile;
                   }
                 }
                 // close "APPLIED HYPOTHESES" hdf group
@@ -4682,18 +5772,27 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         if ( aTopGroup->ExistInternalObject( name_group ) ) {
           aGroup = new HDFgroup( name_group, aTopGroup );
           aGroup->OpenOnDisk();
-          // get number of groups
-          int aNbSubObjects = aGroup->nInternalObjects();
-          for ( int j = 0; j < aNbSubObjects; j++ ) {
-            char name_dataset[ HDF_NAME_MAX_LEN+1 ];
-            aGroup->InternalObjectIndentify( j, name_dataset );
-            // check if it is an group
-            if ( string( name_dataset ).substr( 0, 5 ) == string( "Group" ) ) {
+          // PAL23514: get all names from the HDFgroup to avoid iteration on its contents
+          // within aGroup->ExistInternalObject( name )
+          std::vector< std::string > subNames;
+          TColStd_MapOfAsciiString mapOfNames;
+          aGroup->GetAllObjects( subNames );
+          for ( size_t iN = 0; iN < subNames.size(); ++iN )
+            mapOfNames.Add( subNames[ iN ].c_str() );
+          // loop on groups
+          for ( size_t j = 0; j < subNames.size(); j++ ) {
+            const std::string& name_dataset = subNames[ j ];
+            // check if it is a group
+            if ( name_dataset.substr( 0, 5 ) == "Group" ) {
               // --> get group id
-              int subid = atoi( string( name_dataset ).substr( 5 ).c_str() );
+              char * endptr;
+              int subid = strtol( name_dataset.data() + 5, &endptr, 10 );
               if ( subid <= 0 )
                 continue;
-              aDataset = new HDFdataset( name_dataset, aGroup );
+              int groupID = -1; // group local ID (also persistent)
+              if ( *endptr )
+                groupID = atoi( endptr + 1 );
+              aDataset = new HDFdataset( name_dataset.c_str(), aGroup );
               aDataset->OpenOnDisk();
 
               // Retrieve actual group name
@@ -4706,7 +5805,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               TopoDS_Shape aShape;
               char aRefName[ 30 ];
               sprintf( aRefName, "Ref on shape %d", subid);
-              if ( aGroup->ExistInternalObject( aRefName ) ) {
+              if ( mapOfNames.Contains( aRefName ))
+              {
                 // load mesh "Ref on shape" - it's an entry to SObject
                 aDataset = new HDFdataset( aRefName, aGroup );
                 aDataset->OpenOnDisk();
@@ -4715,7 +5815,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                 aDataset->ReadFromDisk( refFromFile );
                 aDataset->CloseOnDisk();
                 if ( strlen( refFromFile ) > 0 ) {
-                  SALOMEDS::SObject_wrap shapeSO = myCurrentStudy->FindObjectID( refFromFile );
+                  SALOMEDS::SObject_wrap shapeSO = aStudy->FindObjectID( refFromFile );
                   CORBA::Object_var shapeObject = SObjectToObject( shapeSO );
                   if ( !CORBA::is_nil( shapeObject ) ) {
                     aShapeObject = GEOM::GEOM_Object::_narrow( shapeObject );
@@ -4723,12 +5823,13 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                       aShape = GeomObjectToShape( aShapeObject );
                   }
                 }
+                delete [] refFromFile;
               }
               // Try to read a filter of SMESH_GroupOnFilter
               SMESH::Filter_var filter;
               SMESH_PredicatePtr predicate;
-              std::string hdfGrpName = "Filter " + SMESH_Comment(subid);
-              if ( aGroup->ExistInternalObject( hdfGrpName.c_str() ))
+              std::string hdfGrpName = ( SMESH_Comment( "Filter ") << subid );
+              if ( mapOfNames.Contains( hdfGrpName.c_str() ))
               {
                 aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup );
                 aDataset->OpenOnDisk();
@@ -4741,17 +5842,20 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                   predicate = SMESH_GroupOnFilter_i::GetPredicate( filter );
                   filters.push_back( filter );
                 }
+                delete [] persistStr;
               }
 
               // Create group servant
               SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1);
               SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate
-                ( myNewMeshImpl->createGroup( type, nameFromFile, aShape, predicate ) );
+                ( myNewMeshImpl->createGroup( type, nameFromFile, groupID, aShape, predicate ) );
+              delete [] nameFromFile;
               // Obtain a SMESHDS_Group object
               if ( aNewGroup->_is_nil() )
                 continue;
 
-              string iorSubString = GetORB()->object_to_string( aNewGroup );
+              CORBA::String_var iorSubStringVar = GetORB()->object_to_string( aNewGroup );
+              string iorSubString(iorSubStringVar.in());
               int        newSubId = myStudyContext->findId( iorSubString );
               myStudyContext->mapOldToNew( subid, newSubId );
 
@@ -4769,13 +5873,13 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               if ( !aGroupBaseDS )
                 continue;
 
-              aGroupBaseDS->SetStoreName( name_dataset );
+              aGroupBaseDS->SetStoreName( name_dataset.c_str() );
 
               // ouv : NPAL12872
               // Read color of the group
               char aGroupColorName[ 30 ];
               sprintf( aGroupColorName, "ColorGroup %d", subid);
-              if ( aGroup->ExistInternalObject( aGroupColorName ) )
+              if ( mapOfNames.Contains( aGroupColorName ))
               {
                 aDataset = new HDFdataset( aGroupColorName, aGroup );
                 aDataset->OpenOnDisk();
@@ -4785,6 +5889,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                 aDataset->CloseOnDisk();
                 Quantity_Color aColor( anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB );
                 aGroupBaseDS->SetColor( aColor );
+                delete [] anRGB;
               }
             }
           }
@@ -4793,16 +5898,16 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
       } // reading GROUPs
 
       // instead of reading mesh data, we read only brief information of all
-      // objects: mesh, groups, sub-meshes (issue 0021208 )
+      // objects: mesh, groups, sub-meshes (issue 0021208)
       if ( hasData )
       {
-        SMESH_PreMeshInfo::LoadFromFile( myNewMeshImpl, id,
+        SMESH_PreMeshInfo::LoadFromFile( myNewMeshImpl, meshOldId,
                                          meshfile.ToCString(), filename.ToCString(),
                                          !isMultiFile );
       }
 
       // read Sub-Mesh ORDER if any
-      if( aTopGroup->ExistInternalObject( "Mesh Order" ) ) {
+      if ( aTopGroup->ExistInternalObject( "Mesh Order" )) { // old version keeps ids
         aDataset = new HDFdataset( "Mesh Order", aTopGroup );
         aDataset->OpenOnDisk();
         size = aDataset->GetSize();
@@ -4818,6 +5923,33 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             anOrderIds.back().push_back(smIDs[ i ]);
 
         myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
+        delete [] smIDs;
+      }
+      if ( aTopGroup->ExistInternalObject( "MeshOrder_new" )) // new version keeps entries
+      {
+        aDataset = new HDFdataset( "MeshOrder_new", aTopGroup );
+        aDataset->OpenOnDisk();
+        size = aDataset->GetSize();
+        std::string dataString; dataString.resize( size );
+        aDataset->ReadFromDisk((char*) dataString.data() );
+        aDataset->CloseOnDisk();
+
+        std::list< std::list< std::string > > orderEntryLists;
+        SMESHUtils::BoostTxtArchive( dataString ) >> orderEntryLists;
+
+        TListOfListOfInt anOrderIds;
+        for ( const std::list< std::string >& entryList : orderEntryLists )
+        {
+          anOrderIds.emplace_back();
+          for ( const std::string & entry : entryList )
+          {
+            GEOM::GEOM_Object_var go = GetGeomObjectByEntry( entry );
+            TopoDS_Shape       shape = GeomObjectToShape( go );
+            if ( SMESH_subMesh*   sm = myNewMeshImpl->GetImpl().GetSubMesh( shape ))
+              anOrderIds.back().emplace_back( sm->GetId() );
+          }
+        }
+        myNewMeshImpl->GetImpl().SetMeshOrder( anOrderIds );
       }
     } // loop on meshes
 
@@ -4865,7 +5997,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
     SMESH_File meshFile( meshfile.ToCString() );
     if ( !meshFile ) // no meshfile exists
     {
-      SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
+      SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq, true );
     }
     else
     {
@@ -4878,16 +6010,14 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
       }
     }
   }
-  pd << ""; // prevent optimizing pd out
 
   // creation of tree nodes for all data objects in the study
   // to support tree representation customization and drag-n-drop:
-  SALOMEDS::Study_var                    study = theComponent->GetStudy();
-  SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = study->GetUseCaseBuilder();
+  SALOMEDS::UseCaseBuilder_wrap useCaseBuilder = aStudy->GetUseCaseBuilder();
   if ( !useCaseBuilder->IsUseCaseNode( theComponent ) ) {
     useCaseBuilder->SetRootCurrent();
     useCaseBuilder->Append( theComponent ); // component object is added as the top level item
-    SALOMEDS::ChildIterator_wrap it = study->NewChildIterator( theComponent );
+    SALOMEDS::ChildIterator_wrap it = aStudy->NewChildIterator( theComponent );
     for (it->InitEx(true); it->More(); it->Next()) {
       useCaseBuilder->AppendTo( it->Value()->GetFather(), it->Value() );
     }
@@ -4947,22 +6077,15 @@ void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
 {
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Close" );
 
-  // set correct current study
-  SALOMEDS::Study_var study = theComponent->GetStudy();
-  if ( study->StudyId() != GetCurrentStudyID())
-    setCurrentStudy( study, /*IsBeingClosed=*/true );
-
   // Clear study contexts data
-  int studyId = GetCurrentStudyID();
-  if ( myStudyContextMap.find( studyId ) != myStudyContextMap.end() ) {
-    delete myStudyContextMap[ studyId ];
-    myStudyContextMap.erase( studyId );
-  }
+  myStudyContext->Clear();
 
   // remove the tmp files meshes are loaded from
   SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD( theComponent );
 
-  myCurrentStudy = SALOMEDS::Study::_nil();
+  // Clean trace of API methods calls
+  CleanPythonTrace();
+
   return;
 }
 
@@ -4995,7 +6118,6 @@ char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/,
                                            CORBA::Boolean        /*isASCII*/ )
 {
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
-  StudyContext* myStudyContext = GetCurrentStudyContext();
 
   if ( myStudyContext && strcmp( IORString, "" ) != 0 ) {
     int anId = myStudyContext->findId( IORString );
@@ -5023,7 +6145,6 @@ char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
                                            CORBA::Boolean        /*isASCII*/ )
 {
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
-  StudyContext* myStudyContext = GetCurrentStudyContext();
 
   if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) {
     int anId = atoi( aLocalPersistentID );
@@ -5039,7 +6160,6 @@ char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
 
 int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
 {
-  StudyContext* myStudyContext = GetCurrentStudyContext();
   if ( myStudyContext && !CORBA::is_nil( theObject )) {
     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
     return myStudyContext->addObject( string( iorString.in() ) );
@@ -5055,12 +6175,12 @@ int SMESH_Gen_i::RegisterObject(CORBA::Object_ptr theObject)
  */
 //================================================================================
 
-CORBA::Long SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
+CORBA::Long  SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
 {
-  StudyContext* myStudyContext = GetCurrentStudyContext();
   if ( myStudyContext && !CORBA::is_nil( theObject )) {
-    string iorString = GetORB()->object_to_string( theObject );
-    return myStudyContext->findId( iorString );
+    CORBA::String_var iorString = GetORB()->object_to_string( theObject );
+    string iorStringCpp(iorString.in()); 
+    return myStudyContext->findId( iorStringCpp );
   }
   return 0;
 }
@@ -5072,23 +6192,19 @@ CORBA::Long SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
  *  Set a new object name
  */
 //=============================================================================
+
 void SMESH_Gen_i::SetName(const char* theIOR,
                           const char* theName)
 {
   if ( theIOR && strcmp( theIOR, "" ) ) {
     CORBA::Object_var anObject = GetORB()->string_to_object( theIOR );
-    SALOMEDS::SObject_wrap aSO = ObjectToSObject( myCurrentStudy, anObject );
+    SALOMEDS::SObject_wrap aSO = ObjectToSObject( anObject );
     if ( !aSO->_is_nil() ) {
       SetName( aSO, theName );
     }
   }
 }
 
-int SMESH_Gen_i::GetCurrentStudyID()
-{
-  return myCurrentStudy->_is_nil() || myCurrentStudy->_non_existent() ? -1 : myCurrentStudy->StudyId();
-}
-
 // Version information
 char* SMESH_Gen_i::getVersion()
 {
@@ -5104,15 +6220,15 @@ char* SMESH_Gen_i::getVersion()
 // purpose  : Moves objects to the specified position.
 //            Is used in the drag-n-drop functionality.
 //=================================================================================
+
 void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
                         SALOMEDS::SObject_ptr      where,
                         CORBA::Long                row )
 {
   if ( CORBA::is_nil( where ) ) return;
 
-  SALOMEDS::Study_var study = where->GetStudy();
-  SALOMEDS::StudyBuilder_var studyBuilder = study->NewBuilder();
-  SALOMEDS::UseCaseBuilder_var useCaseBuilder = study->GetUseCaseBuilder();
+  SALOMEDS::StudyBuilder_var studyBuilder = getStudyServant()->NewBuilder();
+  SALOMEDS::UseCaseBuilder_var useCaseBuilder = getStudyServant()->GetUseCaseBuilder();
   SALOMEDS::SComponent_var father = where->GetFatherComponent();
   std::string dataType = father->ComponentDataType();
   if ( dataType != "SMESH" ) return; // not a SMESH component
@@ -5158,13 +6274,13 @@ CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
   SMESH_TRY;
 
   std::string aPlatformLibName;
-  typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char*);
   GenericHypothesisCreator_i* aCreator =
     getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
   if (aCreator)
   {
     TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
-    return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll );
+    const SMESH_Algo::Features& feat = SMESH_Algo::GetFeatures( theAlgoType );
+    return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll, feat._dim );
   }
   else
   {
@@ -5179,10 +6295,12 @@ CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
   return true;
 }
 
-//=================================================================================
-// function : GetInsideSphere
-// purpose  : Collect indices of elements, which are located inside the sphere
-//=================================================================================
+//================================================================================
+/*!
+ * \brief Collect indices of elements, which are located inside the sphere
+ */
+//================================================================================
+
 SMESH::long_array* SMESH_Gen_i::GetInsideSphere( SMESH::SMESH_IDSource_ptr meshPart,
                                                  SMESH::ElementType     theElemType,
                                                  CORBA::Double         theX,
@@ -5209,6 +6327,12 @@ SMESH::long_array* SMESH_Gen_i::GetInsideSphere( SMESH::SMESH_IDSource_ptr meshP
   return aResult._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Collect indices of elements, which are located inside the box
+ */
+//================================================================================
+
 SMESH::long_array* SMESH_Gen_i::GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart,
                                               SMESH::ElementType        theElemType,
                                               CORBA::Double             theX1,
@@ -5216,12 +6340,14 @@ SMESH::long_array* SMESH_Gen_i::GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart
                                               CORBA::Double             theZ1,
                                               CORBA::Double             theX2,
                                               CORBA::Double             theY2,
-                                              CORBA::Double             theZ2) {
+                                              CORBA::Double             theZ2)
+{
   SMESH::long_array_var aResult = new SMESH::long_array();
   if( meshPart->_is_nil() )
     return aResult._retn();
 
-  TopoDS_Shape aShape = BRepPrimAPI_MakeBox( gp_Pnt( theX1, theY1, theZ1 ), gp_Pnt( theX2, theY2, theZ2 ) ).Shape();
+  TopoDS_Shape aShape = BRepPrimAPI_MakeBox( gp_Pnt( theX1, theY1, theZ1 ),
+                                             gp_Pnt( theX2, theY2, theZ2 ) ).Shape();
 
   std::vector<long> lst =_GetInside(meshPart, theElemType, aShape);
 
@@ -5234,6 +6360,12 @@ SMESH::long_array* SMESH_Gen_i::GetInsideBox( SMESH::SMESH_IDSource_ptr meshPart
   return aResult._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Collect indices of elements, which are located inside the cylinder
+ */
+//================================================================================
+
 SMESH::long_array* SMESH_Gen_i::GetInsideCylinder( SMESH::SMESH_IDSource_ptr meshPart,
                                                    SMESH::ElementType        theElemType,
                                                    CORBA::Double             theX,
@@ -5243,7 +6375,8 @@ SMESH::long_array* SMESH_Gen_i::GetInsideCylinder( SMESH::SMESH_IDSource_ptr mes
                                                    CORBA::Double             theDY,
                                                    CORBA::Double             theDZ,
                                                    CORBA::Double             theH,
-                                                   CORBA::Double             theR ){
+                                                   CORBA::Double             theR )
+{
   SMESH::long_array_var aResult = new SMESH::long_array();
   if( meshPart->_is_nil() )
     return aResult._retn();
@@ -5265,10 +6398,17 @@ SMESH::long_array* SMESH_Gen_i::GetInsideCylinder( SMESH::SMESH_IDSource_ptr mes
   return aResult._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Collect indices of elements, which are located inside the geom object
+ */
+//================================================================================
+
 SMESH::long_array* SMESH_Gen_i::GetInside( SMESH::SMESH_IDSource_ptr meshPart,
                                            SMESH::ElementType        theElemType,
                                            GEOM::GEOM_Object_ptr     theGeom,
-                                           CORBA::Double             theTolerance ) {
+                                           CORBA::Double             theTolerance )
+{
   SMESH::long_array_var aResult = new SMESH::long_array();
   if( meshPart->_is_nil() || theGeom->_is_nil() )
     return aResult._retn();
@@ -5286,12 +6426,16 @@ SMESH::long_array* SMESH_Gen_i::GetInside( SMESH::SMESH_IDSource_ptr meshPart,
   return aResult._retn();
 }
 
-
+//================================================================================
+/*!
+ * \brief Collect indices of elements, which are located inside the TopoDS_Shape
+ */
+//================================================================================
 
 std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
-                                           SMESH::ElementType theElemType,
-                                           TopoDS_Shape& aShape,
-                                           double* theTolerance) {
+                                           SMESH::ElementType        theElemType,
+                                           const TopoDS_Shape&       theShape,
+                                           double*                   theTolerance) {
 
   std::vector<long> res;
   SMESH::SMESH_Mesh_var mesh = meshPart->GetMesh();
@@ -5312,7 +6456,7 @@ std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
   SMESH::Controls::ElementsOnShape* anElementsOnShape = new SMESH::Controls::ElementsOnShape();
   anElementsOnShape->SetAllNodes( true );
   anElementsOnShape->SetMesh( meshDS );
-  anElementsOnShape->SetShape( aShape, aType );
+  anElementsOnShape->SetShape( theShape, aType );
 
   if(theTolerance)
     anElementsOnShape->SetTolerance(*theTolerance);
@@ -5332,7 +6476,7 @@ std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
   SMESH::SMESH_Group_var gsource = SMESH::SMESH_Group::_narrow(meshPart);
   if ( !gsource->_is_nil() ) {
     if(theElemType == SMESH::NODE) {
-      SMESH::long_array_var nodes = gsource->GetNodeIDs();
+      SMESH::smIdType_array_var nodes = gsource->GetNodeIDs();
       for ( CORBA::ULong i = 0; i < nodes->length(); ++i ) {
         if ( const SMDS_MeshNode* node = meshDS->FindNode( nodes[i] )) {
           long anId = node->GetID();
@@ -5341,7 +6485,7 @@ std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
         }
       }
     } else if (gsource->GetType() == theElemType || theElemType == SMESH::ALL ) {
-      SMESH::long_array_var elems = gsource->GetListOfID();
+      SMESH::smIdType_array_var elems = gsource->GetListOfID();
       for ( CORBA::ULong i = 0; i < elems->length(); ++i ) {
         if ( const SMDS_MeshElement* elem = meshDS->FindElement( elems[i] )) {
           long anId = elem->GetID();
@@ -5353,7 +6497,7 @@ std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
   }
   SMESH::SMESH_subMesh_var smsource = SMESH::SMESH_subMesh::_narrow(meshPart);
   if ( !smsource->_is_nil() ) {
-    SMESH::long_array_var elems = smsource->GetElementsByType( theElemType );
+    SMESH::smIdType_array_var elems = smsource->GetElementsByType( theElemType );
     for ( CORBA::ULong i = 0; i < elems->length(); ++i ) {
       const SMDS_MeshElement* elem = ( theElemType == SMESH::NODE ) ? meshDS->FindNode( elems[i] ) : meshDS->FindElement( elems[i] );
       if (elem) {
@@ -5365,27 +6509,3 @@ std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
   }
   return res;
 }
-
-
-//=============================================================================
-/*!
- *  SMESHEngine_factory
- *
- *  C factory, accessible with dlsym, after dlopen
- */
-//=============================================================================
-
-extern "C"
-{ SMESH_I_EXPORT
-  PortableServer::ObjectId* SMESHEngine_factory( CORBA::ORB_ptr            orb,
-                                                 PortableServer::POA_ptr   poa,
-                                                 PortableServer::ObjectId* contId,
-                                                 const char*               instanceName,
-                                                 const char*               interfaceName )
-  {
-    if(MYDEBUG) MESSAGE( "PortableServer::ObjectId* SMESHEngine_factory()" );
-    if(MYDEBUG) SCRUTE(interfaceName);
-    SMESH_Gen_i* aSMESHGen = new SMESH_Gen_i(orb, poa, contId, instanceName, interfaceName);
-    return aSMESHGen->getId() ;
-  }
-}