Salome HOME
53061: "Clear mesh data" removes too many (if !HasShapeToMesh())
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
index 2e4d1772c2a1bd5c01ea74c750e27528eda85aeb..b025573b9b559add0fb7ed705d7ffc70251e04ef 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  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
@@ -6,7 +6,7 @@
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 // License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 #include "SMESH_Mesh_i.hxx"
 
 #include "DriverMED_R_SMESHDS_Mesh.h"
+#include "DriverMED_W_Field.h"
 #include "DriverMED_W_SMESHDS_Mesh.h"
+#include "MED_Factory.hxx"
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_ElemIterator.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_IteratorOnIterators.hxx"
+#include "SMDS_MeshGroup.hxx"
 #include "SMDS_SetIterator.hxx"
 #include "SMDS_VolumeTool.hxx"
 #include "SMESHDS_Command.hxx"
 #include "SMESHDS_CommandType.hxx"
+#include "SMESHDS_Group.hxx"
 #include "SMESHDS_GroupOnGeom.hxx"
+#include "SMESH_Controls.hxx"
+#include "SMESH_File.hxx"
 #include "SMESH_Filter_i.hxx"
 #include "SMESH_Gen_i.hxx"
 #include "SMESH_Group.hxx"
 #include "SMESH_Group_i.hxx"
-#include "SMESH_MEDMesh_i.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshAlgos.hxx"
 #include "SMESH_MeshEditor.hxx"
 #include "SMESH_MeshEditor_i.hxx"
+#include "SMESH_MeshPartDS.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_PreMeshInfo.hxx"
 #include "SMESH_PythonDump.hxx"
 #include "SMESH_subMesh_i.hxx"
 
-#include <OpUtil.hxx>
-#include <SALOME_NamingService.hxx>
-#include <Utils_CorbaException.hxx>
+#include <SALOMEDS_Attributes_wrap.hxx>
+#include <SALOMEDS_wrap.hxx>
 #include <Utils_ExceptHandlers.hxx>
-#include <Utils_SINGLETON.hxx>
 #include <utilities.h>
+
 #include <GEOMImpl_Types.hxx>
+#include <GEOM_wrap.hxx>
 
 // OCCT Includes
 #include <BRep_Builder.hxx>
-#include <OSD_Directory.hxx>
-#include <OSD_File.hxx>
-#include <OSD_Path.hxx>
-#include <OSD_Protection.hxx>
-#include <TColStd_MapIteratorOfMapOfInteger.hxx>
+#include <Standard_ErrorHandler.hxx>
 #include <TColStd_MapOfInteger.hxx>
-#include <TColStd_SequenceOfInteger.hxx>
-#include <TCollection_AsciiString.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
-#include <TopoDS_Compound.hxx>
-#include <TopTools_MapOfShape.hxx>
 #include <TopTools_MapIteratorOfMapOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopoDS_Compound.hxx>
 
 // STL Includes
 #include <algorithm>
-#include <string>
 #include <iostream>
 #include <sstream>
-#include <sys/stat.h>
+
+#include <vtkUnstructuredGridWriter.h>
+
+// to pass CORBA exception through SMESH_TRY
+#define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
+
+#include "SMESH_TryCatch.hxx" // include after OCCT headers!
 
 #ifdef _DEBUG_
 static int MYDEBUG = 0;
@@ -90,10 +97,6 @@ using SMESH::TPythonDump;
 
 int SMESH_Mesh_i::_idGenerator = 0;
 
-//To disable automatic genericobj management, the following line should be commented.
-//Otherwise, it should be uncommented. Refer to KERNEL_SRC/src/SALOMEDSImpl/SALOMEDSImpl_AttributeIOR.cxx
-#define WITHGENERICOBJ
-
 //=============================================================================
 /*!
  *  Constructor
@@ -102,15 +105,18 @@ int SMESH_Mesh_i::_idGenerator = 0;
 
 SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
                             SMESH_Gen_i*            gen_i,
-                            CORBA::Long studyId )
+                            CORBA::Long             studyId )
 : SALOME::GenericObj_i( thePOA )
 {
   MESSAGE("SMESH_Mesh_i");
-  _impl = NULL;
-  _gen_i = gen_i;
-  _id = _idGenerator++;
-  _studyId = studyId;
-  _preMeshInfo = NULL;
+  _impl          = NULL;
+  _gen_i         = gen_i;
+  _id            = _idGenerator++;
+  _studyId       = studyId;
+  _editor        = NULL;
+  _previewEditor = NULL;
+  _preMeshInfo   = NULL;
+  _mainShapeTick = 0;
 }
 
 //=============================================================================
@@ -123,50 +129,47 @@ SMESH_Mesh_i::~SMESH_Mesh_i()
 {
   MESSAGE("~SMESH_Mesh_i");
 
-#ifdef WITHGENERICOBJ
   // destroy groups
   map<int, SMESH::SMESH_GroupBase_ptr>::iterator itGr;
-  for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++) {
-    if ( CORBA::is_nil( itGr->second ))
-      continue;
-    SMESH_GroupBase_i* aGroup = dynamic_cast<SMESH_GroupBase_i*>(SMESH_Gen_i::GetServant(itGr->second).in());
-    if (aGroup) {
-      // this method is called from destructor of group (PAL6331)
-      //_impl->RemoveGroup( aGroup->GetLocalID() );
-      aGroup->myMeshServant = 0;
+  for (itGr = _mapGroups.begin(); itGr != _mapGroups.end(); itGr++)
+    if (SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>(itGr->second))
+    {
       aGroup->UnRegister();
+      SMESH::SMESH_GroupBase_var( itGr->second );
     }
-  }
   _mapGroups.clear();
 
   // destroy submeshes
   map<int, SMESH::SMESH_subMesh_ptr>::iterator itSM;
-  for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ ) {
-    if ( CORBA::is_nil( itSM->second ))
-      continue;
-    SMESH_subMesh_i* aSubMesh = dynamic_cast<SMESH_subMesh_i*>(SMESH_Gen_i::GetServant(itSM->second).in());
-    if (aSubMesh) {
+  for ( itSM = _mapSubMeshIor.begin(); itSM != _mapSubMeshIor.end(); itSM++ )
+    if ( SMESH_subMesh_i* aSubMesh = SMESH::DownCast<SMESH_subMesh_i*>( itSM->second ))
+    {
       aSubMesh->UnRegister();
+      SMESH::SMESH_subMesh_var( itSM->second );
     }
-  }
   _mapSubMeshIor.clear();
 
-  // destroy hypotheses
+  // destroy hypotheses. _mapHypo contains all hyps ever been assigned
   map<int, SMESH::SMESH_Hypothesis_ptr>::iterator itH;
   for ( itH = _mapHypo.begin(); itH != _mapHypo.end(); itH++ ) {
-    if ( CORBA::is_nil( itH->second ))
-      continue;
-    SMESH_Hypothesis_i* aHypo = dynamic_cast<SMESH_Hypothesis_i*>(SMESH_Gen_i::GetServant(itH->second).in());
-    if (aHypo) {
-      aHypo->UnRegister();
-    }
+    if ( SMESH_Hypothesis_i* hyp_i = SMESH::DownCast<SMESH_Hypothesis_i*>( itH->second ))
+      if ( SMESH_Hypothesis * smHyp = _impl->GetHypothesis( itH->first ))
+        if ( _impl->GetMeshDS()->IsUsedHypothesis( smHyp ))
+          hyp_i->UnRegister();
+
+    SMESH::SMESH_Hypothesis_var( itH->second ); // decref CORBA object
   }
   _mapHypo.clear();
-#endif
 
-  delete _impl; _impl = NULL;
+  // clear cashed shapes if no more meshes remain; (the cash is blame,
+  // together with publishing, of spent time increasing in issue 22874)
+  if ( _impl->NbMeshes() == 1 )
+    _gen_i->GetShapeReader()->ClearClientBuffer();
 
-  if ( _preMeshInfo ) delete _preMeshInfo; _preMeshInfo = NULL;
+  delete _editor; _editor = NULL;
+  delete _previewEditor; _previewEditor = NULL;
+  delete _impl; _impl = NULL;
+  delete _preMeshInfo; _preMeshInfo = NULL;
 }
 
 //=============================================================================
@@ -190,7 +193,10 @@ void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
   }
   // to track changes of GEOM groups
-  addGeomGroupData( theShapeObject, _this() );
+  SMESH::SMESH_Mesh_var mesh = _this();
+  addGeomGroupData( theShapeObject, mesh );
+  if ( !CORBA::is_nil( theShapeObject ))
+    _mainShapeTick = theShapeObject->GetTick();
 }
 
 //================================================================================
@@ -226,7 +232,25 @@ GEOM::GEOM_Object_ptr SMESH_Mesh_i::GetShapeToMesh()
   try {
     TopoDS_Shape S = _impl->GetMeshDS()->ShapeToMesh();
     if ( !S.IsNull() )
+    {
       aShapeObj = _gen_i->ShapeToGeomObject( S );
+      if ( aShapeObj->_is_nil() )
+      {
+        // S was removed from GEOM_Client by newGroupShape() called by other mesh;
+        // find GEOM_Object by entry (IPAL52735)
+        list<TGeomGroupData>::iterator data = _geomGroupData.begin();
+        for ( ; data != _geomGroupData.end(); ++data )
+          if ( data->_smeshObject->_is_equivalent( _this() ))
+          {
+            SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
+            if ( study->_is_nil() ) break;
+            SALOMEDS::SObject_wrap so = study->FindObjectID( data->_groupEntry.c_str() );
+            CORBA::Object_var     obj = _gen_i->SObjectToObject( so );
+            aShapeObj = GEOM::GEOM_Object::_narrow( obj );
+            break;
+          }
+      }
+    }
   }
   catch(SALOME_Exception & S_ex) {
     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
@@ -269,16 +293,18 @@ void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
-    _preMeshInfo->ForgetAllData();
+    _preMeshInfo->ForgetOrLoad(); // load in case if !HasShapeToMesh()
 
   try {
     _impl->Clear();
-    CheckGeomGroupModif(); // issue 20145
+    //CheckGeomGroupModif(); // issue 20145
   }
   catch(SALOME_Exception & S_ex) {
     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
   }
-  TPythonDump() <<  _this() << ".Clear()";
+  _impl->GetMeshDS()->Modified();
+
+  TPythonDump() <<  SMESH::SMESH_Mesh_var(_this()) << ".Clear()";
 }
 
 //================================================================================
@@ -300,11 +326,14 @@ void SMESH_Mesh_i::ClearSubMesh(CORBA::Long ShapeID)
   catch(SALOME_Exception & S_ex) {
     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
   }
+  _impl->GetMeshDS()->Modified();
+
+  TPythonDump() <<  SMESH::SMESH_Mesh_var(_this()) << ".ClearSubMesh( " << ShapeID << " )";
 }
 
 //=============================================================================
 /*!
- *
+ * Convert enum Driver_Mesh::Status to SMESH::DriverMED_ReadStatus
  */
 //=============================================================================
 
@@ -321,6 +350,8 @@ static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
     res = SMESH::DRS_WARN_RENUMBER; break;
   case DriverMED_R_SMESHDS_Mesh::DRS_WARN_SKIP_ELEM:
     res = SMESH::DRS_WARN_SKIP_ELEM; break;
+  case DriverMED_R_SMESHDS_Mesh::DRS_WARN_DESCENDING:
+    res = SMESH::DRS_WARN_DESCENDING; break;
   case DriverMED_R_SMESHDS_Mesh::DRS_FAIL:
   default:
     res = SMESH::DRS_FAIL; break;
@@ -328,6 +359,30 @@ static SMESH::DriverMED_ReadStatus ConvertDriverMEDReadStatus (int theStatus)
   return res;
 }
 
+//=============================================================================
+/*!
+ * Convert ::SMESH_ComputeError to SMESH::ComputeError
+ */
+//=============================================================================
+
+static SMESH::ComputeError* ConvertComputeError( SMESH_ComputeErrorPtr errorPtr )
+{
+  SMESH::ComputeError_var errVar = new SMESH::ComputeError();
+  errVar->subShapeID = -1;
+  errVar->hasBadMesh = false;
+
+  if ( !errorPtr || errorPtr->IsOK() )
+  {
+    errVar->code = SMESH::COMPERR_OK;
+  }
+  else
+  {
+    errVar->code    = ConvertDriverMEDReadStatus( errorPtr->myName );
+    errVar->comment = errorPtr->myComment.c_str();
+  }
+  return errVar._retn();
+}
+
 //=============================================================================
 /*!
  *  ImportMEDFile
@@ -357,20 +412,13 @@ SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
   int major, minor, release;
   if( !MED::getMEDVersion( theFileName, major, minor, release ) )
     major = minor = release = -1;
-  _medFileInfo           = new SALOME_MED::MedFileInfo();
+  _medFileInfo           = new SMESH::MedFileInfo();
   _medFileInfo->fileName = theFileName;
   _medFileInfo->fileSize = 0;
-#ifdef WIN32
-  struct _stati64 d;
-  if ( ::_stati64( theFileName, &d ) != -1 )
-#else
-  struct stat64 d;
-  if ( ::stat64( theFileName, &d ) != -1 )
-#endif
-    _medFileInfo->fileSize = d.st_size;
   _medFileInfo->major    = major;
   _medFileInfo->minor    = minor;
   _medFileInfo->release  = release;
+  _medFileInfo->fileSize = SMESH_File( theFileName ).size();
 
   return ConvertDriverMEDReadStatus(status);
 }
@@ -412,7 +460,7 @@ SMESH::DriverMED_ReadStatus SMESH_Mesh_i::ImportCGNSFile( const char*  theFileNa
 char* SMESH_Mesh_i::GetVersionString(SMESH::MED_VERSION version, CORBA::Short nbDigits)
 {
   string ver = DriverMED_W_SMESHDS_Mesh::GetVersionString(MED::EVersion(version),
-                                                               nbDigits);
+                                                          nbDigits);
   return CORBA::string_dup( ver.c_str() );
 }
 
@@ -427,11 +475,15 @@ char* SMESH_Mesh_i::GetVersionString(SMESH::MED_VERSION version, CORBA::Short nb
 int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
   throw ( SALOME::SALOME_Exception )
 {
+  SMESH_TRY;
+
   // Read mesh with name = <theMeshName> into SMESH_Mesh
   _impl->UNVToMesh( theFileName );
 
   CreateGroupServants();
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+
   return 1;
 }
 
@@ -445,12 +497,57 @@ int SMESH_Mesh_i::ImportUNVFile( const char* theFileName )
 int SMESH_Mesh_i::ImportSTLFile( const char* theFileName )
   throw ( SALOME::SALOME_Exception )
 {
+  SMESH_TRY;
+
   // Read mesh with name = <theMeshName> into SMESH_Mesh
   _impl->STLToMesh( theFileName );
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+
   return 1;
 }
 
+//================================================================================
+/*!
+ * \brief Function used in SMESH_CATCH by ImportGMFFile()
+ */
+//================================================================================
+
+namespace
+{
+  SMESH_ComputeErrorPtr exceptionToComputeError(const char* excText)
+  {
+    return SMESH_ComputeError::New( Driver_Mesh::DRS_FAIL, excText );
+  }
+}
+
+//================================================================================
+/*!
+ * \brief Imports data from a GMF file and returns an error description
+ */
+//================================================================================
+
+SMESH::ComputeError* SMESH_Mesh_i::ImportGMFFile( const char* theFileName,
+                                                  bool        theMakeRequiredGroups )
+  throw (SALOME::SALOME_Exception)
+{
+  SMESH_ComputeErrorPtr error;
+
+#undef SMESH_CAUGHT
+#define SMESH_CAUGHT error =
+  SMESH_TRY;
+
+  error = _impl->GMFToMesh( theFileName, theMakeRequiredGroups );
+
+  SMESH_CATCH( exceptionToComputeError );
+#undef SMESH_CAUGHT
+#define SMESH_CAUGHT
+
+  CreateGroupServants();
+
+  return ConvertComputeError( error );
+}
+
 //=============================================================================
 /*!
  *
@@ -477,6 +574,7 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
   RETURNCASE( HYP_BAD_SUBSHAPE  );
   RETURNCASE( HYP_BAD_GEOMETRY  );
   RETURNCASE( HYP_NEED_SHAPE    );
+  RETURNCASE( HYP_INCOMPAT_HYPS );
   default:;
   }
   return SMESH::HYP_UNKNOWN_FATAL;
@@ -492,31 +590,32 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::ConvertHypothesisStatus
  */
 //=============================================================================
 
-SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
-                                                     SMESH::SMESH_Hypothesis_ptr anHyp)
+SMESH::Hypothesis_Status
+SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
+                            SMESH::SMESH_Hypothesis_ptr anHyp,
+                            CORBA::String_out           anErrorText)
   throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
     _preMeshInfo->ForgetOrLoad();
 
-  SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShapeObject, anHyp );
+  std::string error;
+  SMESH_Hypothesis::Hypothesis_Status status = addHypothesis( aSubShape, anHyp, &error );
+  anErrorText = error.c_str();
 
+  SMESH::SMESH_Mesh_var mesh( _this() );
   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
-    _gen_i->AddHypothesisToShape(_gen_i->GetCurrentStudy(), _this(),
-                                 aSubShapeObject, anHyp );
-
+  {
+    SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
+    _gen_i->AddHypothesisToShape( study, mesh, aSubShape, anHyp );
+  }
   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
 
   // Update Python script
-  if(_impl->HasShapeToMesh()) {
-    TPythonDump() << "status = " << _this() << ".AddHypothesis( "
-                  << aSubShapeObject << ", " << anHyp << " )";
-  }
-  else {
-    TPythonDump() << "status = " << _this() << ".AddHypothesis( "<< anHyp << " )";
-  }
-  
+  TPythonDump() << "status = " << mesh << ".AddHypothesis( "
+                << aSubShape << ", " << anHyp << " )";
+
   return ConvertHypothesisStatus(status);
 }
 
@@ -527,19 +626,17 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::AddHypothesis(GEOM::GEOM_Object_ptr
 //=============================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-  SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
-                              SMESH::SMESH_Hypothesis_ptr anHyp)
+SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
+                            SMESH::SMESH_Hypothesis_ptr anHyp,
+                            std::string*                anErrorText)
 {
   if(MYDEBUG) MESSAGE("addHypothesis");
 
-  if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
-    THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",
-                                 SALOME::BAD_PARAM);
+  if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
+    THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
 
-  SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
-  if (CORBA::is_nil(myHyp))
-    THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",
-                                 SALOME::BAD_PARAM);
+  if (CORBA::is_nil( anHyp ))
+    THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference",SALOME::BAD_PARAM);
 
   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
   try
@@ -547,24 +644,28 @@ SMESH_Hypothesis::Hypothesis_Status
     TopoDS_Shape myLocSubShape;
     //use PseudoShape in case if mesh has no shape
     if(HasShapeToMesh())
-      myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
+      myLocSubShape = _gen_i->GeomObjectToShape( aSubShape);
     else              
       myLocSubShape = _impl->GetShapeToMesh();
     
-    int hypId = myHyp->GetId();
-    status = _impl->AddHypothesis(myLocSubShape, hypId);
-    if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
-      _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( myHyp );
-#ifdef WITHGENERICOBJ
-      _mapHypo[hypId]->Register();
-#endif
+    const int hypId = anHyp->GetId();
+    std::string error;
+    status = _impl->AddHypothesis( myLocSubShape, hypId, &error );
+    if ( !SMESH_Hypothesis::IsStatusFatal(status) )
+    {
+      _mapHypo[hypId] = SMESH::SMESH_Hypothesis::_duplicate( anHyp );
+      anHyp->Register();
       // assure there is a corresponding submesh
       if ( !_impl->IsMainShape( myLocSubShape )) {
         int shapeId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
         if ( _mapSubMesh_i.find( shapeId ) == _mapSubMesh_i.end() )
-          createSubMesh( aSubShapeObject );
+          SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
       }
     }
+    else if ( anErrorText )
+    {
+      *anErrorText = error;
+    }
   }
   catch(SALOME_Exception & S_ex)
   {
@@ -579,30 +680,29 @@ SMESH_Hypothesis::Hypothesis_Status
  */
 //=============================================================================
 
-SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShapeObject,
+SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aSubShape,
                                                         SMESH::SMESH_Hypothesis_ptr anHyp)
-     throw(SALOME::SALOME_Exception)
+  throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
     _preMeshInfo->ForgetOrLoad();
 
-  SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShapeObject, anHyp );
+  SMESH_Hypothesis::Hypothesis_Status status = removeHypothesis( aSubShape, anHyp );
+  SMESH::SMESH_Mesh_var mesh = _this();
 
   if ( !SMESH_Hypothesis::IsStatusFatal(status) )
-    _gen_i->RemoveHypothesisFromShape(_gen_i->GetCurrentStudy(), _this(),
-                                      aSubShapeObject, anHyp );
-
-  // Update Python script
-    // Update Python script
-  if(_impl->HasShapeToMesh()) {
-  TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
-                << aSubShapeObject << ", " << anHyp << " )";
+  {
+    SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
+    _gen_i->RemoveHypothesisFromShape( study, mesh, aSubShape, anHyp );
   }
-  else {
-    TPythonDump() << "status = " << _this() << ".RemoveHypothesis( "
+  // Update Python script
+  if(_impl->HasShapeToMesh())
+    TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
+                  << aSubShape << ", " << anHyp << " )";
+  else
+    TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
                   << anHyp << " )";
-  }
 
   return ConvertHypothesisStatus(status);
 }
@@ -614,17 +714,15 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aS
 //=============================================================================
 
 SMESH_Hypothesis::Hypothesis_Status
-SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
+SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShape,
                                SMESH::SMESH_Hypothesis_ptr anHyp)
 {
   if(MYDEBUG) MESSAGE("removeHypothesis()");
-  // **** proposer liste de sub-shape (selection multiple)
 
-  if (CORBA::is_nil(aSubShapeObject) && HasShapeToMesh())
+  if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
 
-  SMESH::SMESH_Hypothesis_var myHyp = SMESH::SMESH_Hypothesis::_narrow(anHyp);
-  if (CORBA::is_nil(myHyp))
+  if (CORBA::is_nil( anHyp ))
     THROW_SALOME_CORBA_EXCEPTION("bad hypothesis reference", SALOME::BAD_PARAM);
 
   SMESH_Hypothesis::Hypothesis_Status status = SMESH_Hypothesis::HYP_OK;
@@ -632,15 +730,18 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
   {
     TopoDS_Shape myLocSubShape;
     //use PseudoShape in case if mesh has no shape
-    if(HasShapeToMesh())
-      myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject);
+    if( _impl->HasShapeToMesh() )
+      myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
     else
       myLocSubShape = _impl->GetShapeToMesh();
 
-    int hypId = myHyp->GetId();
+    const int hypId = anHyp->GetId();
     status = _impl->RemoveHypothesis(myLocSubShape, hypId);
-//     if ( !SMESH_Hypothesis::IsStatusFatal(status) ) EAP: hyp can be used on many sub-shapes
-//       _mapHypo.erase( hypId );
+    if ( !SMESH_Hypothesis::IsStatusFatal(status) )
+    {
+      // _mapHypo.erase( hypId ); EAP: hyp can be used on many sub-shapes
+      anHyp->UnRegister();
+    }
   }
   catch(SALOME_Exception & S_ex)
   {
@@ -656,30 +757,32 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
 //=============================================================================
 
 SMESH::ListOfHypothesis *
-        SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShapeObject)
+SMESH_Mesh_i::GetHypothesisList(GEOM::GEOM_Object_ptr aSubShape)
 throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if (MYDEBUG) MESSAGE("GetHypothesisList");
-  if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShapeObject))
+  if (_impl->HasShapeToMesh() && CORBA::is_nil(aSubShape))
     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
 
   SMESH::ListOfHypothesis_var aList = new SMESH::ListOfHypothesis();
 
   try {
-    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
+    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
     if ( myLocSubShape.IsNull() && !_impl->HasShapeToMesh() )
       myLocSubShape = _impl->GetShapeToMesh();
     const list<const SMESHDS_Hypothesis*>& aLocalList = _impl->GetHypothesisList( myLocSubShape );
     int i = 0, n = aLocalList.size();
     aList->length( n );
 
-    for ( list<const SMESHDS_Hypothesis*>::const_iterator anIt = aLocalList.begin(); i < n && anIt != aLocalList.end(); anIt++ ) {
-      SMESHDS_Hypothesis* aHyp = (SMESHDS_Hypothesis*)(*anIt);
-      if ( _mapHypo.find( aHyp->GetID() ) != _mapHypo.end() )
-        aList[i++] = SMESH::SMESH_Hypothesis::_narrow( _mapHypo[aHyp->GetID()] );
+    list<const SMESHDS_Hypothesis*>::const_iterator aHyp = aLocalList.begin();
+    std::map<int, SMESH::SMESH_Hypothesis_ptr>::iterator id_hypptr;
+    for ( ; i < n && aHyp != aLocalList.end(); aHyp++ )
+    {
+      id_hypptr = _mapHypo.find( (*aHyp)->GetID() );
+      if ( id_hypptr != _mapHypo.end() )
+        aList[i++] = SMESH::SMESH_Hypothesis::_narrow( id_hypptr->second );
     }
-
     aList->length( i );
   }
   catch(SALOME_Exception & S_ex) {
@@ -720,7 +823,7 @@ SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes() throw (SALOME::SALOME_Excepti
 
   // Update Python script
   if ( !_mapSubMeshIor.empty() )
-    aPythonDump << " ] = " << _this() << ".GetSubMeshes()";
+    aPythonDump << " ] = " << SMESH::SMESH_Mesh_var( _this() ) << ".GetSubMeshes()";
 
   return aList._retn();
 }
@@ -730,20 +833,19 @@ SMESH::submesh_array* SMESH_Mesh_i::GetSubMeshes() throw (SALOME::SALOME_Excepti
  *
  */
 //=============================================================================
-SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShapeObject,
+
+SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShape,
                                                   const char*           theName )
      throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
-  MESSAGE("SMESH_Mesh_i::GetSubMesh");
-  if (CORBA::is_nil(aSubShapeObject))
-    THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",
-                                 SALOME::BAD_PARAM);
+  if (CORBA::is_nil(aSubShape))
+    THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
 
   SMESH::SMESH_subMesh_var subMesh;
-  SMESH::SMESH_Mesh_var    aMesh = SMESH::SMESH_Mesh::_narrow(_this());
+  SMESH::SMESH_Mesh_var    aMesh = _this();
   try {
-    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
+    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
 
     //Get or Create the SMESH_subMesh object implementation
 
@@ -759,15 +861,16 @@ SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShap
 
     // create a new subMesh object servant if there is none for the shape
     if ( subMesh->_is_nil() )
-      subMesh = createSubMesh( aSubShapeObject );
-    if ( _gen_i->CanPublishInStudy( subMesh )) {
-      SALOMEDS::SObject_var aSO =
-        _gen_i->PublishSubMesh(_gen_i->GetCurrentStudy(), aMesh,
-                               subMesh, aSubShapeObject, theName );
+      subMesh = createSubMesh( aSubShape );
+    if ( _gen_i->CanPublishInStudy( subMesh ))
+    {
+      SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
+      SALOMEDS::SObject_wrap aSO =
+        _gen_i->PublishSubMesh( study, aMesh, subMesh, aSubShape, theName );
       if ( !aSO->_is_nil()) {
         // Update Python script
-        TPythonDump() << aSO << " = " << _this() << ".GetSubMesh( "
-                      << aSubShapeObject << ", '" << theName << "' )";
+        TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
+                      << aSubShape << ", '" << theName << "' )";
       }
     }
   }
@@ -784,36 +887,43 @@ SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::GetSubMesh(GEOM::GEOM_Object_ptr aSubShap
 //=============================================================================
 
 void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
-     throw (SALOME::SALOME_Exception)
+  throw (SALOME::SALOME_Exception)
 {
-  if(MYDEBUG) MESSAGE("SMESH_Mesh_i::RemoveSubMesh");
+  SMESH_TRY;
+
   if ( theSubMesh->_is_nil() )
     return;
 
-  GEOM::GEOM_Object_var aSubShapeObject;
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
+  GEOM::GEOM_Object_var aSubShape;
+  SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
   if ( !aStudy->_is_nil() )  {
     // Remove submesh's SObject
-    SALOMEDS::SObject_var anSO = _gen_i->ObjectToSObject( aStudy, theSubMesh );
+    SALOMEDS::SObject_wrap anSO = _gen_i->ObjectToSObject( aStudy, theSubMesh );
     if ( !anSO->_is_nil() ) {
       long aTag = SMESH_Gen_i::GetRefOnShapeTag();
-      SALOMEDS::SObject_var anObj, aRef;
-      if ( anSO->FindSubObject( aTag, anObj ) && anObj->ReferencedObject( aRef ) )
-        aSubShapeObject = GEOM::GEOM_Object::_narrow( aRef->GetObject() );
-
-//       if ( aSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
-//         aSubShapeObject = theSubMesh->GetSubShape();
+      SALOMEDS::SObject_wrap anObj, aRef;
+      if ( anSO->FindSubObject( aTag, anObj.inout() ) &&
+           anObj->ReferencedObject( aRef.inout() ))
+      {
+        CORBA::Object_var obj = aRef->GetObject();
+        aSubShape = GEOM::GEOM_Object::_narrow( obj );
+      }
+      // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
+      //   aSubShape = theSubMesh->GetSubShape();
 
-      aStudy->NewBuilder()->RemoveObjectWithChildren( anSO );
+      SALOMEDS::StudyBuilder_var builder = aStudy->NewBuilder();
+      builder->RemoveObjectWithChildren( anSO );
 
       // Update Python script
-      TPythonDump() << _this() << ".RemoveSubMesh( " << anSO << " )";
+      TPythonDump() << SMESH::SMESH_Mesh_var( _this() ) << ".RemoveSubMesh( " << anSO << " )";
     }
   }
 
-  if ( removeSubMesh( theSubMesh, aSubShapeObject.in() ))
+  if ( removeSubMesh( theSubMesh, aSubShape.in() ))
     if ( _preMeshInfo )
       _preMeshInfo->ForgetOrLoad();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -824,7 +934,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
 
 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType,
                                                   const char*        theName )
-     throw(SALOME::SALOME_Exception)
+  throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
@@ -833,20 +943,20 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::CreateGroup( SMESH::ElementType theElemType
   SMESH::SMESH_Group_var aNewGroup =
     SMESH::SMESH_Group::_narrow( createGroup( theElemType, theName ));
 
-  if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
-    SALOMEDS::SObject_var aSO =
-      _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
-                           aNewGroup, GEOM::GEOM_Object::_nil(), theName);
-    if ( !aSO->_is_nil()) {
+  if ( _gen_i->CanPublishInStudy( aNewGroup ) )
+  {
+    SMESH::SMESH_Mesh_var mesh = _this();
+    SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
+    SALOMEDS::SObject_wrap aSO =
+      _gen_i->PublishGroup( study, mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName);
+    if ( !aSO->_is_nil())
       // Update Python script
-      TPythonDump() << aSO << " = " << _this() << ".CreateGroup( "
+      TPythonDump() << aSO << " = " << mesh << ".CreateGroup( "
                     << theElemType << ", '" << theName << "' )";
-    }
   }
   return aNewGroup._retn();
 }
 
-
 //=============================================================================
 /*!
  *
@@ -856,7 +966,7 @@ SMESH::SMESH_GroupOnGeom_ptr
 SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
                                    const char*           theName,
                                    GEOM::GEOM_Object_ptr theGeomObj)
-     throw(SALOME::SALOME_Exception)
+  throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
@@ -867,18 +977,18 @@ SMESH_Mesh_i::CreateGroupFromGEOM (SMESH::ElementType    theElemType,
   TopoDS_Shape aShape = _gen_i->GeomObjectToShape( theGeomObj );
   if ( !aShape.IsNull() )
   {
-    aNewGroup = SMESH::SMESH_GroupOnGeom::_narrow
-      ( createGroup( theElemType, theName, aShape ));
+    aNewGroup = 
+      SMESH::SMESH_GroupOnGeom::_narrow( createGroup( theElemType, theName, aShape ));
 
-    if ( _gen_i->CanPublishInStudy( aNewGroup ) ) {
-      SALOMEDS::SObject_var aSO =
-        _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(),
-                             aNewGroup, theGeomObj, theName);
-      if ( !aSO->_is_nil()) {
-        // Update Python script
-        TPythonDump() << aSO << " = " << _this() << ".CreateGroupFromGEOM("
+    if ( _gen_i->CanPublishInStudy( aNewGroup ) )
+    {
+      SMESH::SMESH_Mesh_var mesh = _this();
+      SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
+      SALOMEDS::SObject_wrap aSO =
+        _gen_i->PublishGroup( study, mesh, aNewGroup, theGeomObj, theName );
+      if ( !aSO->_is_nil())
+        TPythonDump() << aSO << " = " << mesh << ".CreateGroupFromGEOM( "
                       << theElemType << ", '" << theName << "', " << theGeomObj << " )";
-      }
     }
   }
 
@@ -899,7 +1009,7 @@ SMESH::SMESH_GroupOnFilter_ptr
 SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
                                     const char*        theName,
                                     SMESH::Filter_ptr  theFilter )
-    throw (SALOME::SALOME_Exception)
+  throw (SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
@@ -921,16 +1031,15 @@ SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
 
   if ( _gen_i->CanPublishInStudy( aNewGroup ) )
   {
-    SALOMEDS::SObject_var aSO =
-      _gen_i->PublishGroup(_gen_i->GetCurrentStudy(), _this(), aNewGroup,
-                           GEOM::GEOM_Object::_nil(), theName);
-    if ( !aSO->_is_nil()) {
-      // Update Python script
-      pd << aSO << " = " << _this() << ".CreateGroupFromFilter("
+    SMESH::SMESH_Mesh_var mesh = _this();
+    SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
+    SALOMEDS::SObject_wrap aSO =
+      _gen_i->PublishGroup( study, mesh, aNewGroup, GEOM::GEOM_Object::_nil(), theName );
+
+    if ( !aSO->_is_nil())
+      pd << aSO << " = " << mesh << ".CreateGroupFromFilter( "
          << theElemType << ", '" << theName << "', " << theFilter << " )";
-    }
   }
-
   return aNewGroup._retn();
 }
 
@@ -941,31 +1050,37 @@ SMESH_Mesh_i::CreateGroupFromFilter(SMESH::ElementType theElemType,
 //=============================================================================
 
 void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
-     throw (SALOME::SALOME_Exception)
+  throw (SALOME::SALOME_Exception)
 {
   if ( theGroup->_is_nil() )
     return;
 
-  SMESH_GroupBase_i* aGroup =
-    dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
+  SMESH_TRY;
+
+  SMESH_GroupBase_i* aGroup = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
   if ( !aGroup )
     return;
 
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-  if ( !aStudy->_is_nil() )  {
-    SALOMEDS::SObject_var aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
-
-    if ( !aGroupSO->_is_nil() ) {
+  SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
+  if ( !aStudy->_is_nil() )
+  {
+    SALOMEDS::SObject_wrap aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
+    if ( !aGroupSO->_is_nil() )
+    {
       // Update Python script
-      TPythonDump() << _this() << ".RemoveGroup( " << aGroupSO << " )";
+      TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".RemoveGroup( " << aGroupSO << " )";
 
       // Remove group's SObject
-      aStudy->NewBuilder()->RemoveObjectWithChildren( aGroupSO );
+      SALOMEDS::StudyBuilder_var builder = aStudy->NewBuilder();
+      builder->RemoveObjectWithChildren( aGroupSO );
     }
   }
+  aGroup->Modified(/*removed=*/true); // notify dependent Filter with FT_BelongToMeshGroup criterion
 
   // Remove the group from SMESH data structures
   removeGroup( aGroup->GetLocalID() );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -977,39 +1092,59 @@ void SMESH_Mesh_i::RemoveGroup( SMESH::SMESH_GroupBase_ptr theGroup )
 void SMESH_Mesh_i::RemoveGroupWithContents( SMESH::SMESH_GroupBase_ptr theGroup )
   throw (SALOME::SALOME_Exception)
 {
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
   if ( theGroup->_is_nil() )
     return;
 
-  SMESH_GroupBase_i* aGroup =
-    dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
-  if ( !aGroup )
-    return;
+  vector<int> nodeIds; // to remove nodes becoming free
+  if ( !theGroup->IsEmpty() )
+  {
+    CORBA::Long elemID = theGroup->GetID( 1 );
+    int nbElemNodes = GetElemNbNodes( elemID );
+    if ( nbElemNodes > 0 )
+      nodeIds.reserve( theGroup->Size() * nbElemNodes );
+  }
+
+  // Remove contents
+  SMESH::SMESH_IDSource_var idSrc = SMESH::SMESH_IDSource::_narrow( theGroup );
+  SMDS_ElemIteratorPtr     elemIt = GetElements( idSrc, theGroup->GetType() );
+  while ( elemIt->more() )
+  {
+    const SMDS_MeshElement* e = elemIt->next();
 
-  SMESH::long_array_var anIds = aGroup->GetListOfID();
-  SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
+    SMDS_ElemIteratorPtr nIt = e->nodesIterator();
+    while ( nIt->more() )
+      nodeIds.push_back( nIt->next()->GetID() );
 
-  TPythonDump pyDump; // Supress dump from RemoveNodes/Elements() and RemoveGroup()
+    _impl->GetMeshDS()->RemoveElement( e );
+  }
 
-  // Remove contents
-  if ( aGroup->GetType() == SMESH::NODE )
-    aMeshEditor->RemoveNodes( anIds );
-  else
-    aMeshEditor->RemoveElements( anIds );
+  // Remove free nodes
+  if ( theGroup->GetType() != SMESH::NODE )
+    for ( size_t i = 0 ; i < nodeIds.size(); ++i )
+      if ( const SMDS_MeshNode* n = _impl->GetMeshDS()->FindNode( nodeIds[i] ))
+        if ( n->NbInverseElements() == 0 )
+          _impl->GetMeshDS()->RemoveFreeNode( n, /*sm=*/0 );
+
+  TPythonDump pyDump; // Supress dump from RemoveGroup()
+
+  // Update Python script (theGroup must be alive for this)
+  pyDump << SMESH::SMESH_Mesh_var(_this())
+         << ".RemoveGroupWithContents( " << theGroup << " )";
 
   // Remove group
   RemoveGroup( theGroup );
 
-  // Update Python script
-  pyDump << _this() << ".RemoveGroupWithContents( " << theGroup << " )";
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //================================================================================
 /*!
  * \brief Get the list of groups existing in the mesh
 * \retval SMESH::ListOfGroups * - list of groups
 \retval SMESH::ListOfGroups * - list of groups
  */
 //================================================================================
 
@@ -1022,30 +1157,27 @@ SMESH::ListOfGroups * SMESH_Mesh_i::GetGroups() throw(SALOME::SALOME_Exception)
 
   // Python Dump
   TPythonDump aPythonDump;
-  if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
+  if ( !_mapGroups.empty() )
+  {
     aPythonDump << "[ ";
-
-  try {
-    aList->length( _mapGroups.size() );
-    int i = 0;
-    map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
-    for ( ; it != _mapGroups.end(); it++ ) {
-      if ( CORBA::is_nil( it->second )) continue;
-      aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
-      // Python Dump
-      if (i > 1) aPythonDump << ", ";
-      aPythonDump << it->second;
+    try {
+      aList->length( _mapGroups.size() );
+      int i = 0;
+      map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
+      for ( ; it != _mapGroups.end(); it++ ) {
+        if ( CORBA::is_nil( it->second )) continue;
+        aList[i++] = SMESH::SMESH_GroupBase::_duplicate( it->second );
+        // Python Dump
+        if (i > 1) aPythonDump << ", ";
+        aPythonDump << it->second;
+      }
+      aList->length( i );
     }
-    aList->length( i );
-  }
-  catch(SALOME_Exception & S_ex) {
-    THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
+    catch(SALOME_Exception & S_ex) {
+      THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
+    }
+    aPythonDump << " ] = " << SMESH::SMESH_Mesh_var(_this()) << ".GetGroups()";
   }
-
-  // Update Python script
-  if ( !_mapGroups.empty() ) // (IMP13463) avoid "SyntaxError: can't assign to []"
-    aPythonDump << " ] = " << _this() << ".GetGroups()";
-
   return aList._retn();
 }
 
@@ -1062,204 +1194,170 @@ CORBA::Long SMESH_Mesh_i::NbGroups() throw (SALOME::SALOME_Exception)
 }
 
 //=============================================================================
-/*! UnionGroups
- *  New group is created. All mesh elements that are
- *  present in initial groups are added to the new one
+/*!
+ * New group including all mesh elements present in initial groups is created.
  */
 //=============================================================================
+
 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
                                                   SMESH::SMESH_GroupBase_ptr theGroup2,
-                                                  const char* theName )
+                                                  const char*                theName )
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_Group_var aResGrp;
+
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  try
-  {
-    if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
-         theGroup1->GetType() != theGroup2->GetType() )
-      return SMESH::SMESH_Group::_nil();
-
-    // Create Union
-    SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
-    if ( aResGrp->_is_nil() )
-      return SMESH::SMESH_Group::_nil();
-
-    SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
-    SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
-
-    TColStd_MapOfInteger aResMap;
-
-    for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
-      aResMap.Add( anIds1[ i1 ] );
-
-    for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
-      aResMap.Add( anIds2[ i2 ] );
-
-    SMESH::long_array_var aResIds = new SMESH::long_array;
-    aResIds->length( aResMap.Extent() );
+  if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
+    THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): NULL Group",
+                                 SALOME::BAD_PARAM);
+  if ( theGroup1->GetType() != theGroup2->GetType() )
+    THROW_SALOME_CORBA_EXCEPTION("UnionGroups(): different group types",
+                                 SALOME::BAD_PARAM);
+  TPythonDump pyDump;
 
-    int resI = 0;
-    TColStd_MapIteratorOfMapOfInteger anIter( aResMap );
-    for( ; anIter.More(); anIter.Next() )
-      aResIds[ resI++ ] = anIter.Key();
+  // Create Union
+  aResGrp = CreateGroup( theGroup1->GetType(), theName );
+  if ( aResGrp->_is_nil() )
+    return SMESH::SMESH_Group::_nil();
 
-    aResGrp->Add( aResIds );
+  aResGrp->AddFrom( theGroup1 );
+  aResGrp->AddFrom( theGroup2 );
 
-    // Clear python lines, created by CreateGroup() and Add()
-    SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-    _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
-    _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
+  // Update Python script
+  pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this())
+         << ".UnionGroups( " << theGroup1 << ", " << theGroup2 << ", '" << theName << "' )";
 
-    // Update Python script
-    TPythonDump() << aResGrp << " = " << _this() << ".UnionGroups( "
-                  << theGroup1 << ", " << theGroup2 << ", '"
-                  << theName << "' )";
+  SMESH_CATCH( SMESH::throwCorbaException );
 
-    return aResGrp._retn();
-  }
-  catch( ... )
-  {
-    return SMESH::SMESH_Group::_nil();
-  }
+  return aResGrp._retn();
 }
 
 //=============================================================================
 /*!
-  \brief Union list of groups. New group is created. All mesh elements that are
-   present in initial groups are added to the new one.
-  \param theGroups list of groups
-  \param theName name of group to be created
-  \return pointer on the group
-*/
+ * \brief New group including all mesh elements present in initial groups is created.
+ *  \param theGroups list of groups
+ *  \param theName name of group to be created
+ *  \return pointer to the new group
+ */
 //=============================================================================
+
 SMESH::SMESH_Group_ptr SMESH_Mesh_i::UnionListOfGroups(const SMESH::ListOfGroups& theGroups,
                                                        const char*                theName )
-throw (SALOME::SALOME_Exception)
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_Group_var aResGrp;
+
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
   if ( !theName )
     return SMESH::SMESH_Group::_nil();
 
-  try
+  SMESH_TRY;
+
+  // check types
+  SMESH::ElementType aType = SMESH::ALL;
+  for ( int g = 0, n = theGroups.length(); g < n; g++ )
   {
-    vector< int > anIds;
-    SMESH::ElementType aType = SMESH::ALL;
-    for ( int g = 0, n = theGroups.length(); g < n; g++ )
-    {
-      SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
-      if ( CORBA::is_nil( aGrp ) )
-        continue;
+    SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
+    if ( CORBA::is_nil( aGrp ) )
+      continue;
+    if ( aType == SMESH::ALL )
+      aType = aGrp->GetType();
+    else if ( aType != aGrp->GetType() )
+      THROW_SALOME_CORBA_EXCEPTION("UnionListOfGroups(): different group types",
+                                   SALOME::BAD_PARAM);
+  }
+  if ( aType == SMESH::ALL )
+    return SMESH::SMESH_Group::_nil();
 
-      // check type
-      SMESH::ElementType aCurrType = aGrp->GetType();
-      if ( aType == SMESH::ALL )
-        aType = aCurrType;
-      else 
-      {
-        if ( aType != aCurrType )
-          return SMESH::SMESH_Group::_nil();
-      }
+  TPythonDump pyDump;
 
-      // unite ids
-      SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
-      for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
-      {
-        int aCurrId = aCurrIds[ i ];
-        anIds.push_back( aCurrId );
-      }
-    }
+  // Create Union
+  aResGrp = CreateGroup( aType, theName );
+  if ( aResGrp->_is_nil() )
+    return SMESH::SMESH_Group::_nil();
 
-    // Create group
-    SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
-    if ( aResGrp->_is_nil() )
-      return SMESH::SMESH_Group::_nil();
-    
-    // Create array of identifiers
-    SMESH::long_array_var aResIds = new SMESH::long_array;
-    aResIds->length( anIds.size() );
-    
-    //NCollection_Map< int >::Iterator anIter( anIds );
-    for ( int i = 0; i<anIds.size(); i++ )
+  pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".UnionListOfGroups([ ";
+  for ( int g = 0, n = theGroups.length(); g < n; g++ )
+  {
+    SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
+    if ( !CORBA::is_nil( aGrp ) )
     {
-      aResIds[ i ] = anIds[i];
+      aResGrp->AddFrom( aGrp );
+      if ( g > 0 ) pyDump << ", ";
+      pyDump << aGrp;
     }
-    aResGrp->Add( aResIds );
-
-    // Clear python lines, created by CreateGroup() and Add()
-    SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-    _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
-    _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
+  }
+  pyDump << " ], '" << theName << "' )";
 
-    // Update Python script
-    
-    TPythonDump() << aResGrp << " = " << _this() << ".UnionListOfGroups( "
-                  << &theGroups << ", '" << theName << "' )";
+  SMESH_CATCH( SMESH::throwCorbaException );
 
-    return aResGrp._retn();
-  }
-  catch( ... )
-  {
-    return SMESH::SMESH_Group::_nil();
-  }
+  return aResGrp._retn();
 }
 
 //=============================================================================
-/*! IntersectGroups
+/*!
  *  New group is created. All mesh elements that are
  *  present in both initial groups are added to the new one.
  */
 //=============================================================================
+
 SMESH::SMESH_Group_ptr SMESH_Mesh_i::IntersectGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
                                                       SMESH::SMESH_GroupBase_ptr theGroup2,
-                                                      const char* theName )
+                                                      const char*                theName )
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_Group_var aResGrp;
+
+  SMESH_TRY;
+
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
-       theGroup1->GetType() != theGroup2->GetType() )
-    return SMESH::SMESH_Group::_nil();
+  if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
+    THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): NULL Group",
+                                 SALOME::BAD_PARAM);
+  if ( theGroup1->GetType() != theGroup2->GetType() )
+    THROW_SALOME_CORBA_EXCEPTION("IntersectGroups(): different group types",
+                                 SALOME::BAD_PARAM);
+  TPythonDump pyDump;
 
   // Create Intersection
-  SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
+  aResGrp = CreateGroup( theGroup1->GetType(), theName );
   if ( aResGrp->_is_nil() )
-    return aResGrp;
-
-  SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
-  SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
-
-  TColStd_MapOfInteger aMap1;
-
-  for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
-    aMap1.Add( anIds1[ i1 ] );
-
-  TColStd_SequenceOfInteger aSeq;
-
-  for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
-    if ( aMap1.Contains( anIds2[ i2 ] ) )
-      aSeq.Append( anIds2[ i2 ] );
-
-  SMESH::long_array_var aResIds = new SMESH::long_array;
-  aResIds->length( aSeq.Length() );
+    return aResGrp._retn();
 
-  for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
-    aResIds[ resI ] = aSeq( resI + 1 );
+  SMESHDS_GroupBase* groupDS1 = 0;
+  if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
+    groupDS1 = grp_i->GetGroupDS();
 
-  aResGrp->Add( aResIds );
+  SMESHDS_GroupBase* groupDS2 = 0;
+  if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
+    groupDS2 = grp_i->GetGroupDS();
 
-  // Clear python lines, created by CreateGroup() and Add()
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-  _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
-  _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
+  SMESHDS_Group* resGroupDS = 0;
+  if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
+    resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
 
+  if ( groupDS1 && groupDS2 && resGroupDS && !groupDS2->IsEmpty() )
+  {
+    SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
+    while ( elemIt1->more() )
+    {
+      const SMDS_MeshElement* e = elemIt1->next();
+      if ( groupDS2->Contains( e ))
+        resGroupDS->SMDSGroup().Add( e );
+    }
+  }
   // Update Python script
-  TPythonDump() << aResGrp << " = " << _this() << ".IntersectGroups( "
-                << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
+  pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".IntersectGroups( "
+         << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 
   return aResGrp._retn();
 }
@@ -1278,143 +1376,136 @@ SMESH_Mesh_i::IntersectListOfGroups(const SMESH::ListOfGroups& theGroups,
                                     const char*                theName )
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_Group_var aResGrp;
+
+  SMESH_TRY;
+
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
   if ( !theName )
     return SMESH::SMESH_Group::_nil();
 
-  try
+  // check types and get SMESHDS_GroupBase's
+  SMESH::ElementType aType = SMESH::ALL;
+  vector< SMESHDS_GroupBase* > groupVec;
+  for ( int g = 0, n = theGroups.length(); g < n; g++ )
   {
-    NCollection_DataMap< int, int > anIdToCount;
-    SMESH::ElementType aType = SMESH::ALL;
-    for ( int g = 0, n = theGroups.length(); g < n; g++ )
-    {
-      SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
-      if ( CORBA::is_nil( aGrp ) )
-        continue;
-
-      // check type
-      SMESH::ElementType aCurrType = aGrp->GetType();
-      if ( aType == SMESH::ALL )
-        aType = aCurrType;
-      else 
+    SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
+    if ( CORBA::is_nil( aGrp ) )
+      continue;
+    if ( aType == SMESH::ALL )
+      aType = aGrp->GetType();
+    else if ( aType != aGrp->GetType() )
+      THROW_SALOME_CORBA_EXCEPTION("IntersectListOfGroups(): different group types",
+                                   SALOME::BAD_PARAM);
+
+    if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
+      if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
       {
-        if ( aType != aCurrType )
-          return SMESH::SMESH_Group::_nil();
-      }
-
-      // calculates number of occurance ids in groups
-      SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
-      for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
-      {
-        int aCurrId = aCurrIds[ i ];
-        if ( !anIdToCount.IsBound( aCurrId ) )
-          anIdToCount.Bind( aCurrId, 1 );
-        else 
-          anIdToCount( aCurrId ) = anIdToCount( aCurrId ) + 1;
+        if ( grpDS->IsEmpty() )
+        {
+          groupVec.clear();
+          break;
+        }
+        groupVec.push_back( grpDS );
       }
-    }
-    
-    // create map of ids
-    int nbGrp = theGroups.length();
-    vector< int > anIds;
-    NCollection_DataMap< int, int >::Iterator anIter( anIdToCount );
-    for ( ; anIter.More(); anIter.Next() )
-    {
-      int aCurrId = anIter.Key();
-      int aCurrNb = anIter.Value();
-      if ( aCurrNb == nbGrp )
-        anIds.push_back( aCurrId );
-    }
-
-    // Create group
-    SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
-    if ( aResGrp->_is_nil() )
-      return SMESH::SMESH_Group::_nil();
-    
-    // Create array of identifiers
-    SMESH::long_array_var aResIds = new SMESH::long_array;
-    aResIds->length( anIds.size() );
-    
-    //NCollection_Map< int >::Iterator aListIter( anIds );
-    for ( int i = 0; i<anIds.size(); i++ )
-    {
-      aResIds[ i ] = anIds[i];
-    }
-    aResGrp->Add( aResIds );
+  }
+  if ( aType == SMESH::ALL ) // all groups are nil
+    return SMESH::SMESH_Group::_nil();
 
-    // Clear python lines, created by CreateGroup() and Add()
-    SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-    _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
-    _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
+  TPythonDump pyDump;
 
-    // Update Python script
-    
-    TPythonDump() << aResGrp << " = " << _this() << ".IntersectListOfGroups( "
-                  << &theGroups << ", '" << theName << "' )";
+  // Create a group
+  aResGrp = CreateGroup( aType, theName );
 
+  SMESHDS_Group* resGroupDS = 0;
+  if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
+    resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
+  if ( !resGroupDS || groupVec.empty() )
     return aResGrp._retn();
-  }
-  catch( ... )
+
+  // Fill the group
+  size_t i, nb = groupVec.size();
+  SMDS_ElemIteratorPtr elemIt1 = groupVec[0]->GetElements();
+  while ( elemIt1->more() )
   {
-    return SMESH::SMESH_Group::_nil();
+    const SMDS_MeshElement* e = elemIt1->next();
+    bool inAll = true;
+    for ( i = 1; ( i < nb && inAll ); ++i )
+      inAll = groupVec[i]->Contains( e );
+
+    if ( inAll )
+      resGroupDS->SMDSGroup().Add( e );
   }
+
+  // Update Python script
+  pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
+         << ".IntersectListOfGroups( " << theGroups << ", '" << theName << "' )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return aResGrp._retn();
 }
 
 //=============================================================================
-/*! CutGroups
+/*! 
  *  New group is created. All mesh elements that are present in
- *  main group but do not present in tool group are added to the new one
+ *  a main group but is not present in a tool group are added to the new one
  */
 //=============================================================================
+
 SMESH::SMESH_Group_ptr SMESH_Mesh_i::CutGroups( SMESH::SMESH_GroupBase_ptr theGroup1,
                                                 SMESH::SMESH_GroupBase_ptr theGroup2,
                                                 const char*                theName )
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_Group_var aResGrp;
+
+  SMESH_TRY;
+
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  if ( theGroup1->_is_nil() || theGroup2->_is_nil() ||
-       theGroup1->GetType() != theGroup2->GetType() )
-    return SMESH::SMESH_Group::_nil();
+  if ( theGroup1->_is_nil() || theGroup2->_is_nil() )
+    THROW_SALOME_CORBA_EXCEPTION("CutGroups(): NULL Group",
+                                 SALOME::BAD_PARAM);
+  if ( theGroup1->GetType() != theGroup2->GetType() )
+    THROW_SALOME_CORBA_EXCEPTION("CutGroups(): different group types",
+                                 SALOME::BAD_PARAM);
+  TPythonDump pyDump;
 
-  // Perform Cutting
-  SMESH::SMESH_Group_var aResGrp = CreateGroup( theGroup1->GetType(), theName );
+  aResGrp = CreateGroup( theGroup1->GetType(), theName );
   if ( aResGrp->_is_nil() )
-    return aResGrp;
-
-  SMESH::long_array_var anIds1 = theGroup1->GetListOfID();
-  SMESH::long_array_var anIds2 = theGroup2->GetListOfID();
-
-  TColStd_MapOfInteger aMap2;
-
-  for ( int i2 = 0, n2 = anIds2->length(); i2 < n2; i2++ )
-    aMap2.Add( anIds2[ i2 ] );
-
-  TColStd_SequenceOfInteger aSeq;
-  for ( int i1 = 0, n1 = anIds1->length(); i1 < n1; i1++ )
-    if ( !aMap2.Contains( anIds1[ i1 ] ) )
-      aSeq.Append( anIds1[ i1 ] );
-
-  SMESH::long_array_var aResIds = new SMESH::long_array;
-  aResIds->length( aSeq.Length() );
+    return aResGrp._retn();
 
-  for ( int resI = 0, resN = aSeq.Length(); resI < resN; resI++ )
-    aResIds[ resI ] = aSeq( resI + 1 );
+  SMESHDS_GroupBase* groupDS1 = 0;
+  if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup1 ))
+    groupDS1 = grp_i->GetGroupDS();
 
-  aResGrp->Add( aResIds );
+  SMESHDS_GroupBase* groupDS2 = 0;
+  if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( theGroup2 ))
+    groupDS2 = grp_i->GetGroupDS();
 
-  // Clear python lines, created by CreateGroup() and Add()
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-  _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
-  _gen_i->RemoveLastFromPythonScript(aStudy->StudyId());
+  SMESHDS_Group* resGroupDS = 0;
+  if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
+    resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
 
+  if ( groupDS1 && groupDS2 && resGroupDS )
+  {
+    SMDS_ElemIteratorPtr elemIt1 = groupDS1->GetElements();
+    while ( elemIt1->more() )
+    {
+      const SMDS_MeshElement* e = elemIt1->next();
+      if ( !groupDS2->Contains( e ))
+        resGroupDS->SMDSGroup().Add( e );
+    }
+  }
   // Update Python script
-  TPythonDump() << aResGrp << " = " << _this() << ".CutGroups( "
-                << theGroup1 << ", " << theGroup2 << ", '"
-                << theName << "' )";
+  pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var(_this()) << ".CutGroups( "
+         << theGroup1 << ", " << theGroup2 << ", '" << theName << "')";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 
   return aResGrp._retn();
 }
@@ -1435,124 +1526,142 @@ SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
                               const char*                theName )
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_Group_var aResGrp;
+
+  SMESH_TRY;
+
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
   if ( !theName )
     return SMESH::SMESH_Group::_nil();
 
-  try
+  // check types and get SMESHDS_GroupBase's
+  SMESH::ElementType aType = SMESH::ALL;
+  vector< SMESHDS_GroupBase* >   toolGroupVec;
+  vector< SMDS_ElemIteratorPtr > mainIterVec;
+
+  for ( int g = 0, n = theMainGroups.length(); g < n; g++ )
   {
-    set< int > aToolIds;
-    SMESH::ElementType aType = SMESH::ALL;
-    int g, n;
-    // iterate through tool groups
-    for ( g = 0, n = theToolGroups.length(); g < n; g++ )
-    {
-      SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
-      if ( CORBA::is_nil( aGrp ) )
-        continue;
+    SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
+    if ( CORBA::is_nil( aGrp ) )
+      continue;
+    if ( aType == SMESH::ALL )
+      aType = aGrp->GetType();
+    else if ( aType != aGrp->GetType() )
+      THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
+                                   SALOME::BAD_PARAM);
+    if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
+      if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
+        if ( !grpDS->IsEmpty() )
+          mainIterVec.push_back( grpDS->GetElements() );
+  }
+  if ( aType == SMESH::ALL ) // all main groups are nil
+    return SMESH::SMESH_Group::_nil();
+  if ( mainIterVec.empty() ) // all main groups are empty
+    return aResGrp._retn();
 
-      // check type
-      SMESH::ElementType aCurrType = aGrp->GetType();
-      if ( aType == SMESH::ALL )
-        aType = aCurrType;
-      else 
-      {
-        if ( aType != aCurrType )
-          return SMESH::SMESH_Group::_nil();
-      }
+  for ( int g = 0, n = theToolGroups.length(); g < n; g++ )
+  {
+    SMESH::SMESH_GroupBase_var aGrp = theToolGroups[ g ];
+    if ( CORBA::is_nil( aGrp ) )
+      continue;
+    if ( aType != aGrp->GetType() )
+      THROW_SALOME_CORBA_EXCEPTION("CutListOfGroups(): different group types",
+                                   SALOME::BAD_PARAM);
+    if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aGrp ))
+      if ( SMESHDS_GroupBase* grpDS = grp_i->GetGroupDS() )
+        toolGroupVec.push_back( grpDS );
+  }
 
-      // unite tool ids
-      SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
-      for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
-      {
-        int aCurrId = aCurrIds[ i ];
-        aToolIds.insert( aCurrId );
-      }
-    }
+  TPythonDump pyDump;
 
-    vector< int > anIds; // result
+  // Create a group
+  aResGrp = CreateGroup( aType, theName );
 
-    // Iterate through main group 
-    for ( g = 0, n = theMainGroups.length(); g < n; g++ )
-    {
-      SMESH::SMESH_GroupBase_var aGrp = theMainGroups[ g ];
-      if ( CORBA::is_nil( aGrp ) )
-        continue;
+  SMESHDS_Group* resGroupDS = 0;
+  if ( SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( aResGrp ))
+    resGroupDS = dynamic_cast<SMESHDS_Group*>( grp_i->GetGroupDS() );
+  if ( !resGroupDS )
+    return aResGrp._retn();
 
-      // check type
-      SMESH::ElementType aCurrType = aGrp->GetType();
-      if ( aType == SMESH::ALL )
-        aType = aCurrType;
-      else 
-      {
-        if ( aType != aCurrType )
-          return SMESH::SMESH_Group::_nil();
-      }
+  // Fill the group
+  size_t i, nb = toolGroupVec.size();
+  SMDS_ElemIteratorPtr mainElemIt
+    ( new SMDS_IteratorOnIterators
+      < const SMDS_MeshElement*, vector< SMDS_ElemIteratorPtr > >( mainIterVec ));
+  while ( mainElemIt->more() )
+  {
+    const SMDS_MeshElement* e = mainElemIt->next();
+    bool isIn = false;
+    for ( i = 0; ( i < nb && !isIn ); ++i )
+      isIn = toolGroupVec[i]->Contains( e );
 
-      // unite tool ids
-      SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
-      for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
-      {
-        int aCurrId = aCurrIds[ i ];
-        if ( !aToolIds.count( aCurrId ) )
-          anIds.push_back( aCurrId );
-      }
-    }
+    if ( !isIn )
+      resGroupDS->SMDSGroup().Add( e );
+  }
 
-    // Create group
-    SMESH::SMESH_Group_var aResGrp = CreateGroup( aType, theName );
-    if ( aResGrp->_is_nil() )
-      return SMESH::SMESH_Group::_nil();
-    
-    // Create array of identifiers
-    SMESH::long_array_var aResIds = new SMESH::long_array;
-    aResIds->length( anIds.size() );
-    
-    for (int i=0; i<anIds.size(); i++ )
-    {
-      aResIds[ i ] = anIds[i];
-    }
-    aResGrp->Add( aResIds );
+  // Update Python script
+  pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
+         << ".CutListOfGroups( " << theMainGroups << ", "
+         << theToolGroups << ", '" << theName << "' )";
 
-    // Clear python lines, created by CreateGroup() and Add()
-    SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-    _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
-    _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
+  SMESH_CATCH( SMESH::throwCorbaException );
 
-    // Update Python script
+  return aResGrp._retn();
+}
 
-    TPythonDump() << aResGrp << " = " << _this() << ".CutListOfGroups( "
-                  << &theMainGroups << ", " << &theToolGroups << ", '"
-                  << theName << "' )";
-    
-    return aResGrp._retn();
+namespace // functions making checks according to SMESH::NB_COMMON_NODES_ENUM
+{
+  bool isAllNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
+                        bool & toStopChecking )
+  {
+    toStopChecking = ( nbCommon < nbChecked );
+    return nbCommon == nbNodes;
   }
-  catch( ... )
+  bool isMainNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
+                         bool & toStopChecking )
   {
-    return SMESH::SMESH_Group::_nil();
+    toStopChecking = ( nbCommon < nbChecked || nbChecked >= nbCorners );
+    return nbCommon == nbCorners;
+  }
+  bool isAtLeastOneNodeCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
+                              bool & toStopChecking )
+  {
+    return nbCommon > 0;
+  }
+  bool isMajorityOfNodesCommon(int nbChecked, int nbCommon, int nbNodes, int nbCorners,
+                               bool & toStopChecking )
+  {
+    return nbCommon >= (nbNodes+1) / 2;
   }
 }
 
 //=============================================================================
 /*!
-  \brief Create groups of entities from existing groups of superior dimensions 
-  System 
-  1) extract all nodes from each group,
 2) combine all elements of specified dimension laying on these nodes.
-  \param theGroups list of source groups 
-  \param theElemType dimension of elements 
-  \param theName name of new group
 \return pointer on new group
+ * Create a group of entities basing on nodes of other groups.
+ *  \param [in] theGroups - list of either groups, sub-meshes or filters.
+ *  \param [in] anElemType - a type of elements to include to the new group.
*  \param [in] theName - a name of the new group.
+ *  \param [in] theNbCommonNodes - criterion of inclusion of an element to the new group.
+ *  \param [in] theUnderlyingOnly - if \c True, an element is included to the
+ *         new group provided that it is based on nodes of an element of \a aListOfGroups
*  \return SMESH_Group - the created group
 */
+// IMP 19939, bug 22010, IMP 22635
 //=============================================================================
+
 SMESH::SMESH_Group_ptr
-SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfGroups& theGroups, 
-                             SMESH::ElementType         theElemType, 
-                             const char*                theName )
+SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfIDSources& theGroups,
+                             SMESH::ElementType            theElemType,
+                             const char*                   theName,
+                             SMESH::NB_COMMON_NODES_ENUM   theNbCommonNodes,
+                             CORBA::Boolean                theUnderlyingOnly)
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_Group_var aResGrp;
+
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
@@ -1563,141 +1672,154 @@ SMESH_Mesh_i::CreateDimGroup(const SMESH::ListOfGroups& theGroups,
 
   SMDSAbs_ElementType anElemType = (SMDSAbs_ElementType)theElemType;
 
-  try
+  bool (*isToInclude)(int nbChecked, int nbCommon, int nbNodes, int nbCorners, bool & toStop);
+  SMESH_Comment nbCoNoStr( "SMESH.");
+  switch ( theNbCommonNodes ) {
+  case SMESH::ALL_NODES   : isToInclude = isAllNodesCommon;        nbCoNoStr<<"ALL_NODES"   ;break;
+  case SMESH::MAIN        : isToInclude = isMainNodesCommon;       nbCoNoStr<<"MAIN"        ;break;
+  case SMESH::AT_LEAST_ONE: isToInclude = isAtLeastOneNodeCommon;  nbCoNoStr<<"AT_LEAST_ONE";break;
+  case SMESH::MAJORITY    : isToInclude = isMajorityOfNodesCommon; nbCoNoStr<<"MAJORITY"    ;break;
+  default: return aResGrp._retn();
+  }
+  int nbChecked, nbCommon, nbNodes, nbCorners;
+
+  // Create a group
+
+  TPythonDump pyDump;
+
+  aResGrp = CreateGroup( theElemType, theName );
+  if ( aResGrp->_is_nil() )
+    return SMESH::SMESH_Group::_nil();
+
+  SMESHDS_GroupBase* groupBaseDS =
+    SMESH::DownCast<SMESH_GroupBase_i*>( aResGrp )->GetGroupDS();
+  SMDS_MeshGroup& resGroupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
+
+  vector<bool> isNodeInGroups;
+
+  for ( int g = 0, n = theGroups.length(); g < n; g++ ) // loop on theGroups
   {
-    // Create map of nodes from all groups 
+    SMESH::SMESH_IDSource_var aGrp = theGroups[ g ];
+    if ( CORBA::is_nil( aGrp ) )
+      continue;
+    SMESH::SMESH_Mesh_var mesh = aGrp->GetMesh();
+    if ( mesh->_is_nil() || mesh->GetId() != this->GetId() )
+      continue;
 
-    set< int > aNodeMap;
-    
-    for ( int g = 0, n = theGroups.length(); g < n; g++ )
-    {
-      SMESH::SMESH_GroupBase_var aGrp = theGroups[ g ];
-      if ( CORBA::is_nil( aGrp ) )
-        continue;
+    SMDS_ElemIteratorPtr elIt = GetElements( aGrp, SMESH::ALL );
+    if ( !elIt ) continue;
 
-      SMESH::ElementType aType = aGrp->GetType();
-      if ( aType == SMESH::ALL )
-        continue;
-      else if ( aType == SMESH::NODE )
-      {
-        SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
-        for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
-        {
-          int aCurrId = aCurrIds[ i ];
-          const SMDS_MeshNode* aNode = aMeshDS->FindNode( aCurrId );
-          if ( aNode )
-            aNodeMap.insert( aNode->GetID() );
-        }
+    if ( theElemType == SMESH::NODE ) // get all nodes of elements
+    {
+      while ( elIt->more() ) {
+        const SMDS_MeshElement* el = elIt->next();
+        SMDS_ElemIteratorPtr nIt = el->nodesIterator();
+        while ( nIt->more() )
+          resGroupCore.Add( nIt->next() );
       }
-      else 
+    }
+    // get elements of theElemType based on nodes of every element of group
+    else if ( theUnderlyingOnly )
+    {
+      while ( elIt->more() )
       {
-        SMESH::long_array_var aCurrIds = aGrp->GetListOfID();
-        for ( int i = 0, n = aCurrIds->length(); i < n; i++ )
+        const SMDS_MeshElement* el = elIt->next(); // an element of ref group
+        TIDSortedElemSet elNodes( el->begin_nodes(), el->end_nodes() );
+        TIDSortedElemSet checkedElems;
+        SMDS_NodeIteratorPtr nIt = el->nodeIterator();
+        while ( nIt->more() )
         {
-          int aCurrId = aCurrIds[ i ];
-          const SMDS_MeshElement* anElem = aMeshDS->FindElement( aCurrId );
-          if ( !anElem )
-            continue;
-          SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
-          while( aNodeIter->more() )
+          const SMDS_MeshNode* n = nIt->next();
+          SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
+          // check nodes of elements of theElemType around el
+          while ( elOfTypeIt->more() )
           {
-            const SMDS_MeshNode* aNode = 
-              dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
-            if ( aNode )
-              aNodeMap.insert( aNode->GetID() );
+            const SMDS_MeshElement* elOfType = elOfTypeIt->next();
+            if ( !checkedElems.insert( elOfType ).second ) continue;
+            nbNodes   = elOfType->NbNodes();
+            nbCorners = elOfType->NbCornerNodes();
+            nbCommon  = 0;
+            bool toStopChecking = false;
+            SMDS_ElemIteratorPtr nIt2 = elOfType->nodesIterator();
+            for ( nbChecked = 1; nIt2->more() && !toStopChecking; ++nbChecked )
+              if ( elNodes.count( nIt2->next() ) &&
+                   isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
+              {
+                resGroupCore.Add( elOfType );
+                break;
+              }
           }
         }
       }
     }
-
-    // Get result identifiers 
-
-    vector< int > aResultIds;
-    if ( theElemType == SMESH::NODE )
-    {
-      //NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
-      set<int>::iterator iter = aNodeMap.begin();
-      for ( ; iter != aNodeMap.end(); iter++ )
-        aResultIds.push_back( *iter);
-    }
+    // get all nodes of elements of groups
     else
     {
-      // Create list of elements of given dimension constructed on the nodes
-      vector< int > anElemList;
-      //NCollection_Map< int >::Iterator aNodeIter( aNodeMap );
-      //for ( ; aNodeIter.More(); aNodeIter.Next() )
-      set<int>::iterator iter = aNodeMap.begin();
-      for ( ; iter != aNodeMap.end(); iter++ )
+      while ( elIt->more() )
       {
-        const SMDS_MeshElement* aNode = 
-          dynamic_cast<const SMDS_MeshElement*>( aMeshDS->FindNode( *iter ) );
-        if ( !aNode )
-          continue;
-
-         SMDS_ElemIteratorPtr anElemIter = aNode->elementsIterator( anElemType );
-        while( anElemIter->more() )
+        const SMDS_MeshElement* el = elIt->next(); // an element of group
+        SMDS_NodeIteratorPtr nIt = el->nodeIterator();
+        while ( nIt->more() )
         {
-          const SMDS_MeshElement* anElem = 
-            dynamic_cast<const SMDS_MeshElement*>( anElemIter->next() );
-          if ( anElem && anElem->GetType() == anElemType )
-            anElemList.push_back( anElem->GetID() );
+          const SMDS_MeshNode* n = nIt->next();
+          if ( n->GetID() >= (int) isNodeInGroups.size() )
+            isNodeInGroups.resize( n->GetID() + 1, false );
+          isNodeInGroups[ n->GetID() ] = true;
         }
       }
+    }
+  }
+
+  // Get elements of theElemType based on a certain number of nodes of elements of groups
+  if ( !theUnderlyingOnly && !isNodeInGroups.empty() )
+  {
+    const SMDS_MeshNode* n;
+    vector<bool> isElemChecked( aMeshDS->MaxElementID() + 1 );
+    const int isNodeInGroupsSize = isNodeInGroups.size();
+    for ( int iN = 0; iN < isNodeInGroupsSize; ++iN )
+    {
+      if ( !isNodeInGroups[ iN ] ||
+           !( n = aMeshDS->FindNode( iN )))
+        continue;
 
-      // check whether all nodes of elements are present in nodes map
-      for (int i=0; i< anElemList.size(); i++)
+      // check nodes of elements of theElemType around n
+      SMDS_ElemIteratorPtr elOfTypeIt = n->GetInverseElementIterator( anElemType );
+      while ( elOfTypeIt->more() )
       {
-        const SMDS_MeshElement* anElem = aMeshDS->FindElement( anElemList[i] );
-        if ( !anElem )
+        const SMDS_MeshElement*  elOfType = elOfTypeIt->next();
+        vector<bool>::reference isChecked = isElemChecked[ elOfType->GetID() ];
+        if ( isChecked )
           continue;
-
-        bool isOk = true;
-        SMDS_ElemIteratorPtr aNodeIter = anElem->nodesIterator();
-        while( aNodeIter->more() )
+        isChecked = true;
+
+        nbNodes   = elOfType->NbNodes();
+        nbCorners = elOfType->NbCornerNodes();
+        nbCommon  = 0;
+        bool toStopChecking = false;
+        SMDS_ElemIteratorPtr nIt = elOfType->nodesIterator();
+        for ( nbChecked = 1; nIt->more() && !toStopChecking; ++nbChecked )
         {
-          const SMDS_MeshNode* aNode = 
-            dynamic_cast<const SMDS_MeshNode*>( aNodeIter->next() );
-          if ( !aNode || !aNodeMap.count( aNode->GetID() ) )
+          const int nID = nIt->next()->GetID();
+          if ( nID < isNodeInGroupsSize && isNodeInGroups[ nID ] &&
+               isToInclude( nbChecked, ++nbCommon, nbNodes, nbCorners, toStopChecking ))
           {
-            isOk = false;
+            resGroupCore.Add( elOfType );
             break;
           }
-        } 
-        if ( isOk )
-          aResultIds.push_back( anElem->GetID() );
+        }
       }
     }
+  }
 
-    // Create group
-
-    SMESH::SMESH_Group_var aResGrp = CreateGroup( theElemType, theName );
-    if ( aResGrp->_is_nil() )
-      return SMESH::SMESH_Group::_nil();
-    
-    // Create array of identifiers
-    SMESH::long_array_var aResIds = new SMESH::long_array;
-    aResIds->length( aResultIds.size() );
-    
-    for (int i=0; i< aResultIds.size(); i++)
-      aResIds[ i ] = aResultIds[i];
-    aResGrp->Add( aResIds );
-
-    // Remove strings corresponding to group creation
-    SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-    _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
-    _gen_i->RemoveLastFromPythonScript( aStudy->StudyId() );
+  // Update Python script
+  pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this())
+         << ".CreateDimGroup( "
+         << theGroups << ", " << theElemType << ", '" << theName << "', "
+         << nbCoNoStr << ", " << theUnderlyingOnly << ")";
 
-    // Update Python script
-    
-    TPythonDump() << aResGrp << " = " << _this() << ".CreateDimGroup( "
-                  << &theGroups << ", " << theElemType << ", '" << theName << "' )";
+  SMESH_CATCH( SMESH::throwCorbaException );
 
-    return aResGrp._retn();
-  }
-  catch( ... )
-  {
-    return SMESH::SMESH_Group::_nil();
-  }
+  return aResGrp._retn();
 }
 
 //================================================================================
@@ -1712,13 +1834,13 @@ void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
   if ( CORBA::is_nil( theGeomObj ) || theGeomObj->GetType() != GEOM_GROUP )
     return;
   // group SO
-  SALOMEDS::Study_var   study  = _gen_i->GetCurrentStudy();
-  SALOMEDS::SObject_var groupSO = _gen_i->ObjectToSObject( study, theGeomObj );
+  SALOMEDS::Study_var    study   = _gen_i->GetCurrentStudy();
+  SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( study, theGeomObj );
   if ( groupSO->_is_nil() )
     return;
   // group indices
   GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
-  GEOM::GEOM_IGroupOperations_var groupOp =
+  GEOM::GEOM_IGroupOperations_wrap groupOp =
     geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
   GEOM::ListOfLong_var ids = groupOp->GetObjects( theGeomObj );
 
@@ -1729,10 +1851,13 @@ void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
   CORBA::String_var entry = groupSO->GetID();
   groupData._groupEntry = entry.in();
   // indices
-  for ( int i = 0; i < ids->length(); ++i )
+  for ( CORBA::ULong i = 0; i < ids->length(); ++i )
     groupData._indices.insert( ids[i] );
   // SMESH object
-  groupData._smeshObject = theSmeshObj;
+  groupData._smeshObject = CORBA::Object::_duplicate( theSmeshObj );
+  // shape index in SMESHDS
+  // TopoDS_Shape shape = _gen_i->GeomObjectToShape( theGeomObj );
+  // groupData._dsID = shape.IsNull() ? 0 : _impl->GetSubMesh( shape )->GetId();
 }
 
 //================================================================================
@@ -1766,7 +1891,7 @@ TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
   // get geom group
   SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
   if ( study->_is_nil() ) return newShape; // means "not changed"
-  SALOMEDS::SObject_var groupSO = study->FindObjectID( groupData._groupEntry.c_str() );
+  SALOMEDS::SObject_wrap groupSO = study->FindObjectID( groupData._groupEntry.c_str() );
   if ( !groupSO->_is_nil() )
   {
     CORBA::Object_var groupObj = _gen_i->SObjectToObject( groupSO );
@@ -1776,10 +1901,10 @@ TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
     // get indices of group items
     set<int> curIndices;
     GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
-    GEOM::GEOM_IGroupOperations_var groupOp =
+    GEOM::GEOM_IGroupOperations_wrap groupOp =
       geomGen->GetIGroupOperations( _gen_i->GetCurrentStudyID() );
-    GEOM::ListOfLong_var ids = groupOp->GetObjects( geomGroup );
-    for ( int i = 0; i < ids->length(); ++i )
+    GEOM::ListOfLong_var   ids = groupOp->GetObjects( geomGroup );
+    for ( CORBA::ULong i = 0; i < ids->length(); ++i )
       curIndices.insert( ids[i] );
 
     if ( groupData._indices == curIndices )
@@ -1790,10 +1915,10 @@ TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
 
     GEOM_Client* geomClient = _gen_i->GetShapeReader();
     if ( !geomClient ) return newShape;
-    TCollection_AsciiString groupIOR = geomGen->GetStringFromIOR( geomGroup );
-    geomClient->RemoveShapeFromBuffer( groupIOR );
+    CORBA::String_var groupIOR = geomGen->GetStringFromIOR( geomGroup );
+    geomClient->RemoveShapeFromBuffer( groupIOR.in() );
     newShape = _gen_i->GeomObjectToShape( geomGroup );
-  }    
+  }
 
   if ( newShape.IsNull() ) {
     // geom group becomes empty - return empty compound
@@ -1806,22 +1931,182 @@ TopoDS_Shape SMESH_Mesh_i::newGroupShape( TGeomGroupData & groupData)
 
 namespace
 {
-  //=============================================================================
+  //-----------------------------------------------------------------------------
   /*!
    * \brief Storage of shape and index used in CheckGeomGroupModif()
    */
-  //=============================================================================
   struct TIndexedShape
   {
     int          _index;
     TopoDS_Shape _shape;
     TIndexedShape( int i, const TopoDS_Shape& s ):_index(i), _shape(s) {}
   };
+  //-----------------------------------------------------------------------------
+  /*!
+   * \brief Data to re-create a group on geometry
+   */
+  struct TGroupOnGeomData
+  {
+    int                 _oldID;
+    int                 _shapeID;
+    SMDSAbs_ElementType _type;
+    std::string         _name;
+    Quantity_Color      _color;
+  };
+}
+
+//=============================================================================
+/*!
+ * \brief Update data if geometry changes
+ *
+ * Issue 0022501
+ */
+//=============================================================================
+
+void SMESH_Mesh_i::CheckGeomModif()
+{
+  if ( !_impl->HasShapeToMesh() ) return;
+
+  SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
+  if ( study->_is_nil() ) return;
+
+  GEOM::GEOM_Object_var mainGO = _gen_i->ShapeToGeomObject( _impl->GetShapeToMesh() );
+  //if ( mainGO->_is_nil() ) return;
+
+  // Update after group modification
+
+  if ( mainGO->_is_nil() || /* shape was removed from GEOM_Client by newGroupShape()
+                               called by other mesh (IPAL52735) */
+       mainGO->GetType() == GEOM_GROUP ||
+       mainGO->GetTick() == _mainShapeTick )
+  {
+    CheckGeomGroupModif();
+    return;
+  }
+
+  // Update after shape transformation like Translate
+
+  GEOM_Client* geomClient = _gen_i->GetShapeReader();
+  if ( !geomClient ) return;
+  GEOM::GEOM_Gen_var geomGen = _gen_i->GetGeomEngine();
+  if ( geomGen->_is_nil() ) return;
+
+  CORBA::String_var ior = geomGen->GetStringFromIOR( mainGO );
+  geomClient->RemoveShapeFromBuffer( ior.in() );
+
+  // Update data taking into account that
+  // all sub-shapes change but IDs of sub-shapes remain (except for geom groups)
+
+  _impl->Clear();
+  TopoDS_Shape newShape = _gen_i->GeomObjectToShape( mainGO );
+  if ( newShape.IsNull() )
+    return;
+
+  _mainShapeTick = mainGO->GetTick();
+
+  SMESHDS_Mesh * meshDS = _impl->GetMeshDS();
+
+  // store data of groups on geometry
+  vector< TGroupOnGeomData > groupsData;
+  const set<SMESHDS_GroupBase*>& groups = meshDS->GetGroups();
+  groupsData.reserve( groups.size() );
+  set<SMESHDS_GroupBase*>::const_iterator g = groups.begin();
+  for ( ; g != groups.end(); ++g )
+    if ( const SMESHDS_GroupOnGeom* group = dynamic_cast< SMESHDS_GroupOnGeom* >( *g ))
+    {
+      TGroupOnGeomData data;
+      data._oldID   = group->GetID();
+      data._shapeID = meshDS->ShapeToIndex( group->GetShape() );
+      data._type    = group->GetType();
+      data._name    = group->GetStoreName();
+      data._color   = group->GetColor();
+      groupsData.push_back( data );
+    }
+  // store assigned hypotheses
+  vector< pair< int, THypList > > ids2Hyps;
+  const ShapeToHypothesis & hyps = meshDS->GetHypotheses();
+  for ( ShapeToHypothesis::Iterator s2hyps( hyps ); s2hyps.More(); s2hyps.Next() )
+  {
+    const TopoDS_Shape& s = s2hyps.Key();
+    const THypList&  hyps = s2hyps.ChangeValue();
+    ids2Hyps.push_back( make_pair( meshDS->ShapeToIndex( s ), hyps ));
+  }
+
+  // change shape to mesh
+  int oldNbSubShapes = meshDS->MaxShapeIndex();
+  _impl->ShapeToMesh( TopoDS_Shape() );
+  _impl->ShapeToMesh( newShape );
+
+  // re-add shapes of geom groups
+  list<TGeomGroupData>::iterator data = _geomGroupData.begin();
+  for ( ; data != _geomGroupData.end(); ++data )
+  {
+    TopoDS_Shape newShape = newGroupShape( *data );
+    if ( !newShape.IsNull() )
+    {
+      if ( meshDS->ShapeToIndex( newShape ) > 0 ) // a group reduced to one sub-shape
+      {
+        TopoDS_Compound compound;
+        BRep_Builder().MakeCompound( compound );
+        BRep_Builder().Add( compound, newShape );
+        newShape = compound;
+      }
+      _impl->GetSubMesh( newShape );
+    }
+  }
+  if ( oldNbSubShapes != meshDS->MaxShapeIndex() )
+    THROW_SALOME_CORBA_EXCEPTION( "SMESH_Mesh_i::CheckGeomModif() bug",
+                                  SALOME::INTERNAL_ERROR );
+
+  // re-assign hypotheses
+  for ( size_t i = 0; i < ids2Hyps.size(); ++i )
+  {
+    const TopoDS_Shape& s = meshDS->IndexToShape( ids2Hyps[i].first );
+    const THypList&  hyps = ids2Hyps[i].second;
+    THypList::const_iterator h = hyps.begin();
+    for ( ; h != hyps.end(); ++h )
+      _impl->AddHypothesis( s, (*h)->GetID() );
+  }
+
+  // restore groups
+  for ( size_t i = 0; i < groupsData.size(); ++i )
+  {
+    const TGroupOnGeomData& data = groupsData[i];
+
+    map<int, SMESH::SMESH_GroupBase_ptr>::iterator i2g = _mapGroups.find( data._oldID );
+    if ( i2g == _mapGroups.end() ) continue;
+
+    SMESH_GroupBase_i* gr_i = SMESH::DownCast<SMESH_GroupBase_i*>( i2g->second );
+    if ( !gr_i ) continue;
+
+    int id;
+    SMESH_Group* g = _impl->AddGroup( data._type, data._name.c_str(), id,
+                                      meshDS->IndexToShape( data._shapeID ));
+    if ( !g )
+    {
+      _mapGroups.erase( i2g );
+    }
+    else
+    {
+      g->GetGroupDS()->SetColor( data._color );
+      gr_i->changeLocalId( id );
+      _mapGroups[ id ] = i2g->second;
+      if ( data._oldID != id )
+        _mapGroups.erase( i2g );
+    }
+  }
+
+  // update _mapSubMesh
+  map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
+  for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
+    i_sm->second = _impl->GetSubMesh( meshDS->IndexToShape( i_sm->first ));
+
 }
+
 //=============================================================================
 /*!
  * \brief Update objects depending on changed geom groups
- * 
+ *
  * NPAL16168: geometrical group edition from a submesh don't modifiy mesh computation
  * issue 0020210: Update of a smesh group after modification of the associated geom group
  */
@@ -1869,7 +2154,7 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
     if ( !submesh->_is_nil() ) // -------------- Sub mesh ---------------------
     {
       int oldID = submesh->GetId();
-      if ( _mapSubMeshIor.find( oldID ) == _mapSubMeshIor.end() )
+      if ( !_mapSubMeshIor.count( oldID ))
         continue;
       TopoDS_Shape oldShape = _mapSubMesh[oldID]->GetSubShape();
 
@@ -1978,9 +2263,11 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
           groupData.push_back
             ( make_pair( TIndexedShape( gog->GetID(),gog->GetShape()), gog->GetType()));
       }
-      // set new shape to mesh -> DS of submeshes and geom groups is deleted
+      // set new shape to mesh -> DS of sub-meshes and geom groups are deleted
+      _impl->Clear();
+      _impl->ShapeToMesh( TopoDS_Shape() ); // IPAL52730
       _impl->ShapeToMesh( newShape );
-      
+
       // reassign hypotheses
       TShapeHypList::iterator indS_hyps = assignedHyps.begin();
       for ( ; indS_hyps != assignedHyps.end(); ++indS_hyps )
@@ -1989,15 +2276,15 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
         list<const SMESHDS_Hypothesis*>& hyps = indS_hyps->second;
         int oldID = geom._index;
         int newID = meshDS->ShapeToIndex( geom._shape );
-        if ( !newID )
-          continue;
         if ( oldID == 1 ) { // main shape
           newID = 1;
           geom._shape = newShape;
         }
+        if ( !newID )
+          continue;
         for ( hypIt = hyps.begin(); hypIt != hyps.end(); ++hypIt )
           _impl->AddHypothesis( geom._shape, (*hypIt)->GetID());
-        // care of submeshes
+        // care of sub-meshes
         SMESH_subMesh* newSubmesh = _impl->GetSubMesh( geom._shape );
         if ( newID != oldID ) {
           _mapSubMesh   [ newID ] = newSubmesh;
@@ -2018,10 +2305,10 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
         if ( _mapGroups.find( oldID ) == _mapGroups.end() )
           continue;
         // get group name
-        SALOMEDS::SObject_var groupSO = _gen_i->ObjectToSObject( study,_mapGroups[oldID] );
-        CORBA::String_var     name    = groupSO->GetName();
+        SALOMEDS::SObject_wrap groupSO = _gen_i->ObjectToSObject( study,_mapGroups[oldID] );
+        CORBA::String_var      name    = groupSO->GetName();
         // update
-        SMESH_GroupBase_i* group_i    = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID] );
+        SMESH_GroupBase_i*  group_i    = SMESH::DownCast<SMESH_GroupBase_i*>(_mapGroups[oldID] );
         int newID;
         if ( group_i && _impl->AddGroup( geomType->second, name.in(), newID, geom._shape ))
           group_i->changeLocalId( newID );
@@ -2035,7 +2322,7 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
   // Update icons
 
   CORBA::Long newNbEntities = NbNodes() + NbElements();
-  list< SALOMEDS::SObject_var > soToUpdateIcons;
+  list< SALOMEDS::SObject_wrap > soToUpdateIcons;
   if ( newNbEntities != nbEntities )
   {
     // Add all SObjects with icons to soToUpdateIcons
@@ -2050,7 +2337,7 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
       soToUpdateIcons.push_back( _gen_i->ObjectToSObject( study, i_gr->second ));
   }
 
-  list< SALOMEDS::SObject_var >::iterator so = soToUpdateIcons.begin();
+  list< SALOMEDS::SObject_wrap >::iterator so = soToUpdateIcons.begin();
   for ( ; so != soToUpdateIcons.end(); ++so )
     _gen_i->SetPixMap( *so, "ICON_SMESH_TREE_MESH_WARN" );
 }
@@ -2062,24 +2349,25 @@ void SMESH_Mesh_i::CheckGeomGroupModif()
 //=============================================================================
 
 SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroup )
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_Group_var aGroup;
+
+  SMESH_TRY;
+
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  SMESH::SMESH_Group_var aGroup;
   if ( theGroup->_is_nil() )
     return aGroup._retn();
 
-  Unexpect aCatch(SALOME_SalomeException);
-
-  SMESH_GroupBase_i* aGroupToRem =
-    dynamic_cast<SMESH_GroupBase_i*>( SMESH_Gen_i::GetServant( theGroup ).in() );
+  SMESH_GroupBase_i* aGroupToRem = SMESH::DownCast<SMESH_GroupBase_i*>( theGroup );
   if ( !aGroupToRem )
     return aGroup._retn();
 
   const bool isOnFilter = ( SMESH::DownCast< SMESH_GroupOnFilter_i* > ( theGroup ));
 
-  int anId = aGroupToRem->GetLocalID();
+  const int anId = aGroupToRem->GetLocalID();
   if ( !_impl->ConvertToStandalone( anId ) )
     return aGroup._retn();
   removeGeomGroupData( theGroup );
@@ -2087,25 +2375,26 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase
   SMESH_GroupBase_i* aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
 
   // remove old instance of group from own map
+  { SMESH::SMESH_GroupBase_var var( _mapGroups[anId] ); } // decref CORBA object
   _mapGroups.erase( anId );
 
   SALOMEDS::StudyBuilder_var builder;
-  SALOMEDS::SObject_var aGroupSO;
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-  if ( !aStudy->_is_nil() )  {
-    builder = aStudy->NewBuilder();
+  SALOMEDS::SObject_wrap     aGroupSO;
+  SALOMEDS::Study_var        aStudy = _gen_i->GetCurrentStudy();
+  if ( !aStudy->_is_nil() ) {
+    builder  = aStudy->NewBuilder();
     aGroupSO = _gen_i->ObjectToSObject( aStudy, theGroup );
-    if ( !aGroupSO->_is_nil() ) {
-
+    if ( !aGroupSO->_is_nil() )
+    {
       // remove reference to geometry
-      SALOMEDS::ChildIterator_var chItr = aStudy->NewChildIterator(aGroupSO);
+      SALOMEDS::ChildIterator_wrap chItr = aStudy->NewChildIterator(aGroupSO);
       for ( ; chItr->More(); chItr->Next() )
         // Remove group's child SObject
         builder->RemoveObject( chItr->Value() );
 
       // Update Python script
-      TPythonDump() << aGroupSO << " = " << _this() << ".ConvertToStandalone( "
-                    << aGroupSO << " )";
+      TPythonDump() << aGroupSO << " = " << SMESH::SMESH_Mesh_var(_this())
+                    << ".ConvertToStandalone( " << aGroupSO << " )";
 
       // change icon of Group on Filter
       if ( isOnFilter )
@@ -2114,28 +2403,28 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase
         const int isEmpty = ( elemTypes->length() == 0 );
         if ( !isEmpty )
         {
-          SALOMEDS::GenericAttribute_var anAttr =
+          SALOMEDS::GenericAttribute_wrap anAttr =
             builder->FindOrCreateAttribute( aGroupSO, "AttributePixMap" );
-          SALOMEDS::AttributePixMap_var pm = SALOMEDS::AttributePixMap::_narrow( anAttr );
+          SALOMEDS::AttributePixMap_wrap pm = anAttr;
           pm->SetPixMap( "ICON_SMESH_TREE_GROUP" );
         }
       }
     }
   }
 
-  // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
-  SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
-  aGroupImpl->Register();
-  // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
-
   // remember new group in own map
   aGroup = SMESH::SMESH_Group::_narrow( aGroupImpl->_this() );
   _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
 
   // register CORBA object for persistence
-  /*int nextId =*/ _gen_i->RegisterObject( aGroup );
+  _gen_i->RegisterObject( aGroup );
 
-  builder->SetIOR( aGroupSO, _gen_i->GetORB()->object_to_string( aGroup ) );
+  CORBA::String_var ior = _gen_i->GetORB()->object_to_string( aGroup );
+  builder->SetIOR( aGroupSO, ior.in() ); //  == aGroup->Register();
+  //aGroup->Register();
+  aGroupToRem->UnRegister();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 
   return aGroup._retn();
 }
@@ -2149,21 +2438,23 @@ SMESH::SMESH_Group_ptr SMESH_Mesh_i::ConvertToStandalone( SMESH::SMESH_GroupBase
 SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::createSubMesh( GEOM::GEOM_Object_ptr theSubShapeObject )
 {
   if(MYDEBUG) MESSAGE( "createSubMesh" );
-  TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
-
+  TopoDS_Shape  myLocSubShape = _gen_i->GeomObjectToShape(theSubShapeObject);
   ::SMESH_subMesh * mySubMesh = _impl->GetSubMesh(myLocSubShape);
-  int subMeshId = _impl->GetMeshDS()->ShapeToIndex( myLocSubShape );
-  SMESH_subMesh_i *subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
-  SMESH::SMESH_subMesh_var subMesh
-    = SMESH::SMESH_subMesh::_narrow(subMeshServant->_this());
+  const int         subMeshId = mySubMesh->GetId();
+
+  SMESH_subMesh_i * subMeshServant = new SMESH_subMesh_i(myPOA, _gen_i, this, subMeshId);
+  SMESH::SMESH_subMesh_var subMesh = subMeshServant->_this();
+
+  _mapSubMesh   [subMeshId] = mySubMesh;
+  _mapSubMesh_i [subMeshId] = subMeshServant;
+  _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate( subMesh );
 
-  _mapSubMesh[subMeshId] = mySubMesh;
-  _mapSubMesh_i[subMeshId] = subMeshServant;
-  _mapSubMeshIor[subMeshId] = SMESH::SMESH_subMesh::_duplicate(subMesh);
+  subMeshServant->Register();
 
   // register CORBA object for persistence
   int nextId = _gen_i->RegisterObject( subMesh );
-  if(MYDEBUG) MESSAGE( "Add submesh to map with id = "<< nextId);
+  if(MYDEBUG) { MESSAGE( "Add submesh to map with id = "<< nextId); }
+  else        { nextId = 0; } // avoid "unused variable" warning
 
   // to track changes of GEOM groups
   addGeomGroupData( theSubShapeObject, subMesh );
@@ -2185,7 +2476,6 @@ SMESH::SMESH_subMesh_ptr SMESH_Mesh_i::getSubMesh(int shapeID)
   return SMESH::SMESH_subMesh::_duplicate( (*it).second );
 }
 
-
 //=============================================================================
 /*!
  *
@@ -2199,12 +2489,13 @@ bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
   if ( theSubMesh->_is_nil() /*|| theSubShapeObject->_is_nil()*/ )
     return isHypChanged;
 
+  const int subMeshId = theSubMesh->GetId();
+
   if ( theSubShapeObject->_is_nil() )  // not published shape (IPAL13617)
   {
-    CORBA::Long shapeId = theSubMesh->GetId();
-    if ( _mapSubMesh.find( shapeId ) != _mapSubMesh.end())
+    if ( _mapSubMesh.find( subMeshId ) != _mapSubMesh.end())
     {
-      TopoDS_Shape S = _mapSubMesh[ shapeId ]->GetSubShape();
+      TopoDS_Shape S = _mapSubMesh[ subMeshId ]->GetSubShape();
       if ( !S.IsNull() )
       {
         list<const SMESHDS_Hypothesis*> hyps = _impl->GetHypothesisList( S );
@@ -2229,7 +2520,16 @@ bool SMESH_Mesh_i::removeSubMesh (SMESH::SMESH_subMesh_ptr theSubMesh,
     }
     removeGeomGroupData( theSubShapeObject );
   }
-  int subMeshId = theSubMesh->GetId();
+
+  // remove a servant
+  std::map<int, SMESH_subMesh_i*>::iterator id_smi = _mapSubMesh_i.find( subMeshId );
+  if ( id_smi != _mapSubMesh_i.end() )
+    id_smi->second->UnRegister();
+
+  // remove a CORBA object
+  std::map<int, SMESH::SMESH_subMesh_ptr>::iterator id_smptr = _mapSubMeshIor.find( subMeshId );
+  if ( id_smptr != _mapSubMeshIor.end() )
+    SMESH::SMESH_subMesh_var( id_smptr->second );
 
   _mapSubMesh.erase(subMeshId);
   _mapSubMesh_i.erase(subMeshId);
@@ -2255,7 +2555,10 @@ SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType
     std::set< std::string > presentNames;
     std::map<int, SMESH::SMESH_GroupBase_ptr>::const_iterator i_gr = _mapGroups.begin();
     for ( ; i_gr != _mapGroups.end(); ++i_gr )
-      presentNames.insert( i_gr->second->GetName() );
+    {
+      CORBA::String_var name = i_gr->second->GetName();
+      presentNames.insert( name.in() );
+    }
     do {
       newName = "noname_Group_" + SMESH_Comment( presentNames.size() + 1 );
     } while ( !presentNames.insert( newName ).second );
@@ -2273,17 +2576,14 @@ SMESH::SMESH_GroupBase_ptr SMESH_Mesh_i::createGroup (SMESH::ElementType
     else
       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
 
-    // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
-    SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
-    aGroupImpl->Register();
-    // PAL7962: san -- To ensure correct mapping of servant and correct reference counting in GenericObj_i
-
-    aGroup = SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
+    aGroup = aGroupImpl->_this();
     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( aGroup );
+    aGroupImpl->Register();
 
     // register CORBA object for persistence
     int nextId = _gen_i->RegisterObject( aGroup );
-    if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
+    if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
+    else        { nextId = 0; } // avoid "unused variable" warning in release mode
 
     // to track changes of GEOM groups
     if ( !theShape.IsNull() ) {
@@ -2306,14 +2606,15 @@ void SMESH_Mesh_i::removeGroup( const int theId )
 {
   if(MYDEBUG) MESSAGE("SMESH_Mesh_i::removeGroup()" );
   if ( _mapGroups.find( theId ) != _mapGroups.end() ) {
-    SMESH::SMESH_GroupBase_ptr group = _mapGroups[theId];
+    SMESH::SMESH_GroupBase_var group = _mapGroups[theId];
     _mapGroups.erase( theId );
     removeGeomGroupData( group );
-    if (_impl->RemoveGroup( theId ))
+    if ( !_impl->RemoveGroup( theId ))
     {
       // it seems to be a call up from _impl caused by hyp modification (issue 0020918)
       RemoveGroup( group );
     }
+    group->UnRegister();
   }
 }
 
@@ -2324,57 +2625,57 @@ void SMESH_Mesh_i::removeGroup( const int theId )
 //=============================================================================
 
 SMESH::log_array * SMESH_Mesh_i::GetLog(CORBA::Boolean clearAfterGet)
-throw(SALOME::SALOME_Exception)
+  throw(SALOME::SALOME_Exception)
 {
+  SMESH::log_array_var aLog;
+
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  SMESH::log_array_var aLog;
-  try{
-    list < SMESHDS_Command * >logDS = _impl->GetLog();
-    aLog = new SMESH::log_array;
-    int indexLog = 0;
-    int lg = logDS.size();
-    SCRUTE(lg);
-    aLog->length(lg);
-    list < SMESHDS_Command * >::iterator its = logDS.begin();
-    while(its != logDS.end()){
-      SMESHDS_Command *com = *its;
-      int comType = com->GetType();
-      //SCRUTE(comType);
-      int lgcom = com->GetNumber();
-      //SCRUTE(lgcom);
-      const list < int >&intList = com->GetIndexes();
-      int inum = intList.size();
-      //SCRUTE(inum);
-      list < int >::const_iterator ii = intList.begin();
-      const list < double >&coordList = com->GetCoords();
-      int rnum = coordList.size();
-      //SCRUTE(rnum);
-      list < double >::const_iterator ir = coordList.begin();
-      aLog[indexLog].commandType = comType;
-      aLog[indexLog].number = lgcom;
-      aLog[indexLog].coords.length(rnum);
-      aLog[indexLog].indexes.length(inum);
-      for(int i = 0; i < rnum; i++){
-        aLog[indexLog].coords[i] = *ir;
-        //MESSAGE(" "<<i<<" "<<ir.Value());
-        ir++;
-      }
-      for(int i = 0; i < inum; i++){
-        aLog[indexLog].indexes[i] = *ii;
-        //MESSAGE(" "<<i<<" "<<ii.Value());
-        ii++;
-      }
-      indexLog++;
-      its++;
+  list < SMESHDS_Command * >logDS = _impl->GetLog();
+  aLog = new SMESH::log_array;
+  int indexLog = 0;
+  int lg = logDS.size();
+  SCRUTE(lg);
+  aLog->length(lg);
+  list < SMESHDS_Command * >::iterator its = logDS.begin();
+  while(its != logDS.end()){
+    SMESHDS_Command *com = *its;
+    int comType = com->GetType();
+    //SCRUTE(comType);
+    int lgcom = com->GetNumber();
+    //SCRUTE(lgcom);
+    const list < int >&intList = com->GetIndexes();
+    int inum = intList.size();
+    //SCRUTE(inum);
+    list < int >::const_iterator ii = intList.begin();
+    const list < double >&coordList = com->GetCoords();
+    int rnum = coordList.size();
+    //SCRUTE(rnum);
+    list < double >::const_iterator ir = coordList.begin();
+    aLog[indexLog].commandType = comType;
+    aLog[indexLog].number = lgcom;
+    aLog[indexLog].coords.length(rnum);
+    aLog[indexLog].indexes.length(inum);
+    for(int i = 0; i < rnum; i++){
+      aLog[indexLog].coords[i] = *ir;
+      //MESSAGE(" "<<i<<" "<<ir.Value());
+      ir++;
     }
-    if(clearAfterGet)
-      _impl->ClearLog();
-  }
-  catch(SALOME_Exception & S_ex){
-    THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
+    for(int i = 0; i < inum; i++){
+      aLog[indexLog].indexes[i] = *ii;
+      //MESSAGE(" "<<i<<" "<<ii.Value());
+      ii++;
+    }
+    indexLog++;
+    its++;
   }
+  if(clearAfterGet)
+    _impl->ClearLog();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+
   return aLog._retn();
 }
 
@@ -2387,8 +2688,9 @@ throw(SALOME::SALOME_Exception)
 
 void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
 {
-  if(MYDEBUG) MESSAGE("SMESH_Mesh_i::ClearLog");
+  SMESH_TRY;
   _impl->ClearLog();
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //=============================================================================
@@ -2399,7 +2701,6 @@ void SMESH_Mesh_i::ClearLog() throw(SALOME::SALOME_Exception)
 
 CORBA::Long SMESH_Mesh_i::GetId()throw(SALOME::SALOME_Exception)
 {
-  if(MYDEBUG) MESSAGE("SMESH_Mesh_i::GetId");
   return _id;
 }
 
@@ -2475,18 +2776,26 @@ void SMESH_Mesh_i::SetImpl(::SMESH_Mesh * impl)
 //=============================================================================
 
 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_MeshEditor_var aMeshEdVar;
+
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
   // Create MeshEditor
-  SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, false );
-  SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
+  if ( !_editor )
+    _editor = new SMESH_MeshEditor_i( this, false );
+  aMeshEdVar = _editor->_this();
 
   // Update Python script
-  TPythonDump() << aMeshEditor << " = " << _this() << ".GetMeshEditor()";
+  TPythonDump() << _editor << " = "
+                << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshEditor()";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 
-  return aMesh._retn();
+  return aMeshEdVar._retn();
 }
 
 //=============================================================================
@@ -2496,13 +2805,21 @@ SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditor()
 //=============================================================================
 
 SMESH::SMESH_MeshEditor_ptr SMESH_Mesh_i::GetMeshEditPreviewer()
+  throw (SALOME::SALOME_Exception)
 {
+  SMESH::SMESH_MeshEditor_var aMeshEdVar;
+
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  SMESH_MeshEditor_i *aMeshEditor = new SMESH_MeshEditor_i( this, true );
-  SMESH::SMESH_MeshEditor_var aMesh = aMeshEditor->_this();
-  return aMesh._retn();
+  if ( !_previewEditor )
+    _previewEditor = new SMESH_MeshEditor_i( this, true );
+  aMeshEdVar = _previewEditor->_this();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return aMeshEdVar._retn();
 }
 
 //================================================================================
@@ -2566,7 +2883,7 @@ void SMESH_Mesh_i::SetAutoColor(CORBA::Boolean theAutoColor) throw(SALOME::SALOM
   _impl->SetAutoColor(theAutoColor);
 
   TPythonDump pyDump; // not to dump group->SetColor() from below code
-  pyDump<<_this()<<".SetAutoColor( "<<theAutoColor<<" )";
+  pyDump << SMESH::SMESH_Mesh_var(_this()) <<".SetAutoColor( "<<theAutoColor<<" )";
 
   std::list<SALOMEDS::Color> aReservedColors;
   map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.begin();
@@ -2609,44 +2926,36 @@ CORBA::Boolean SMESH_Mesh_i::HasDuplicatedGroupNamesMED()
 
 void SMESH_Mesh_i::PrepareForWriting (const char* file, bool overwrite)
 {
-  TCollection_AsciiString aFullName ((char*)file);
-  OSD_Path aPath (aFullName);
-  OSD_File aFile (aPath);
-  if (aFile.Exists()) {
+  SMESH_File aFile( file );
+  SMESH_Comment msg;
+  if (aFile.exists()) {
     // existing filesystem node
-    if (aFile.KindOfFile() == OSD_FILE) {
-      if (aFile.IsWriteable()) {
-        if (overwrite) {
-          aFile.Reset();
-          aFile.Remove();
-        }
-        if (aFile.Failed()) {
-          TCollection_AsciiString msg ("File ");
-          msg += aFullName + " cannot be replaced.";
-          THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
+    if ( !aFile.isDirectory() ) {
+      if ( aFile.openForWriting() ) {
+        if ( overwrite && ! aFile.remove()) {
+          msg << "Can't replace " << aFile.getName();
         }
       } else {
-        TCollection_AsciiString msg ("File ");
-        msg += aFullName + " cannot be overwritten.";
-        THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
+        msg << "Can't write into " << aFile.getName();
       }
     } else {
-      TCollection_AsciiString msg ("Location ");
-      msg += aFullName + " is not a file.";
-      THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
+      msg << "Location " << aFile.getName() << " is not a file";
     }
-  } else {
+  }
+  else {
     // nonexisting file; check if it can be created
-    aFile.Reset();
-    aFile.Build(OSD_WriteOnly, OSD_Protection());
-    if (aFile.Failed()) {
-      TCollection_AsciiString msg ("You cannot create the file ");
-      msg += aFullName + ". Check the directory existance and access rights.";
-      THROW_SALOME_CORBA_EXCEPTION(msg.ToCString(), SALOME::BAD_PARAM);
-    } else {
-      aFile.Close();
-      aFile.Remove();
+    if ( !aFile.openForWriting() ) {
+      msg << "You cannot create the file "
+          << aFile.getName()
+          << ". Check the directory existance and access rights";
     }
+    aFile.remove();
+  }
+
+  if ( !msg.empty() )
+  {
+    msg << ".";
+    THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::BAD_PARAM);
   }
 }
 
@@ -2665,25 +2974,23 @@ string SMESH_Mesh_i::prepareMeshNameAndGroups(const char*    file,
   // Perform Export
   PrepareForWriting(file, overwrite);
   string aMeshName = "Mesh";
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
+  SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
   if ( !aStudy->_is_nil() ) {
-    SALOMEDS::SObject_var aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
+    SALOMEDS::SObject_wrap aMeshSO = _gen_i->ObjectToSObject( aStudy, _this() );
     if ( !aMeshSO->_is_nil() ) {
       CORBA::String_var name = aMeshSO->GetName();
       aMeshName = name;
       // asv : 27.10.04 : fix of 6903: check for StudyLocked before adding attributes
       if ( !aStudy->GetProperties()->IsLocked() )
       {
-        SALOMEDS::GenericAttribute_var anAttr;
+        SALOMEDS::GenericAttribute_wrap anAttr;
         SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
-        SALOMEDS::AttributeExternalFileDef_var aFileName;
         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeExternalFileDef");
-        aFileName = SALOMEDS::AttributeExternalFileDef::_narrow(anAttr);
+        SALOMEDS::AttributeExternalFileDef_wrap aFileName = anAttr;
         ASSERT(!aFileName->_is_nil());
         aFileName->SetValue(file);
-        SALOMEDS::AttributeFileType_var aFileType;
         anAttr=aStudyBuilder->FindOrCreateAttribute(aMeshSO, "AttributeFileType");
-        aFileType = SALOMEDS::AttributeFileType::_narrow(anAttr);
+        SALOMEDS::AttributeFileType_wrap aFileType = anAttr;
         ASSERT(!aFileType->_is_nil());
         aFileType->SetValue("FICHIERMED");
       }
@@ -2691,7 +2998,8 @@ string SMESH_Mesh_i::prepareMeshNameAndGroups(const char*    file,
   }
   // Update Python script
   // set name of mesh before export
-  TPythonDump() << _gen_i << ".SetName(" << _this() << ", '" << aMeshName.c_str() << "')";
+  TPythonDump() << _gen_i << ".SetName("
+                << SMESH::SMESH_Mesh_var(_this()) << ", '" << aMeshName.c_str() << "')";
 
   // check names of groups
   checkGroupNames();
@@ -2708,18 +3016,23 @@ string SMESH_Mesh_i::prepareMeshNameAndGroups(const char*    file,
 void SMESH_Mesh_i::ExportToMEDX (const char*        file,
                                  CORBA::Boolean     auto_groups,
                                  SMESH::MED_VERSION theVersion,
-                                 CORBA::Boolean     overwrite)
+                                 CORBA::Boolean     overwrite,
+                                 CORBA::Boolean     autoDimension)
   throw(SALOME::SALOME_Exception)
 {
-  Unexpect aCatch(SALOME_SalomeException);
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
   string aMeshName = prepareMeshNameAndGroups(file, overwrite);
-  TPythonDump() << _this() << ".ExportToMEDX( r'"
-                << file << "', " << auto_groups << ", " << theVersion << ", " << overwrite << " )";
+  _impl->ExportMED( file, aMeshName.c_str(), auto_groups, theVersion, 0, autoDimension );
 
-  _impl->ExportMED( file, aMeshName.c_str(), auto_groups, theVersion );
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportToMEDX( r'"
+                << file << "', " << auto_groups << ", "
+                << theVersion << ", " << overwrite << ", "
+                << autoDimension << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
 }
 
 //================================================================================
@@ -2764,7 +3077,8 @@ void SMESH_Mesh_i::ExportSAUV (const char* file,
     _preMeshInfo->FullLoadFromFile();
 
   string aMeshName = prepareMeshNameAndGroups(file, true);
-  TPythonDump() << _this() << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
+  TPythonDump() << SMESH::SMESH_Mesh_var( _this())
+                << ".ExportSAUV( r'" << file << "', " << auto_groups << " )";
   _impl->ExportSAUV(file, aMeshName.c_str(), auto_groups);
 }
 
@@ -2785,7 +3099,7 @@ void SMESH_Mesh_i::ExportDAT (const char *file)
   // Update Python script
   // check names of groups
   checkGroupNames();
-  TPythonDump() << _this() << ".ExportDAT( r'" << file << "' )";
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportDAT( r'" << file << "' )";
 
   // Perform Export
   PrepareForWriting(file);
@@ -2808,7 +3122,7 @@ void SMESH_Mesh_i::ExportUNV (const char *file)
   // Update Python script
   // check names of groups
   checkGroupNames();
-  TPythonDump() << _this() << ".ExportUNV( r'" << file << "' )";
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportUNV( r'" << file << "' )";
 
   // Perform Export
   PrepareForWriting(file);
@@ -2831,77 +3145,376 @@ void SMESH_Mesh_i::ExportSTL (const char *file, const bool isascii)
   // Update Python script
   // check names of groups
   checkGroupNames();
-  TPythonDump() << _this() << ".ExportSTL( r'" << file << "', " << isascii << " )";
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this())
+                << ".ExportSTL( r'" << file << "', " << isascii << " )";
 
   // Perform Export
   PrepareForWriting(file);
   _impl->ExportSTL(file, isascii);
 }
 
-//=============================================================================
+//================================================================================
 /*!
- * \brief Class providing SMESHDS_Mesh API to SMESH_IDSource. 
- *        It is used to export a part of mesh as a whole mesh.
+ * \brief Export a part of mesh to a med file
  */
-class SMESH_MeshPartDS : public SMESHDS_Mesh
+//================================================================================
+
+void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
+                                   const char*               file,
+                                   CORBA::Boolean            auto_groups,
+                                   SMESH::MED_VERSION        version,
+                                   CORBA::Boolean            overwrite,
+                                   CORBA::Boolean            autoDimension,
+                                   const GEOM::ListOfFields& fields,
+                                   const char*               geomAssocFields)
+  throw (SALOME::SALOME_Exception)
 {
-public:
-  SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart);
+  SMESH_TRY;
+  if ( _preMeshInfo )
+    _preMeshInfo->FullLoadFromFile();
+
+  // check fields
+  bool have0dField = false;
+  if ( fields.length() > 0 )
+  {
+    GEOM::GEOM_Object_var shapeToMesh = GetShapeToMesh();
+    if ( shapeToMesh->_is_nil() )
+      THROW_SALOME_CORBA_EXCEPTION( "No shape to mesh", SALOME::INTERNAL_ERROR );
+
+    for ( size_t i = 0; i < fields.length(); ++i )
+    {
+      if ( fields[i]->GetDataType() == GEOM::FDT_String )
+        THROW_SALOME_CORBA_EXCEPTION
+          ( "Export of string fields is not supported", SALOME::BAD_PARAM);
+      GEOM::GEOM_Object_var fieldShape = fields[i]->GetShape();
+      if ( fieldShape->_is_nil() )
+        THROW_SALOME_CORBA_EXCEPTION( "Null shape under a field", SALOME::INTERNAL_ERROR );
+      if ( !fieldShape->IsSame( shapeToMesh ) )
+        THROW_SALOME_CORBA_EXCEPTION
+          ( "Field defined not on shape", SALOME::BAD_PARAM);
+      if ( fields[i]->GetDimension() == 0 )
+        have0dField = true;
+    }
+    if ( geomAssocFields )
+      for ( int i = 0; geomAssocFields[i]; ++i )
+        switch ( geomAssocFields[i] ) {
+        case 'v':case 'e':case 'f':case 's': break;
+        case 'V':case 'E':case 'F':case 'S': break;
+        default: THROW_SALOME_CORBA_EXCEPTION
+            ( "geomAssocFields can include only [vefs] characters", SALOME::BAD_PARAM);
+        }
+  }
 
-  virtual SMDS_NodeIteratorPtr   nodesIterator     (bool idInceasingOrder=false) const;
-  virtual SMDS_EdgeIteratorPtr   edgesIterator     (bool idInceasingOrder=false) const;
-  virtual SMDS_FaceIteratorPtr   facesIterator     (bool idInceasingOrder=false) const;
-  virtual SMDS_VolumeIteratorPtr volumesIterator   (bool idInceasingOrder=false) const;
+  SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
 
-  virtual SMDS_ElemIteratorPtr elementsIterator(SMDSAbs_ElementType type=SMDSAbs_All) const;
-  virtual SMDS_ElemIteratorPtr elementGeomIterator(SMDSAbs_GeometryType type) const;
-  virtual SMDS_ElemIteratorPtr elementEntityIterator(SMDSAbs_EntityType type) const;
+  // write mesh
 
-private:
-  TIDSortedElemSet _elements[ SMDSAbs_NbElementTypes ];
-  SMESHDS_Mesh*    _meshDS;
-  /*!
-   * \brief Class used to access to protected data of SMDS_MeshInfo
-   */
-  struct TMeshInfo : public SMDS_MeshInfo
+  string aMeshName = "Mesh";
+  SMESHUtils::Deleter< SMESH_MeshPartDS > tmpDSDeleter(0);
+  if ( CORBA::is_nil( meshPart ) ||
+       SMESH::DownCast< SMESH_Mesh_i* >( meshPart ))
   {
-    void Add(const SMDS_MeshElement* e) { SMDS_MeshInfo::addWithPoly( e ); }
-  };
-};
+    aMeshName = prepareMeshNameAndGroups(file, overwrite);
+    _impl->ExportMED( file, aMeshName.c_str(), auto_groups,
+                      version, 0, autoDimension, /*addODOnVertices=*/have0dField);
+    meshDS = _impl->GetMeshDS();
+  }
+  else
+  {
+    if ( _preMeshInfo )
+      _preMeshInfo->FullLoadFromFile();
+
+    PrepareForWriting(file, overwrite);
+
+    SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
+    if ( !aStudy->_is_nil() ) {
+      SALOMEDS::SObject_wrap SO = _gen_i->ObjectToSObject( aStudy, meshPart );
+      if ( !SO->_is_nil() ) {
+        CORBA::String_var name = SO->GetName();
+        aMeshName = name;
+      }
+    }
+    SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
+    _impl->ExportMED( file, aMeshName.c_str(), auto_groups,
+                      version, partDS, autoDimension, /*addODOnVertices=*/have0dField);
+    meshDS = tmpDSDeleter._obj = partDS;
+  }
+
+  // write fields
+
+  if ( _impl->HasShapeToMesh() )
+  {
+    DriverMED_W_Field fieldWriter;
+    fieldWriter.SetFile( file );
+    fieldWriter.SetMeshName( aMeshName );
+    fieldWriter.AddODOnVertices( have0dField );
+
+    exportMEDFields( fieldWriter, meshDS, fields, geomAssocFields );
+  }
+
+  // dump
+  GEOM::ListOfGBO_var goList = new GEOM::ListOfGBO;
+  goList->length( fields.length() );
+  for ( size_t i = 0; i < fields.length(); ++i )
+  {
+    GEOM::GEOM_BaseObject_var gbo = GEOM::GEOM_BaseObject::_narrow( fields[i] );
+    goList[i] = gbo;
+  }
+  TPythonDump() << _this() << ".ExportPartToMED( "
+                << meshPart << ", r'" << file << "', "
+                << auto_groups << ", " << version << ", " << overwrite << ", "
+                << autoDimension << ", " << goList
+                << ", '" << ( geomAssocFields ? geomAssocFields : "" ) << "'" << " )";
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+}
 
 //================================================================================
 /*!
- * \brief Export a part of mesh to a med file
+ * Write GEOM fields to MED file
  */
 //================================================================================
 
-void SMESH_Mesh_i::ExportPartToMED(::SMESH::SMESH_IDSource_ptr meshPart,
-                                   const char*                 file,
-                                   CORBA::Boolean              auto_groups,
-                                   ::SMESH::MED_VERSION        version,
-                                   ::CORBA::Boolean            overwrite)
-  throw (SALOME::SALOME_Exception)
+void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
+                                    SMESHDS_Mesh*             meshDS,
+                                    const GEOM::ListOfFields& fields,
+                                    const char*               geomAssocFields)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-  if ( _preMeshInfo )
-    _preMeshInfo->FullLoadFromFile();
+#define METH "SMESH_Mesh_i::exportMEDFields() "
 
-  PrepareForWriting(file, overwrite);
+  if (( fields.length() < 1 ) &&
+      ( !geomAssocFields || !geomAssocFields[0] ))
+    return;
 
-  string aMeshName = "Mesh";
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
-  if ( !aStudy->_is_nil() ) {
-    SALOMEDS::SObject_var SO = _gen_i->ObjectToSObject( aStudy, meshPart );
-    if ( !SO->_is_nil() ) {
-      CORBA::String_var name = SO->GetName();
-      aMeshName = name;
+  std::vector< double > dblVals( meshDS->MaxShapeIndex()+1 );
+  std::vector< int >    intVals( meshDS->MaxShapeIndex()+1 );
+  std::vector< int >    subIdsByDim[ 4 ];
+  const double noneDblValue = 0.;
+  const double noneIntValue = 0;
+
+  for ( size_t iF = 0; iF < fields.length(); ++iF )
+  {
+    // set field data
+
+    int dim = fields[ iF ]->GetDimension();
+    SMDSAbs_ElementType elemType;
+    TopAbs_ShapeEnum    shapeType;
+    switch ( dim ) {
+    case 0: elemType = SMDSAbs_0DElement; shapeType = TopAbs_VERTEX; break;
+    case 1: elemType = SMDSAbs_Edge;      shapeType = TopAbs_EDGE;   break;
+    case 2: elemType = SMDSAbs_Face;      shapeType = TopAbs_FACE;   break;
+    case 3: elemType = SMDSAbs_Volume;    shapeType = TopAbs_SOLID;  break;
+    default:
+      continue; // skip fields on whole shape
     }
-  }
-  SMESH_MeshPartDS partDS( meshPart );
-  _impl->ExportMED( file, aMeshName.c_str(), auto_groups, version, &partDS );
+    GEOM::field_data_type dataType = fields[ iF ]->GetDataType();
+    if ( dataType == GEOM::FDT_String )
+      continue;
+    GEOM::ListOfLong_var stepIDs = fields[ iF ]->GetSteps();
+    if ( stepIDs->length() < 1 )
+      continue;
+    GEOM::string_array_var comps = fields[ iF ]->GetComponents();
+    if ( comps->length() < 1 )
+      continue;
+    CORBA::String_var       name = fields[ iF ]->GetName();
+
+    if ( !fieldWriter.Set( meshDS,
+                           name.in(),
+                           elemType,
+                           comps->length(),
+                           /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
+      continue;
 
-  TPythonDump() << _this() << ".ExportPartToMED( " << meshPart << ", r'" << file << "', "
-                << auto_groups << ", " << version << ", " << overwrite << " )";
+    for ( size_t iC = 0; iC < comps->length(); ++iC )
+      fieldWriter.SetCompName( iC, comps[ iC ].in() );
+
+    // find sub-shape IDs
+
+    std::vector< int >& subIds = subIdsByDim[ dim ];
+    if ( subIds.empty() )
+      for ( int id = 1; id <= meshDS->MaxShapeIndex(); ++id )
+        if ( meshDS->IndexToShape( id ).ShapeType() == shapeType )
+          subIds.push_back( id );
+
+    // write steps
+
+    SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
+    if ( !elemIt )
+      continue;
+
+    for ( size_t iS = 0; iS < stepIDs->length(); ++iS )
+    {
+      GEOM::GEOM_FieldStep_var step = fields[ iF ]->GetStep( stepIDs[ iS ]);
+      if ( step->_is_nil() )
+        continue;
+
+      CORBA::Long stamp = step->GetStamp();
+      CORBA::Long id    = step->GetID();
+      fieldWriter.SetDtIt( int( stamp ), int( id ));
+
+      // fill dblVals or intVals
+      switch ( dataType )
+      {
+      case GEOM::FDT_Double:
+      {
+        GEOM::GEOM_DoubleFieldStep_var dblStep = GEOM::GEOM_DoubleFieldStep::_narrow( step );
+        if ( dblStep->_is_nil() ) continue;
+        GEOM::ListOfDouble_var vv = dblStep->GetValues();
+        if ( vv->length() != subIds.size() )
+          THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
+        for ( size_t i = 0; i < vv->length(); ++i )
+          dblVals[ subIds[ i ]] = vv[ i ];
+        break;
+      }
+      case GEOM::FDT_Int:
+      {
+        GEOM::GEOM_IntFieldStep_var intStep = GEOM::GEOM_IntFieldStep::_narrow( step );
+        if ( intStep->_is_nil() ) continue;
+        GEOM::ListOfLong_var vv = intStep->GetValues();
+        if ( vv->length() != subIds.size() )
+          THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
+        for ( size_t i = 0; i < vv->length(); ++i )
+          intVals[ subIds[ i ]] = (int) vv[ i ];
+        break;
+      }
+      case GEOM::FDT_Bool:
+      {
+        GEOM::GEOM_BoolFieldStep_var boolStep = GEOM::GEOM_BoolFieldStep::_narrow( step );
+        if ( boolStep->_is_nil() ) continue;
+        GEOM::short_array_var vv = boolStep->GetValues();
+        if ( vv->length() != subIds.size() )
+          THROW_SALOME_CORBA_EXCEPTION( METH "BUG: wrong nb subIds", SALOME::INTERNAL_ERROR );
+        for ( size_t i = 0; i < vv->length(); ++i )
+          intVals[ subIds[ i ]] = (int) vv[ i ];
+        break;
+      }
+      default: continue;
+      }
+
+      // pass values to fieldWriter
+      elemIt = fieldWriter.GetOrderedElems();
+      if ( dataType == GEOM::FDT_Double )
+        while ( elemIt->more() )
+        {
+          const SMDS_MeshElement* e = elemIt->next();
+          const int shapeID = e->getshapeId();
+          if ( shapeID < 1 || shapeID >= (int) dblVals.size() )
+            fieldWriter.AddValue( noneDblValue );
+          else
+            fieldWriter.AddValue( dblVals[ shapeID ]);
+        }
+      else
+        while ( elemIt->more() )
+        {
+          const SMDS_MeshElement* e = elemIt->next();
+          const int shapeID = e->getshapeId();
+          if ( shapeID < 1 || shapeID >= (int) intVals.size() )
+            fieldWriter.AddValue( (double) noneIntValue );
+          else
+            fieldWriter.AddValue( (double) intVals[ shapeID ]);
+        }
+
+      // write a step
+      fieldWriter.Perform();
+      SMESH_ComputeErrorPtr res = fieldWriter.GetError();
+      if ( res && res->IsKO() )
+      {
+        if ( res->myComment.empty() )
+        { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
+        else
+        { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
+      }
+
+    } // loop on steps
+  } // loop on fields
+
+  if ( !geomAssocFields || !geomAssocFields[0] )
+    return;
+
+  // write geomAssocFields
+
+  std::vector< int > shapeDim( TopAbs_SHAPE + 1 );
+  shapeDim[ TopAbs_COMPOUND  ] = 3;
+  shapeDim[ TopAbs_COMPSOLID ] = 3;
+  shapeDim[ TopAbs_SOLID     ] = 3;
+  shapeDim[ TopAbs_SHELL     ] = 2;
+  shapeDim[ TopAbs_FACE      ] = 2;
+  shapeDim[ TopAbs_WIRE      ] = 1;
+  shapeDim[ TopAbs_EDGE      ] = 1;
+  shapeDim[ TopAbs_VERTEX    ] = 0;
+  shapeDim[ TopAbs_SHAPE     ] = 3;
+
+  for ( int iF = 0; geomAssocFields[ iF ]; ++iF )
+  {
+    std::vector< std::string > compNames;
+    switch ( geomAssocFields[ iF ]) {
+    case 'v': case 'V':
+      fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/false );
+      compNames.push_back( "dim" );
+      break;
+    case 'e': case 'E':
+      fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
+      break;
+    case 'f': case 'F':
+      fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
+      break;
+    case 's': case 'S':
+      fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
+      break;
+    default: continue;
+    }
+    compNames.push_back( "id" );
+    for ( size_t iC = 0; iC < compNames.size(); ++iC )
+      fieldWriter.SetCompName( iC, compNames[ iC ].c_str() );
+
+    fieldWriter.SetDtIt( -1, -1 );
+
+    SMDS_ElemIteratorPtr elemIt = fieldWriter.GetOrderedElems();
+    if ( !elemIt )
+      continue;
+
+    if ( compNames.size() == 2 ) // _vertices_
+      while ( elemIt->more() )
+      {
+        const SMDS_MeshElement* e = elemIt->next();
+        const int shapeID = e->getshapeId();
+        if ( shapeID < 1 )
+        {
+          fieldWriter.AddValue( (double) -1 );
+          fieldWriter.AddValue( (double) -1 );
+        }
+        else
+        {
+          const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
+          fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
+          fieldWriter.AddValue( (double) shapeID );
+        }
+      }
+    else
+      while ( elemIt->more() )
+      {
+        const SMDS_MeshElement* e = elemIt->next();
+        const int shapeID = e->getshapeId();
+        if ( shapeID < 1 )
+          fieldWriter.AddValue( (double) -1 );
+        else
+          fieldWriter.AddValue( (double) shapeID );
+      }
+
+    // write a step
+    fieldWriter.Perform();
+    SMESH_ComputeErrorPtr res = fieldWriter.GetError();
+    if ( res && res->IsKO() )
+    {
+      if ( res->myComment.empty() )
+      { THROW_SALOME_CORBA_EXCEPTION( METH "Fatal error", SALOME::INTERNAL_ERROR ); }
+      else
+      { THROW_SALOME_CORBA_EXCEPTION( res->myComment.c_str(), SALOME::INTERNAL_ERROR ); }
+    }
+
+  } // loop on geomAssocFields
+
+#undef METH
 }
 
 //================================================================================
@@ -2923,7 +3536,8 @@ void SMESH_Mesh_i::ExportPartToDAT(::SMESH::SMESH_IDSource_ptr meshPart,
   SMESH_MeshPartDS partDS( meshPart );
   _impl->ExportDAT(file,&partDS);
 
-  TPythonDump() << _this() << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this())
+                << ".ExportPartToDAT( " << meshPart << ", r'" << file << "' )";
 }
 //================================================================================
 /*!
@@ -2944,7 +3558,8 @@ void SMESH_Mesh_i::ExportPartToUNV(::SMESH::SMESH_IDSource_ptr meshPart,
   SMESH_MeshPartDS partDS( meshPart );
   _impl->ExportUNV(file, &partDS);
 
-  TPythonDump() << _this() << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this())
+                << ".ExportPartToUNV( " << meshPart<< ", r'" << file << "' )";
 }
 //================================================================================
 /*!
@@ -2966,7 +3581,7 @@ void SMESH_Mesh_i::ExportPartToSTL(::SMESH::SMESH_IDSource_ptr meshPart,
   SMESH_MeshPartDS partDS( meshPart );
   _impl->ExportSTL(file, isascii, &partDS);
 
-  TPythonDump() << _this() << ".ExportPartToSTL( "
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportPartToSTL( "
                 << meshPart<< ", r'" << file << "', " << isascii << ")";
 }
 
@@ -2988,34 +3603,65 @@ void SMESH_Mesh_i::ExportCGNS(::SMESH::SMESH_IDSource_ptr meshPart,
 
   PrepareForWriting(file,overwrite);
 
+  std::string meshName("");
+  SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
+  SALOMEDS::SObject_wrap so = _gen_i->ObjectToSObject( study, meshPart );
+  if ( !so->_is_nil() )
+  {
+    CORBA::String_var name = so->GetName();
+    meshName = name.in();
+  }
   SMESH_MeshPartDS partDS( meshPart );
-  _impl->ExportCGNS(file, &partDS);
+  _impl->ExportCGNS(file, &partDS, meshName.c_str() );
 
-  TPythonDump() << _this() << ".ExportCGNS( "
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportCGNS( "
                 << meshPart<< ", r'" << file << "', " << overwrite << ")";
 #else
   THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
 #endif
 }
 
-//=============================================================================
+//================================================================================
 /*!
- * Return implementation of SALOME_MED::MESH interfaces
+ * \brief Export a part of mesh to a GMF file
  */
-//=============================================================================
+//================================================================================
 
-SALOME_MED::MESH_ptr SMESH_Mesh_i::GetMEDMesh()throw(SALOME::SALOME_Exception)
+void SMESH_Mesh_i::ExportGMF(::SMESH::SMESH_IDSource_ptr meshPart,
+                             const char*                 file,
+                             bool                        withRequiredGroups)
+  throw (SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  SMESH_MEDMesh_i *aMedMesh = new SMESH_MEDMesh_i(this);
-  SALOME_MED::MESH_var aMesh = aMedMesh->_this();
-  return aMesh._retn();
+  PrepareForWriting(file,/*overwrite=*/true);
+
+  SMESH_MeshPartDS partDS( meshPart );
+  _impl->ExportGMF(file, &partDS, withRequiredGroups);
+
+  TPythonDump() << SMESH::SMESH_Mesh_var(_this()) << ".ExportGMF( "
+                << meshPart<< ", r'"
+                << file << "', "
+                << withRequiredGroups << ")";
 }
 
 //=============================================================================
+/*!
+ * Return computation progress [0.,1]
+ */
+//=============================================================================
+
+CORBA::Double SMESH_Mesh_i::GetComputeProgress()
+{
+  SMESH_TRY;
+
+  return _impl->GetComputeProgress();
+
+  SMESH_CATCH( SMESH::doNothing );
+  return 0.;
+}
 
 CORBA::Long SMESH_Mesh_i::NbNodes()throw(SALOME::SALOME_Exception)
 {
@@ -3092,6 +3738,15 @@ CORBA::Long SMESH_Mesh_i::NbTriangles()throw(SALOME::SALOME_Exception)
   return _impl->NbTriangles();
 }
 
+CORBA::Long SMESH_Mesh_i::NbBiQuadTriangles()throw(SALOME::SALOME_Exception)
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  if ( _preMeshInfo )
+    return _preMeshInfo->NbBiQuadTriangles();
+
+  return _impl->NbBiQuadTriangles();
+}
+
 CORBA::Long SMESH_Mesh_i::NbQuadrangles()throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
@@ -3110,7 +3765,7 @@ CORBA::Long SMESH_Mesh_i::NbBiQuadQuadrangles()throw(SALOME::SALOME_Exception)
   return _impl->NbBiQuadQuadrangles();
 }
 
-CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
+CORBA::Long SMESH_Mesh_i::NbPolygons() throw(SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
@@ -3119,6 +3774,15 @@ CORBA::Long SMESH_Mesh_i::NbPolygons()throw(SALOME::SALOME_Exception)
   return _impl->NbPolygons();
 }
 
+CORBA::Long SMESH_Mesh_i::NbPolygonsOfOrder(SMESH::ElementOrder order) throw(SALOME::SALOME_Exception)
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  if ( _preMeshInfo )
+    return _preMeshInfo->NbPolygons((SMDSAbs_ElementOrder) order);
+
+  return _impl->NbPolygons((SMDSAbs_ElementOrder)order);
+}
+
 CORBA::Long SMESH_Mesh_i::NbFacesOfOrder(SMESH::ElementOrder order)
   throw(SALOME::SALOME_Exception)
 {
@@ -3316,7 +3980,7 @@ SMESH::long_array* SMESH_Mesh_i::GetIDs()
 //=============================================================================
 
 SMESH::long_array* SMESH_Mesh_i::GetElementsId()
-     throw (SALOME::SALOME_Exception)
+  throw (SALOME::SALOME_Exception)
 {
   Unexpect aCatch(SALOME_SalomeException);
   if ( _preMeshInfo )
@@ -3369,12 +4033,9 @@ SMESH::long_array* SMESH_Mesh_i::GetElementsByType( SMESH::ElementType theElemTy
 
   int i = 0;
 
-  SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator();
-  while ( i < nbElements && anIt->more() ) {
-    const SMDS_MeshElement* anElem = anIt->next();
-    if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
-      aResult[i++] = anElem->GetID();
-  }
+  SMDS_ElemIteratorPtr anIt = aSMESHDS_Mesh->elementsIterator( (SMDSAbs_ElementType)theElemType );
+  while ( i < nbElements && anIt->more() )
+    aResult[i++] = anIt->next()->GetID();
 
   aResult->length( i );
 
@@ -3418,10 +4079,17 @@ SMESH::long_array* SMESH_Mesh_i::GetNodesId()
 SMESH::ElementType SMESH_Mesh_i::GetElementType( const CORBA::Long id, const bool iselem )
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::ElementType type;
+  SMESH_TRY;
+
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  return ( SMESH::ElementType )_impl->GetElementType( id, iselem );
+  type = ( SMESH::ElementType ) _impl->GetElementType( id, iselem );
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return type;
 }
 
 //=============================================================================
@@ -3443,6 +4111,25 @@ SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
   return ( SMESH::EntityType ) e->GetEntityType();
 }
 
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+
+SMESH::GeometryType SMESH_Mesh_i::GetElementShape( const CORBA::Long id )
+  throw (SALOME::SALOME_Exception)
+{
+  if ( _preMeshInfo )
+    _preMeshInfo->FullLoadFromFile();
+
+  const SMDS_MeshElement* e = _impl->GetMeshDS()->FindElement(id);
+  if ( !e )
+    THROW_SALOME_CORBA_EXCEPTION( "invalid element id", SALOME::BAD_PARAM );
+
+  return ( SMESH::GeometryType ) e->GetGeomType();
+}
+
 //=============================================================================
 /*!
  * Returns ID of elements for given submesh
@@ -3451,11 +4138,12 @@ SMESH::EntityType SMESH_Mesh_i::GetElementGeomType( const CORBA::Long id )
 SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
      throw (SALOME::SALOME_Exception)
 {
+  SMESH::long_array_var aResult = new SMESH::long_array();
+
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  SMESH::long_array_var aResult = new SMESH::long_array();
-
   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
   if(!SM) return aResult._retn();
 
@@ -3470,10 +4158,11 @@ SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
     aResult[i++] = eIt->next()->GetID();
   }
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+
   return aResult._retn();
 }
 
-
 //=============================================================================
 /*!
  * Returns ID of nodes for given submesh
@@ -3481,15 +4170,17 @@ SMESH::long_array* SMESH_Mesh_i::GetSubMeshElementsId(const CORBA::Long ShapeID)
  * returns only nodes on shapes.
  */
 //=============================================================================
+
 SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
                                                    CORBA::Boolean    all)
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::long_array_var aResult = new SMESH::long_array();
+
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
-  SMESH::long_array_var aResult = new SMESH::long_array();
-
   SMESH_subMesh* SM = _impl->GetSubMeshContaining(ShapeID);
   if(!SM) return aResult._retn();
 
@@ -3522,6 +4213,8 @@ SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
     aResult[i++] = *itElem;
 
+  SMESH_CATCH( SMESH::throwCorbaException );
+
   return aResult._retn();
 }
   
@@ -3534,6 +4227,9 @@ SMESH::long_array* SMESH_Mesh_i::GetSubMeshNodesId(const CORBA::Long ShapeID,
 SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID)
   throw (SALOME::SALOME_Exception)
 {
+  SMESH::ElementType type;
+
+  SMESH_TRY;
   if ( _preMeshInfo )
     _preMeshInfo->FullLoadFromFile();
 
@@ -3548,7 +4244,12 @@ SMESH::ElementType SMESH_Mesh_i::GetSubMeshElementType(const CORBA::Long ShapeID
 
   SMDS_ElemIteratorPtr eIt = SDSM->GetElements();
   const SMDS_MeshElement* anElem = eIt->next();
-  return ( SMESH::ElementType ) anElem->GetType();
+
+  type = ( SMESH::ElementType ) anElem->GetType();
+
+  SMESH_CATCH( SMESH::throwCorbaException );
+
+  return type; 
 }
   
 
@@ -3625,17 +4326,11 @@ SMESH::long_array* SMESH_Mesh_i::GetNodeInverseElements(const CORBA::Long id)
 
   // find inverse elements
   SMDS_ElemIteratorPtr eIt = aNode->GetInverseElementIterator();
-  TColStd_SequenceOfInteger IDs;
-  while(eIt->more()) {
+  aResult->length( aNode->NbInverseElements() );  
+  for( int i = 0; eIt->more(); ++i )
+  {
     const SMDS_MeshElement* elem = eIt->next();
-    IDs.Append(elem->GetID());
-  }
-  if(IDs.Length()>0) {
-    aResult->length(IDs.Length());
-    int i = 1;
-    for(; i<=IDs.Length(); i++) {
-      aResult[i-1] = IDs.Value(i);
-    }
+    aResult[ i ] = elem->GetID();
   }
   return aResult._retn();
 }
@@ -3694,6 +4389,52 @@ SMESH::NodePosition* SMESH_Mesh_i::GetNodePosition(CORBA::Long NodeID)
   return aNodePosition;
 }
 
+//=============================================================================
+/*!
+ * \brief Return position of an element on shape
+ */
+//=============================================================================
+
+SMESH::ElementPosition SMESH_Mesh_i::GetElementPosition(CORBA::Long ElemID)
+{
+  if ( _preMeshInfo )
+    _preMeshInfo->FullLoadFromFile();
+
+  SMESH::ElementPosition anElementPosition;
+  anElementPosition.shapeID = 0;
+  anElementPosition.shapeType = GEOM::SHAPE;
+
+  SMESHDS_Mesh* mesh = _impl->GetMeshDS();
+  if ( !mesh ) return anElementPosition;
+
+  if ( const SMDS_MeshElement* anElem = mesh->FindElement( ElemID ) )
+  {
+    anElementPosition.shapeID = anElem->getshapeId();
+    const TopoDS_Shape& aSp = mesh->IndexToShape( anElem->getshapeId() );
+    if ( !aSp.IsNull() ) {
+      switch ( aSp.ShapeType() ) {
+      case TopAbs_EDGE:
+        anElementPosition.shapeType = GEOM::EDGE;
+        break;
+      case TopAbs_FACE:
+        anElementPosition.shapeType = GEOM::FACE;
+        break;
+      case TopAbs_VERTEX:
+        anElementPosition.shapeType = GEOM::VERTEX;
+        break;
+      case TopAbs_SOLID:
+        anElementPosition.shapeType = GEOM::SOLID;
+        break;
+      case TopAbs_SHELL:
+        anElementPosition.shapeType = GEOM::SHELL;
+        break;
+      default:;
+      }
+    }
+  }
+  return anElementPosition;
+}
+
 //=============================================================================
 /*!
  * If given element is node returns IDs of shape from position
@@ -3742,7 +4483,6 @@ CORBA::Long SMESH_Mesh_i::GetShapeIDForElem(const CORBA::Long id)
   if(!elem)
     return -1;
 
-  //SMESH::SMESH_MeshEditor_var aMeshEditor = SMESH_Mesh_i::GetMeshEditor();
   ::SMESH_MeshEditor aMeshEditor(_impl);
   int index = aMeshEditor.FindShape( elem );
   if(index>0)
@@ -3933,7 +4673,7 @@ SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
       {
         aResult->length( vtool.NbFaceNodes( faceIndex ));
         const SMDS_MeshNode** nn = vtool.GetFaceNodes( faceIndex );
-        for ( int i = 0; i < aResult->length(); ++i )
+        for ( CORBA::ULong i = 0; i < aResult->length(); ++i )
           aResult[ i ] = nn[ i ]->GetID();
       }
     }
@@ -3941,6 +4681,33 @@ SMESH::long_array* SMESH_Mesh_i::GetElemFaceNodes(CORBA::Long  elemId,
   return aResult._retn();
 }
 
+//=======================================================================
+//function : GetElemFaceNodes
+//purpose  : Returns three components of normal of given mesh face.
+//=======================================================================
+
+SMESH::double_array* SMESH_Mesh_i::GetFaceNormal(CORBA::Long    elemId,
+                                                 CORBA::Boolean normalized)
+{
+  if ( _preMeshInfo )
+    _preMeshInfo->FullLoadFromFile();
+
+  SMESH::double_array_var aResult = new SMESH::double_array();
+
+  if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
+  {
+    gp_XYZ normal;
+    if ( SMESH_MeshAlgos::FaceNormal( mesh->FindElement(elemId), normal, normalized ))
+    {
+      aResult->length( 3 );
+      aResult[ 0 ] = normal.X();
+      aResult[ 1 ] = normal.Y();
+      aResult[ 2 ] = normal.Z();
+    }
+  }
+  return aResult._retn();
+}
+
 //=======================================================================
 //function : FindElementByNodes
 //purpose  : Returns an element based on all given nodes.
@@ -3955,11 +4722,11 @@ CORBA::Long SMESH_Mesh_i::FindElementByNodes(const SMESH::long_array& nodes)
   if ( SMESHDS_Mesh* mesh = _impl->GetMeshDS() )
   {
     vector< const SMDS_MeshNode * > nn( nodes.length() );
-    for ( int i = 0; i < nodes.length(); ++i )
+    for ( CORBA::ULong i = 0; i < nodes.length(); ++i )
       if ( !( nn[i] = mesh->FindNode( nodes[i] )))
         return elemID;
 
-    const SMDS_MeshElement* elem = mesh->FindElement( nn );
+    const SMDS_MeshElement* elem = mesh->FindElement( nn, SMDSAbs_All, /*noMedium=*/false );
     if ( !elem && ( _impl->NbEdges  ( ORDER_QUADRATIC ) ||
                     _impl->NbFaces  ( ORDER_QUADRATIC ) ||
                     _impl->NbVolumes( ORDER_QUADRATIC )))
@@ -4076,6 +4843,96 @@ SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
   return aResult._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Create a group of elements preventing computation of a sub-shape
+ */
+//================================================================================
+
+SMESH::ListOfGroups*
+SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
+                                            const char* theGroupName )
+  throw ( SALOME::SALOME_Exception )
+{
+  Unexpect aCatch(SALOME_SalomeException);
+
+  if ( !theGroupName || strlen( theGroupName) == 0 )
+    THROW_SALOME_CORBA_EXCEPTION( "empty group name",SALOME::BAD_PARAM );
+
+  SMESH::ListOfGroups_var groups = new SMESH::ListOfGroups;
+  ::SMESH_MeshEditor::ElemFeatures elemType;
+
+  // submesh by subshape id
+  if ( !_impl->HasShapeToMesh() ) theSubShapeID = 1;
+  if ( SMESH_subMesh * sm = _impl->GetSubMeshContaining( theSubShapeID ))
+  {
+    // compute error
+    SMESH_ComputeErrorPtr error = sm->GetComputeError();
+    if ( error && !error->myBadElements.empty())
+    {
+      // sort bad elements by type
+      vector< const SMDS_MeshElement* > elemsByType[ SMDSAbs_NbElementTypes ];
+      list<const SMDS_MeshElement*>::iterator elemIt  = error->myBadElements.begin();
+      list<const SMDS_MeshElement*>::iterator elemEnd = error->myBadElements.end();
+      for ( ; elemIt != elemEnd; ++elemIt )
+      {
+        const SMDS_MeshElement* elem = *elemIt;
+        if ( !elem ) continue;
+
+        if ( elem->GetID() < 1 )
+        {
+          // elem is a temporary element, make a real element
+          vector< const SMDS_MeshNode* > nodes;
+          SMDS_NodeIteratorPtr nIt = elem->nodeIterator();
+          while ( nIt->more() && elem )
+          {
+            nodes.push_back( nIt->next() );
+            if ( nodes.back()->GetID() < 1 )
+              elem = 0;  // a temporary element on temporary nodes
+          }
+          if ( elem )
+          {
+            ::SMESH_MeshEditor editor( _impl );
+            elem = editor.AddElement( nodes, elemType.Init( elem ));
+          }
+        }
+        if ( elem )
+          elemsByType[ elem->GetType() ].push_back( elem );
+      }
+
+      // how many groups to create?
+      int nbTypes = 0;
+      for ( int i = 0; i < SMDSAbs_NbElementTypes; ++i )
+        nbTypes += int( !elemsByType[ i ].empty() );
+      groups->length( nbTypes );
+
+      // create groups
+      for ( int i = 0, iG = -1; i < SMDSAbs_NbElementTypes; ++i )
+      {
+        vector< const SMDS_MeshElement* >& elems = elemsByType[ i ];
+        if ( elems.empty() ) continue;
+
+        groups[ ++iG ] = createGroup( SMESH::ElementType(i), theGroupName );
+        if ( _gen_i->CanPublishInStudy( groups[ iG ] ))
+        {
+          SALOMEDS::Study_var  study = _gen_i->GetCurrentStudy();
+          SMESH::SMESH_Mesh_var mesh = _this();
+          SALOMEDS::SObject_wrap aSO =
+            _gen_i->PublishGroup( study, mesh, groups[ iG ],
+                                 GEOM::GEOM_Object::_nil(), theGroupName);
+        }
+        SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
+        if ( !grp_i ) continue;
+
+        if ( SMESHDS_Group*  grpDS = dynamic_cast< SMESHDS_Group* >( grp_i->GetGroupDS() ))
+          for ( size_t iE = 0; iE < elems.size(); ++iE )
+            grpDS->SMDSGroup().Add( elems[ iE ]);
+      }
+    }
+  }
+
+  return groups._retn();
+}
 
 //=============================================================================
 /*!
@@ -4083,9 +4940,10 @@ SMESH::double_array* SMESH_Mesh_i::BaryCenter(const CORBA::Long id)
  */
 //=============================================================================
 
-void SMESH_Mesh_i::CreateGroupServants() 
+void SMESH_Mesh_i::CreateGroupServants()
 {
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
+  SALOMEDS::Study_var  aStudy = _gen_i->GetCurrentStudy();
+  SMESH::SMESH_Mesh_var aMesh = _this();
 
   set<int> addedIDs;
   ::SMESH_Mesh::GroupIteratorPtr groupIt = _impl->GetGroups();
@@ -4111,22 +4969,19 @@ void SMESH_Mesh_i::CreateGroupServants()
       aGroupImpl = new SMESH_Group_i( SMESH_Gen_i::GetPOA(), this, anId );
     }
 
-    // To ensure correct mapping of servant and correct reference counting in GenericObj_i
-    SMESH_Gen_i::GetPOA()->activate_object( aGroupImpl );
-    aGroupImpl->Register();
-
-    SMESH::SMESH_GroupBase_var groupVar =
-      SMESH::SMESH_GroupBase::_narrow( aGroupImpl->_this() );
+    SMESH::SMESH_GroupBase_var groupVar = aGroupImpl->_this();
     _mapGroups[anId] = SMESH::SMESH_GroupBase::_duplicate( groupVar );
+    aGroupImpl->Register();
 
     // register CORBA object for persistence
     int nextId = _gen_i->RegisterObject( groupVar );
-    if(MYDEBUG) MESSAGE( "Add group to map with id = "<< nextId);
+    if(MYDEBUG) { MESSAGE( "Add group to map with id = "<< nextId); }
+    else        { nextId = 0; } // avoid "unused variable" warning in release mode
 
     // publishing the groups in the study
     if ( !aStudy->_is_nil() ) {
       GEOM::GEOM_Object_var shapeVar = _gen_i->ShapeToGeomObject( shape );
-      _gen_i->PublishGroup( aStudy, _this(), groupVar, shapeVar, groupVar->GetName());
+      _gen_i->PublishGroup( aStudy, aMesh, groupVar, shapeVar, group->GetName());
     }
   }
   if ( !addedIDs.empty() )
@@ -4137,7 +4992,7 @@ void SMESH_Mesh_i::CreateGroupServants()
     {
       map<int, SMESH::SMESH_GroupBase_ptr>::iterator it = _mapGroups.find(*id);
       int i = std::distance( _mapGroups.begin(), it );
-      TPythonDump() << it->second << " = " << _this() << ".GetGroups()[ "<< i << " ]";
+      TPythonDump() << it->second << " = " << aMesh << ".GetGroups()[ "<< i << " ]";
     }
   }
 }
@@ -4171,11 +5026,11 @@ SMESH::ListOfGroups* SMESH_Mesh_i::GetGroups(const list<int>& groupIDs) const
  */
 //=============================================================================
 
-SALOME_MED::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
+SMESH::MedFileInfo* SMESH_Mesh_i::GetMEDFileInfo()
 {
-  SALOME_MED::MedFileInfo_var res( _medFileInfo );
+  SMESH::MedFileInfo_var res( _medFileInfo );
   if ( !res.operator->() ) {
-    res = new SALOME_MED::MedFileInfo;
+    res = new SMESH::MedFileInfo;
     res->fileName = "";
     res->fileSize = res->major = res->minor = res->release = -1;
   }
@@ -4194,7 +5049,7 @@ void SMESH_Mesh_i::checkGroupNames()
   if ( !nbGrp )
     return;
 
-  SALOMEDS::Study_ptr aStudy = _gen_i->GetCurrentStudy();
+  SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
   if ( aStudy->_is_nil() )
     return; // nothing to do
   
@@ -4210,7 +5065,7 @@ void SMESH_Mesh_i::checkGroupNames()
     SMESH::SMESH_GroupBase_ptr aGrp = (*grpList)[ gIndx ];
     if ( !aGrp )
       continue;
-    SALOMEDS::SObject_var aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
+    SALOMEDS::SObject_wrap aGrpSO = _gen_i->ObjectToSObject( aStudy, aGrp );
     if ( aGrpSO->_is_nil() )
       continue;
     // correct name of the mesh group if necessary
@@ -4227,9 +5082,8 @@ void SMESH_Mesh_i::checkGroupNames()
 //=============================================================================
 void SMESH_Mesh_i::SetParameters(const char* theParameters)
 {
-  // SMESH_Gen_i::GetSMESHGen()->UpdateParameters(SMESH::SMESH_Mesh::_narrow(_this()),
-  //                                              CORBA::string_dup(theParameters));
-  SMESH_Gen_i::GetSMESHGen()->UpdateParameters(theParameters);
+  SMESH_Gen_i::GetSMESHGen()->UpdateParameters( CORBA::Object_var( _this() ).in(),
+                                                theParameters );
 }
 
 //=============================================================================
@@ -4237,10 +5091,10 @@ void SMESH_Mesh_i::SetParameters(const char* theParameters)
  * \brief Returns list of notebook variables used for Mesh operations separated by ":" symbol
  */
 //=============================================================================
+
 char* SMESH_Mesh_i::GetParameters()
 {
-  SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
-  return CORBA::string_dup(gen->GetParameters(SMESH::SMESH_Mesh::_narrow(_this())));
+  return SMESH_Gen_i::GetSMESHGen()->GetParameters( SMESH::SMESH_Mesh_var( _this()) );
 }
 
 //=============================================================================
@@ -4253,15 +5107,15 @@ SMESH::string_array* SMESH_Mesh_i::GetLastParameters()
   SMESH::string_array_var aResult = new SMESH::string_array();
   SMESH_Gen_i *gen = SMESH_Gen_i::GetSMESHGen();
   if(gen) {
-    char *aParameters = GetParameters();
-    SALOMEDS::Study_ptr aStudy = gen->GetCurrentStudy();
-    if(!aStudy->_is_nil()) {
+    CORBA::String_var aParameters = GetParameters();
+    SALOMEDS::Study_var    aStudy = gen->GetCurrentStudy();
+    if ( !aStudy->_is_nil()) {
       SALOMEDS::ListOfListOfStrings_var aSections = aStudy->ParseVariables(aParameters); 
-      if(aSections->length() > 0) {
-        SALOMEDS::ListOfStrings aVars = aSections[aSections->length()-1];
-        aResult->length(aVars.length());
-        for(int i = 0;i < aVars.length();i++)
-          aResult[i] = CORBA::string_dup( aVars[i]);
+      if ( aSections->length() > 0 ) {
+        SALOMEDS::ListOfStrings aVars = aSections[ aSections->length() - 1 ];
+        aResult->length( aVars.length() );
+        for ( CORBA::ULong i = 0;i < aVars.length(); i++ )
+          aResult[i] = CORBA::string_dup( aVars[i] );
       }
     }
   }
@@ -4287,6 +5141,8 @@ SMESH::array_of_ElementType* SMESH_Mesh_i::GetTypes()
   if (_impl->NbVolumes())    types[nbTypes++] = SMESH::VOLUME;
   if (_impl->Nb0DElements()) types[nbTypes++] = SMESH::ELEM0D;
   if (_impl->NbBalls())      types[nbTypes++] = SMESH::BALL;
+  if (_impl->NbNodes() &&
+      nbTypes == 0 )         types[nbTypes++] = SMESH::NODE;
   types->length( nbTypes );
 
   return types._retn();
@@ -4315,7 +5171,7 @@ bool SMESH_Mesh_i::IsMeshInfoCorrect()
 
 //=============================================================================
 /*!
- * \brief Returns statistic of mesh elements
+ * \brief Returns number of mesh elements per each \a EntityType
  */
 //=============================================================================
 
@@ -4339,7 +5195,33 @@ SMESH::long_array* SMESH_Mesh_i::GetMeshInfo()
 
 //=============================================================================
 /*!
- * \brief Collect statistic of mesh elements given by iterator
+ * \brief Returns number of mesh elements per each \a ElementType
+ */
+//=============================================================================
+
+SMESH::long_array* SMESH_Mesh_i::GetNbElementsByType()
+{
+  SMESH::long_array_var aRes = new SMESH::long_array();
+  aRes->length(SMESH::NB_ELEMENT_TYPES);
+  for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
+    aRes[ i ] = 0;
+
+  const SMDS_MeshInfo* meshInfo = 0;
+  if ( _preMeshInfo )
+    meshInfo = _preMeshInfo;
+  else if ( SMESHDS_Mesh* meshDS = _impl->GetMeshDS() )
+    meshInfo = & meshDS->GetMeshInfo();
+
+  if (meshInfo)
+    for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
+      aRes[i] = meshInfo->NbElements((SMDSAbs_ElementType)i);
+
+  return aRes._retn();
+}
+
+//=============================================================================
+/*
+ * Collect statistic of mesh elements given by iterator
  */
 //=============================================================================
 
@@ -4350,14 +5232,277 @@ void SMESH_Mesh_i::CollectMeshInfo(const SMDS_ElemIteratorPtr theItr,
   while (theItr->more())
     theInfo[ theItr->next()->GetEntityType() ]++;
 }
+//=============================================================================
+/*
+ * Returns mesh unstructed grid information.
+ */
+//=============================================================================
+
+SALOMEDS::TMPFile* SMESH_Mesh_i::GetVtkUgStream()
+{
+  SALOMEDS::TMPFile_var SeqFile;
+  if ( SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS() ) {
+    SMDS_UnstructuredGrid* aGrid = aMeshDS->getGrid();
+    if(aGrid) {
+      vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
+      aWriter->WriteToOutputStringOn();
+      aWriter->SetInputData(aGrid);
+      aWriter->SetFileTypeToBinary();
+      aWriter->Write();
+      char* str = aWriter->GetOutputString();
+      int size = aWriter->GetOutputStringLength();
+      
+      //Allocate octect buffer of required size
+      CORBA::Octet* OctetBuf = SALOMEDS::TMPFile::allocbuf(size);
+      //Copy ostrstream content to the octect buffer
+      memcpy(OctetBuf, str, size);
+      //Create and return TMPFile
+      SeqFile = new SALOMEDS::TMPFile(size, size, OctetBuf, 1);
+      aWriter->Delete();
+    }
+  }
+  return SeqFile._retn();
+}
 
 //=============================================================================
-/*!
- * \brief mapping of mesh dimension into shape type
+namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
+           *                                             SMESH::ElementType        type) */
+{
+  using namespace SMESH::Controls;
+  //-----------------------------------------------------------------------------
+  struct PredicateIterator : public SMDS_ElemIterator
+  {
+    SMDS_ElemIteratorPtr    _elemIter;
+    PredicatePtr            _predicate;
+    const SMDS_MeshElement* _elem;
+
+    PredicateIterator( SMDS_ElemIteratorPtr   iterator,
+                       PredicatePtr predicate):
+      _elemIter(iterator), _predicate(predicate)
+    {
+      next();
+    }
+    virtual bool more()
+    {
+      return _elem;
+    }
+    virtual const SMDS_MeshElement* next()
+    {
+      const SMDS_MeshElement* res = _elem;
+      _elem = 0;
+      while ( _elemIter->more() && !_elem )
+      {
+        _elem = _elemIter->next();
+        if ( _elem && ( !_predicate->IsSatisfy( _elem->GetID() )))
+          _elem = 0;
+      }
+      return res;
+    }
+  };
+
+  //-----------------------------------------------------------------------------
+  struct IDSourceIterator : public SMDS_ElemIterator
+  {
+    const CORBA::Long*        _idPtr;
+    const CORBA::Long*        _idEndPtr;
+    SMESH::long_array_var     _idArray;
+    const SMDS_Mesh*          _mesh;
+    const SMDSAbs_ElementType _type;
+    const SMDS_MeshElement*   _elem;
+
+    IDSourceIterator( const SMDS_Mesh*    mesh,
+                      const CORBA::Long*  ids,
+                      const int           nbIds,
+                      SMDSAbs_ElementType type):
+      _idPtr( ids ), _idEndPtr( ids + nbIds ), _mesh( mesh ), _type( type ), _elem( 0 )
+    {
+      if ( _idPtr && nbIds && _mesh )
+        next();
+    }
+    IDSourceIterator( const SMDS_Mesh*    mesh,
+                      SMESH::long_array*  idArray,
+                      SMDSAbs_ElementType type):
+      _idPtr( 0 ), _idEndPtr( 0 ), _idArray( idArray), _mesh( mesh ), _type( type ), _elem( 0 )
+    {
+      if ( idArray && _mesh )
+      {
+        _idPtr    = &_idArray[0];
+        _idEndPtr = _idPtr + _idArray->length();
+        next();
+      }
+    }
+    virtual bool more()
+    {
+      return _elem;
+    }
+    virtual const SMDS_MeshElement* next()
+    {
+      const SMDS_MeshElement* res = _elem;
+      _elem = 0;
+      while ( _idPtr < _idEndPtr && !_elem )
+      {
+        if ( _type == SMDSAbs_Node )
+        {
+          _elem = _mesh->FindNode( *_idPtr++ );
+        }
+        else if ((_elem = _mesh->FindElement( *_idPtr++ )) &&
+                 (_elem->GetType() != _type && _type != SMDSAbs_All ))
+        {
+          _elem = 0;
+        }
+      }
+      return res;
+    }
+  };
+  //-----------------------------------------------------------------------------
+
+  struct NodeOfElemIterator : public SMDS_ElemIterator
+  {
+    TColStd_MapOfInteger    _checkedNodeIDs;
+    SMDS_ElemIteratorPtr    _elemIter;
+    SMDS_ElemIteratorPtr    _nodeIter;
+    const SMDS_MeshElement* _node;
+
+    NodeOfElemIterator( SMDS_ElemIteratorPtr iter ): _elemIter( iter ), _node( 0 )
+    {
+      if ( _elemIter && _elemIter->more() )
+      {
+        _nodeIter = _elemIter->next()->nodesIterator();
+        next();
+      }
+    }
+    virtual bool more()
+    {
+      return _node;
+    }
+    virtual const SMDS_MeshElement* next()
+    {
+      const SMDS_MeshElement* res = _node;
+      _node = 0;
+      while (( _elemIter->more() || _nodeIter->more() ) && !_node )
+      {
+        if ( _nodeIter->more() )
+        {
+          _node = _nodeIter->next();
+          if ( !_checkedNodeIDs.Add( _node->GetID() ))
+            _node = 0;
+        }
+        else
+        {
+          _nodeIter = _elemIter->next()->nodesIterator();
+        }
+      }
+      return res;
+    }
+  };
+}
+
+//=============================================================================
+/*
+ * Return iterator on elements of given type in given object
  */
 //=============================================================================
 
-static TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
+SMDS_ElemIteratorPtr SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_ptr theObject,
+                                               SMESH::ElementType        theType)
+{
+  SMDS_ElemIteratorPtr  elemIt;
+  bool                  typeOK = ( theType == SMESH::ALL );
+  SMDSAbs_ElementType elemType = SMDSAbs_ElementType( theType );
+
+  SMESH::SMESH_Mesh_var meshVar = theObject->GetMesh();
+  SMESH_Mesh_i*          mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( meshVar );
+  if ( !mesh_i ) return elemIt;
+  SMESHDS_Mesh*          meshDS = mesh_i->GetImpl().GetMeshDS();
+
+  if ( SMESH::DownCast<SMESH_Mesh_i*>( theObject ))
+  {
+    elemIt = meshDS->elementsIterator( elemType );
+    typeOK = true;
+  }
+  else if ( SMESH_subMesh_i* submesh_i = SMESH::DownCast<SMESH_subMesh_i*>( theObject ))
+  {
+    SMESHDS_SubMesh* sm = ((SMESHDS_Mesh*) meshDS)->MeshElements( submesh_i->GetId() );
+    if ( sm )
+    {
+      elemIt = sm->GetElements();
+      if ( elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
+      {
+        typeOK = ( elemIt && elemIt->more() && elemIt->next()->GetType() == elemType );
+        elemIt = typeOK ? sm->GetElements() : SMDS_ElemIteratorPtr();
+      }
+    }
+  }
+  else if ( SMESH_GroupBase_i* group_i = SMESH::DownCast<SMESH_GroupBase_i*>( theObject ))
+  {
+    SMESHDS_GroupBase* groupDS = group_i->GetGroupDS();
+    if ( groupDS && ( elemType == groupDS->GetType()  ||
+                      elemType == SMDSAbs_Node ||
+                      elemType == SMDSAbs_All ))
+    {
+      elemIt = groupDS->GetElements();
+      typeOK = ( groupDS->GetType() == elemType || elemType == SMDSAbs_All );
+    }
+  }
+  else if ( SMESH::Filter_i* filter_i = SMESH::DownCast<SMESH::Filter_i*>( theObject ))
+  {
+    if ( filter_i->GetElementType() == theType ||
+         elemType == SMDSAbs_Node ||
+         elemType == SMDSAbs_All)
+    {
+      SMESH::Predicate_i* pred_i = filter_i->GetPredicate_i();
+      if ( pred_i && pred_i->GetPredicate() )
+      {
+        SMDSAbs_ElementType filterType = SMDSAbs_ElementType( filter_i->GetElementType() );
+        SMDS_ElemIteratorPtr allElemIt = meshDS->elementsIterator( filterType );
+        elemIt = SMDS_ElemIteratorPtr( new PredicateIterator( allElemIt, pred_i->GetPredicate() ));
+        typeOK = ( filterType == elemType || elemType == SMDSAbs_All );
+      }
+    }
+  }
+  else
+  {
+    SMESH::array_of_ElementType_var types = theObject->GetTypes();
+    const bool                    isNodes = ( types->length() == 1 && types[0] == SMESH::NODE );
+    if ( isNodes && elemType != SMDSAbs_Node && elemType != SMDSAbs_All )
+      return elemIt;
+    if ( SMESH_MeshEditor_i::IsTemporaryIDSource( theObject ))
+    {
+      int nbIds;
+      if ( CORBA::Long* ids = SMESH_MeshEditor_i::GetTemporaryIDs( theObject, nbIds ))
+        elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids, nbIds, elemType ));
+    }
+    else
+    {
+      SMESH::long_array_var ids = theObject->GetIDs();
+      elemIt = SMDS_ElemIteratorPtr( new IDSourceIterator( meshDS, ids._retn(), elemType ));
+    }
+    typeOK = ( isNodes == ( elemType == SMDSAbs_Node )) || ( elemType == SMDSAbs_All );
+  }
+
+  if ( elemIt && elemIt->more() && !typeOK )
+  {
+    if ( elemType == SMDSAbs_Node )
+    {
+      elemIt = SMDS_ElemIteratorPtr( new NodeOfElemIterator( elemIt ));
+    }
+    else
+    {
+      elemIt = SMDS_ElemIteratorPtr();
+    }
+  }
+  return elemIt;
+}
+
+//=============================================================================
+namespace // Finding concurrent hypotheses
+//=============================================================================
+{
+
+/*!
+ * \brief mapping of mesh dimension into shape type
+ */
+TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
 {
   TopAbs_ShapeEnum aType = TopAbs_SOLID;
   switch ( theDim ) {
@@ -4370,7 +5515,7 @@ static TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
   return aType;
 }
 
-//=============================================================================
+//-----------------------------------------------------------------------------
 /*!
  * \brief Internal structure used to find concurent submeshes
  *
@@ -4379,8 +5524,6 @@ static TopAbs_ShapeEnum shapeTypeByDim(const int theDim)
  *  with another submesh. In other words, it is dimension of a hypothesis assigned
  *  to submesh.
  */
-//=============================================================================
-
 class SMESH_DimHyp
 {
  public:
@@ -4389,23 +5532,30 @@ class SMESH_DimHyp
   int _ownDim; //!< dimension of shape of _subMesh (>=_dim)
   TopTools_MapOfShape _shapeMap;
   SMESH_subMesh*      _subMesh;
-  list<const SMESHDS_Hypothesis*> _hypothesises; //!< algo is first, then its parameters
+  list<const SMESHDS_Hypothesis*> _hypotheses; //!< algo is first, then its parameters
 
+  //-----------------------------------------------------------------------------
+  // Return the algorithm
+  const SMESH_Algo* GetAlgo() const
+  { return _hypotheses.empty() ? 0 : dynamic_cast<const SMESH_Algo*>( _hypotheses.front() ); }
+
+  //-----------------------------------------------------------------------------
   //! Constructors
-  SMESH_DimHyp(const SMESH_subMesh*  theSubMesh,
-               const int             theDim,
-               const TopoDS_Shape&   theShape)
+  SMESH_DimHyp(const SMESH_subMesh* theSubMesh,
+               const int            theDim,
+               const TopoDS_Shape&  theShape)
   {
     _subMesh = (SMESH_subMesh*)theSubMesh;
     SetShape( theDim, theShape );
   }
 
+  //-----------------------------------------------------------------------------
   //! set shape
   void SetShape(const int           theDim,
                 const TopoDS_Shape& theShape)
   {
     _dim = theDim;
-    _ownDim = (int)SMESH_Gen::GetShapeDim(theShape);
+    _ownDim = SMESH_Gen::GetShapeDim(theShape);
     if (_dim >= _ownDim)
       _shapeMap.Add( theShape );
     else {
@@ -4415,6 +5565,7 @@ class SMESH_DimHyp
     }
   }
 
+  //-----------------------------------------------------------------------------
   //! Check sharing of sub-shapes
   static bool isShareSubShapes(const TopTools_MapOfShape& theToCheck,
                                const TopTools_MapOfShape& theToFind,
@@ -4435,11 +5586,13 @@ class SMESH_DimHyp
     return isShared;
   }
   
+  //-----------------------------------------------------------------------------
   //! check algorithms
   static bool checkAlgo(const SMESHDS_Hypothesis* theA1,
                         const SMESHDS_Hypothesis* theA2)
   {
-    if ( theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
+    if ( !theA1 || !theA2 ||
+         theA1->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ||
          theA2->GetType() == SMESHDS_Hypothesis::PARAM_ALGO )
       return false; // one of the hypothesis is not algorithm
     // check algorithm names (should be equal)
@@ -4447,6 +5600,7 @@ class SMESH_DimHyp
   }
 
   
+  //-----------------------------------------------------------------------------
   //! Check if sub-shape hypotheses are concurrent
   bool IsConcurrent(const SMESH_DimHyp* theOther) const
   {
@@ -4456,8 +5610,10 @@ class SMESH_DimHyp
     // if ( <own dim of either of submeshes> == <concurrent dim> &&
     //      any of the two submeshes is not on COMPOUND shape )
     //  -> no concurrency
-    bool meIsCompound = (_subMesh->GetSubMeshDS() && _subMesh->GetSubMeshDS()->IsComplexSubmesh());
-    bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() && theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
+    bool meIsCompound    = (_subMesh->GetSubMeshDS() &&
+                            _subMesh->GetSubMeshDS()->IsComplexSubmesh());
+    bool otherIsCompound = (theOther->_subMesh->GetSubMeshDS() &&
+                            theOther->_subMesh->GetSubMeshDS()->IsComplexSubmesh());
     if ( (_ownDim == _dim  || theOther->_ownDim == _dim ) && (!meIsCompound || !otherIsCompound))
       return false;
 
@@ -4469,65 +5625,102 @@ class SMESH_DimHyp
         return false;
 
     // check algorithms to be same
-    if (!checkAlgo( _hypothesises.front(), theOther->_hypothesises.front() ))
-      return true; // different algorithms
-    
+    if ( !checkAlgo( this->GetAlgo(), theOther->GetAlgo() ))
+      return true; // different algorithms -> concurrency !
+
     // check hypothesises for concurrence (skip first as algorithm)
     int nbSame = 0;
-    // pointers should be same, becase it is referenes from mesh hypothesis partition
-    list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypothesises.begin();
-    list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypothesises.end();
-    for ( hypIt++ /*skip first as algo*/; hypIt != _hypothesises.end(); hypIt++ )
-      if ( find( theOther->_hypothesises.begin(), otheEndIt, *hypIt ) != otheEndIt )
+    // pointers should be same, because it is referened from mesh hypothesis partition
+    list <const SMESHDS_Hypothesis*>::const_iterator hypIt = _hypotheses.begin();
+    list <const SMESHDS_Hypothesis*>::const_iterator otheEndIt = theOther->_hypotheses.end();
+    for ( hypIt++ /*skip first as algo*/; hypIt != _hypotheses.end(); hypIt++ )
+      if ( find( theOther->_hypotheses.begin(), otheEndIt, *hypIt ) != otheEndIt )
         nbSame++;
     // the submeshes are concurrent if their algorithms has different parameters
-    return nbSame != theOther->_hypothesises.size() - 1;
+    return nbSame != (int)theOther->_hypotheses.size() - 1;
+  }
+
+  // Return true if algorithm of this SMESH_DimHyp is used if no
+  // sub-mesh order is imposed by the user
+  bool IsHigherPriorityThan( const SMESH_DimHyp* theOther ) const
+  {
+    // NeedDiscreteBoundary() algo has a higher priority
+    if ( this    ->GetAlgo()->NeedDiscreteBoundary() !=
+         theOther->GetAlgo()->NeedDiscreteBoundary() )
+      return !this->GetAlgo()->NeedDiscreteBoundary();
+
+    return ( this->_subMesh->GetId() < theOther->_subMesh->GetId() );
   }
   
 }; // end of SMESH_DimHyp
+//-----------------------------------------------------------------------------
+
+typedef list<const SMESH_DimHyp*> TDimHypList;
 
-typedef list<SMESH_DimHyp*> TDimHypList;
+//-----------------------------------------------------------------------------
 
-static void addDimHypInstance(const int               theDim, 
-                              const TopoDS_Shape&     theShape,
-                              const SMESH_Algo*       theAlgo,
-                              const SMESH_subMesh*    theSubMesh,
-                              const list <const SMESHDS_Hypothesis*>& theHypList,
-                              TDimHypList*            theDimHypListArr )
+void addDimHypInstance(const int                               theDim, 
+                       const TopoDS_Shape&                     theShape,
+                       const SMESH_Algo*                       theAlgo,
+                       const SMESH_subMesh*                    theSubMesh,
+                       const list <const SMESHDS_Hypothesis*>& theHypList,
+                       TDimHypList*                            theDimHypListArr )
 {
   TDimHypList& listOfdimHyp = theDimHypListArr[theDim];
   if ( listOfdimHyp.empty() || listOfdimHyp.back()->_subMesh != theSubMesh ) {
     SMESH_DimHyp* dimHyp = new SMESH_DimHyp( theSubMesh, theDim, theShape );
+    dimHyp->_hypotheses.push_front(theAlgo);
     listOfdimHyp.push_back( dimHyp );
   }
   
-  SMESH_DimHyp* dimHyp = listOfdimHyp.back();
-  dimHyp->_hypothesises.push_front(theAlgo);
-  list <const SMESHDS_Hypothesis*>::const_iterator hypIt = theHypList.begin();
-  for( ; hypIt != theHypList.end(); hypIt++ )
-    dimHyp->_hypothesises.push_back( *hypIt );
+  SMESH_DimHyp* dimHyp = const_cast<SMESH_DimHyp*>( listOfdimHyp.back() );
+  dimHyp->_hypotheses.insert( dimHyp->_hypotheses.end(),
+                              theHypList.begin(), theHypList.end() );
+}
+
+//-----------------------------------------------------------------------------
+void addInOrderOfPriority( const SMESH_DimHyp* theDimHyp,
+                           TDimHypList&        theListOfConcurr)
+{
+  if ( theListOfConcurr.empty() )
+  {
+    theListOfConcurr.push_back( theDimHyp );
+  }
+  else
+  {
+    TDimHypList::iterator hypIt = theListOfConcurr.begin();
+    while ( hypIt != theListOfConcurr.end() &&
+            !theDimHyp->IsHigherPriorityThan( *hypIt ))
+      ++hypIt;
+    theListOfConcurr.insert( hypIt, theDimHyp );
+  }
 }
 
-static void findConcurrents(const SMESH_DimHyp* theDimHyp,
-                            const TDimHypList&  theListOfDimHyp,
-                            TListOfInt&         theListOfConcurr )
+//-----------------------------------------------------------------------------
+void findConcurrents(const SMESH_DimHyp* theDimHyp,
+                     const TDimHypList&  theListOfDimHyp,
+                     TDimHypList&        theListOfConcurrHyp,
+                     set<int>&           theSetOfConcurrId )
 {
   TDimHypList::const_reverse_iterator rIt = theListOfDimHyp.rbegin();
-  for ( ; rIt != theListOfDimHyp.rend(); rIt++ ) {
+  for ( ; rIt != theListOfDimHyp.rend(); rIt++ )
+  {
     const SMESH_DimHyp* curDimHyp = *rIt;
     if ( curDimHyp == theDimHyp )
       break; // meet own dimHyp pointer in same dimension
-    else if ( theDimHyp->IsConcurrent( curDimHyp ) )
-      if ( find( theListOfConcurr.begin(),
-                 theListOfConcurr.end(),
-                 curDimHyp->_subMesh->GetId() ) == theListOfConcurr.end() )
-        theListOfConcurr.push_back( curDimHyp->_subMesh->GetId() );
+
+    if ( theDimHyp->IsConcurrent( curDimHyp ) &&
+         theSetOfConcurrId.insert( curDimHyp->_subMesh->GetId() ).second )
+    {
+      addInOrderOfPriority( curDimHyp, theListOfConcurrHyp );
+    }
   }
 }
 
-static void unionLists(TListOfInt&       theListOfId,
-                       TListOfListOfInt& theListOfListOfId,
-                       const int         theIndx )
+//-----------------------------------------------------------------------------
+void unionLists(TListOfInt&       theListOfId,
+                TListOfListOfInt& theListOfListOfId,
+                const int         theIndx )
 {
   TListOfListOfInt::iterator it = theListOfListOfId.begin();
   for ( int i = 0; it != theListOfListOfId.end(); it++, i++ ) {
@@ -4549,9 +5742,10 @@ static void unionLists(TListOfInt&       theListOfId,
     otherListOfId.clear();
   }
 }
+//-----------------------------------------------------------------------------
 
 //! free memory allocated for dimension-hypothesis objects
-static void removeDimHyps( TDimHypList* theArrOfList )
+void removeDimHyps( TDimHypList* theArrOfList )
 {
   for (int i = 0; i < 4; i++ ) {
     TDimHypList& listOfdimHyp = theArrOfList[i];
@@ -4561,6 +5755,57 @@ static void removeDimHyps( TDimHypList* theArrOfList )
   }
 }
 
+//-----------------------------------------------------------------------------
+/*!
+ * \brief find common submeshes with given submesh
+ * \param theSubMeshList list of already collected submesh to check
+ * \param theSubMesh given submesh to intersect with other
+ * \param theCommonSubMeshes collected common submeshes
+ */
+void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
+                        const SMESH_subMesh*        theSubMesh,
+                        set<const SMESH_subMesh*>&  theCommon )
+{
+  if ( !theSubMesh )
+    return;
+  list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
+  for ( ; it != theSubMeshList.end(); it++ )
+    theSubMesh->FindIntersection( *it, theCommon );
+  theSubMeshList.push_back( theSubMesh );
+  //theCommon.insert( theSubMesh );
+}
+
+//-----------------------------------------------------------------------------
+bool isSubMeshInList ( int smID, const TListOfListOfInt& smLists )
+{
+  TListOfListOfInt::const_iterator listsIt = smLists.begin();
+  for ( ; listsIt != smLists.end(); ++listsIt )
+  {
+    const TListOfInt& smIDs = *listsIt;
+    if ( std::find( smIDs.begin(), smIDs.end(), smID ) != smIDs.end() )
+      return true;
+  }
+  return false;
+}
+
+} // namespace
+
+//=============================================================================
+/*!
+ * \brief Return \c true if a meshing order not yet set for a concurrent sub-mesh
+ */
+//=============================================================================
+
+CORBA::Boolean SMESH_Mesh_i::IsUnorderedSubMesh(CORBA::Long submeshID)
+{
+  TListOfListOfInt anOrder = GetImpl().GetMeshOrder(); // already defined order
+  if ( isSubMeshInList( submeshID, anOrder ))
+    return false;
+
+  TListOfListOfInt allConurrent = findConcurrentSubMeshes();
+  return isSubMeshInList( submeshID, allConurrent );
+}
+
 //=============================================================================
 /*!
  * \brief Return submesh objects list in meshing order
@@ -4574,20 +5819,43 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
   SMESHDS_Mesh* aMeshDS = _impl->GetMeshDS();
   if ( !aMeshDS )
     return aResult._retn();
-  
-  ::SMESH_Mesh& mesh = GetImpl();
-  TListOfListOfInt anOrder = mesh.GetMeshOrder(); // is there already defined order?
-  if ( !anOrder.size() ) {
 
-    // collect submeshes detecting concurrent algorithms and hypothesises
+  TListOfListOfInt      anOrder = GetImpl().GetMeshOrder(); // already defined order
+  TListOfListOfInt allConurrent = findConcurrentSubMeshes();
+  anOrder.splice( anOrder.end(), allConurrent );
+
+  int listIndx = 0;
+  TListOfListOfInt::iterator listIt = anOrder.begin();
+  for(; listIt != anOrder.end(); listIt++, listIndx++ )
+    unionLists( *listIt,  anOrder, listIndx + 1 );
+
+  // convert submesh ids into interface instances
+  //  and dump command into python
+  convertMeshOrder( anOrder, aResult, false );
+
+  return aResult._retn();
+}
+
+//=============================================================================
+/*!
+ * \brief Finds concurrent sub-meshes
+ */
+//=============================================================================
+
+TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
+{
+  TListOfListOfInt anOrder;
+  ::SMESH_Mesh& mesh = GetImpl();
+  {
+    // collect submeshes and detect concurrent algorithms and hypothesises
     TDimHypList dimHypListArr[4]; // dimHyp list for each shape dimension
-    
+
     map<int, ::SMESH_subMesh*>::iterator i_sm = _mapSubMesh.begin();
     for ( ; i_sm != _mapSubMesh.end(); i_sm++ ) {
       ::SMESH_subMesh* sm = (*i_sm).second;
       // shape of submesh
       const TopoDS_Shape& aSubMeshShape = sm->GetSubShape();
-      
+
       // list of assigned hypothesises
       const list <const SMESHDS_Hypothesis*>& hypList = mesh.GetHypothesisList(aSubMeshShape);
       // Find out dimensions where the submesh can be concurrent.
@@ -4606,7 +5874,7 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
             anAlgo = mesh.GetGen()->GetAlgo( mesh, anExp.Current() );
         }
         if (!anAlgo)
-          continue; // no assigned algorithm to current submesh
+          continue; // no algorithm assigned to a current submesh
 
         int dim = anAlgo->GetDim(); // top concurrent dimension (see comment to SMESH_DimHyp)
         // the submesh can concurrent at <dim> (or lower dims if !anAlgo->NeedDiscreteBoundary())
@@ -4619,20 +5887,25 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
     
     // iterate on created dimension-hypotheses and check for concurrents
     for ( int i = 0; i < 4; i++ ) {
-      const list<SMESH_DimHyp*>& listOfDimHyp = dimHypListArr[i];
+      const TDimHypList& listOfDimHyp = dimHypListArr[i];
       // check for concurrents in own and other dimensions (step-by-step)
       TDimHypList::const_iterator dhIt = listOfDimHyp.begin();
       for ( ; dhIt != listOfDimHyp.end(); dhIt++ ) {
         const SMESH_DimHyp* dimHyp = *dhIt;
-        TListOfInt listOfConcurr;
+        TDimHypList listOfConcurr;
+        set<int>    setOfConcurrIds;
         // looking for concurrents and collect into own list
         for ( int j = i; j < 4; j++ )
-          findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr );
+          findConcurrents( dimHyp, dimHypListArr[j], listOfConcurr, setOfConcurrIds );
         // check if any concurrents found
         if ( listOfConcurr.size() > 0 ) {
           // add own submesh to list of concurrent
-          listOfConcurr.push_front( dimHyp->_subMesh->GetId() );
-          anOrder.push_back( listOfConcurr );
+          addInOrderOfPriority( dimHyp, listOfConcurr );
+          list<int> listOfConcurrIds;
+          TDimHypList::iterator hypIt = listOfConcurr.begin();
+          for ( ; hypIt != listOfConcurr.end(); ++hypIt )
+            listOfConcurrIds.push_back( (*hypIt)->_subMesh->GetId() );
+          anOrder.push_back( listOfConcurrIds );
         }
       }
     }
@@ -4648,33 +5921,8 @@ SMESH::submesh_array_array* SMESH_Mesh_i::GetMeshOrder()
     for(; listIt != anOrder.end(); listIt++, listIndx++ )
       unionLists( *listIt,  anOrder, listIndx + 1 );
   }
-  // convert submesh ids into interface instances
-  //  and dump command into python
-  convertMeshOrder( anOrder, aResult, false );
 
-  return aResult._retn();
-}
-
-//=============================================================================
-/*!
- * \brief find common submeshes with given submesh
- * \param theSubMeshList list of already collected submesh to check
- * \param theSubMesh given submesh to intersect with other
- * \param theCommonSubMeshes collected common submeshes
- */
-//=============================================================================
-
-static void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
-                               const SMESH_subMesh*        theSubMesh,
-                               set<const SMESH_subMesh*>&  theCommon )
-{
-  if ( !theSubMesh )
-    return;
-  list<const SMESH_subMesh*>::const_iterator it = theSubMeshList.begin();
-  for ( ; it != theSubMeshList.end(); it++ )
-    theSubMesh->FindIntersection( *it, theCommon );
-  theSubMeshList.push_back( theSubMesh );
-  //theCommon.insert( theSubMesh );
+  return anOrder;
 }
 
 //=============================================================================
@@ -4693,13 +5941,15 @@ static void findCommonSubMesh (list<const SMESH_subMesh*>& theSubMeshList,
   ::SMESH_Mesh& mesh = GetImpl();
 
   TPythonDump aPythonDump; // prevent dump of called methods
-  aPythonDump << "isDone = " << _this() << ".SetMeshOrder( [ ";
+  aPythonDump << "isDone = " << SMESH::SMESH_Mesh_var(_this()) << ".SetMeshOrder( [ ";
 
   TListOfListOfInt subMeshOrder;
   for ( int i = 0, n = theSubMeshArray.length(); i < n; i++ )
   {
     const SMESH::submesh_array& aSMArray = theSubMeshArray[i];
     TListOfInt subMeshIds;
+    if ( i > 0 )
+      aPythonDump << ", ";
     aPythonDump << "[ ";
     // Collect subMeshes which should be clear
     //  do it list-by-list, because modification of submesh order
@@ -4763,7 +6013,8 @@ void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
     SMESH::submesh_array_var aResSubSet = new SMESH::submesh_array();
     aResSubSet->length(aSubOrder.size());
     TListOfInt::const_iterator subIt = aSubOrder.begin();
-    for( int j = 0; subIt != aSubOrder.end(); subIt++ ) {
+    int j;
+    for( j = 0; subIt != aSubOrder.end(); subIt++ ) {
       if ( _mapSubMeshIor.find(*subIt) == _mapSubMeshIor.end() )
         continue;
       SMESH::SMESH_subMesh_var subMesh =
@@ -4777,7 +6028,8 @@ void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
     }
     if ( theIsDump )
       aPythonDump << " ]";
-    theResOrder[ listIndx++ ] = aResSubSet;
+    if ( j > 1 )
+      theResOrder[ listIndx++ ] = aResSubSet;
   }
   // correct number of lists
   theResOrder.length( listIndx );
@@ -4785,7 +6037,7 @@ void SMESH_Mesh_i::convertMeshOrder (const TListOfListOfInt&     theIdsOrder,
   if ( theIsDump ) {
     // finilise python dump
     aPythonDump << " ]";
-    aPythonDump << " = " << _this() << ".GetMeshOrder()";
+    aPythonDump << " = " << SMESH::SMESH_Mesh_var(_this()) << ".GetMeshOrder()";
   }
 }
 
@@ -4818,14 +6070,14 @@ SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
     SMESH::array_of_ElementType_var types = meshPart->GetTypes();
     if ( types->length() == 1 && types[0] == SMESH::NODE ) // group of nodes
     {
-      for (int i=0; i < anIDs->length(); i++)
-        if ( const SMDS_MeshNode * n = _meshDS->FindNode(anIDs[i]))
+      for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
+        if ( const SMDS_MeshNode * n = _meshDS->FindNode( anIDs[i] ))
           if ( _elements[ SMDSAbs_Node ].insert( n ).second )
             tmpInfo.Add( n );
     }
     else
     {
-      for (int i=0; i < anIDs->length(); i++)
+      for ( CORBA::ULong i=0; i < anIDs->length(); i++ )
         if ( const SMDS_MeshElement * e = _meshDS->FindElement(anIDs[i]))
           if ( _elements[ e->GetType() ].insert( e ).second )
           {
@@ -4841,10 +6093,33 @@ SMESH_MeshPartDS::SMESH_MeshPartDS(SMESH::SMESH_IDSource_ptr meshPart):
     }
     myInfo = tmpInfo;
 
+    ShapeToMesh( _meshDS->ShapeToMesh() );
+
     _meshDS = 0; // to enforce iteration on _elements and _nodes
   }
 }
 // -------------------------------------------------------------------------------------
+SMESH_MeshPartDS::SMESH_MeshPartDS(const std::list< const SMDS_MeshElement* > & meshPart):
+  SMESHDS_Mesh( /*meshID=*/-1, /*isEmbeddedMode=*/true), _meshDS(0)
+{
+  TMeshInfo tmpInfo;
+  list< const SMDS_MeshElement* >::const_iterator partIt = meshPart.begin();
+  for ( ; partIt != meshPart.end(); ++partIt )
+    if ( const SMDS_MeshElement * e = *partIt )
+      if ( _elements[ e->GetType() ].insert( e ).second )
+      {
+        tmpInfo.Add( e );
+        SMDS_ElemIteratorPtr nIt = e->nodesIterator();
+        while ( nIt->more() )
+        {
+          const SMDS_MeshNode * n = (const SMDS_MeshNode*) nIt->next();
+          if ( _elements[ SMDSAbs_Node ].insert( n ).second )
+            tmpInfo.Add( n );
+        }
+      }
+  myInfo = tmpInfo;
+}
+// -------------------------------------------------------------------------------------
 SMDS_ElemIteratorPtr SMESH_MeshPartDS::elementGeomIterator(SMDSAbs_GeometryType geomType) const
 {
   if ( _meshDS ) return _meshDS->elementGeomIterator( geomType );
@@ -4917,3 +6192,5 @@ _GET_ITER_DEFINE( SMDS_VolumeIteratorPtr, volumesIterator, SMDS_MeshVolume, SMDS
 // END Implementation of SMESH_MeshPartDS
 //
 //================================================================================
+
+