Salome HOME
[bos #40653][CEA] New mesh import export formats with meshio.
[modules/smesh.git] / src / SMESH_I / SMESH_Gen_i.cxx
index f6abcbdceb5767cac2dcc9937152b2f81a7deaf3..1c78a25268a822ff4b26e282c0f1e8ffd35028e0 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2022  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 "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; }
@@ -161,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;
@@ -455,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;
@@ -465,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);
@@ -491,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)
@@ -502,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)
       {
@@ -553,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();
 }
@@ -570,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) {
@@ -593,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
@@ -641,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
@@ -1200,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
@@ -1223,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
@@ -1234,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();
 
@@ -1274,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;
+  }
 }
 
 //=============================================================================
@@ -1573,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();
+}
 
 //=============================================================================
 /*!
@@ -1586,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",
@@ -1660,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 );
@@ -1734,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 );
@@ -1855,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 );
@@ -1916,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;
@@ -1943,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());
@@ -1963,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++;
     }
   }
@@ -1990,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",
@@ -2002,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
@@ -2085,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",
@@ -2271,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 );
@@ -2833,7 +3030,6 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh
   if ( CORBA::is_nil( mesh ))
     THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
 
-  std::cout << mesh << std::endl;
   SMESH::SMESH_Mesh_var srcMesh = mesh->GetMesh();
   SMESH_Mesh_i*       srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
   if ( !srcMesh_i )
@@ -2846,7 +3042,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh
   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;
+  std::string mesh_name(meshName);
   MESSAGE("Working in folder" + tmp_folder.string());
 
   // Running Python script
@@ -2854,21 +3050,48 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh
   PyGILState_STATE gstate;
   gstate = PyGILState_Ensure();
 
-  std::string cmd="import salome.smesh.smesh_tools as smt";
-  PyRun_SimpleString(cmd.c_str());
+
   std::string ats;
   if(adapt_to_shape)
     ats = "True";
   else
     ats = "False";
 
-  cmd = "smt.smesh_create_dual_mesh(\"" + mesh_ior + "\", \"" +
+  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);
-  PyRun_SimpleString(cmd.c_str());
+
+  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("Executed python script");
+
   MESSAGE("Mesh created in " + dual_mesh_file.string());
 
   // Import created MED
@@ -2882,24 +3105,36 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh
     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 " << mesh_name);
-  newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName);
-
-  MESSAGE("Imported created MED")
 
-  SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS();
+  MESSAGE("Loading file: " << dual_mesh_file.string() << " with mesh " << meshName);
+  int ret = newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName);
+    */
 
-  newMeshDS->Modified();
+  newMesh_i->GetImpl().GetMeshDS()->Modified();
 
   *pyDump << newMesh << " = " << this
           << ".CreateDualMesh("
           << mesh << ", "
-          << "'" << meshName << "', "
+          << "'" << 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();
 }
 
@@ -5188,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();
 
@@ -5328,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();
@@ -5350,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;
 
@@ -5370,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" );
           }
         }
       }
@@ -5427,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();
@@ -5439,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();
@@ -5450,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;
 
@@ -5474,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" );
           }
         }
       }
@@ -5503,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 )
@@ -5639,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 );
@@ -6142,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
@@ -6179,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();
@@ -6203,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" );
 }
 
@@ -6221,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 );
@@ -6248,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 );
@@ -6612,8 +6847,6 @@ CORBA::Boolean SMESH_Gen_i::IsApplicable ( const char*           theAlgoType,
 
   SMESH_CATCH( SMESH::doNothing );
 
-#ifdef _DEBUG_
-  cout << "SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : "") << endl;
-#endif
+  MESSAGE("SMESH_Gen_i::IsApplicable(): exception in " << ( theAlgoType ? theAlgoType : ""));
   return true;
 }