Salome HOME
Merge branch 'OCCT780'
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
index 30d0352628819ea10452f6257cbef4ee2c3d539b..1c78a25268a822ff4b26e282c0f1e8ffd35028e0 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2024  CEA, EDF, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #include <TopoDS_Wire.hxx>
 #include <gp_Pnt.hxx>
 
+// Have to be included before std headers
+#include <Python.h>
+#include <structmember.h>
+
 #ifdef WIN32
  #include <windows.h>
  #include <process.h>
 #include "SMESH_Hypothesis.hxx"
 #include "SMESH_Hypothesis_i.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_ParallelMesh.hxx"
 #include "SMESH_MeshEditor.hxx"
 #include "SMESH_Mesh_i.hxx"
+#include <SMESH_SequentialMesh_i.hxx>
+#include "SMESH_ParallelMesh_i.hxx"
 #include "SMESH_PreMeshInfo.hxx"
 #include "SMESH_PythonDump.hxx"
 #include "SMESH_ControlsDef.hxx"
 #include <SMESH_BoostTxtArchive.hxx>
+#include <SMESH_SequentialMesh_i.hxx>
+#include <SMESH_ParallelMesh_i.hxx>
+#include "SMESH_Meshio.h"
 
 // to pass CORBA exception through SMESH_TRY
 #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
 #include <memory>
 
 #include <boost/archive/text_oarchive.hpp>
-#include <boost/archive/text_iarchive.hpp>
 #include <boost/serialization/list.hpp>
 #include <boost/serialization/string.hpp>
+#include <boost/filesystem.hpp>
+
+namespace fs = boost::filesystem;
 
 using namespace std;
 using SMESH::TPythonDump;
@@ -155,12 +167,6 @@ using SMESH::TVar;
 
 #define NUM_TMP_FILES 2
 
-#ifdef _DEBUG_
-static int MYDEBUG = 0;
-#else
-static int MYDEBUG = 0;
-#endif
-
 // Static variables definition
 GEOM::GEOM_Gen_var      SMESH_Gen_i::myGeomGen;
 CORBA::ORB_var          SMESH_Gen_i::myOrb;
@@ -190,22 +196,22 @@ PortableServer::ServantBase_var SMESH_Gen_i::GetServant( CORBA::Object_ptr theOb
   }
   catch (PortableServer::POA::ObjectNotActive &ex)
   {
-    INFOS("GetServant: ObjectNotActive");
+    MESSAGE("GetServant: ObjectNotActive");
     return NULL;
   }
   catch (PortableServer::POA::WrongAdapter &ex)
   {
-    INFOS("GetServant: WrongAdapter: OK when several servants used to build several mesh in parallel...");
+    MESSAGE("GetServant: WrongAdapter: OK when several servants used to build several mesh in parallel...");
     return NULL;
   }
   catch (PortableServer::POA::WrongPolicy &ex)
   {
-    INFOS("GetServant: WrongPolicy");
+    MESSAGE("GetServant: WrongPolicy");
     return NULL;
   }
   catch (...)
   {
-    INFOS( "GetServant - Unknown exception was caught!!!" );
+    MESSAGE( "GetServant - Unknown exception was caught!!!" );
     return NULL;
   }
 }
@@ -449,7 +455,7 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
   thePlatformLibName = aPlatformLibName;
 
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "Create Hypothesis <" << theHypName << "> from " << aPlatformLibName);
+  MESSAGE( "Create Hypothesis <" << theHypName << "> from " << aPlatformLibName);
 
   typedef GenericHypothesisCreator_i* (*GetHypothesisCreator)(const char* );
   GenericHypothesisCreator_i* aCreator;
@@ -459,7 +465,7 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
     if (myHypCreatorMap.find(string(theHypName)) == myHypCreatorMap.end())
     {
       // load plugin library
-      if(MYDEBUG) MESSAGE("Loading server meshers plugin library ...");
+      MESSAGE("Loading server meshers plugin library ...");
 #ifdef WIN32
 #  ifdef UNICODE
       const wchar_t* path = Kernel_Utils::decode_s(aPlatformLibName);
@@ -485,7 +491,7 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
       }
 
       // get method, returning hypothesis creator
-      if(MYDEBUG) MESSAGE("Find GetHypothesisCreator() method ...");
+      MESSAGE("Find GetHypothesisCreator() method ...");
       GetHypothesisCreator procHandle =
         (GetHypothesisCreator)GetProc( libHandle, "GetHypothesisCreator" );
       if (!procHandle)
@@ -496,7 +502,7 @@ GenericHypothesisCreator_i* SMESH_Gen_i::getHypothesisCreator(const char* theHyp
       }
 
       // get hypothesis creator
-      if(MYDEBUG) MESSAGE("Get Hypothesis Creator for " << theHypName);
+      MESSAGE("Get Hypothesis Creator for " << theHypName);
       aCreator = procHandle(theHypName);
       if (!aCreator)
       {
@@ -547,8 +553,7 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
     // activate the CORBA servant of hypothesis
     hypothesis_i = myHypothesis_i->_this();
     int nextId = RegisterObject( hypothesis_i );
-    if(MYDEBUG) { MESSAGE( "Add hypo to map with id = "<< nextId ); }
-    else        { (void)nextId; } // avoid "unused variable" warning in release mode
+    MESSAGE( "Add hypo to map with id = "<< nextId );
   }
   return hypothesis_i._retn();
 }
@@ -564,21 +569,24 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::createMesh" );
+  MESSAGE( "SMESH_Gen_i::createMesh" );
 
   // Get or create the GEOM_Client instance
   try {
     // create a new mesh object servant, store it in a map in study context
     SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this );
     // create a new mesh object
-    if(MYDEBUG) MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
-    meshServant->SetImpl( myGen.CreateMesh( myIsEmbeddedMode ));
+    MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
+    SMESH_Mesh* myImpl = dynamic_cast<SMESH_Mesh*>(myGen.CreateMesh( myIsEmbeddedMode ));
+    if(myImpl == NULL )
+      THROW_SALOME_CORBA_EXCEPTION( "Could not cast SequentialMesh as Mesh", SALOME::INTERNAL_ERROR );
+    meshServant->SetImpl(myImpl);
 
     // activate the CORBA servant of Mesh
     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( meshServant->_this() );
     int nextId = RegisterObject( mesh );
-    if(MYDEBUG) { MESSAGE( "Add mesh to map with id = "<< nextId); }
-    else        { (void)nextId; } // avoid "unused variable" warning in release mode
+    MESSAGE( "Add mesh to map with id = "<< nextId);
+
     return mesh._retn();
   }
   catch (SALOME_Exception& S_ex) {
@@ -587,6 +595,42 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
   return SMESH::SMESH_Mesh::_nil();
 }
 
+//=============================================================================
+/*!
+ *  SMESH_Gen_i::createParallelMesh
+ *
+ *  Create empty parallel mesh on shape
+ */
+//=============================================================================
+SMESH::SMESH_ParallelMesh_ptr SMESH_Gen_i::createParallelMesh()
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  MESSAGE( "SMESH_Gen_i::createParallelMesh" );
+
+  // Get or create the GEOM_Client instance
+  try {
+    // create a new mesh object servant, store it in a map in study context
+    SMESH_ParallelMesh_i* meshServant = new SMESH_ParallelMesh_i( GetPOA(), this );
+    // create a new mesh object
+    MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
+    SMESH_Mesh* myImpl = dynamic_cast<SMESH_Mesh*>(myGen.CreateParallelMesh( myIsEmbeddedMode ));
+    if(myImpl == NULL )
+      THROW_SALOME_CORBA_EXCEPTION( "Could not cast ParallelMesh as Mesh", SALOME::INTERNAL_ERROR );
+    meshServant->SetImpl(myImpl);
+
+    // activate the CORBA servant of Mesh
+    SMESH::SMESH_ParallelMesh_var mesh = SMESH::SMESH_ParallelMesh::_narrow( meshServant->_this() );
+    int nextId = RegisterObject( mesh );
+    MESSAGE( "Add mesh to map with id = "<< nextId);
+
+    return mesh._retn();
+  }
+  catch (SALOME_Exception& S_ex) {
+    THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
+  }
+  return SMESH::SMESH_ParallelMesh::_nil();
+}
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::GetShapeReader
@@ -635,14 +679,19 @@ void SMESH_Gen_i::SetEmbeddedMode( CORBA::Boolean theMode )
     if (!envNoCatchSignals || !atoi(envNoCatchSignals))
     {
       bool raiseFPE;
-#ifdef _DEBUG_
-      raiseFPE = true;
-      char* envDisableFPE = getenv("DISABLE_FPE");
-      if (envDisableFPE && atoi(envDisableFPE))
+
+      if (SALOME::VerbosityActivated())
+      {
+        raiseFPE = true;
+        char* envDisableFPE = getenv("DISABLE_FPE");
+        if (envDisableFPE && atoi(envDisableFPE))
+          raiseFPE = false;
+      }
+      else
+      {
         raiseFPE = false;
-#else
-      raiseFPE = false;
-#endif
+      }
+
       OSD::SetSignal( raiseFPE );
     }
     // else OSD::SetSignal() is called in GUI
@@ -1194,7 +1243,7 @@ char* SMESH_Gen_i::GetOption(const char* name)
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObject )
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
+  MESSAGE( "SMESH_Gen_i::CreateMesh(GEOM_Object_ptr)" );
   // create mesh
   SMESH::SMESH_Mesh_var mesh = this->createMesh();
   // set shape
@@ -1217,6 +1266,40 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObj
   return mesh._retn();
 }
 
+//=============================================================================
+/*!
+ *  SMESH_Gen_i::CreateParallelMesh
+ *
+ *  Create empty parallel mesh on a shape and publish it in the study
+ */
+//=============================================================================
+
+SMESH::SMESH_ParallelMesh_ptr SMESH_Gen_i::CreateParallelMesh( GEOM::GEOM_Object_ptr theShapeObject )
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  MESSAGE( "SMESH_Gen_i::CreateParallelMesh" );
+  // create mesh
+  SMESH::SMESH_ParallelMesh_var mesh = this->createParallelMesh();
+  // set shape
+  SMESH_ParallelMesh_i* meshServant = SMESH::DownCast<SMESH_ParallelMesh_i*>( mesh );
+  ASSERT( meshServant );
+  meshServant->SetShape( theShapeObject );
+
+  // publish mesh in the study
+  if ( CanPublishInStudy( mesh ) ) {
+    SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
+    aStudyBuilder->NewCommand();  // There is a transaction
+    SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() );
+    aStudyBuilder->CommitCommand();
+    if ( !aSO->_is_nil() ) {
+      // Update Python script
+      TPythonDump(this) << aSO << " = " << this << ".CreateParallelMesh(" << theShapeObject << ")";
+    }
+  }
+
+  return mesh._retn();
+}
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::CreateEmptyMesh
@@ -1228,7 +1311,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObj
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateEmptyMesh()
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::CreateMesh" );
+  MESSAGE( "SMESH_Gen_i::CreateEmptyMesh" );
   // create mesh
   SMESH::SMESH_Mesh_var mesh = this->createMesh();
 
@@ -1268,6 +1351,39 @@ namespace
          SALOME::BAD_PARAM );
     }
   }
+
+  //================================================================================
+  /*!
+   * \brief Makes a python dump for a function by iterating the given SObjects 
+   */
+  //================================================================================
+
+  void functionToPythonDump(
+    SMESH_Gen_i* smesh, const std::string& functionName, std::vector<SALOMEDS::SObject_wrap>& sobjects)
+  {
+    TPythonDump aPythonDump(smesh);
+    aPythonDump << "([";
+
+    int i = 0;
+    for (const SALOMEDS::SObject_wrap& so : sobjects)
+    {
+      if (i > 0)
+      {
+        aPythonDump << ", ";
+      }
+
+      if (!so->_is_nil())
+      {
+        aPythonDump << so;
+      }
+      else
+      {
+        aPythonDump << "mesh_" << i;
+      }
+    }
+
+    aPythonDump << "], status) = " << smesh << functionName;
+  }
 }
 
 //=============================================================================
@@ -1317,17 +1433,17 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName
  */
 //=============================================================================
 
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileName,
-                                                           SMESH::DriverMED_ReadStatus& theStatus,
-                                                           const char* theCommandNameForPython,
-                                                           const char* theFileNameForPython)
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char*                  theFileName,
+                                                     SMESH::DriverMED_ReadStatus& theStatus )
 {
+  checkFileReadable( theFileName );
+
 #ifdef WIN32
   char bname[ _MAX_FNAME ];
-  _splitpath( theFileNameForPython, NULL, NULL, bname, NULL );
+  _splitpath( theFileName, NULL, NULL, bname, NULL );
   string aFileName = bname;
 #else
-  string aFileName = basename( const_cast<char *>(theFileNameForPython) );
+  string aFileName = basename( const_cast<char *>( theFileName ));
 #endif
   // Retrieve mesh names from the file
   DriverMED_R_SMESHDS_Mesh myReader;
@@ -1340,59 +1456,57 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileNa
 
   { // open a new scope to make aPythonDump die before PythonDump in SMESH_Mesh::GetGroups()
 
-  // Python Dump
-  TPythonDump aPythonDump(this);
-  aPythonDump << "([";
+    // Python Dump
+    TPythonDump aPythonDump(this);
+    aPythonDump << "([";
+
+    if (theStatus == SMESH::DRS_OK)
+    {
+      SALOMEDS::StudyBuilder_var aStudyBuilder;
+      aStudyBuilder = getStudyServant()->NewBuilder();
+      aStudyBuilder->NewCommand();  // There is a transaction
 
-  if (theStatus == SMESH::DRS_OK) {
-    SALOMEDS::StudyBuilder_var aStudyBuilder;
-    aStudyBuilder = getStudyServant()->NewBuilder();
-    aStudyBuilder->NewCommand();  // There is a transaction
+      aResult->length( aNames.size() );
+      int i = 0;
 
-    aResult->length( aNames.size() );
-    int i = 0;
+      // Iterate through all meshes and create mesh objects
+      for ( const std::string & meshName : aNames )
+      {
+        // Python Dump
+        if (i > 0) aPythonDump << ", ";
 
-    // Iterate through all meshes and create mesh objects
-    for ( list<string>::iterator it = aNames.begin(); it != aNames.end(); it++ )
-    {
-      // Python Dump
-      if (i > 0) aPythonDump << ", ";
+        // create mesh
+        SMESH::SMESH_Mesh_var mesh = createMesh();
 
-      // create mesh
-      SMESH::SMESH_Mesh_var mesh = createMesh();
+        // publish mesh in the study
+        SALOMEDS::SObject_wrap aSO;
+        if ( CanPublishInStudy( mesh ) )
+          aSO = PublishMesh( mesh.in(), meshName.c_str() );
 
-      // publish mesh in the study
-      SALOMEDS::SObject_wrap aSO;
-      if ( CanPublishInStudy( mesh ) )
-        // little trick: for MED file theFileName and theFileNameForPython are the same, but they are different for SAUV
-        // - as names of meshes are stored in MED file, we use them for data publishing
-        // - as mesh name is not stored in UNV file, we use file name as name of mesh when publishing data
-        aSO = PublishMesh( mesh.in(), ( theFileName == theFileNameForPython ) ? (*it).c_str() : aFileName.c_str() );
-
-      // Python Dump
-      if ( !aSO->_is_nil() ) {
-        aPythonDump << aSO;
-      } else {
-        aPythonDump << "mesh_" << i;
-      }
+        // Python Dump
+        if ( !aSO->_is_nil() ) {
+          aPythonDump << aSO;
+        } else {
+          aPythonDump << "mesh_" << i;
+        }
 
-      // Read mesh data (groups are published automatically by ImportMEDFile())
-      SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
-      ASSERT( meshServant );
-      SMESH::DriverMED_ReadStatus status1 =
-        meshServant->ImportMEDFile( theFileName, (*it).c_str() );
-      if (status1 > theStatus)
-        theStatus = status1;
+        // Read mesh data (groups are published automatically by ImportMEDFile())
+        SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>( GetServant( mesh ).in() );
+        ASSERT( meshServant );
+        SMESH::DriverMED_ReadStatus status1 =
+          meshServant->ImportMEDFile( theFileName, meshName.c_str() );
+        if (status1 > theStatus)
+          theStatus = status1;
 
-      aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
-      meshServant->GetImpl().GetMeshDS()->Modified();
+        aResult[i++] = SMESH::SMESH_Mesh::_duplicate( mesh );
+        meshServant->GetImpl().GetMeshDS()->Modified();
+      }
+      if ( !aStudyBuilder->_is_nil() )
+        aStudyBuilder->CommitCommand();
     }
-    if ( !aStudyBuilder->_is_nil() )
-      aStudyBuilder->CommitCommand();
-  }
 
-  // Update Python script
-  aPythonDump << "], status) = " << this << "." << theCommandNameForPython << "(r'" << theFileNameForPython << "')";
+    // Update Python script
+    aPythonDump << "], status) = " << this << ".CreateMeshesFromMED( r'" << theFileName << "' )";
   }
   // Dump creation of groups
   for ( CORBA::ULong  i = 0; i < aResult->length(); ++i )
@@ -1401,66 +1515,6 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMEDorSAUV( const char* theFileNa
   return aResult._retn();
 }
 
-//================================================================================
-/*!
- * \brief Create meshes by reading a MED file
- */
-//================================================================================
-
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char*                  theFileName,
-                                                     SMESH::DriverMED_ReadStatus& theStatus)
-{
-  Unexpect aCatch(SALOME_SalomeException);
-  checkFileReadable( theFileName );
-
-  SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(theFileName, theStatus,
-                                                        "CreateMeshesFromMED", theFileName);
-  return result;
-}
-
-//=============================================================================
-/*!
- *  SMESH_Gen_i::CreateMeshFromSAUV
- *
- *  Create mesh and import data from SAUV file
- */
-//=============================================================================
-
-SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromSAUV( const char*                  theFileName,
-                                                      SMESH::DriverMED_ReadStatus& theStatus)
-{
-  Unexpect aCatch(SALOME_SalomeException);
-  checkFileReadable( theFileName );
-
-  std::string sauvfilename(theFileName);
-  std::string medfilename(theFileName);
-  medfilename += ".med";
-  std::string cmd;
-#ifdef WIN32
-  cmd = "%PYTHONBIN% ";
-#else
-  cmd = "python3 ";
-#endif
-  cmd += "-c \"";
-  cmd += "from medutilities import convert ; convert(r'" + sauvfilename + "', 'GIBI', 'MED', 1, r'" + medfilename + "')";
-  cmd += "\"";
-  system(cmd.c_str());
-  SMESH::mesh_array* result = CreateMeshesFromMEDorSAUV(medfilename.c_str(),
-                                                        theStatus,
-                                                        "CreateMeshesFromSAUV",
-                                                        sauvfilename.c_str());
-#ifdef WIN32
-  cmd = "%PYTHONBIN% ";
-#else
-  cmd = "python3 ";
-#endif
-  cmd += "-c \"";
-  cmd += "from medutilities import my_remove ; my_remove(r'" + medfilename + "')";
-  cmd += "\"";
-  system(cmd.c_str());
-  return result;
-}
-
 //=============================================================================
 /*!
  *  SMESH_Gen_i::CreateMeshFromSTL
@@ -1629,6 +1683,91 @@ SMESH_Gen_i::CreateMeshesFromGMF( const char*             theFileName,
   return aMesh._retn();
 }
 
+//================================================================================
+/*!
+ * \brief Create a mesh and import data from any file supported by meshio library
+ */
+//================================================================================
+
+SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMESHIO(const char* theFileName,
+                                                       SMESH::DriverMED_ReadStatus& theStatus)
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  checkFileReadable(theFileName);
+
+  MESSAGE("Import part with meshio through an intermediate MED file");
+
+  // Create an object that holds a temp file name and
+  // removes the file when goes out of scope.
+  SMESH_Meshio meshio;
+  const QString tempFileName = meshio.CreateTempFileName(theFileName);
+
+  // Convert temp file into a target one with meshio command
+  meshio.Convert(theFileName, tempFileName);
+
+  // We don't need a python dump from SMESH_Gen_i::CreateMeshesFromMED(), so
+  // we can't use this method as is here. The followed code is an edited part of
+  // copy pasted CreateMeshesFromMED().
+
+  // Retrieve mesh names from the file
+  DriverMED_R_SMESHDS_Mesh myReader;
+  myReader.SetFile(tempFileName.toStdString());
+  myReader.SetMeshId(-1);
+  Driver_Mesh::Status aStatus;
+  list<string> aNames = myReader.GetMeshNames(aStatus);
+  SMESH::mesh_array_var aResult = new SMESH::mesh_array();
+  theStatus = (SMESH::DriverMED_ReadStatus)aStatus;
+
+  if (theStatus == SMESH::DRS_OK)
+  {
+    SALOMEDS::StudyBuilder_var aStudyBuilder;
+    aStudyBuilder = getStudyServant()->NewBuilder();
+    aStudyBuilder->NewCommand();  // There is a transaction
+
+    aResult->length(aNames.size());
+    std::vector<SALOMEDS::SObject_wrap> sobjects;
+    int i = 0;
+
+    // Iterate through all meshes and create mesh objects
+    for (const std::string& meshName : aNames)
+    {
+      // create mesh
+      SMESH::SMESH_Mesh_var mesh = createMesh();
+
+      // publish mesh in the study
+      SALOMEDS::SObject_wrap aSO;
+      if (CanPublishInStudy(mesh))
+        aSO = PublishMesh(mesh.in(), meshName.c_str());
+
+      // Save SO to use in a python dump
+      sobjects.emplace_back(aSO);
+
+      // Read mesh data (groups are published automatically by ImportMEDFile())
+      SMESH_Mesh_i* meshServant = dynamic_cast<SMESH_Mesh_i*>(GetServant(mesh).in());
+      ASSERT(meshServant);
+      SMESH::DriverMED_ReadStatus status1 =
+        meshServant->ImportMEDFile(tempFileName.toUtf8().data(), meshName.c_str());
+      if (status1 > theStatus)
+        theStatus = status1;
+
+      aResult[i++] = SMESH::SMESH_Mesh::_duplicate(mesh);
+      meshServant->GetImpl().GetMeshDS()->Modified();
+    }
+
+    if (!aStudyBuilder->_is_nil())
+      aStudyBuilder->CommitCommand();
+
+    // Python dump
+    const std::string functionName = std::string(".CreateMeshesFromMESHIO(r'") + theFileName + "')";
+    functionToPythonDump(this, functionName, sobjects);
+  }
+
+  // Dump creation of groups
+  for (CORBA::ULong  i = 0; i < aResult->length(); ++i)
+    SMESH::ListOfGroups_var groups = aResult[i]->GetGroups();
+
+  return aResult._retn();
+}
 
 //=============================================================================
 /*!
@@ -1642,7 +1781,7 @@ CORBA::Boolean SMESH_Gen_i::IsReadyToCompute( SMESH::SMESH_Mesh_ptr theMesh,
                                               GEOM::GEOM_Object_ptr theShapeObject )
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IsReadyToCompute" );
+  MESSAGE( "SMESH_Gen_i::IsReadyToCompute" );
 
   if ( CORBA::is_nil( theShapeObject ) )
     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
@@ -1716,7 +1855,7 @@ SMESH::compute_error_array* SMESH_Gen_i::GetComputeErrors( SMESH::SMESH_Mesh_ptr
                                                            GEOM::GEOM_Object_ptr theSubObject )
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetComputeErrors()" );
+  MESSAGE( "SMESH_Gen_i::GetComputeErrors()" );
 
   if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
@@ -1790,7 +1929,7 @@ SMESH_Gen_i::GetBadInputElements( SMESH::SMESH_Mesh_ptr theMesh,
                                   CORBA::Short          theSubShapeID )
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetBadInputElements()" );
+  MESSAGE( "SMESH_Gen_i::GetBadInputElements()" );
 
   if ( CORBA::is_nil( theMesh ) )
     THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference",SALOME::BAD_PARAM );
@@ -1911,7 +2050,7 @@ SMESH::algo_error_array* SMESH_Gen_i::GetAlgoState( SMESH::SMESH_Mesh_ptr theMes
                                                     GEOM::GEOM_Object_ptr theSubObject )
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetAlgoState()" );
+  MESSAGE( "SMESH_Gen_i::GetAlgoState()" );
 
   if ( CORBA::is_nil( theSubObject ) && theMesh->HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
@@ -1972,7 +2111,7 @@ SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr      theMainShapeObject,
                              const SMESH::object_array& theListOfSubShapeObject )
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::GetSubShapesId" );
+  MESSAGE( "SMESH_Gen_i::GetSubShapesId" );
 
   SMESH::long_array_var shapesId = new SMESH::long_array;
   set<int> setId;
@@ -1999,19 +2138,19 @@ SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr      theMainShapeObject,
       {
         const TopoDS_Face& F = TopoDS::Face(exp.Current());
         setId.insert(myIndexToShape.FindIndex(F));
-        if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(F));
+        SCRUTE(myIndexToShape.FindIndex(F));
       }
       for (TopExp_Explorer exp(locShape,TopAbs_EDGE); exp.More(); exp.Next())
       {
         const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
         setId.insert(myIndexToShape.FindIndex(E));
-        if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(E));
+        SCRUTE(myIndexToShape.FindIndex(E));
       }
       for (TopExp_Explorer exp(locShape,TopAbs_VERTEX); exp.More(); exp.Next())
       {
         const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current());
         setId.insert(myIndexToShape.FindIndex(V));
-        if(MYDEBUG) SCRUTE(myIndexToShape.FindIndex(V));
+        SCRUTE(myIndexToShape.FindIndex(V));
       }
     }
     shapesId->length(setId.size());
@@ -2019,9 +2158,9 @@ SMESH_Gen_i::GetSubShapesId( GEOM::GEOM_Object_ptr      theMainShapeObject,
     int i=0;
     for (iind = setId.begin(); iind != setId.end(); iind++)
     {
-      if(MYDEBUG) SCRUTE((*iind));
+      SCRUTE((*iind));
       shapesId[i] = (*iind);
-      if(MYDEBUG) SCRUTE(shapesId[i]);
+      SCRUTE(shapesId[i]);
       i++;
     }
   }
@@ -2046,7 +2185,7 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
 {
   //MEMOSTAT;
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Compute" );
+  MESSAGE( "SMESH_Gen_i::Compute" );
 
   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
@@ -2058,7 +2197,9 @@ CORBA::Boolean SMESH_Gen_i::Compute( SMESH::SMESH_Mesh_ptr theMesh,
 
   // Update Python script
   TPythonDump(this) << "isDone = " << this << ".Compute( "
-                << theMesh << ", " << theShapeObject << ")";
+                    << theMesh << ", " << theShapeObject << ")";
+  TPythonDump(this) << this << ".CheckCompute( "
+                    << theMesh << ")";
 
   try {
     // get mesh servant
@@ -2141,7 +2282,7 @@ SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh
                                                    SMESH::long_array&    theShapesId)
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Precompute" );
+  MESSAGE( "SMESH_Gen_i::Precompute" );
 
   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference",
@@ -2327,7 +2468,7 @@ SMESH::smIdType_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh,
                                              GEOM::GEOM_Object_ptr theShapeObject)
 {
   Unexpect aCatch(SALOME_SalomeException);
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Evaluate" );
+  MESSAGE( "SMESH_Gen_i::Evaluate" );
 
   if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh())
     THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", SALOME::BAD_PARAM );
@@ -2676,28 +2817,31 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
 
     // copy elements
 
-    SMESH::array_of_ElementType_var srcElemTypes = theMeshesArray[i]->GetTypes();
-    if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes
-      continue;
     std::vector< const SMDS_MeshElement* > newElems( initMeshDS->NbElements() + 1, 0 );
-    elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
-    while ( elemIt->more() )
+    SMESH::array_of_ElementType_var srcElemTypes = theMeshesArray[i]->GetTypes();
+    bool hasElems = (( srcElemTypes->length() > 1 ) ||
+                     ( srcElemTypes->length() == 1 && srcElemTypes[0] != SMESH::NODE ));
+    if ( hasElems )
     {
-      const SMDS_MeshElement* elem = elemIt->next();
-      elemType.myNodes.resize( elem->NbNodes() );
-
-      SMDS_NodeIteratorPtr itNodes = elem->nodeIterator();
-      for ( int k = 0; itNodes->more(); k++)
+      elemIt = initImpl->GetElements( theMeshesArray[i], SMESH::ALL );
+      while ( elemIt->more() )
       {
-        const SMDS_MeshNode* node = itNodes->next();
-        elemType.myNodes[ k ] = static_cast< const SMDS_MeshNode*> ( newNodes[ node->GetID() ]);
-      }
+        const SMDS_MeshElement* elem = elemIt->next();
+        elemType.myNodes.resize( elem->NbNodes() );
 
-      // creates a corresponding element on existent nodes in new mesh
-      newElems[ elem->GetID() ] =
-        newEditor.AddElement( elemType.myNodes, elemType.Init( elem, /*basicOnly=*/false ));
+        SMDS_NodeIteratorPtr itNodes = elem->nodeIterator();
+        for ( int k = 0; itNodes->more(); k++)
+        {
+          const SMDS_MeshNode* node = itNodes->next();
+          elemType.myNodes[ k ] = static_cast< const SMDS_MeshNode*> ( newNodes[ node->GetID() ]);
+        }
+
+        // creates a corresponding element on existent nodes in new mesh
+        newElems[ elem->GetID() ] =
+          newEditor.AddElement( elemType.myNodes, elemType.Init( elem, /*basicOnly=*/false ));
+      }
+      newEditor.ClearLastCreated(); // forget the history
     }
-    newEditor.ClearLastCreated(); // forget the history
 
 
     // create groups of just added elements
@@ -2862,6 +3006,138 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray,
   return newMesh._retn();
 }
 
+
+//================================================================================
+/*!
+ * \brief Create a mesh by copying a part of another mesh
+ *  \param mesh - TetraHedron mesh
+ *  \param meshName Name of the created mesh
+ *  \retval SMESH::SMESH_Mesh_ptr - the new mesh
+ */
+//================================================================================
+
+SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh,
+                                                  const char*               meshName,
+                                                  CORBA::Boolean            adapt_to_shape)
+{
+  Unexpect aCatch(SALOME_SalomeException);
+
+  TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh()
+  std::unique_ptr<TPythonDump> pyDumpDeleter( pyDump );
+
+  // 1. Get source mesh
+
+  if ( CORBA::is_nil( mesh ))
+    THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
+
+  SMESH::SMESH_Mesh_var srcMesh = mesh->GetMesh();
+  SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
+  if ( !srcMesh_i )
+    THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
+
+  CORBA::String_var mesh_var=GetORB()->object_to_string(mesh);
+  std::string mesh_ior = mesh_var.in();
+
+  //temporary folder for the generation of the med file
+  fs::path tmp_folder = fs::temp_directory_path() / fs::unique_path(fs::path("dual_mesh-%%%%"));
+  fs::create_directories(tmp_folder);
+  fs::path dual_mesh_file = tmp_folder / fs::path("tmp_dual_mesh.med");
+  std::string mesh_name(meshName);
+  MESSAGE("Working in folder" + tmp_folder.string());
+
+  // Running Python script
+  assert(Py_IsInitialized());
+  PyGILState_STATE gstate;
+  gstate = PyGILState_Ensure();
+
+
+  std::string ats;
+  if(adapt_to_shape)
+    ats = "True";
+  else
+    ats = "False";
+
+  std::string cmd="import salome.smesh.smesh_tools as smt\n";
+  cmd +="smt.smesh_create_dual_mesh(\"" + mesh_ior + "\", r\"" +
+        dual_mesh_file.string() + "\", mesh_name=\"" + mesh_name + "\", adapt_to_shape=" + ats + ")";
+  MESSAGE(cmd);
+
+  PyObject *py_main = PyImport_AddModule("__main__");
+  PyObject *py_dict = PyModule_GetDict(py_main);
+  PyObject *local_dict = PyDict_New();
+
+  PyRun_String(cmd.c_str(), Py_file_input, py_dict, local_dict);
+
+  if (PyErr_Occurred()) {
+    // Restrieving python error
+    MESSAGE("Catching error");
+    PyObject *errtype, *errvalue, *traceback;
+    PyErr_Fetch(&errtype, &errvalue, &traceback);
+    if(errvalue != NULL) {
+      MESSAGE("Error has a value");
+      PyObject *s = PyObject_Str(errvalue);
+      Py_ssize_t size;
+      std::string msg = PyUnicode_AsUTF8AndSize(s, &size);
+      msg = "Issue with the execution of create_dual_mesh:\n"+msg;
+      MESSAGE("throwing exception");
+      // We need to deactivate the GIL before throwing the exception
+      PyGILState_Release(gstate);
+      THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::INTERNAL_ERROR );
+      Py_DECREF(s);
+    }
+    Py_XDECREF(errvalue);
+    Py_XDECREF(errtype);
+    Py_XDECREF(traceback);
+  }
+
+  PyGILState_Release(gstate);
+
+  MESSAGE("Mesh created in " + dual_mesh_file.string());
+
+  // Import created MED
+  SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
+  SMESH_Mesh_i*       newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( newMesh );
+  if ( !newMesh_i )
+    THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR );
+  SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh );
+  if ( !meshSO->_is_nil() )
+  {
+    SetName( meshSO, meshName, meshName );
+    SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED");
+  }
+  int ret = newMesh_i->ImportMEDFile(dual_mesh_file.string().c_str(), meshName);
+  if(ret)
+    THROW_SALOME_CORBA_EXCEPTION( "Issue when importing mesh", SALOME::INTERNAL_ERROR );
+
+  /*
+  SMESH_Mesh& newMesh2 = newMesh_i->GetImpl();
+
+
+  MESSAGE("Loading file: " << dual_mesh_file.string() << " with mesh " << meshName);
+  int ret = newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName);
+    */
+
+  newMesh_i->GetImpl().GetMeshDS()->Modified();
+
+  *pyDump << newMesh << " = " << this
+          << ".CreateDualMesh("
+          << mesh << ", "
+          << "'" << mesh_name << "', "
+          << ats << ") ";
+
+  pyDumpDeleter.reset(); // allow dump in GetGroups()
+
+  if ( srcMesh_i->GetImpl().GetGroupIds().size() > 0 ) // dump created groups
+    MESSAGE("Dump of groups");
+    SMESH::ListOfGroups_var groups = newMesh->GetGroups();
+
+#ifndef _DEBUG_
+  fs::remove_all(tmp_folder);
+#endif
+
+  return newMesh._retn();
+}
+
 //================================================================================
 /*!
  * \brief Create a mesh by copying a part of another mesh
@@ -5147,7 +5423,7 @@ SALOMEDS::TMPFile* SMESH_Gen_i::Save( SALOMEDS::SComponent_ptr theComponent,
 SALOMEDS::TMPFile* SMESH_Gen_i::SaveASCII( SALOMEDS::SComponent_ptr theComponent,
                                            const char*              theURL,
                                            bool                     isMultiFile ) {
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::SaveASCII" );
+  MESSAGE( "SMESH_Gen_i::SaveASCII" );
   SALOMEDS::TMPFile_var aStreamFile = Save( theComponent, theURL, isMultiFile );
   return aStreamFile._retn();
 
@@ -5287,7 +5563,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               size = aDataset->GetSize();
               char* libname_str = new char[ size ];
               aDataset->ReadFromDisk( libname_str );
-              if(MYDEBUG) SCRUTE( libname_str );
+              SCRUTE( libname_str );
               libname = string( libname_str );
               delete [] libname_str;
               aDataset->CloseOnDisk();
@@ -5309,7 +5585,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
 
           // --> restore hypothesis from data
           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
-            if(MYDEBUG) MESSAGE("VSR - load hypothesis : id = " << id <<
+            MESSAGE("VSR - load hypothesis : id = " << id <<
                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
             SMESH::SMESH_Hypothesis_var myHyp;
 
@@ -5329,7 +5605,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               myStudyContext->mapOldToNew( id, newId );
             }
             else
-              if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
+              MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
           }
         }
       }
@@ -5386,7 +5662,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               size = aDataset->GetSize();
               char* libname_str = new char[ size ];
               aDataset->ReadFromDisk( libname_str );
-              if(MYDEBUG) SCRUTE( libname_str );
+              SCRUTE( libname_str );
               libname = string( libname_str );
               delete [] libname_str;
               aDataset->CloseOnDisk();
@@ -5398,7 +5674,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               size = aDataset->GetSize();
               char* hypdata_str = new char[ size ];
               aDataset->ReadFromDisk( hypdata_str );
-              if(MYDEBUG) SCRUTE( hypdata_str );
+              SCRUTE( hypdata_str );
               hypdata = string( hypdata_str );
               delete [] hypdata_str;
               aDataset->CloseOnDisk();
@@ -5409,7 +5685,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
 
           // --> restore algorithm from data
           if ( id > 0 && !hypname.empty()/* && !hypdata.empty()*/ ) { // VSR : persistent data can be empty
-            if(MYDEBUG) MESSAGE("VSR - load algo : id = " << id <<
+            MESSAGE("VSR - load algo : id = " << id <<
                                 ", name = " << hypname.c_str() << ", persistent string = " << hypdata.c_str());
             SMESH::SMESH_Hypothesis_var myHyp;
 
@@ -5433,7 +5709,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
               myStudyContext->mapOldToNew( id, newId );
             }
             else
-              if(MYDEBUG) MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
+              MESSAGE( "VSR - SMESH_Gen::Load - can't get servant" );
           }
         }
       }
@@ -5462,7 +5738,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         int aNbObjects = aTopGroup->nInternalObjects();
         if ( aNbObjects > 0 ) {
           // create mesh
-          if(MYDEBUG) MESSAGE( "VSR - load mesh : id = " << id );
+          MESSAGE( "VSR - load mesh : id = " << id );
           SMESH::SMESH_Mesh_var myNewMesh = this->createMesh();
           SMESH_Mesh_i* myNewMeshImpl = dynamic_cast<SMESH_Mesh_i*>( GetServant( myNewMesh ).in() );
           if ( !myNewMeshImpl )
@@ -5598,7 +5874,7 @@ bool SMESH_Gen_i::Load( SALOMEDS::SComponent_ptr theComponent,
         aGroup->OpenOnDisk();
         // get number of applied algorithms
         int aNbSubObjects = aGroup->nInternalObjects();
-        if(MYDEBUG) MESSAGE( "VSR - number of applied algos " << aNbSubObjects );
+        MESSAGE( "VSR - number of applied algos " << aNbSubObjects );
         for ( int j = 0; j < aNbSubObjects; j++ ) {
           char name_dataset[ HDF_NAME_MAX_LEN+1 ];
           aGroup->InternalObjectIndentify( j, name_dataset );
@@ -6101,7 +6377,7 @@ bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
                              const SALOMEDS::TMPFile& theStream,
                              const char*              theURL,
                              bool                     isMultiFile ) {
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LoadASCII" );
+  MESSAGE( "SMESH_Gen_i::LoadASCII" );
   return Load( theComponent, theStream, theURL, isMultiFile );
 
   //before call main ::Load method it's need for decipher text format to
@@ -6138,7 +6414,7 @@ bool SMESH_Gen_i::LoadASCII( SALOMEDS::SComponent_ptr theComponent,
 
 void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
 {
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Close" );
+  MESSAGE( "SMESH_Gen_i::Close" );
 
   // Clear study contexts data
   myStudyContext->Clear();
@@ -6162,7 +6438,7 @@ void SMESH_Gen_i::Close( SALOMEDS::SComponent_ptr theComponent )
 
 char* SMESH_Gen_i::ComponentDataType()
 {
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::ComponentDataType" );
+  MESSAGE( "SMESH_Gen_i::ComponentDataType" );
   return CORBA::string_dup( "SMESH" );
 }
 
@@ -6180,12 +6456,12 @@ char* SMESH_Gen_i::IORToLocalPersistentID( SALOMEDS::SObject_ptr /*theSObject*/,
                                            CORBA::Boolean        /*isMultiFile*/,
                                            CORBA::Boolean        /*isASCII*/ )
 {
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
+  MESSAGE( "SMESH_Gen_i::IORToLocalPersistentID" );
 
   if ( myStudyContext && strcmp( IORString, "" ) != 0 ) {
     int anId = myStudyContext->findId( IORString );
     if ( anId ) {
-      if(MYDEBUG) MESSAGE( "VSR " << anId )
+      MESSAGE( "VSR " << anId );
       char strId[ 20 ];
       sprintf( strId, "%d", anId );
       return  CORBA::string_dup( strId );
@@ -6207,7 +6483,7 @@ char* SMESH_Gen_i::LocalPersistentIDToIOR( SALOMEDS::SObject_ptr /*theSObject*/,
                                            CORBA::Boolean        /*isMultiFile*/,
                                            CORBA::Boolean        /*isASCII*/ )
 {
-  if(MYDEBUG) MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
+  MESSAGE( "SMESH_Gen_i::LocalPersistentIDToIOR(): id = " << aLocalPersistentID );
 
   if ( myStudyContext && strcmp( aLocalPersistentID, "" ) != 0 ) {
     int anId = atoi( aLocalPersistentID );
@@ -6242,7 +6518,7 @@ CORBA::Long  SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject)
 {
   if ( myStudyContext && !CORBA::is_nil( theObject )) {
     CORBA::String_var iorString = GetORB()->object_to_string( theObject );
-    string iorStringCpp(iorString.in()); 
+    string iorStringCpp(iorString.in());
     return myStudyContext->findId( iorStringCpp );
   }
   return 0;
@@ -6317,46 +6593,6 @@ void SMESH_Gen_i::Move( const SMESH::sobject_list& what,
       useCaseBuilder->AppendTo( where, sobj );        // append to the end of list
   }
 }
-//================================================================================
-/*!
- * \brief Returns true if algorithm can be used to mesh a given geometry
- *  \param [in] theAlgoType - the algorithm type
- *  \param [in] theLibName - a name of the Plug-in library implementing the algorithm
- *  \param [in] theGeomObject - the geometry to mesh
- *  \param [in] toCheckAll - if \c True, returns \c True if all shapes are meshable,
- *         else, returns \c True if at least one shape is meshable
- *  \return CORBA::Boolean - can or can't
- */
-//================================================================================
-
-CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
-                                           const char*           theLibName,
-                                           GEOM::GEOM_Object_ptr theGeomObject,
-                                           CORBA::Boolean        toCheckAll)
-{
-  SMESH_TRY;
-
-  std::string aPlatformLibName;
-  GenericHypothesisCreator_i* aCreator =
-    getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
-  if (aCreator)
-  {
-    TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
-    const SMESH_Algo::Features& feat = SMESH_Algo::GetFeatures( theAlgoType );
-    return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll, feat._dim );
-  }
-  else
-  {
-    return false;
-  }
-
-  SMESH_CATCH( SMESH::doNothing );
-
-#ifdef _DEBUG_
-  cout << "SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : "") << endl;
-#endif
-  return true;
-}
 
 //================================================================================
 /*!
@@ -6572,3 +6808,45 @@ std::vector<long> SMESH_Gen_i::_GetInside( SMESH::SMESH_IDSource_ptr meshPart,
   }
   return res;
 }
+
+//================================================================================
+/*!
+ * \brief Returns true if algorithm can be used to mesh a given geometry
+ *  \param [in] theAlgoType - the algorithm type
+ *  \param [in] theLibName - a name of the Plug-in library implementing the algorithm
+ *  \param [in] theGeomObject - the geometry to mesh
+ *  \param [in] toCheckAll - if \c True, returns \c True if all shapes are meshable,
+ *         else, returns \c True if at least one shape is meshable
+ *  \return CORBA::Boolean - can or can't
+ */
+//================================================================================
+
+#undef SMY_OWN_CATCH
+#define SMY_OWN_CATCH // prevent re-throwing SALOME::SALOME_Exception in IsApplicable()
+
+CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
+                                           const char*           theLibName,
+                                           GEOM::GEOM_Object_ptr theGeomObject,
+                                           CORBA::Boolean        toCheckAll)
+{
+  SMESH_TRY;
+
+  std::string aPlatformLibName;
+  GenericHypothesisCreator_i* aCreator =
+    getHypothesisCreator(theAlgoType, theLibName, aPlatformLibName);
+  if (aCreator)
+  {
+    TopoDS_Shape shape = GeomObjectToShape( theGeomObject );
+    const SMESH_Algo::Features& feat = SMESH_Algo::GetFeatures( theAlgoType );
+    return shape.IsNull() || aCreator->IsApplicable( shape, toCheckAll, feat._dim );
+  }
+  else
+  {
+    return false;
+  }
+
+  SMESH_CATCH( SMESH::doNothing );
+
+  MESSAGE("SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : ""));
+  return true;
+}