Salome HOME
Merge from V6_5_BR 05/06/2012
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
index 0840d7b109ab658c5b7c405bc4a0688b7e15c2fa..5f62002b991960c5ee6927d3635d9ef022fc9ff6 100644 (file)
@@ -1,25 +1,24 @@
-//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2012  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
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 //
-//  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.
+// 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.
 //
-//  This library is distributed in the hope that it will be useful,
-//  but WITHOUT ANY WARRANTY; without even the implied warranty of
-//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-//  Lesser General Public License for more details.
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
 //
-//  You should have received a copy of the GNU Lesser General Public
-//  License along with this library; if not, write to the Free Software
-//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
 //  File   : SMESH_Gen_i.cxx
 //  Author : Paul RASCLE, EDF
 //  Module : SMESH
 #include <TCollection_AsciiString.hxx>
 #include <OSD.hxx>
 
-#include "Utils_CorbaException.hxx"
-
-#include "utilities.h"
-#include <fstream>
-#include <stdio.h>
-
 #ifdef WNT
  #include <windows.h>
  #include <process.h>
  #define UnLoadLib( handle ) dlclose( handle );
 #endif
 
-#include <HDFOI.hxx>
-
 #include "SMESH_Gen_i.hxx"
-#include "SMESH_Mesh_i.hxx"
-#include "SMESH_Hypothesis_i.hxx"
-#include "SMESH_Algo_i.hxx"
-#include "SMESH_Group_i.hxx"
-#include "SMESH_PythonDump.hxx"
-
-#include "SMESHDS_Document.hxx"
-#include "SMESHDS_Group.hxx"
-#include "SMESHDS_GroupOnGeom.hxx"
-#include "SMESH_Mesh.hxx"
-#include "SMESH_Hypothesis.hxx"
-#include "SMESH_Group.hxx"
-#include "SMESH_MeshEditor.hxx"
 
 #include "SMDS_EdgePosition.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_SetIterator.hxx"
 #include "SMDS_SpacePosition.hxx"
 #include "SMDS_VertexPosition.hxx"
+#include "SMESHDS_Document.hxx"
+#include "SMESHDS_Group.hxx"
+#include "SMESHDS_GroupOnGeom.hxx"
+#include "SMESH_Algo_i.hxx"
+#include "SMESH_File.hxx"
+#include "SMESH_Group.hxx"
+#include "SMESH_Group_i.hxx"
+#include "SMESH_Hypothesis.hxx"
+#include "SMESH_Hypothesis_i.hxx"
+#include "SMESH_Mesh.hxx"
+#include "SMESH_MeshEditor.hxx"
+#include "SMESH_Mesh_i.hxx"
+#include "SMESH_PreMeshInfo.hxx"
+#include "SMESH_PythonDump.hxx"
 
 #include CORBA_SERVER_HEADER(SMESH_Group)
 #include CORBA_SERVER_HEADER(SMESH_Filter)
 
 #include "DriverMED_W_SMESHDS_Mesh.h"
 #include "DriverMED_R_SMESHDS_Mesh.h"
+#ifdef WITH_CGNS
+#include "DriverCGNS_Read.hxx"
+#endif
+#include "memoire.h"
+
+#include <GEOM_Client.hxx>
 
-#include "SALOMEDS_Tool.hxx"
-#include "SALOME_NamingService.hxx"
-#include "SALOME_LifeCycleCORBA.hxx"
-#include "Utils_SINGLETON.hxx"
-#include "OpUtil.hxx"
+#include <Basics_Utils.hxx>
+#include <HDFOI.hxx>
+#include <OpUtil.hxx>
+#include <SALOMEDS_Tool.hxx>
+#include <SALOME_Container_i.hxx>
+#include <SALOME_LifeCycleCORBA.hxx>
+#include <SALOME_NamingService.hxx>
+#include <Utils_CorbaException.hxx>
+#include <Utils_ExceptHandlers.hxx>
+#include <Utils_SINGLETON.hxx>
+#include <utilities.h>
 
 #include CORBA_CLIENT_HEADER(SALOME_ModuleCatalog)
 #include CORBA_CLIENT_HEADER(SALOME_Session)
 
-#include "GEOM_Client.hxx"
-#include "Utils_ExceptHandlers.hxx"
-#include "memoire.h"
-#include "Basics_Utils.hxx"
-
 #include <map>
+#include <fstream>
+#include <cstdio>
 
 using namespace std;
 using SMESH::TPythonDump;
+using SMESH::TVar;
 
 #define NUM_TMP_FILES 2
 
@@ -281,6 +283,8 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
   myIsEmbeddedMode = false;
   myShapeReader = NULL;  // shape reader
   mySMESHGen = this;
+  myIsHistoricalPythonDump = true;
+  myToForgetMeshDataOnHypModif = false;
 
   // set it in standalone mode only
   //OSD::SetSignal( true );
@@ -295,7 +299,7 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
     SALOME::Session_var session = SALOME::Session::_narrow( obj ) ;
     if ( !session->_is_nil() )
     {
-      CORBA::String_var s_host = session->getHostname();
+      CORBA::String_var str_host = session->getHostname();
       CORBA::Long        s_pid = session->getPID();
       string my_host = Kernel_Utils::GetHostname();
 #ifdef WNT
@@ -303,7 +307,7 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
 #else
       long    my_pid = (long) getpid();
 #endif
-      SetEmbeddedMode( s_pid == my_pid && my_host == s_host.in() );
+      SetEmbeddedMode( s_pid == my_pid && my_host == str_host.in() );
     }
   }
 }
@@ -318,7 +322,7 @@ SMESH_Gen_i::SMESH_Gen_i( CORBA::ORB_ptr            orb,
 
 SMESH_Gen_i::~SMESH_Gen_i()
 {
-  INFOS( "SMESH_Gen_i::~SMESH_Gen_i" );
+  MESSAGE( "SMESH_Gen_i::~SMESH_Gen_i" );
 
   // delete hypothesis creators
   map<string, GenericHypothesisCreator_i*>::iterator itHyp;
@@ -752,7 +756,7 @@ SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
       }
     }
 
-    // let the temporary hypothesis find out some how parameter values by mesh
+    // let the temporary hypothesis find out somehow parameter values by mesh
     if ( hyp->SetParametersByMesh( mesh, shape ))
       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
   }
@@ -765,6 +769,7 @@ SMESH_Gen_i::GetHypothesisParameterValues (const char*           theHypType,
     ::SMESH_Hypothesis::TDefaults dflts;
     dflts._elemLength = diagonal / myGen.GetBoundaryBoxSegmentation();
     dflts._nbSegments = myGen.GetDefaultNbSegments();
+    dflts._shape      = &shape;
     // let the temporary hypothesis initialize it's values
     if ( hyp->SetParametersByDefaults( dflts, mesh ))
       return SMESH::SMESH_Hypothesis::_duplicate( tmpHyp );
@@ -802,6 +807,63 @@ void SMESH_Gen_i::SetDefaultNbSegments(CORBA::Long theNbSegments)
     THROW_SALOME_CORBA_EXCEPTION( "non-positive number of segments", SALOME::BAD_PARAM );
 }
 
+//=============================================================================
+/*!
+  Set an option value
+*/
+//=============================================================================
+
+void SMESH_Gen_i::SetOption(const char* name, const char* value)
+{
+  if ( name && value && strlen( value ) > 0 )
+  {
+    string msgToGUI; 
+    if ( strcmp(name, "historical_python_dump") == 0 )
+    {
+      myIsHistoricalPythonDump = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
+      msgToGUI = "preferences/SMESH/historical_python_dump/";
+      msgToGUI += myIsHistoricalPythonDump ? "true" : "false";
+    }
+    else if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 )
+    {
+      myToForgetMeshDataOnHypModif = ( value[0] == '1' || toupper(value[0]) == 'T' ); // 1 || true
+      msgToGUI = "preferences/SMESH/forget_mesh_on_hyp_modif/";
+      msgToGUI += myToForgetMeshDataOnHypModif ? "true" : "false";
+    }
+
+    // update preferences in case if SetOption() is invoked from python console
+    if ( !msgToGUI.empty() )
+    {
+      CORBA::Object_var obj = SMESH_Gen_i::GetNS()->Resolve( "/Kernel/Session" );
+      SALOME::Session_var session = SALOME::Session::_narrow( obj );
+      if ( !CORBA::is_nil( session ) )
+        session->emitMessageOneWay(msgToGUI.c_str());
+    }
+  }
+}
+
+//=============================================================================
+/*!
+  Return an option value
+*/
+//=============================================================================
+
+char* SMESH_Gen_i::GetOption(const char* name)
+{
+  if ( name )
+  {
+    if ( strcmp(name, "historical_python_dump") == 0 )
+    {
+      return CORBA::string_dup( myIsHistoricalPythonDump ? "true" : "false" );
+    }
+    if ( strcmp(name, "forget_mesh_on_hyp_modif") == 0 )
+    {
+      return CORBA::string_dup( myToForgetMeshDataOnHypModif ? "true" : "false" );
+    }
+  }
+  return CORBA::string_dup( "" );
+}
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::CreateMesh
@@ -915,13 +977,11 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName
  */
 //=============================================================================
 
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName,
-                                                     SMESH::DriverMED_ReadStatus& theStatus)
-     throw ( SALOME::SALOME_Exception )
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileName,
+                                                           SMESH::DriverMED_ReadStatus& theStatus,
+                                                           const char* theCommandNameForPython,
+                                                           const char* theFileNameForPython)
 {
-  Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshFromMED" );
-
   // Retrieve mesh names from the file
   DriverMED_R_SMESHDS_Mesh myReader;
   myReader.SetFile( theFileName );
@@ -978,7 +1038,7 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName,
   }
 
   // Update Python script
-  aPythonDump << "], status) = " << this << ".CreateMeshesFromMED(r'" << theFileName << "')";
+  aPythonDump << "], status) = " << this << "." << theCommandNameForPython << "(r'" << theFileNameForPython << "')";
   }
   // Dump creation of groups
   for ( int i = 0; i < aResult->length(); ++i )
@@ -987,6 +1047,56 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName,
   return aResult._retn();
 }
 
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName,
+                                                     SMESH::DriverMED_ReadStatus& theStatus)
+     throw ( SALOME::SALOME_Exception )
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshFromMED" );
+  SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(theFileName, theStatus, "CreateMeshesFromMED", theFileName);
+  return result;
+}
+
+//=============================================================================
+/*!
+ *  SMESH_Gen_i::CreateMeshFromSAUV
+ *
+ *  Create mesh and import data from SAUV file
+ */
+//=============================================================================
+
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromSAUV( const char* theFileName,
+                                                      SMESH::DriverMED_ReadStatus& theStatus)
+     throw ( SALOME::SALOME_Exception )
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMeshFromSAUV" );
+  std::string sauvfilename(theFileName);
+  std::string medfilename(theFileName);
+  medfilename += ".med";
+  std::string cmd;
+#ifdef WNT
+  cmd = "%PYTHONBIN% ";
+#else
+  cmd = "python ";
+#endif
+  cmd += "-c \"";
+  cmd += "from medutilities import convert ; convert(r'" + sauvfilename + "', 'GIBI', 'MED', 1, r'" + medfilename + "')";
+  cmd += "\"";
+  system(cmd.c_str());
+  SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(medfilename.c_str(), theStatus, "CreateMeshesFromSAUV", sauvfilename.c_str());
+#ifdef WNT
+  cmd = "%PYTHONBIN% ";
+#else
+  cmd = "python ";
+#endif
+  cmd += "-c \"";
+  cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
+  cmd += "\"";
+  system(cmd.c_str());
+  return result;
+}
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::CreateMeshFromSTL
@@ -1023,6 +1133,89 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromSTL( const char* theFileName
   return aMesh._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Create meshes and import data from the CGSN file
+ */
+//================================================================================
+
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromCGNS( const char* theFileName,
+                                                      SMESH::DriverMED_ReadStatus& theStatus)
+  throw ( SALOME::SALOME_Exception )
+{
+  Unexpect aCatch(SALOME_SalomeException);
+
+  SMESH::mesh_array_var aResult = new SMESH::mesh_array();
+
+#ifdef WITH_CGNS
+  // Retrieve nb meshes from the file
+  DriverCGNS_Read myReader;
+  myReader.SetFile( theFileName );
+  Driver_Mesh::Status aStatus;
+  int nbMeshes = myReader.GetNbMeshes(aStatus);
+  theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
+
+  aResult->length( nbMeshes );
+
+  { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
+
+    // Python Dump
+    TPythonDump aPythonDump;
+    aPythonDump << "([";
+
+    if (theStatus == SMESH::DRS_OK)
+    {
+      SALOMEDS::StudyBuilder_var aStudyBuilder = myCurrentStudy->NewBuilder();
+      aStudyBuilder->NewCommand();  // There is a transaction
+
+      int i = 0;
+
+      // Iterate through all meshes and create mesh objects
+      for ( ; i < nbMeshes; ++i )
+      {
+        // Python Dump
+        if (i > 0) aPythonDump << ", ";
+
+        // create mesh
+        SMESH::SMESH_Mesh_var mesh = createMesh();
+        aResult[i] = SMESH::SMESH_Mesh::_duplicate( mesh );
+
+        // Read mesh data (groups are published automatically by ImportMEDFile())
+        SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
+        ASSERT( meshServant );
+        string meshName;
+        SMESH::DriverMED_ReadStatus status1 =
+          meshServant->ImportCGNSFile( theFileName, i, meshName );
+        if (status1 > theStatus)
+          theStatus = status1;
+
+        meshServant->GetImpl().GetMeshDS()->Modified();
+        // publish mesh in the study
+        SALOMEDS::SObject_var aSO;
+        if ( CanPublishInStudy( mesh ) )
+          aSO = PublishMesh( myCurrentStudy, mesh.in(), meshName.c_str() );
+
+        // Python Dump
+        if ( !aSO->_is_nil() )
+          aPythonDump << aSO;
+        else
+          aPythonDump << "mesh_" << i;
+      }
+      aStudyBuilder->CommitCommand();
+    }
+
+    aPythonDump << "], status) = " << this << ".CreateMeshesFromCGNS(r'" << theFileName << "')";
+  }
+  // Dump creation of groups
+  for ( int i = 0; i < aResult->length(); ++i )
+    SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups();
+#else
+  THROW_SALOME_CORBA_EXCEPTION("CGNS library is unavailable", SALOME::INTERNAL_ERROR);
+#endif
+
+  return aResult._retn();
+}
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::IsReadyToCompute
@@ -1421,6 +1614,7 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
   try {
     // get mesh servant
     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
+    meshServant->Load();
     ASSERT( meshServant );
     if ( meshServant ) {
       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
@@ -1506,6 +1700,7 @@ SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh
   try {
     // get mesh servant
     SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( theMesh ).in() );
+    meshServant->Load();
     ASSERT( meshServant );
     if ( meshServant ) {
       // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation"
@@ -1726,7 +1921,7 @@ SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
             SMESH_subMesh* sm = anIt->first;
             SMESH_ComputeErrorPtr& error = sm->GetComputeError();
             const SMESH_Algo* algo = myGen.GetAlgo( myLocMesh, sm->GetSubShape());
-            if ( algo && !error.get() || error->IsOK() )
+            if ( (algo && !error.get()) || error->IsOK() )
               error.reset( new SMESH_ComputeError( COMPERR_ALGO_FAILED,"Failed to evaluate",algo));
           }
           else
@@ -2229,7 +2424,7 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::mesh_array& theMeshesArray,
   aPythonDump << "], ";
   aPythonDump << theUniteIdenticalGroups << ", "
               << theMergeNodesAndElements << ", "
-              << theMergeTolerance << ")";
+              << TVar( theMergeTolerance ) << ")";
 
   delete pPythonDump; // enable python dump from GetGroups()
 
@@ -2302,12 +2497,13 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
 
   // 3. Get elements to copy
 
-  SMDS_ElemIteratorPtr srcElemIt;
+  SMDS_ElemIteratorPtr srcElemIt; SMDS_NodeIteratorPtr srcNodeIt;
   TIDSortedElemSet srcElems;
   SMESH::array_of_ElementType_var srcElemTypes = meshPart->GetTypes();
   if ( SMESH::DownCast<SMESH_Mesh_i*>( meshPart ))
   {
     srcElemIt = srcMeshDS->elementsIterator();
+    srcNodeIt = srcMeshDS->nodesIterator();
   }
   else
   {
@@ -2367,15 +2563,37 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
     if ( elem->GetType() != SMDSAbs_Node )
     {
       int ID = toKeepIDs ? elem->GetID() : 0;
-      const SMDS_MeshElement * newElem = editor.AddElement( nodes,
-                                                            elem->GetType(),
-                                                            elem->IsPoly(),
-                                                            ID);
+      const SMDS_MeshElement * newElem;
+      if ( elem->GetEntityType() == SMDSEntity_Polyhedra )
+        newElem = editor.GetMeshDS()->
+          AddPolyhedralVolumeWithID( nodes,
+                                     static_cast<const SMDS_VtkVolume*>(elem)->GetQuantities(),
+                                     elem->GetID());
+      else
+        newElem = editor.AddElement( nodes,elem->GetType(),elem->IsPoly(),ID);
+
       if ( toCopyGroups && !toKeepIDs )
         e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem ));
     }
   }
 
+  // 4(b). Copy free nodes
+
+  if ( srcNodeIt && srcMeshDS->NbNodes() != newMeshDS->NbNodes() )
+  {
+    while ( srcNodeIt->more() )
+    {
+      nSrc = srcNodeIt->next();
+      if ( nSrc->NbInverseElements() == 0 )
+      {
+        if ( toKeepIDs )
+          nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID());
+        else
+          n2nMap[ nSrc ] = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() );
+      }
+    }
+  }
+
   // 5. Copy groups
 
   int nbNewGroups = 0;
@@ -2445,6 +2663,8 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
     }
   }
 
+  newMeshDS->Modified();
+
   *pyDump << newMesh << " = " << this
           << ".CopyMesh( " << meshPart << ", "
           << "'" << meshName << "', "
@@ -2590,7 +2810,10 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
         if ( !CORBA::is_nil( anObject ) ) {
           SMESH::SMESH_Mesh_var myMesh = SMESH::SMESH_Mesh::_narrow( anObject ) ;
           if ( !myMesh->_is_nil() ) {
+            myMesh->Load(); // load from study file if not yet done
+            TPythonDump pd; // not to dump GetGroups()
             SMESH::ListOfGroups_var groups = myMesh->GetGroups();
+            pd << ""; // to avoid optimizing pd out
             for ( int i = 0; i < groups->length(); ++i )
             {
               SMESH_GroupBase_i* grImpl = SMESH::DownCast<SMESH_GroupBase_i*>( groups[i]);
@@ -3139,7 +3362,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
 
             // groups root sub-branch
             SALOMEDS::SObject_var myGroupsBranch;
-            for ( int i = GetNodeGroupsTag(); i <= GetVolumeGroupsTag(); i++ ) {
+            for ( int i = GetNodeGroupsTag(); i <= Get0DElementsGroupsTag(); i++ ) {
               found = gotBranch->FindSubObject( i, myGroupsBranch );
               if ( found ) {
                 char name_group[ 30 ];
@@ -3151,6 +3374,8 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                   strcpy( name_group, "Groups of Faces" );
                 else if ( i == GetVolumeGroupsTag() )
                   strcpy( name_group, "Groups of Volumes" );
+                else if ( i == Get0DElementsGroupsTag() )
+                  strcpy( name_group, "Groups of 0D Elements" );
 
                 aGroup = new HDFgroup( name_group, aTopGroup );
                 aGroup->CreateOnDisk();
@@ -3229,6 +3454,17 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                         myWriter.AddGroup( aGeomGrp );
                       }
                     }
+                    else if ( SMESH_GroupOnFilter_i* aFilterGrp_i = 
+                              dynamic_cast<SMESH_GroupOnFilter_i*>( myGroupImpl ))
+                    {
+                      std::string str = aFilterGrp_i->FilterToString();
+                      std::string hdfGrpName = "Filter " + SMESH_Comment(anId);
+                      aSize[ 0 ] = str.length() + 1;
+                      aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup, HDF_STRING, aSize, 1);
+                      aDataset->CreateOnDisk();
+                      aDataset->WriteOnDisk( ( char* )( str.c_str() ) );
+                      aDataset->CloseOnDisk();
+                    }
                   }
                 }
                 aGroup->CloseOnDisk();
@@ -3240,6 +3476,9 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
               // Flush current mesh information into MED file
               myWriter.Perform();
 
+              // save info on nb of elements
+              SMESH_PreMeshInfo::SaveToFile( myImpl, id, aFile );
+
               // maybe a shape was deleted in the study
               if ( !shapeRefFound && !mySMESHDSMesh->ShapeToMesh().IsNull() && hasShape) {
                 TopoDS_Shape nullShape;
@@ -3316,6 +3555,8 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
                   delete[] smIDs;
                 }
 
+                aGroup->CloseOnDisk();
+
                 // Store node positions on sub-shapes (SMDS_Position):
                 // ----------------------------------------------------
 
@@ -3492,7 +3733,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent
   int size = aStreamFile.in().length();
   _CORBA_Octet* buffer = new _CORBA_Octet[size*3+1];
   for ( int i = 0; i < size; i++ )
-    sprintf( (char*)&(buffer[i*3]), "|%02x", (char*)(aStreamFile[i]) );
+    sprintf( (char*)&(buffer[i*3]), "|%02x", aStreamFile[i] );
 
   buffer[size * 3] = '\0';
 
@@ -3521,33 +3762,6 @@ void SMESH_Gen_i::loadGeomData( SALOMEDS::SComponent_ptr theCompRoot )
   SALOMEDS::StudyBuilder_var aStudyBuilder = aStudy->NewBuilder();
   aStudyBuilder->LoadWith( theCompRoot, GetGeomEngine() );
 }
-//=============================================================================
-/*!
- * \brief Creates SMDS_Position according to shape type
- */
-//=============================================================================
-
-class PositionCreator {
-public:
-  SMDS_PositionPtr MakePosition(const TopAbs_ShapeEnum type) {
-    return (this->*myFuncTable[ type ])();
-  }
-  PositionCreator() {
-    myFuncTable.resize( (size_t) TopAbs_SHAPE, & PositionCreator::defaultPosition );
-    myFuncTable[ TopAbs_SOLID  ] = & PositionCreator::volumePosition;
-    myFuncTable[ TopAbs_FACE   ] = & PositionCreator::facePosition;
-    myFuncTable[ TopAbs_EDGE   ] = & PositionCreator::edgePosition;
-    myFuncTable[ TopAbs_VERTEX ] = & PositionCreator::vertexPosition;
-  }
-private:
-  SMDS_PositionPtr edgePosition()    const { return SMDS_PositionPtr( new SMDS_EdgePosition  ); }
-  SMDS_PositionPtr facePosition()    const { return SMDS_PositionPtr( new SMDS_FacePosition  ); }
-  SMDS_PositionPtr volumePosition()  const { return SMDS_PositionPtr( new SMDS_SpacePosition ); }
-  SMDS_PositionPtr vertexPosition()  const { return SMDS_PositionPtr( new SMDS_VertexPosition); }
-  SMDS_PositionPtr defaultPosition() const { return SMDS_SpacePosition::originSpacePosition();  }
-  typedef SMDS_PositionPtr (PositionCreator:: * FmakePos)() const;
-  vector<FmakePos> myFuncTable;
-};
 
 //=============================================================================
 /*!
@@ -3617,8 +3831,10 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
     return false;
   }
 
-  DriverMED_R_SMESHDS_Mesh myReader;
-  myReader.SetFile( meshfile.ToCString() );
+  TPythonDump pd; // prevent dump during loading
+
+  // DriverMED_R_SMESHDS_Mesh myReader;
+  // myReader.SetFile( meshfile.ToCString() );
 
   // For PAL13473 ("Repetitive mesh") implementation.
   // New dependencies between SMESH objects are established:
@@ -3878,7 +4094,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             int* anAutoColor = new int[ size ];
             aDataset->ReadFromDisk( anAutoColor );
             aDataset->CloseOnDisk();
-            myNewMeshImpl->SetAutoColor( (bool)anAutoColor[0] );
+            myNewMeshImpl->GetImpl().SetAutoColor( (bool)anAutoColor[0] );
           }
 
           // try to read and set reference to shape
@@ -3931,7 +4147,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
           }
         }
       }
-    }
+    } // reading MESHes
 
     // As all object that can be referred by hypothesis are created,
     // we can restore hypothesis data
@@ -3951,8 +4167,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
     {
       aTopGroup                   = meshi_group->second;
       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
-      ::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
-      SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
+      //::SMESH_Mesh& myLocMesh     = myNewMeshImpl->GetImpl();
+      //SMESHDS_Mesh* mySMESHDSMesh = myLocMesh.GetMeshDS();
 
       GEOM::GEOM_Object_var aShapeObject = myNewMeshImpl->GetShapeToMesh();
       bool hasData = false;
@@ -3973,14 +4189,15 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         aDataset->CloseOnDisk();
         if ( strcmp( strHasData, "1") == 0 ) {
           // read mesh data from MED file
-          myReader.SetMesh( mySMESHDSMesh );
-          myReader.SetMeshId( id );
-          myReader.Perform();
+          // myReader.SetMesh( mySMESHDSMesh );
+          // myReader.SetMeshId( id );
+          // myReader.Perform();
           hasData = true;
         }
       }
 
-      // try to get applied algorithms
+      // Try to get applied ALGORITHMS (mesh is not cleared by algo addition because
+      // nodes and elements are not yet put into sub-meshes)
       if ( aTopGroup->ExistInternalObject( "Applied Algorithms" ) ) {
         aGroup = new HDFgroup( "Applied Algorithms", aTopGroup );
         aGroup->OpenOnDisk();
@@ -3998,9 +4215,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             char* refFromFile = new char[ size ];
             aDataset->ReadFromDisk( refFromFile );
             aDataset->CloseOnDisk();
-
             // san - it is impossible to recover applied algorithms using their entries within Load() method
-
             //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
             //CORBA::Object_var hypObject = SObjectToObject( hypSO );
             int id = atoi( refFromFile );
@@ -4036,9 +4251,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
             char* refFromFile = new char[ size ];
             aDataset->ReadFromDisk( refFromFile );
             aDataset->CloseOnDisk();
-
             // san - it is impossible to recover applied hypotheses using their entries within Load() method
-
             //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
             //CORBA::Object_var hypObject = SObjectToObject( hypSO );
             int id = atoi( refFromFile );
@@ -4057,7 +4270,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         aGroup->CloseOnDisk();
       }
 
-      // --> try to find submeshes containers for each type of submesh
+      // --> try to find SUB-MESHES containers for each type of submesh
       for ( int j = GetSubMeshOnVertexTag(); j <= GetSubMeshOnCompoundTag(); j++ ) {
         char name_meshgroup[ 30 ];
         if ( j == GetSubMeshOnVertexTag() )
@@ -4128,21 +4341,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               if ( aSubMesh->_is_nil() )
                 continue;
 
-              // VSR: Get submesh data from MED convertor
-              //                  int anInternalSubmeshId = aSubMesh->GetId(); // this is not a persistent ID, it's an internal one computed from sub-shape
-              //                  if (myNewMeshImpl->_mapSubMesh.find(anInternalSubmeshId) != myNewMeshImpl->_mapSubMesh.end()) {
-              //                    if(MYDEBUG) MESSAGE("VSR - SMESH_Gen_i::Load(): loading from MED file submesh with ID = " <<
-              //                            subid << " for subshape # " << anInternalSubmeshId);
-              //                    SMESHDS_SubMesh* aSubMeshDS =
-              //                      myNewMeshImpl->_mapSubMesh[anInternalSubmeshId]->CreateSubMeshDS();
-              //                    if ( !aSubMeshDS ) {
-              //                      if(MYDEBUG) MESSAGE("VSR - SMESH_Gen_i::Load(): FAILED to create a submesh for subshape # " <<
-              //                              anInternalSubmeshId << " in current mesh!");
-              //                    }
-              //                    else
-              //                      myReader.GetSubMesh( aSubMeshDS, subid );
-              //                  }
-
               // try to get applied algorithms
               if ( aSubGroup->ExistInternalObject( "Applied Algorithms" ) ) {
                 // open "applied algorithms" HDF group
@@ -4162,8 +4360,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                     aDataset->ReadFromDisk( refFromFile );
                     aDataset->CloseOnDisk();
 
-                    //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
-                    //CORBA::Object_var hypObject = SObjectToObject( hypSO );
                     int id = atoi( refFromFile );
                     string anIOR = myStudyContext->getIORbyOldId( id );
                     if ( !anIOR.empty() ) {
@@ -4199,8 +4395,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                     aDataset->ReadFromDisk( refFromFile );
                     aDataset->CloseOnDisk();
 
-                    //SALOMEDS::SObject_var hypSO = myCurrentStudy->FindObjectID( refFromFile );
-                    //CORBA::Object_var hypObject = SObjectToObject( hypSO );
                     int id = atoi( refFromFile );
                     string anIOR = myStudyContext->getIORbyOldId( id );
                     if ( !anIOR.empty() ) {
@@ -4213,225 +4407,21 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                     }
                   }
                 }
-                // close "applied hypotheses" HDF group
+                // close "APPLIED HYPOTHESES" hdf group
                 aSubSubGroup->CloseOnDisk();
               }
 
-              // close submesh HDF group
+              // close SUB-MESH hdf group
               aSubGroup->CloseOnDisk();
             }
           }
-          // close submeshes containers HDF group
+          // close SUB-MESHES containers hdf group
           aGroup->CloseOnDisk();
         }
       }
 
-      if(hasData) {
-
-        // Read sub-meshes from MED
-        // -------------------------
-        if(MYDEBUG) MESSAGE("Create all sub-meshes");
-        bool submeshesInFamilies = ( ! aTopGroup->ExistInternalObject( "Submeshes" ));
-        if ( submeshesInFamilies )
-        {
-          // old way working before fix of PAL 12992
-          myReader.CreateAllSubMeshes();
-        }
-        else
-        {
-          // open a group
-          aGroup = new HDFgroup( "Submeshes", aTopGroup );
-          aGroup->OpenOnDisk();
-
-          int maxID = Max( mySMESHDSMesh->MaxSubMeshIndex(), mySMESHDSMesh->MaxShapeIndex() );
-          vector< SMESHDS_SubMesh * > subMeshes( maxID + 1, (SMESHDS_SubMesh*) 0 );
-          vector< TopAbs_ShapeEnum  > smType   ( maxID + 1, TopAbs_SHAPE );
-
-          PositionCreator aPositionCreator;
-
-          SMDS_NodeIteratorPtr nIt = mySMESHDSMesh->nodesIterator();
-          SMDS_ElemIteratorPtr eIt = mySMESHDSMesh->elementsIterator();
-          for ( int isNode = 0; isNode < 2; ++isNode )
-          {
-            string aDSName( isNode ? "Node Submeshes" : "Element Submeshes");
-            if ( aGroup->ExistInternalObject( (char*) aDSName.c_str() ))
-            {
-              aDataset = new HDFdataset( (char*) aDSName.c_str(), aGroup );
-              aDataset->OpenOnDisk();
-              // read submesh IDs for all elements sorted by ID
-              int nbElems = aDataset->GetSize();
-              int* smIDs = new int [ nbElems ];
-              aDataset->ReadFromDisk( smIDs );
-              aDataset->CloseOnDisk();
-
-              // get elements sorted by ID
-              TIDSortedElemSet elemSet;
-              if ( isNode )
-                while ( nIt->more() ) elemSet.insert( nIt->next() );
-              else
-                while ( eIt->more() ) elemSet.insert( eIt->next() );
-              //ASSERT( elemSet.size() == nbElems ); -- issue 20182
-              // -- Most probably a bad study was saved when there were
-              // not fixed bugs in SMDS_MeshInfo
-              if ( elemSet.size() < nbElems ) {
-#ifdef _DEBUG_
-                cout << "SMESH_Gen_i::Load(), warning: Node position data is invalid" << endl;
-#endif
-                nbElems = elemSet.size();
-              }
-              // add elements to submeshes
-              TIDSortedElemSet::iterator iE = elemSet.begin();
-              for ( int i = 0; i < nbElems; ++i, ++iE )
-              {
-                int smID = smIDs[ i ];
-                if ( smID == 0 ) continue;
-                const SMDS_MeshElement* elem = *iE;
-                if( smID > maxID ) {
-                  // corresponding subshape no longer exists: maybe geom group has been edited
-                  if ( myNewMeshImpl->HasShapeToMesh() )
-                    mySMESHDSMesh->RemoveElement( elem );
-                  continue;
-                }
-                // get or create submesh
-                SMESHDS_SubMesh* & sm = subMeshes[ smID ];
-                if ( ! sm ) {
-                  sm = mySMESHDSMesh->NewSubMesh( smID );
-                  smType[ smID ] = mySMESHDSMesh->IndexToShape( smID ).ShapeType();
-                }
-                // add
-                if ( isNode ) {
-                  SMDS_PositionPtr pos = aPositionCreator.MakePosition( smType[ smID ]);
-                  SMDS_MeshNode* node = const_cast<SMDS_MeshNode*>( static_cast<const SMDS_MeshNode*>( elem ));
-                  node->SetPosition( pos );
-                  sm->AddNode( node );
-                } else {
-                  sm->AddElement( elem );
-                }
-              }
-              delete [] smIDs;
-            }
-          }
-        } // end reading submeshes
-
-        // Read node positions on sub-shapes (SMDS_Position)
-
-        if ( aTopGroup->ExistInternalObject( "Node Positions" ))
-        {
-          // There are 5 datasets to read:
-          // "Nodes on Edges" - ID of node on edge
-          // "Edge positions" - U parameter on node on edge
-          // "Nodes on Faces" - ID of node on face
-          // "Face U positions" - U parameter of node on face
-          // "Face V positions" - V parameter of node on face
-          const char* aEid_DSName = "Nodes on Edges";
-          const char* aEu_DSName  = "Edge positions";
-          const char* aFu_DSName  = "Face U positions";
-          //char* aFid_DSName = "Nodes on Faces";
-          //char* aFv_DSName  = "Face V positions";
-
-          // data to retrieve
-          int nbEids = 0, nbFids = 0;
-          int *aEids = 0, *aFids  = 0;
-          double *aEpos = 0, *aFupos = 0, *aFvpos = 0;
-
-          // open a group
-          aGroup = new HDFgroup( "Node Positions", aTopGroup );
-          aGroup->OpenOnDisk();
-
-          // loop on 5 data sets
-          int aNbObjects = aGroup->nInternalObjects();
-          for ( int i = 0; i < aNbObjects; i++ )
-          {
-            // identify dataset
-            char aDSName[ HDF_NAME_MAX_LEN+1 ];
-            aGroup->InternalObjectIndentify( i, aDSName );
-            // read data
-            aDataset = new HDFdataset( aDSName, aGroup );
-            aDataset->OpenOnDisk();
-            if ( aDataset->GetType() == HDF_FLOAT64 ) // Positions
-            {
-              double* pos = new double [ aDataset->GetSize() ];
-              aDataset->ReadFromDisk( pos );
-              // which one?
-              if ( strncmp( aDSName, aEu_DSName, strlen( aEu_DSName )) == 0 )
-                aEpos = pos;
-              else if ( strncmp( aDSName, aFu_DSName, strlen( aFu_DSName )) == 0 )
-                aFupos = pos;
-              else
-                aFvpos = pos;
-            }
-            else // NODE IDS
-            {
-              int aSize = aDataset->GetSize();
-
-              // for reading files, created from 18.07.2005 till 10.10.2005
-              if (aDataset->GetType() == HDF_STRING)
-                aSize /= sizeof(int);
-
-              int* ids = new int [aSize];
-              aDataset->ReadFromDisk( ids );
-              // on face or nodes?
-              if ( strncmp( aDSName, aEid_DSName, strlen( aEid_DSName )) == 0 ) {
-                aEids = ids;
-                nbEids = aSize;
-              }
-              else {
-                aFids = ids;
-                nbFids = aSize;
-              }
-            }
-            aDataset->CloseOnDisk();
-          } // loop on 5 datasets
-
-          // Set node positions on edges or faces
-          for ( int onFace = 0; onFace < 2; onFace++ )
-          {
-            int nbNodes = ( onFace ? nbFids : nbEids );
-            if ( nbNodes == 0 ) continue;
-            int* aNodeIDs = ( onFace ? aFids : aEids );
-            double* aUPos = ( onFace ? aFupos : aEpos );
-            double* aVPos = ( onFace ? aFvpos : 0 );
-            // loop on node IDs
-            for ( int iNode = 0; iNode < nbNodes; iNode++ )
-            {
-              const SMDS_MeshNode* node = mySMESHDSMesh->FindNode( aNodeIDs[ iNode ]);
-              if ( !node ) continue; // maybe removed while Loading() if geometry changed
-              SMDS_PositionPtr aPos = node->GetPosition();
-              ASSERT( aPos );
-              if ( onFace ) {
-                // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_FACE );-- issue 20182
-                // -- Most probably a bad study was saved when there were
-                // not fixed bugs in SMDS_MeshInfo
-                if ( aPos->GetTypeOfPosition() == SMDS_TOP_FACE ) {
-                  SMDS_FacePosition* fPos = const_cast<SMDS_FacePosition*>
-                    ( static_cast<const SMDS_FacePosition*>( aPos ));
-                  fPos->SetUParameter( aUPos[ iNode ]);
-                  fPos->SetVParameter( aVPos[ iNode ]);
-                }
-              }
-              else {
-                // ASSERT( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE );-- issue 20182
-                if ( aPos->GetTypeOfPosition() == SMDS_TOP_EDGE ) {
-                  SMDS_EdgePosition* fPos = const_cast<SMDS_EdgePosition*>
-                    ( static_cast<const SMDS_EdgePosition*>( aPos ));
-                  fPos->SetUParameter( aUPos[ iNode ]);
-                }
-              }
-            }
-          }
-          if ( aEids ) delete [] aEids;
-          if ( aFids ) delete [] aFids;
-          if ( aEpos ) delete [] aEpos;
-          if ( aFupos ) delete [] aFupos;
-          if ( aFvpos ) delete [] aFvpos;
-
-          aGroup->CloseOnDisk();
-
-        } // if ( aTopGroup->ExistInternalObject( "Node Positions" ) )
-      } // if ( hasData )
-
-      // try to get groups
-      for ( int ii = GetNodeGroupsTag(); ii <= GetVolumeGroupsTag(); ii++ ) {
+      // try to get GROUPS
+      for ( int ii = GetNodeGroupsTag(); ii <= Get0DElementsGroupsTag(); ii++ ) {
         char name_group[ 30 ];
         if ( ii == GetNodeGroupsTag() )
           strcpy( name_group, "Groups of Nodes" );
@@ -4441,6 +4431,8 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
           strcpy( name_group, "Groups of Faces" );
         else if ( ii == GetVolumeGroupsTag() )
           strcpy( name_group, "Groups of Volumes" );
+        else if ( ii == Get0DElementsGroupsTag() )
+          strcpy( name_group, "Groups of 0D Elements" );
 
         if ( aTopGroup->ExistInternalObject( name_group ) ) {
           aGroup = new HDFgroup( name_group, aTopGroup );
@@ -4487,10 +4479,28 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
                   }
                 }
               }
+              // Try to read a filter of SMESH_GroupOnFilter
+              SMESH::Filter_var filter;
+              SMESH_PredicatePtr predicate;
+              std::string hdfGrpName = "Filter " + SMESH_Comment(subid);
+              if ( aGroup->ExistInternalObject( hdfGrpName.c_str() ))
+              {
+                aDataset = new HDFdataset( hdfGrpName.c_str(), aGroup );
+                aDataset->OpenOnDisk();
+                size = aDataset->GetSize();
+                char* persistStr = new char[ size ];
+                aDataset->ReadFromDisk( persistStr );
+                aDataset->CloseOnDisk();
+                if ( strlen( persistStr ) > 0 ) {
+                  filter = SMESH_GroupOnFilter_i::StringToFilter( persistStr );
+                  predicate = SMESH_GroupOnFilter_i::GetPredicate( filter );
+                }
+              }
+
               // Create group servant
               SMESH::ElementType type = (SMESH::ElementType)(ii - GetNodeGroupsTag() + 1);
               SMESH::SMESH_GroupBase_var aNewGroup = SMESH::SMESH_GroupBase::_duplicate
-                ( myNewMeshImpl->createGroup( type, nameFromFile, aShape ) );
+                ( myNewMeshImpl->createGroup( type, nameFromFile, aShape, predicate ) );
               // Obtain a SMESHDS_Group object
               if ( aNewGroup->_is_nil() )
                 continue;
@@ -4499,16 +4509,18 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               int newSubId = myStudyContext->findId( iorSubString );
               myStudyContext->mapOldToNew( subid, newSubId );
 
-              SMESH_GroupBase_i* aGroupImpl =
-                dynamic_cast<SMESH_GroupBase_i*>( GetServant( aNewGroup ).in() );
+              SMESH_GroupBase_i* aGroupImpl = SMESH::DownCast< SMESH_GroupBase_i*>( aNewGroup );
               if ( !aGroupImpl )
                 continue;
 
-              SMESH_Group* aLocalGroup  = myLocMesh.GetGroup( aGroupImpl->GetLocalID() );
-              if ( !aLocalGroup )
+              if ( SMESH_GroupOnFilter_i* aFilterGroup =
+                   dynamic_cast< SMESH_GroupOnFilter_i*>( aGroupImpl ))
+                aFilterGroup->SetFilter( filter );
+
+              SMESHDS_GroupBase* aGroupBaseDS = aGroupImpl->GetGroupDS();
+              if ( !aGroupBaseDS )
                 continue;
 
-              SMESHDS_GroupBase* aGroupBaseDS = aLocalGroup->GetGroupDS();
               aGroupBaseDS->SetStoreName( name_dataset );
 
               // ouv : NPAL12872
@@ -4528,16 +4540,25 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               }
 
               // Fill group with contents from MED file
-              SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( aGroupBaseDS );
-              if ( aGrp )
-                myReader.GetGroup( aGrp );
+              // SMESHDS_Group* aGrp = dynamic_cast<SMESHDS_Group*>( aGroupBaseDS );
+              // if ( aGrp )
+              //   myReader.GetGroup( aGrp );
             }
           }
           aGroup->CloseOnDisk();
         }
+      } // reading GROUPs
+
+      // instead of reading mesh data, we read only brief information of all
+      // objects: mesh, groups, sub-meshes (issue 0021208 )
+      if ( hasData )
+      {
+        SMESH_PreMeshInfo::LoadFromFile( myNewMeshImpl, id,
+                                         meshfile.ToCString(), filename.ToCString(),
+                                         !isMultiFile );
       }
 
-      // read submeh order if any
+      // read Sub-Mesh ORDER if any
       if( aTopGroup->ExistInternalObject( "Mesh Order" ) ) {
         aDataset = new HDFdataset( "Mesh Order", aTopGroup );
         aDataset->OpenOnDisk();
@@ -4557,7 +4578,14 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
       }
     } // loop on meshes
 
-    // notify algos on completed restoration
+    // update hyps needing full mesh data restored (issue 20918)
+    for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
+    {
+      SMESH_Hypothesis_i* hyp  = hyp_data->first;
+      hyp->UpdateAsMeshesRestored();
+    }
+
+    // notify algos on completed restoration to set sub-mesh event listeners
     for ( meshi_group = meshGroupList.begin(); meshi_group != meshGroupList.end(); ++meshi_group )
     {
       SMESH_Mesh_i* myNewMeshImpl = meshi_group->first;
@@ -4573,12 +4601,6 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         ComputeStateEngine (SMESH_subMesh::SUBMESH_RESTORED);
     }
 
-    for ( hyp_data = hypDataList.begin(); hyp_data != hypDataList.end(); ++hyp_data )
-    {
-      SMESH_Hypothesis_i* hyp  = hyp_data->first;
-      hyp->UpdateAsMeshesRestored(); // for hyps needing full mesh data restored (issue 20918)
-    }
-
     // close mesh group
     if(aTopGroup)
       aTopGroup->CloseOnDisk();
@@ -4589,7 +4611,24 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
 
   // Remove temporary files created from the stream
   if ( !isMultiFile )
-    SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
+  {
+    SMESH_File meshFile( meshfile.ToCString() );
+    if ( !meshFile ) // no meshfile exists
+    {
+      SALOMEDS_Tool::RemoveTemporaryFiles( tmpDir.ToCString(), aFileSeq.in(), true );
+    }
+    else
+    {
+      Engines::Container_var container = GetContainerRef();
+      if ( Engines_Container_i* container_i = SMESH::DownCast<Engines_Container_i*>( container ))
+      {
+        container_i->registerTemporaryFile( filename.ToCString() );
+        container_i->registerTemporaryFile( meshfile.ToCString() );
+        container_i->registerTemporaryFile( tmpDir.ToCString() );
+      }
+    }
+  }
+  pd << ""; // prevent optimizing pd out
 
   INFOS( "SMESH_Gen_i::Load completed" );
   return true;
@@ -4647,8 +4686,9 @@ void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
   if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Close" );
 
   // set correct current study
-  if (theComponent->GetStudy()->StudyId() != GetCurrentStudyID())
-    SetCurrentStudy(theComponent->GetStudy());
+  SALOMEDS::Study_var study = theComponent->GetStudy();
+  if ( study->StudyId() != GetCurrentStudyID())
+    SetCurrentStudy( study );
 
   // Clear study contexts data
   int studyId = GetCurrentStudyID();
@@ -4675,6 +4715,9 @@ void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
 //     context->myDocument = 0;
 //   }
 
+  // remove the tmp files meshes are loaded from
+  SMESH_PreMeshInfo::RemoveStudyFiles_TMP_METHOD( theComponent );
+
   myCurrentStudy = SALOMEDS::Study::_nil();
   return;
 }