Salome HOME
22874: [CEA 1425] Performance SMESH Module
[modules/smesh.git] / src / SMESH_I / SMESH_Mesh_i.cxx
index 0b833714104305ef8ad9bed95e7aabef17d1129d..5669a0b223231e19dc0a3abc51ca077bb57a4232 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  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
 #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_Mesh.hxx"
 #include "SMESH_MeshAlgos.hxx"
 #include "SMESH_MeshEditor.hxx"
 #include "SMESH_MeshEditor_i.hxx"
 #include "SMESH_PythonDump.hxx"
 #include "SMESH_subMesh_i.hxx"
 
-#include <OpUtil.hxx>
 #include <SALOMEDS_Attributes_wrap.hxx>
 #include <SALOMEDS_wrap.hxx>
-#include <SALOME_NamingService.hxx>
 #include <Utils_ExceptHandlers.hxx>
-#include <Utils_SINGLETON.hxx>
 #include <utilities.h>
 
 #include <GEOMImpl_Types.hxx>
 
 // OCCT Includes
 #include <BRep_Builder.hxx>
-#include <OSD_Directory.hxx>
-#include <OSD_File.hxx>
-#include <OSD_Path.hxx>
-#include <OSD_Protection.hxx>
-#include <Standard_OutOfMemory.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 <TopTools_MapIteratorOfMapOfShape.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; }
@@ -125,6 +116,7 @@ SMESH_Mesh_i::SMESH_Mesh_i( PortableServer::POA_ptr thePOA,
   _editor        = NULL;
   _previewEditor = NULL;
   _preMeshInfo   = NULL;
+  _mainShapeTick = 0;
 }
 
 //=============================================================================
@@ -169,6 +161,11 @@ SMESH_Mesh_i::~SMESH_Mesh_i()
   }
   _mapHypo.clear();
 
+  // 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();
+
   delete _editor; _editor = NULL;
   delete _previewEditor; _previewEditor = NULL;
   delete _impl; _impl = NULL;
@@ -198,6 +195,8 @@ void SMESH_Mesh_i::SetShape( GEOM::GEOM_Object_ptr theShapeObject )
   // to track changes of GEOM groups
   SMESH::SMESH_Mesh_var mesh = _this();
   addGeomGroupData( theShapeObject, mesh );
+  if ( !CORBA::is_nil( theShapeObject ))
+    _mainShapeTick = theShapeObject->GetTick();
 }
 
 //================================================================================
@@ -280,7 +279,7 @@ void SMESH_Mesh_i::Clear() throw (SALOME::SALOME_Exception)
 
   try {
     _impl->Clear();
-    CheckGeomGroupModif(); // issue 20145
+    //CheckGeomGroupModif(); // issue 20145
   }
   catch(SALOME_Exception & S_ex) {
     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
@@ -401,14 +400,7 @@ SMESH_Mesh_i::ImportMEDFile( const char* theFileName, const char* theMeshName )
   _medFileInfo->major    = major;
   _medFileInfo->minor    = minor;
   _medFileInfo->release  = release;
-#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->fileSize = SMESH_File( theFileName ).size();
 
   return ConvertDriverMEDReadStatus(status);
 }
@@ -564,6 +556,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;
@@ -579,33 +572,31 @@ 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) )
   {
     SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
-    _gen_i->AddHypothesisToShape( study, mesh, aSubShapeObject, anHyp );
+    _gen_i->AddHypothesisToShape( study, mesh, aSubShape, anHyp );
   }
   if(MYDEBUG) MESSAGE( " AddHypothesis(): status = " << status );
 
   // Update Python script
-  //if(_impl->HasShapeToMesh())
-  {
-    TPythonDump() << "status = " << mesh << ".AddHypothesis( "
-                  << aSubShapeObject << ", " << anHyp << " )";
-  }
-  // else {
-  //   TPythonDump() << "status = " << mesh << ".AddHypothesis( "<< anHyp << " )";
-  // }
+  TPythonDump() << "status = " << mesh << ".AddHypothesis( "
+                << aSubShape << ", " << anHyp << " )";
 
   return ConvertHypothesisStatus(status);
 }
@@ -617,12 +608,13 @@ 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())
+  if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference",SALOME::BAD_PARAM);
 
   if (CORBA::is_nil( anHyp ))
@@ -634,22 +626,28 @@ SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
     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();
     
     const int hypId = anHyp->GetId();
-    status = _impl->AddHypothesis(myLocSubShape, hypId);
-    if ( !SMESH_Hypothesis::IsStatusFatal(status) ) {
+    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() )
-          SMESH::SMESH_subMesh_var( createSubMesh( aSubShapeObject ));
+          SMESH::SMESH_subMesh_var( createSubMesh( aSubShape ));
       }
     }
+    else if ( anErrorText )
+    {
+      *anErrorText = error;
+    }
   }
   catch(SALOME_Exception & S_ex)
   {
@@ -664,7 +662,7 @@ SMESH_Mesh_i::addHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
  */
 //=============================================================================
 
-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)
 {
@@ -672,18 +670,18 @@ SMESH::Hypothesis_Status SMESH_Mesh_i::RemoveHypothesis(GEOM::GEOM_Object_ptr aS
   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) )
   {
     SALOMEDS::Study_var study = _gen_i->GetCurrentStudy();
-    _gen_i->RemoveHypothesisFromShape( study, mesh, aSubShapeObject, anHyp );
+    _gen_i->RemoveHypothesisFromShape( study, mesh, aSubShape, anHyp );
   }
   // Update Python script
   if(_impl->HasShapeToMesh())
     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
-                  << aSubShapeObject << ", " << anHyp << " )";
+                  << aSubShape << ", " << anHyp << " )";
   else
     TPythonDump() << "status = " << mesh << ".RemoveHypothesis( "
                   << anHyp << " )";
@@ -698,12 +696,12 @@ 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()");
 
-  if (CORBA::is_nil( aSubShapeObject ) && HasShapeToMesh())
+  if (CORBA::is_nil( aSubShape ) && HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION("bad Sub-shape reference", SALOME::BAD_PARAM);
 
   if (CORBA::is_nil( anHyp ))
@@ -715,7 +713,7 @@ SMESH_Mesh_i::removeHypothesis(GEOM::GEOM_Object_ptr       aSubShapeObject,
     TopoDS_Shape myLocSubShape;
     //use PseudoShape in case if mesh has no shape
     if( _impl->HasShapeToMesh() )
-      myLocSubShape = _gen_i->GeomObjectToShape( aSubShapeObject );
+      myLocSubShape = _gen_i->GeomObjectToShape( aSubShape );
     else
       myLocSubShape = _impl->GetShapeToMesh();
 
@@ -741,18 +739,18 @@ 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 );
@@ -818,18 +816,18 @@ 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);
-  if (CORBA::is_nil(aSubShapeObject))
+  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 = _this();
   try {
-    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShapeObject);
+    TopoDS_Shape myLocSubShape = _gen_i->GeomObjectToShape(aSubShape);
 
     //Get or Create the SMESH_subMesh object implementation
 
@@ -845,16 +843,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 );
+      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, aSubShapeObject, theName );
+        _gen_i->PublishSubMesh( study, aMesh, subMesh, aSubShape, theName );
       if ( !aSO->_is_nil()) {
         // Update Python script
         TPythonDump() << aSO << " = " << aMesh << ".GetSubMesh( "
-                      << aSubShapeObject << ", '" << theName << "' )";
+                      << aSubShape << ", '" << theName << "' )";
       }
     }
   }
@@ -878,7 +876,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
   if ( theSubMesh->_is_nil() )
     return;
 
-  GEOM::GEOM_Object_var aSubShapeObject;
+  GEOM::GEOM_Object_var aSubShape;
   SALOMEDS::Study_var aStudy = _gen_i->GetCurrentStudy();
   if ( !aStudy->_is_nil() )  {
     // Remove submesh's SObject
@@ -890,10 +888,10 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
            anObj->ReferencedObject( aRef.inout() ))
       {
         CORBA::Object_var obj = aRef->GetObject();
-        aSubShapeObject = GEOM::GEOM_Object::_narrow( obj );
+        aSubShape = GEOM::GEOM_Object::_narrow( obj );
       }
-      // if ( aSubShapeObject->_is_nil() ) // not published shape (IPAL13617)
-      //   aSubShapeObject = theSubMesh->GetSubShape();
+      // if ( aSubShape->_is_nil() ) // not published shape (IPAL13617)
+      //   aSubShape = theSubMesh->GetSubShape();
 
       SALOMEDS::StudyBuilder_var builder = aStudy->NewBuilder();
       builder->RemoveObjectWithChildren( anSO );
@@ -903,7 +901,7 @@ void SMESH_Mesh_i::RemoveSubMesh( SMESH::SMESH_subMesh_ptr theSubMesh )
     }
   }
 
-  if ( removeSubMesh( theSubMesh, aSubShapeObject.in() ))
+  if ( removeSubMesh( theSubMesh, aSubShape.in() ))
     if ( _preMeshInfo )
       _preMeshInfo->ForgetOrLoad();
 
@@ -1562,7 +1560,7 @@ SMESH_Mesh_i::CutListOfGroups(const SMESH::ListOfGroups& theMainGroups,
 
   // Update Python script
   pyDump << aResGrp << " = " << SMESH::SMESH_Mesh_var( _this() )
-         << ".CutListOfGroups( " << theMainGroups
+         << ".CutListOfGroups( " << theMainGroups << ", "
          << theToolGroups << ", '" << theName << "' )";
 
   SMESH_CATCH( SMESH::throwCorbaException );
@@ -1707,6 +1705,9 @@ void SMESH_Mesh_i::addGeomGroupData(GEOM::GEOM_Object_ptr theGeomObj,
     groupData._indices.insert( ids[i] );
   // SMESH object
   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();
 }
 
 //================================================================================
@@ -1780,22 +1781,176 @@ 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;
+
+  if ( mainGO->GetType() == GEOM_GROUP ||
+       mainGO->GetTick() == _mainShapeTick )
+  {
+    CheckGeomGroupModif();
+    return;
+  }
+
+  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
  */
@@ -2613,44 +2768,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);
   }
 }
 
@@ -2911,7 +3058,7 @@ void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
   {
     aMeshName = prepareMeshNameAndGroups(file, overwrite);
     _impl->ExportMED( file, aMeshName.c_str(), auto_groups,
-                      version, 0, autoDimension, have0dField);
+                      version, 0, autoDimension, /*addODOnVertices=*/have0dField);
     meshDS = _impl->GetMeshDS();
   }
   else
@@ -2931,7 +3078,7 @@ void SMESH_Mesh_i::ExportPartToMED(SMESH::SMESH_IDSource_ptr meshPart,
     }
     SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
     _impl->ExportMED( file, aMeshName.c_str(), auto_groups,
-                      version, partDS, autoDimension, have0dField);
+                      version, partDS, autoDimension, /*addODOnVertices=*/have0dField);
     meshDS = tmpDSDeleter._obj = partDS;
   }
 
@@ -3017,7 +3164,7 @@ void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
                            name.in(),
                            elemType,
                            comps->length(),
-                           ( dataType == GEOM::FDT_Int )))
+                           /*isIntData=*/false ))//( dataType == GEOM::FDT_Int )))
       continue;
 
     for ( size_t iC = 0; iC < comps->length(); ++iC )
@@ -3104,9 +3251,9 @@ void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
           const SMDS_MeshElement* e = elemIt->next();
           const int shapeID = e->getshapeId();
           if ( shapeID < 1 || shapeID >= intVals.size() )
-            fieldWriter.AddValue( noneIntValue );
+            fieldWriter.AddValue( (double) noneIntValue );
           else
-            fieldWriter.AddValue( intVals[ shapeID ]);
+            fieldWriter.AddValue( (double) intVals[ shapeID ]);
         }
 
       // write a step
@@ -3144,17 +3291,17 @@ void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
     std::vector< std::string > compNames;
     switch ( geomAssocFields[ iF ]) {
     case 'v': case 'V':
-      fieldWriter.Set( meshDS, "_vertices_", SMDSAbs_Node, /*nbComps=*/2, /*isInt=*/true );
+      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=*/true );
+      fieldWriter.Set( meshDS, "_edges_", SMDSAbs_Edge, /*nbComps=*/1, /*isInt=*/false );
       break;
     case 'f': case 'F':
-      fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/true );
+      fieldWriter.Set( meshDS, "_faces_", SMDSAbs_Face, /*nbComps=*/1, /*isInt=*/false );
       break;
     case 's': case 'S':
-      fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/true );
+      fieldWriter.Set( meshDS, "_solids_", SMDSAbs_Volume, /*nbComps=*/1, /*isInt=*/false );
       break;
     default: continue;
     }
@@ -3175,14 +3322,14 @@ void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
         const int shapeID = e->getshapeId();
         if ( shapeID < 1 )
         {
-          fieldWriter.AddValue( -1 );
-          fieldWriter.AddValue( -1 );
+          fieldWriter.AddValue( (double) -1 );
+          fieldWriter.AddValue( (double) -1 );
         }
         else
         {
           const TopoDS_Shape& S = meshDS->IndexToShape( shapeID );
-          fieldWriter.AddValue( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]);
-          fieldWriter.AddValue( shapeID );
+          fieldWriter.AddValue( (double) ( S.IsNull() ? -1 : shapeDim[ S.ShapeType() ]));
+          fieldWriter.AddValue( (double) shapeID );
         }
       }
     else
@@ -3191,9 +3338,9 @@ void SMESH_Mesh_i::exportMEDFields( DriverMED_W_Field&        fieldWriter,
         const SMDS_MeshElement* e = elemIt->next();
         const int shapeID = e->getshapeId();
         if ( shapeID < 1 )
-          fieldWriter.AddValue( -1 );
+          fieldWriter.AddValue( (double) -1 );
         else
-          fieldWriter.AddValue( shapeID );
+          fieldWriter.AddValue( (double) shapeID );
       }
 
     // write a step
@@ -4004,17 +4151,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();
 }
@@ -4603,7 +4744,6 @@ SMESH_Mesh_i::MakeGroupsOfBadInputElements( int         theSubShapeID,
           SALOMEDS::SObject_wrap aSO =
             _gen_i->PublishGroup( study, mesh, groups[ iG ],
                                  GEOM::GEOM_Object::_nil(), theGroupName);
-          aSO->_is_nil(); // avoid "unused variable" warning
         }
         SMESH_GroupBase_i* grp_i = SMESH::DownCast< SMESH_GroupBase_i* >( groups[ iG ]);
         if ( !grp_i ) continue;
@@ -4914,6 +5054,37 @@ 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();
+}
 
 //=============================================================================
 namespace /* Iterators used in SMESH_Mesh_i::GetElements(SMESH::SMESH_IDSource_var obj,
@@ -5595,6 +5766,8 @@ TListOfListOfInt SMESH_Mesh_i::findConcurrentSubMeshes()
   {
     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