Salome HOME
23414: EDF 14228 - Viscous Layer crashes SALOME
[plugins/ghs3dplugin.git] / src / GHS3DPlugin / GHS3DPlugin_GHS3D.cxx
index 8a41dd93ff6887d701bcba97205df9c671abf576..a01a90e71e22e9070eda1c089298cd066c094e0a 100644 (file)
 //
 #include "GHS3DPlugin_GHS3D.hxx"
 #include "GHS3DPlugin_Hypothesis.hxx"
+#include "MG_Tetra_API.hxx"
 
 #include <SMDS_FaceOfNodes.hxx>
+#include <SMDS_LinearEdge.hxx>
 #include <SMDS_MeshElement.hxx>
 #include <SMDS_MeshNode.hxx>
 #include <SMDS_VolumeOfNodes.hxx>
 #include <SMESHDS_Group.hxx>
+#include <SMESHDS_Mesh.hxx>
 #include <SMESH_Comment.hxx>
+#include <SMESH_File.hxx>
 #include <SMESH_Group.hxx>
 #include <SMESH_HypoFilter.hxx>
 #include <SMESH_Mesh.hxx>
@@ -56,7 +60,6 @@
 #include <Bnd_Box.hxx>
 #include <GProp_GProps.hxx>
 #include <GeomAPI_ProjectPointOnSurf.hxx>
-#include <OSD_File.hxx>
 #include <Precision.hxx>
 #include <Standard_ErrorHandler.hxx>
 #include <Standard_Failure.hxx>
 #include <Basics_Utils.hxx>
 #include <utilities.h>
 
-#ifdef WIN32
-#include <io.h>
-#else
-#include <sys/sysinfo.h>
-#endif
 #include <algorithm>
 #include <errno.h>
 
-#define castToNode(n) static_cast<const SMDS_MeshNode *>( n );
-
-extern "C"
-{
-#ifndef WIN32
-#include <unistd.h>
-#include <sys/mman.h>
+#ifdef _DEBUG_
+//#define _MY_DEBUG_
 #endif
-#include <sys/stat.h>
-#include <fcntl.h>
-}
+
+#define castToNode(n) static_cast<const SMDS_MeshNode *>( n );
 
 using namespace std;
 
@@ -127,9 +119,9 @@ static const char theDomainGroupNamePrefix[] = "Domain_";
 static void removeFile( const TCollection_AsciiString& fileName )
 {
   try {
-    OSD_File( fileName ).Remove();
+    SMESH_File( fileName.ToCString() ).remove();
   }
-  catch ( Standard_ProgramError ) {
+  catch ( ... ) {
     MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied");
   }
 }
@@ -141,9 +133,8 @@ static void removeFile( const TCollection_AsciiString& fileName )
 //=============================================================================
 
 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
-  : SMESH_3D_Algo(hypId, studyId, gen)
+  : SMESH_3D_Algo(hypId, studyId, gen), _isLibUsed( false )
 {
-  MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
   _name = Name();
   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
   _onlyUnaryInput = false; // Compute() will be called on a compound of solids
@@ -151,36 +142,32 @@ GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
   _nbShape=0;
   _compatibleHypothesis.push_back( GHS3DPlugin_Hypothesis::GetHypType());
   _compatibleHypothesis.push_back( StdMeshers_ViscousLayers::GetHypType() );
-  _requireShape = false; // can work without shape_studyId
+  _requireShape = false; // can work without shape
 
-  smeshGen_i = SMESH_Gen_i::GetSMESHGen();
-  CORBA::Object_var anObject = smeshGen_i->GetNS()->Resolve("/myStudyManager");
+  _smeshGen_i = SMESH_Gen_i::GetSMESHGen();
+  CORBA::Object_var anObject = _smeshGen_i->GetNS()->Resolve("/myStudyManager");
   SALOMEDS::StudyManager_var aStudyMgr = SALOMEDS::StudyManager::_narrow(anObject);
 
-  MESSAGE("studyid = " << _studyId);
+  _study = NULL;
+  _study = aStudyMgr->GetStudyByID(_studyId);
 
-  myStudy = NULL;
-  myStudy = aStudyMgr->GetStudyByID(_studyId);
-  if (myStudy)
-    MESSAGE("myStudy->StudyId() = " << myStudy->StudyId());
-  
-  _compute_canceled = false;
+  _computeCanceled = false;
+  _progressAdvance = 1e-4;
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
 
 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
 {
-  MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
 
@@ -208,8 +195,8 @@ bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh&         aMesh,
   }
   if ( _hyp )
   {
-    _keepFiles = _hyp->GetKeepFiles();
-    _removeLogOnSuccess = _hyp->GetRemoveLogOnSuccess();
+    _keepFiles           = _hyp->GetKeepFiles();
+    _removeLogOnSuccess  = _hyp->GetRemoveLogOnSuccess();
     _logInStandardOutput = _hyp->GetStandardOutputLog();
   }
 
@@ -227,66 +214,26 @@ bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh&         aMesh,
 
 TopoDS_Shape GHS3DPlugin_GHS3D::entryToShape(std::string entry)
 {
-  MESSAGE("GHS3DPlugin_GHS3D::entryToShape "<<entry );
+  if ( _study->_is_nil() )
+    throw SALOME_Exception("MG-Tetra plugin can't work w/o publishing in the study");
   GEOM::GEOM_Object_var aGeomObj;
   TopoDS_Shape S = TopoDS_Shape();
-  SALOMEDS::SObject_var aSObj = myStudy->FindObjectID( entry.c_str() );
+  SALOMEDS::SObject_var aSObj = _study->FindObjectID( entry.c_str() );
   if (!aSObj->_is_nil() ) {
     CORBA::Object_var obj = aSObj->GetObject();
     aGeomObj = GEOM::GEOM_Object::_narrow(obj);
     aSObj->UnRegister();
   }
   if ( !aGeomObj->_is_nil() )
-    S = smeshGen_i->GeomObjectToShape( aGeomObj.in() );
+    S = _smeshGen_i->GeomObjectToShape( aGeomObj.in() );
   return S;
 }
 
-//=======================================================================
-//function : findShape
-//purpose  : 
-//=======================================================================
-
-// static TopoDS_Shape findShape(const SMDS_MeshNode *aNode[],
-//                               TopoDS_Shape        aShape,
-//                               const TopoDS_Shape  shape[],
-//                               double**            box,
-//                               const int           nShape,
-//                               TopAbs_State *      state = 0)
-// {
-//   gp_XYZ aPnt(0,0,0);
-//   int j, iShape, nbNode = 4;
-
-//   for ( j=0; j<nbNode; j++ ) {
-//     gp_XYZ p ( aNode[j]->X(), aNode[j]->Y(), aNode[j]->Z() );
-//     if ( aNode[j]->GetPosition()->GetTypeOfPosition() == SMDS_TOP_3DSPACE ) {
-//       aPnt = p;
-//       break;
-//     }
-//     aPnt += p / nbNode;
-//   }
-
-//   BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion());
-//   if (state) *state = SC.State();
-//   if ( SC.State() != TopAbs_IN || aShape.IsNull() || aShape.ShapeType() != TopAbs_SOLID) {
-//     for (iShape = 0; iShape < nShape; iShape++) {
-//       aShape = shape[iShape];
-//       if ( !( aPnt.X() < box[iShape][0] || box[iShape][1] < aPnt.X() ||
-//               aPnt.Y() < box[iShape][2] || box[iShape][3] < aPnt.Y() ||
-//               aPnt.Z() < box[iShape][4] || box[iShape][5] < aPnt.Z()) ) {
-//         BRepClass3d_SolidClassifier SC (aShape, aPnt, Precision::Confusion());
-//         if (state) *state = SC.State();
-//         if (SC.State() == TopAbs_IN)
-//           break;
-//       }
-//     }
-//   }
-//   return aShape;
-// }
-
 //================================================================================
 /*!
- * \brief returns id of a solid if a triangle defined by the nodes is a temporary face on a
- * side facet of pyramid and defines sub-domian outside the pyramid; else returns HOLE_ID
+ * \brief returns id of a solid if a triangle defined by the nodes is a temporary face
+ * either on a side facet of pyramid or a top of pentahedron and defines sub-domian
+ * outside the volume; else returns HOLE_ID
  */
 //================================================================================
 
@@ -298,26 +245,34 @@ static int checkTmpFace(const SMDS_MeshNode* node1,
   SMDS_ElemIteratorPtr vIt1 = node1->GetInverseElementIterator(SMDSAbs_Volume);
   while ( vIt1->more() )
   {
-    const SMDS_MeshElement* pyram = vIt1->next();
-    if ( pyram->NbCornerNodes() != 5 ) continue;
+    const SMDS_MeshElement* vol = vIt1->next();
+    const int           nbNodes = vol->NbCornerNodes();
+    if ( nbNodes != 5 && nbNodes != 6 ) continue;
     int i2, i3;
-    if ( (i2 = pyram->GetNodeIndex( node2 )) >= 0 &&
-         (i3 = pyram->GetNodeIndex( node3 )) >= 0 )
+    if ( (i2 = vol->GetNodeIndex( node2 )) >= 0 &&
+         (i3 = vol->GetNodeIndex( node3 )) >= 0 )
     {
-      // Triangle defines sub-domian inside the pyramid if it's
-      // normal points out of the pyram
-
-      // make i2 and i3 hold indices of base nodes of the pyram while
-      // keeping the nodes order in the triangle
-      const int iApex = 4;
-      if ( i2 == iApex )
-        i2 = i3, i3 = pyram->GetNodeIndex( node1 );
-      else if ( i3 == iApex )
-        i3 = i2, i2 = pyram->GetNodeIndex( node1 );
-
-      int i3base = (i2+1) % 4; // next index after i2 within the pyramid base
-      bool isDomainInPyramid = ( i3base != i3 );
-      return isDomainInPyramid ? HOLE_ID : pyram->getshapeId();
+      if ( nbNodes == 5 )
+      {
+        // Triangle defines sub-domian inside the pyramid if it's
+        // normal points out of the vol
+
+        // make i2 and i3 hold indices of base nodes of the vol while
+        // keeping the nodes order in the triangle
+        const int iApex = 4;
+        if ( i2 == iApex )
+          i2 = i3, i3 = vol->GetNodeIndex( node1 );
+        else if ( i3 == iApex )
+          i3 = i2, i2 = vol->GetNodeIndex( node1 );
+
+        int i3base = (i2+1) % 4; // next index after i2 within the pyramid base
+        bool isDomainInPyramid = ( i3base != i3 );
+        return isDomainInPyramid ? HOLE_ID : vol->getshapeId();
+      }
+      else
+      {
+        return vol->getshapeId(); // triangle is a prism top
+      }
     }
   }
   return HOLE_ID;
@@ -349,7 +304,7 @@ static int findShapeID(SMESH_Mesh&          mesh,
   const SMDS_MeshElement * face = meshDS->FindElement( nodes, SMDSAbs_Face, /*noMedium=*/true);
   if ( !face )
     return checkTmpFace(node1, node2, node3);
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
   std::cout << "bnd face " << face->GetID() << " - ";
 #endif
   // geom face the face assigned to
@@ -500,7 +455,6 @@ static void addElemInMeshGroup(SMESH_Mesh*             theMesh,
       SMESHDS_Group* aGroupDS = static_cast<SMESHDS_Group*>( groupDS );
       aGroupDS->SMDSGroup().Add(anElem);
       groupDone = true;
-//       MESSAGE("Successfully added enforced element to existing group " << groupName);
       break;
     }
   }
@@ -512,7 +466,6 @@ static void addElemInMeshGroup(SMESH_Mesh*             theMesh,
     aGroup->SetName( groupName.c_str() );
     SMESHDS_Group* aGroupDS = static_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
     aGroupDS->SMDSGroup().Add(anElem);
-//     MESSAGE("Successfully created enforced vertex group " << groupName);
     groupDone = true;
   }
   if (!groupDone)
@@ -536,7 +489,6 @@ static void updateMeshGroups(SMESH_Mesh* theMesh, std::set<std::string> groupsTo
     std::string currentGroupName = (string)group->GetName();
     if (groupDS->IsEmpty() && groupsToRemove.find(currentGroupName) != groupsToRemove.end()) {
       // Previous group created by enforced elements
-      MESSAGE("Delete previous group created by removed enforced elements: " << group->GetName())
       theMesh->RemoveGroup(groupDS->GetID());
     }
   }
@@ -628,7 +580,8 @@ static void makeDomainGroups( std::vector< std::vector< const SMDS_MeshElement*
 //purpose  : read GMF file w/o geometry associated to mesh
 //=======================================================================
 
-static bool readGMFFile(const char*                     theFile,
+static bool readGMFFile(MG_Tetra_API*                   MGOutput,
+                        const char*                     theFile,
                         GHS3DPlugin_GHS3D*              theAlgo,
                         SMESH_MesherHelper*             theHelper,
                         std::vector <const SMDS_MeshNode*> &    theNodeByGhs3dId,
@@ -646,16 +599,14 @@ static bool readGMFFile(const char*                     theFile,
   const bool hasGeom = ( theHelper->GetMesh()->HasShapeToMesh() );
 
   int nbInitialNodes = theNodeByGhs3dId.size();
-  int nbMeshNodes = theMeshDS->NbNodes();
   
+#ifdef _MY_DEBUG_
   const bool isQuadMesh = 
     theHelper->GetMesh()->NbEdges( ORDER_QUADRATIC ) ||
     theHelper->GetMesh()->NbFaces( ORDER_QUADRATIC ) ||
     theHelper->GetMesh()->NbVolumes( ORDER_QUADRATIC );
-    
-#ifdef _DEBUG_
   std::cout << "theNodeByGhs3dId.size(): " << nbInitialNodes << std::endl;
-  std::cout << "theHelper->GetMesh()->NbNodes(): " << nbMeshNodes << std::endl;
+  std::cout << "theHelper->GetMesh()->NbNodes(): " << theMeshDS->NbNodes() << std::endl;
   std::cout << "isQuadMesh: " << isQuadMesh << std::endl;
 #endif
   
@@ -665,8 +616,8 @@ static bool readGMFFile(const char*                     theFile,
 
   int nbElem = 0, nbRef = 0;
   int aGMFNodeID = 0;
-  const SMDS_MeshNode** GMFNode;
-#ifdef _DEBUG_
+  std::vector< const SMDS_MeshNode*> GMFNode;
+#ifdef _MY_DEBUG_
   std::map<int, std::set<int> > subdomainId2tetraId;
 #endif
   std::map <GmfKwdCod,int> tabRef;
@@ -683,11 +634,9 @@ static bool readGMFFile(const char*                     theFile,
   tabRef[GmfHexahedra]      = 8;
 
   int ver, dim;
-  MESSAGE("Read " << theFile << " file");
-  int InpMsh = GmfOpenMesh(theFile, GmfRead, &ver, &dim);
+  int InpMsh = MGOutput->GmfOpenMesh( theFile, GmfRead, &ver, &dim);
   if (!InpMsh)
     return false;
-  MESSAGE("Done ");
 
   // Read ids of domains
   vector< int > solidIDByDomain;
@@ -700,17 +649,17 @@ static bool readGMFFile(const char*                     theFile,
       solid1 = theMeshDS->ShapeToIndex
         ( TopExp_Explorer( theHelper->GetSubShape(), TopAbs_SOLID ).Current() );
 
-    int nbDomains = GmfStatKwd( InpMsh, GmfSubDomainFromGeom );
+    int nbDomains = MGOutput->GmfStatKwd( InpMsh, GmfSubDomainFromGeom );
     if ( nbDomains > 1 )
     {
       solidIDByDomain.resize( nbDomains+1, theHelper->GetSubShapeID() );
       int faceNbNodes, faceIndex, orientation, domainNb;
-      GmfGotoKwd( InpMsh, GmfSubDomainFromGeom );
+      MGOutput->GmfGotoKwd( InpMsh, GmfSubDomainFromGeom );
       for ( int i = 0; i < nbDomains; ++i )
       {
         faceIndex = 0;
-        GmfGetLin( InpMsh, GmfSubDomainFromGeom,
-                   &faceNbNodes, &faceIndex, &orientation, &domainNb);
+        MGOutput->GmfGetLin( InpMsh, GmfSubDomainFromGeom,
+                   &faceNbNodes, &faceIndex, &orientation, &domainNb, i);
         solidIDByDomain[ domainNb ] = 1;
         if ( 0 < faceIndex && faceIndex-1 < (int)theFaceByGhs3dId.size() )
         {
@@ -724,7 +673,7 @@ static bool readGMFFile(const char*                     theFile,
             findShapeID( *theHelper->GetMesh(), nn[0], nn[1], nn[2], toMeshHoles );
           if ( solidIDByDomain[ domainNb ] > 0 )
           {
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
             std::cout << "solid " << solidIDByDomain[ domainNb ] << std::endl;
 #endif
             const TopoDS_Shape& foundShape = theMeshDS->IndexToShape( solidIDByDomain[ domainNb ] );
@@ -749,24 +698,24 @@ static bool readGMFFile(const char*                     theFile,
   // IMP 0022172: [CEA 790] create the groups corresponding to domains
   std::vector< std::vector< const SMDS_MeshElement* > > elemsOfDomain;
 
-  int nbVertices = GmfStatKwd(InpMsh, GmfVertices) - nbInitialNodes;
-  GMFNode = new const SMDS_MeshNode*[ nbVertices + 1 ];
+  int nbVertices = MGOutput->GmfStatKwd( InpMsh, GmfVertices ) - nbInitialNodes;
+  if ( nbVertices < 0 )
+    return false;
+  GMFNode.resize( nbVertices + 1 );
 
   std::map <GmfKwdCod,int>::const_iterator it = tabRef.begin();
   for ( ; it != tabRef.end() ; ++it)
   {
     if(theAlgo->computeCanceled()) {
-      GmfCloseMesh(InpMsh);
-      delete [] GMFNode;
       return false;
     }
     int dummy, solidID;
     GmfKwdCod token = it->first;
     nbRef           = it->second;
 
-    nbElem = GmfStatKwd(InpMsh, token);
+    nbElem = MGOutput->GmfStatKwd( InpMsh, token);
     if (nbElem > 0) {
-      GmfGotoKwd(InpMsh, token);
+      MGOutput->GmfGotoKwd( InpMsh, token);
       std::cout << "Read " << nbElem;
     }
     else
@@ -800,18 +749,16 @@ static bool readGMFFile(const char*                     theFile,
 
       for ( int iElem = 0; iElem < nbElem; iElem++ ) {
         if(theAlgo->computeCanceled()) {
-          GmfCloseMesh(InpMsh);
-          delete [] GMFNode;
           return false;
         }
         if (ver == GmfFloat) {
-          GmfGetLin(InpMsh, token, &VerTab_f[0], &VerTab_f[1], &VerTab_f[2], &dummy);
+          MGOutput->GmfGetLin( InpMsh, token, &VerTab_f[0], &VerTab_f[1], &VerTab_f[2], &dummy);
           x = VerTab_f[0];
           y = VerTab_f[1];
           z = VerTab_f[2];
         }
         else {
-          GmfGetLin(InpMsh, token, &x, &y, &z, &dummy);
+          MGOutput->GmfGetLin( InpMsh, token, &x, &y, &z, &dummy);
         }
         if (iElem >= nbInitialNodes) {
           if ( elemSearcher &&
@@ -830,42 +777,41 @@ static bool readGMFFile(const char*                     theFile,
     else if (token == GmfCorners && nbElem > 0) {
       (nbElem <= 1) ? tmpStr = " corner" : tmpStr = " corners";
       for ( int iElem = 0; iElem < nbElem; iElem++ )
-        GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]);
+        MGOutput->GmfGetLin( InpMsh, token, &id[iElem*tabRef[token]]);
     }
     else if (token == GmfRidges && nbElem > 0) {
       (nbElem <= 1) ? tmpStr = " ridge" : tmpStr = " ridges";
       for ( int iElem = 0; iElem < nbElem; iElem++ )
-        GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]]);
+        MGOutput->GmfGetLin( InpMsh, token, &id[iElem*tabRef[token]]);
     }
     else if (token == GmfEdges && nbElem > 0) {
       (nbElem <= 1) ? tmpStr = " edge" : tmpStr = " edges";
       for ( int iElem = 0; iElem < nbElem; iElem++ )
-        GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &domainID[iElem]);
+        MGOutput->GmfGetLin( InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &domainID[iElem]);
     }
     else if (token == GmfTriangles && nbElem > 0) {
       (nbElem <= 1) ? tmpStr = " triangle" : tmpStr = " triangles";
       for ( int iElem = 0; iElem < nbElem; iElem++ )
-        GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &domainID[iElem]);
+        MGOutput->GmfGetLin( InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &domainID[iElem]);
     }
     else if (token == GmfQuadrilaterals && nbElem > 0) {
       (nbElem <= 1) ? tmpStr = " Quadrilateral" : tmpStr = " Quadrilaterals";
       for ( int iElem = 0; iElem < nbElem; iElem++ )
-        GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &domainID[iElem]);
+        MGOutput->GmfGetLin( InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &domainID[iElem]);
     }
     else if (token == GmfTetrahedra && nbElem > 0) {
       (nbElem <= 1) ? tmpStr = " Tetrahedron" : tmpStr = " Tetrahedra";
       for ( int iElem = 0; iElem < nbElem; iElem++ ) {
-        GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &domainID[iElem]);
-#ifdef _DEBUG_
+        MGOutput->GmfGetLin( InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3], &domainID[iElem]);
+#ifdef _MY_DEBUG_
         subdomainId2tetraId[dummy].insert(iElem+1);
-//         MESSAGE("subdomainId2tetraId["<<dummy<<"].insert("<<iElem+1<<")");
 #endif
       }
     }
     else if (token == GmfHexahedra && nbElem > 0) {
       (nbElem <= 1) ? tmpStr = " Hexahedron" : tmpStr = " Hexahedra";
       for ( int iElem = 0; iElem < nbElem; iElem++ )
-        GmfGetLin(InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3],
+        MGOutput->GmfGetLin( InpMsh, token, &id[iElem*tabRef[token]], &id[iElem*tabRef[token]+1], &id[iElem*tabRef[token]+2], &id[iElem*tabRef[token]+3],
                   &id[iElem*tabRef[token]+4], &id[iElem*tabRef[token]+5], &id[iElem*tabRef[token]+6], &id[iElem*tabRef[token]+7], &domainID[iElem]);
     }
     std::cout << tmpStr << std::endl;
@@ -888,8 +834,6 @@ static bool readGMFFile(const char*                     theFile,
       for ( int iElem = 0; iElem < nbElem; iElem++ )
       {
         if(theAlgo->computeCanceled()) {
-          GmfCloseMesh(InpMsh);
-          delete [] GMFNode;
           return false;
         }
         // Check if elem is already in input mesh. If yes => skip
@@ -1026,15 +970,13 @@ static bool readGMFFile(const char*                     theFile,
         theMeshDS->RemoveFreeNode( GMFNode[i], /*sm=*/0, /*fromGroups=*/false );
   }
 
-  GmfCloseMesh(InpMsh);
-  delete [] GMFNode;
+  MGOutput->GmfCloseMesh( InpMsh);
 
   // 0022172: [CEA 790] create the groups corresponding to domains
   if ( toMakeGroupsOfDomains )
     makeDomainGroups( elemsOfDomain, theHelper );
 
-#ifdef _DEBUG_
-  MESSAGE("Nb subdomains " << subdomainId2tetraId.size());
+#ifdef _MY_DEBUG_
   std::map<int, std::set<int> >::const_iterator subdomainIt = subdomainId2tetraId.begin();
   TCollection_AsciiString aSubdomainFileName = theFile;
   aSubdomainFileName = aSubdomainFileName + ".subdomain";
@@ -1044,7 +986,6 @@ static bool readGMFFile(const char*                     theFile,
   for(;subdomainIt != subdomainId2tetraId.end() ; ++subdomainIt) {
     int subdomainId = subdomainIt->first;
     std::set<int> tetraIds = subdomainIt->second;
-    MESSAGE("Subdomain #"<<subdomainId<<": "<<tetraIds.size()<<" tetrahedrons");
     std::set<int>::const_iterator tetraIdsIt = tetraIds.begin();
     aSubdomainFile << subdomainId << std::endl;
     for(;tetraIdsIt != tetraIds.end() ; ++tetraIdsIt) {
@@ -1059,7 +1000,8 @@ static bool readGMFFile(const char*                     theFile,
 }
 
 
-static bool writeGMFFile(const char*                                     theMeshFileName,
+static bool writeGMFFile(MG_Tetra_API*                                   MGInput,
+                         const char*                                     theMeshFileName,
                          const char*                                     theRequiredFileName,
                          const char*                                     theSolFileName,
                          const SMESH_ProxyMesh&                          theProxyMesh,
@@ -1077,7 +1019,6 @@ static bool writeGMFFile(const char*                                     theMesh
                          GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices,
                          int &                                           theInvalidEnforcedFlags)
 {
-  MESSAGE("writeGMFFile w/o geometry");
   std::string tmpStr;
   int idx, idxRequired = 0, idxSol = 0;
   const int dummyint = 0;
@@ -1114,7 +1055,7 @@ static bool writeGMFFile(const char*                                     theMesh
   if ( nbFaces == 0 )
     return false;
   
-  idx = GmfOpenMesh(theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
+  idx = MGInput->GmfOpenMesh( theMeshFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
   if (!idx)
     return false;
   
@@ -1167,7 +1108,7 @@ static bool writeGMFFile(const char*                                     theMesh
         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
         gp_Pnt myPoint(node->X(),node->Y(),node->Z());
         nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
         std::cout << "Node at "<<node->X()<<", "<<node->Y()<<", "<<node->Z()<<std::endl;
         std::cout << "Nb nodes found : "<<nbFoundElems<<std::endl;
 #endif
@@ -1184,7 +1125,7 @@ static bool writeGMFFile(const char*                                     theMesh
         }
         else
           isOK = false;
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
         std::cout << "MG-Tetra node ID: "<<newId<<std::endl;
 #endif
       }
@@ -1225,7 +1166,7 @@ static bool writeGMFFile(const char*                                     theMesh
         const SMDS_MeshNode* node = castToNode( nodeIt->next() );
         gp_Pnt myPoint(node->X(),node->Y(),node->Z());
         nbFoundElems = pntCls->FindElementsByPoint(myPoint, SMDSAbs_Node, foundElems);
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
         std::cout << "Nb nodes found : "<<nbFoundElems<<std::endl;
 #endif
         if (nbFoundElems ==0) {
@@ -1241,7 +1182,7 @@ static bool writeGMFFile(const char*                                     theMesh
         }
         else
           isOK = false;
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
         std::cout << "MG-Tetra node ID: "<<newId<<std::endl;
 #endif
       }
@@ -1253,7 +1194,7 @@ static bool writeGMFFile(const char*                                     theMesh
   }
   
   // put nodes to theNodeByGhs3dId vector
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
   std::cout << "aNodeToGhs3dIdMap.size(): "<<aNodeToGhs3dIdMap.size()<<std::endl;
 #endif
   theNodeByGhs3dId.resize( aNodeToGhs3dIdMap.size() );
@@ -1265,7 +1206,7 @@ static bool writeGMFFile(const char*                                     theMesh
   }
 
   // put nodes to anEnforcedNodeToGhs3dIdMap vector
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
   std::cout << "anEnforcedNodeToGhs3dIdMap.size(): "<<anEnforcedNodeToGhs3dIdMap.size()<<std::endl;
 #endif
   theEnforcedNodeByGhs3dId.resize( anEnforcedNodeToGhs3dIdMap.size());
@@ -1309,13 +1250,13 @@ static bool writeGMFFile(const char*                                     theMesh
     coords.push_back(node->X());
     coords.push_back(node->Y());
     coords.push_back(node->Z());
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
     std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z();
 #endif
     
     if (nodesCoords.find(coords) != nodesCoords.end()) {
       // node already exists in original mesh
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
       std::cout << " found" << std::endl;
 #endif
       continue;
@@ -1323,7 +1264,7 @@ static bool writeGMFFile(const char*                                     theMesh
     
     if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) {
       // node already exists in enforced vertices
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
       std::cout << " found" << std::endl;
 #endif
       continue;
@@ -1345,7 +1286,7 @@ static bool writeGMFFile(const char*                                     theMesh
 //       theOrderedNodes.push_back(existingNode);
 //     }
     
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
     std::cout << " not found" << std::endl;
 #endif
     
@@ -1366,7 +1307,7 @@ static bool writeGMFFile(const char*                                     theMesh
     coords.push_back(node->X());
     coords.push_back(node->Y());
     coords.push_back(node->Z());
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
     std::cout << "Node at " << node->X()<<", " <<node->Y()<<", " <<node->Z();
 #endif
     
@@ -1374,7 +1315,7 @@ static bool writeGMFFile(const char*                                     theMesh
     gp_Pnt myPoint(node->X(),node->Y(),node->Z());
     TopAbs_State result = pntCls->GetPointState( myPoint );
     if ( result == TopAbs_OUT ) {
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
       std::cout << " out of volume" << std::endl;
 #endif
       theInvalidEnforcedFlags |= FLAG_BAD_ENF_NODE;
@@ -1382,7 +1323,7 @@ static bool writeGMFFile(const char*                                     theMesh
     }
     
     if (nodesCoords.find(coords) != nodesCoords.end()) {
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
       std::cout << " found in nodesCoords" << std::endl;
 #endif
 //       theRequiredNodes.push_back(node);
@@ -1390,7 +1331,7 @@ static bool writeGMFFile(const char*                                     theMesh
     }
 
     if (theEnforcedVertices.find(coords) != theEnforcedVertices.end()) {
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
       std::cout << " found in theEnforcedVertices" << std::endl;
 #endif
       continue;
@@ -1419,7 +1360,7 @@ static bool writeGMFFile(const char*                                     theMesh
 //     if ( result != TopAbs_IN )
 //       continue;
     
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
     std::cout << " not found" << std::endl;
 #endif
     nodesCoords.insert(coords);
@@ -1462,9 +1403,9 @@ static bool writeGMFFile(const char*                                     theMesh
   // GmfVertices
   std::cout << "Begin writting required nodes in GmfVertices" << std::endl;
   std::cout << "Nb vertices: " << theOrderedNodes.size() << std::endl;
-  GmfSetKwd(idx, GmfVertices, theOrderedNodes.size()/*+solSize*/);
+  MGInput->GmfSetKwd( idx, GmfVertices, theOrderedNodes.size()/*+solSize*/);
   for (ghs3dNodeIt = theOrderedNodes.begin();ghs3dNodeIt != theOrderedNodes.end();++ghs3dNodeIt) {
-    GmfSetLin(idx, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
+    MGInput->GmfSetLin( idx, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
   }
 
   std::cout << "End writting required nodes in GmfVertices" << std::endl;
@@ -1472,27 +1413,23 @@ static bool writeGMFFile(const char*                                     theMesh
   if (requiredNodes + solSize) {
     std::cout << "Begin writting in req and sol file" << std::endl;
     aNodeGroupByGhs3dId.resize( requiredNodes + solSize );
-    idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
+    idxRequired = MGInput->GmfOpenMesh( theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
     if (!idxRequired) {
-      GmfCloseMesh(idx);
       return false;
     }
-    idxSol = GmfOpenMesh(theSolFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
+    idxSol = MGInput->GmfOpenMesh( theSolFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
     if (!idxSol) {
-      GmfCloseMesh(idx);
-      if (idxRequired)
-        GmfCloseMesh(idxRequired);
       return false;
     }
     int TypTab[] = {GmfSca};
     double ValTab[] = {0.0};
-    GmfSetKwd(idxRequired, GmfVertices, requiredNodes + solSize);
-    GmfSetKwd(idxSol, GmfSolAtVertices, requiredNodes + solSize, 1, TypTab);
+    MGInput->GmfSetKwd( idxRequired, GmfVertices, requiredNodes + solSize);
+    MGInput->GmfSetKwd( idxSol, GmfSolAtVertices, requiredNodes + solSize, 1, TypTab);
 //     int usedEnforcedNodes = 0;
 //     std::string gn = "";
     for (ghs3dNodeIt = theRequiredNodes.begin();ghs3dNodeIt != theRequiredNodes.end();++ghs3dNodeIt) {
-      GmfSetLin(idxRequired, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
-      GmfSetLin(idxSol, GmfSolAtVertices, ValTab);
+      MGInput->GmfSetLin( idxRequired, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
+      MGInput->GmfSetLin( idxSol, GmfSolAtVertices, ValTab);
       if (theEnforcedNodes.find((*ghs3dNodeIt)) != theEnforcedNodes.end())
         gn = theEnforcedNodes.find((*ghs3dNodeIt))->second;
       aNodeGroupByGhs3dId[usedEnforcedNodes] = gn;
@@ -1501,14 +1438,14 @@ static bool writeGMFFile(const char*                                     theMesh
 
     for (int i=0;i<solSize;i++) {
       std::cout << ReqVerTab[i][0] <<" "<< ReqVerTab[i][1] << " "<< ReqVerTab[i][2] << std::endl;
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
       std::cout << "enfVertexSizes.at("<<i<<"): " << enfVertexSizes.at(i) << std::endl;
 #endif
       double solTab[] = {enfVertexSizes.at(i)};
-      GmfSetLin(idxRequired, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
-      GmfSetLin(idxSol, GmfSolAtVertices, solTab);
+      MGInput->GmfSetLin( idxRequired, GmfVertices, ReqVerTab[i][0], ReqVerTab[i][1], ReqVerTab[i][2], dummyint);
+      MGInput->GmfSetLin( idxSol, GmfSolAtVertices, solTab);
       aNodeGroupByGhs3dId[usedEnforcedNodes] = enfVerticesWithGroup.find(ReqVerTab[i])->second;
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
       std::cout << "aNodeGroupByGhs3dId["<<usedEnforcedNodes<<"] = \""<<aNodeGroupByGhs3dId[usedEnforcedNodes]<<"\""<<std::endl;
 #endif
       usedEnforcedNodes++;
@@ -1522,11 +1459,11 @@ static bool writeGMFFile(const char*                                     theMesh
   int usedEnforcedEdges = 0;
   if (theKeptEnforcedEdges.size()) {
     anEdgeGroupByGhs3dId.resize( theKeptEnforcedEdges.size() );
-//    idxRequired = GmfOpenMesh(theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
+//    idxRequired = MGInput->GmfOpenMesh( theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
 //    if (!idxRequired)
 //      return false;
-    GmfSetKwd(idx, GmfEdges, theKeptEnforcedEdges.size());
-//    GmfSetKwd(idxRequired, GmfEdges, theKeptEnforcedEdges.size());
+    MGInput->GmfSetKwd( idx, GmfEdges, theKeptEnforcedEdges.size());
+//    MGInput->GmfSetKwd( idxRequired, GmfEdges, theKeptEnforcedEdges.size());
     for(elemSetIt = theKeptEnforcedEdges.begin() ; elemSetIt != theKeptEnforcedEdges.end() ; ++elemSetIt) {
       elem = (*elemSetIt);
       nodeIt = elem->nodesIterator();
@@ -1543,19 +1480,18 @@ static bool writeGMFFile(const char*                                     theMesh
         nedge[index] = it->second;
         index++;
       }
-      GmfSetLin(idx, GmfEdges, nedge[0], nedge[1], dummyint);
+      MGInput->GmfSetLin( idx, GmfEdges, nedge[0], nedge[1], dummyint);
       anEdgeGroupByGhs3dId[usedEnforcedEdges] = theEnforcedEdges.find(elem)->second;
-//      GmfSetLin(idxRequired, GmfEdges, nedge[0], nedge[1], dummyint);
+//      MGInput->GmfSetLin( idxRequired, GmfEdges, nedge[0], nedge[1], dummyint);
       usedEnforcedEdges++;
     }
-//    GmfCloseMesh(idxRequired);
   }
 
 
   if (usedEnforcedEdges) {
-    GmfSetKwd(idx, GmfRequiredEdges, usedEnforcedEdges);
+    MGInput->GmfSetKwd( idx, GmfRequiredEdges, usedEnforcedEdges);
     for (int enfID=1;enfID<=usedEnforcedEdges;enfID++) {
-      GmfSetLin(idx, GmfRequiredEdges, enfID);
+      MGInput->GmfSetLin( idx, GmfRequiredEdges, enfID);
     }
   }
 
@@ -1563,7 +1499,7 @@ static bool writeGMFFile(const char*                                     theMesh
   int usedEnforcedTriangles = 0;
   if (anElemSet.size()+theKeptEnforcedTriangles.size()) {
     aFaceGroupByGhs3dId.resize( anElemSet.size()+theKeptEnforcedTriangles.size() );
-    GmfSetKwd(idx, GmfTriangles, anElemSet.size()+theKeptEnforcedTriangles.size());
+    MGInput->GmfSetKwd( idx, GmfTriangles, anElemSet.size()+theKeptEnforcedTriangles.size());
     int k=0;
     for(elemSetIt = anElemSet.begin() ; elemSetIt != anElemSet.end() ; ++elemSetIt,++k) {
       elem = (*elemSetIt);
@@ -1579,7 +1515,7 @@ static bool writeGMFFile(const char*                                     theMesh
         ntri[index] = it->second;
         index++;
       }
-      GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
+      MGInput->GmfSetLin( idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
       aFaceGroupByGhs3dId[k] = "";
     }
     if ( !theHelper.GetMesh()->HasShapeToMesh() )
@@ -1601,7 +1537,7 @@ static bool writeGMFFile(const char*                                     theMesh
           ntri[index] = it->second;
           index++;
         }
-        GmfSetLin(idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
+        MGInput->GmfSetLin( idx, GmfTriangles, ntri[0], ntri[1], ntri[2], dummyint);
         aFaceGroupByGhs3dId[k] = theEnforcedTriangles.find(elem)->second;
         usedEnforcedTriangles++;
       }
@@ -1610,19 +1546,18 @@ static bool writeGMFFile(const char*                                     theMesh
 
   
   if (usedEnforcedTriangles) {
-    GmfSetKwd(idx, GmfRequiredTriangles, usedEnforcedTriangles);
+    MGInput->GmfSetKwd( idx, GmfRequiredTriangles, usedEnforcedTriangles);
     for (int enfID=1;enfID<=usedEnforcedTriangles;enfID++)
-      GmfSetLin(idx, GmfRequiredTriangles, anElemSet.size()+enfID);
+      MGInput->GmfSetLin( idx, GmfRequiredTriangles, anElemSet.size()+enfID);
   }
 
-  GmfCloseMesh(idx);
+  MGInput->GmfCloseMesh(idx);
   if (idxRequired)
-    GmfCloseMesh(idxRequired);
+    MGInput->GmfCloseMesh(idxRequired);
   if (idxSol)
-    GmfCloseMesh(idxSol);
-  
+    MGInput->GmfCloseMesh(idxSol);
+
   return true;
-  
 }
 
 //=============================================================================
@@ -1635,36 +1570,7 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
                                 const TopoDS_Shape& theShape)
 {
   bool Ok(false);
-  //SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
-
-  // we count the number of shapes
-  // _nbShape = countShape( meshDS, TopAbs_SOLID ); -- 0020330: Pb with MG-Tetra as a submesh
-  // _nbShape = 0;
   TopExp_Explorer expBox ( theShape, TopAbs_SOLID );
-  // for ( ; expBox.More(); expBox.Next() )
-  //   _nbShape++;
-
-  // create bounding box for every shape inside the compound
-
-  // int iShape = 0;
-  // TopoDS_Shape* tabShape;
-  // double**      tabBox;
-  // tabShape = new TopoDS_Shape[_nbShape];
-  // tabBox   = new double*[_nbShape];
-  // for (int i=0; i<_nbShape; i++)
-  //   tabBox[i] = new double[6];
-  // Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
-
-  // for (expBox.ReInit(); expBox.More(); expBox.Next()) {
-  //   tabShape[iShape] = expBox.Current();
-  //   Bnd_Box BoundingBox;
-  //   BRepBndLib::Add(expBox.Current(), BoundingBox);
-  //   BoundingBox.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
-  //   tabBox[iShape][0] = Xmin; tabBox[iShape][1] = Xmax;
-  //   tabBox[iShape][2] = Ymin; tabBox[iShape][3] = Ymax;
-  //   tabBox[iShape][4] = Zmin; tabBox[iShape][5] = Zmax;
-  //   iShape++;
-  // }
 
   // a unique working file name
   // to avoid access to the same files by eg different users
@@ -1676,28 +1582,19 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   TCollection_AsciiString aResultFileName;
 
   TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName, aResSolFileName;
-//#ifdef _DEBUG_
   aGMFFileName              = aGenericName + ".mesh"; // GMF mesh file
   aResultFileName           = aGenericName + "Vol.mesh"; // GMF mesh file
   aResSolFileName           = aGenericName + "Vol.sol"; // GMF mesh file
   aRequiredVerticesFileName = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file
   aSolFileName              = aGenericNameRequired + ".sol"; // GMF solution file
-//#else
-//  aGMFFileName    = aGenericName + ".meshb"; // GMF mesh file
-//  aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file
-//  aRequiredVerticesFileName    = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file
-//  aSolFileName    = aGenericNameRequired + ".solb"; // GMF solution file
-//#endif
   
   std::map <int,int> aNodeId2NodeIndexMap, aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap;
-  //std::map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
   std::map <int, int> nodeID2nodeIndexMap;
   std::map<std::vector<double>, std::string> enfVerticesWithGroup;
   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues coordsSizeMap = GHS3DPlugin_Hypothesis::GetEnforcedVerticesCoordsSize(_hyp);
   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp);
-//   TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp);
   GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
 
   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexList enfVertices = GHS3DPlugin_Hypothesis::GetEnforcedVertices(_hyp);
@@ -1707,59 +1604,36 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   for ( ; enfVerIt != enfVertices.end() ; ++enfVerIt)
   {
     GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* enfVertex = (*enfVerIt);
-//     if (enfVertex->geomEntry.empty() && enfVertex->coords.size()) {
     if (enfVertex->coords.size()) {
       coordsSizeMap.insert(make_pair(enfVertex->coords,enfVertex->size));
       enfVerticesWithGroup.insert(make_pair(enfVertex->coords,enfVertex->groupName));
-//       MESSAGE("enfVerticesWithGroup.insert(make_pair(("<<enfVertex->coords[0]<<","<<enfVertex->coords[1]<<","<<enfVertex->coords[2]<<"),\""<<enfVertex->groupName<<"\"))");
     }
     else {
-//     if (!enfVertex->geomEntry.empty()) {
       TopoDS_Shape GeomShape = entryToShape(enfVertex->geomEntry);
-//       GeomType = GeomShape.ShapeType();
-
-//       if (!enfVertex->isCompound) {
-// //       if (GeomType == TopAbs_VERTEX) {
-//         coords.clear();
-//         aPnt = BRep_Tool::Pnt(TopoDS::Vertex(GeomShape));
-//         coords.push_back(aPnt.X());
-//         coords.push_back(aPnt.Y());
-//         coords.push_back(aPnt.Z());
-//         if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
-//           coordsSizeMap.insert(make_pair(coords,enfVertex->size));
-//           enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
-//         }
-//       }
-//
-//       // Group Management
-//       else {
-//       if (GeomType == TopAbs_COMPOUND){
-        for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){
-          coords.clear();
-          if (it.Value().ShapeType() == TopAbs_VERTEX){
-            gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
-            coords.push_back(aPnt.X());
-            coords.push_back(aPnt.Y());
-            coords.push_back(aPnt.Z());
-            if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
-              coordsSizeMap.insert(make_pair(coords,enfVertex->size));
-              enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
-//               MESSAGE("enfVerticesWithGroup.insert(make_pair(("<<coords[0]<<","<<coords[1]<<","<<coords[2]<<"),\""<<enfVertex->groupName<<"\"))");
-            }
+      for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){
+        coords.clear();
+        if (it.Value().ShapeType() == TopAbs_VERTEX){
+          gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
+          coords.push_back(aPnt.X());
+          coords.push_back(aPnt.Y());
+          coords.push_back(aPnt.Z());
+          if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
+            coordsSizeMap.insert(make_pair(coords,enfVertex->size));
+            enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
           }
         }
-//       }
+      }
     }
   }
   int nbEnforcedVertices = coordsSizeMap.size();
   int nbEnforcedNodes = enforcedNodes.size();
-  
+
   std::string tmpStr;
   (nbEnforcedNodes <= 1) ? tmpStr = "node" : "nodes";
   std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl;
   (nbEnforcedVertices <= 1) ? tmpStr = "vertex" : "vertices";
   std::cout << nbEnforcedVertices << " enforced " << tmpStr << " from hypo" << std::endl;
-  
+
   SMESH_MesherHelper helper( theMesh );
   helper.SetSubShape( theShape );
 
@@ -1768,53 +1642,59 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   std::map<const SMDS_MeshNode*,int> aNodeToGhs3dIdMap;
   std::vector<std::string> aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId;
 
+  MG_Tetra_API mgTetra( _computeCanceled, _progress );
+
+  _isLibUsed = mgTetra.IsLibrary();
+  if ( theMesh.NbQuadrangles() > 0 )
+    _progressAdvance /= 10;
+  if ( _viscousLayersHyp )
+    _progressAdvance /= 10;
+
   // proxyMesh must live till readGMFFile() as a proxy face can be used by
   // MG-Tetra for domain indication
-  //{
-    SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
+  SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
 
-    // make prisms on quadrangles
-    if ( theMesh.NbQuadrangles() > 0 )
+  // make prisms on quadrangles
+  if ( theMesh.NbQuadrangles() > 0 || _viscousLayersHyp )
+  {
+    vector<SMESH_ProxyMesh::Ptr> components;
+    for (expBox.ReInit(); expBox.More(); expBox.Next())
     {
-      vector<SMESH_ProxyMesh::Ptr> components;
-      for (expBox.ReInit(); expBox.More(); expBox.Next())
+      if ( _viscousLayersHyp )
+      {
+        proxyMesh = _viscousLayersHyp->Compute( theMesh, expBox.Current() );
+        if ( !proxyMesh )
+          return false;
+      }
+      if ( theMesh.NbQuadrangles() > 0 )
       {
-        if ( _viscousLayersHyp )
-        {
-          proxyMesh = _viscousLayersHyp->Compute( theMesh, expBox.Current() );
-          if ( !proxyMesh )
-            return false;
-        }
         StdMeshers_QuadToTriaAdaptor* q2t = new StdMeshers_QuadToTriaAdaptor;
-        q2t->Compute( theMesh, expBox.Current(), proxyMesh.get() );
+        Ok = q2t->Compute( theMesh, expBox.Current(), proxyMesh.get() );
         components.push_back( SMESH_ProxyMesh::Ptr( q2t ));
+        if ( !Ok )
+          return false;
       }
-      proxyMesh.reset( new SMESH_ProxyMesh( components ));
-    }
-    // build viscous layers
-    else if ( _viscousLayersHyp )
-    {
-      proxyMesh = _viscousLayersHyp->Compute( theMesh, theShape );
-      if ( !proxyMesh )
-        return false;
     }
+    proxyMesh.reset( new SMESH_ProxyMesh( components ));
+  }
+  // build viscous layers
+  else if ( _viscousLayersHyp )
+  {
+    proxyMesh = _viscousLayersHyp->Compute( theMesh, theShape );
+    if ( !proxyMesh )
+      return false;
+  }
 
-    // Ok = (writePoints( aPointsFile, helper, 
-    //                    aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap, aGhs3dIdToNodeMap, 
-    //                    nodeIDToSizeMap,
-    //                    coordsSizeMap, enforcedNodes, enforcedEdges, enforcedTriangles)
-    //       &&
-    //       writeFaces ( aFacesFile, *proxyMesh, theShape, 
-    //                    aSmdsToGhs3dIdMap, anEnforcedNodeIdToGhs3dIdMap,
-    //                    enforcedEdges, enforcedTriangles ));
-    int anInvalidEnforcedFlags = 0;
-    Ok = writeGMFFile(aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(),
-                      *proxyMesh, helper,
-                      aNodeByGhs3dId, aFaceByGhs3dId, aNodeToGhs3dIdMap,
-                      aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
-                      enforcedNodes, enforcedEdges, enforcedTriangles, /*enforcedQuadrangles,*/
-                      enfVerticesWithGroup, coordsSizeMap, anInvalidEnforcedFlags);
-    //}
+  int anInvalidEnforcedFlags = 0;
+  Ok = writeGMFFile(&mgTetra,
+                    aGMFFileName.ToCString(),
+                    aRequiredVerticesFileName.ToCString(),
+                    aSolFileName.ToCString(),
+                    *proxyMesh, helper,
+                    aNodeByGhs3dId, aFaceByGhs3dId, aNodeToGhs3dIdMap,
+                    aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
+                    enforcedNodes, enforcedEdges, enforcedTriangles,
+                    enfVerticesWithGroup, coordsSizeMap, anInvalidEnforcedFlags);
 
   // Write aSmdsToGhs3dIdMap to temp file
   TCollection_AsciiString aSmdsToGhs3dIdMapFileName;
@@ -1833,7 +1713,7 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   }
 
   aIdsFile.close();
-  
+
   if ( ! Ok ) {
     if ( !_keepFiles ) {
       removeFile( aGMFFileName );
@@ -1849,74 +1729,54 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   // run MG-Tetra mesher
   // -----------------
 
-  TCollection_AsciiString cmd( (char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp ).c_str() );
-  
-  cmd += TCollection_AsciiString(" --in ") + aGMFFileName;
-  if ( nbEnforcedVertices + nbEnforcedNodes)
-    cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired;
-  cmd += TCollection_AsciiString(" --out ") + aResultFileName;
+  TCollection_AsciiString cmd = GHS3DPlugin_Hypothesis::CommandToRun( _hyp, true, mgTetra.IsExecutable() ).c_str();
+
+  if ( mgTetra.IsExecutable() )
+  {
+    cmd += TCollection_AsciiString(" --in ") + aGMFFileName;
+    if ( nbEnforcedVertices + nbEnforcedNodes)
+      cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired;
+    cmd += TCollection_AsciiString(" --out ") + aResultFileName;
+  }
   if ( !_logInStandardOutput )
+  {
+    mgTetra.SetLogFile( aLogFileName.ToCString() );
     cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
-
+  }
   std::cout << std::endl;
   std::cout << "MG-Tetra execution..." << std::endl;
   std::cout << cmd << std::endl;
 
-  _compute_canceled = false;
-
-  int err = system( cmd.ToCString() ); // run
+  _computeCanceled = false;
 
   std::string errStr;
-  if ( err )
-    errStr = SMESH_Comment("system(mg-tetra.exe ...) command failed with error: ")
-      << strerror( errno );
-  else
+  Ok = mgTetra.Compute( cmd.ToCString(), errStr ); // run
+
+  if ( _logInStandardOutput && mgTetra.IsLibrary() )
+    std::cout << std::endl << mgTetra.GetLog() << std::endl;
+  if ( Ok )
     std::cout << std::endl << "End of MG-Tetra execution !" << std::endl;
 
   // --------------
   // read a result
   // --------------
 
-  // Mapping the result file
-
-  // int fileOpen;
-  // fileOpen = open( aResultFileName.ToCString(), O_RDONLY);
-  // if ( fileOpen < 0 ) {
-  //   std::cout << std::endl;
-  //   std::cout << "Can't open the " << aResultFileName.ToCString() << " MG-Tetra output file" << std::endl;
-  //   std::cout << "Log: " << aLogFileName << std::endl;
-  //   Ok = false;
-  // }
-  // else {
-    GHS3DPlugin_Hypothesis::TSetStrings groupsToRemove = GHS3DPlugin_Hypothesis::GetGroupsToRemove(_hyp);
-    bool toMeshHoles =
-      _hyp ? _hyp->GetToMeshHoles(true) : GHS3DPlugin_Hypothesis::DefaultMeshHoles();
-    const bool toMakeGroupsOfDomains = GHS3DPlugin_Hypothesis::GetToMakeGroupsOfDomains( _hyp );
-
-    helper.IsQuadraticSubMesh( theShape );
-    helper.SetElementsOnShape( false );
-
-//     Ok = readResultFile( fileOpen,
-// #ifdef WIN32
-//                          aResultFileName.ToCString(),
-// #endif
-//                          this,
-//                          /*theMesh, */helper, tabShape, tabBox, _nbShape, 
-//                          aGhs3dIdToNodeMap, aNodeId2NodeIndexMap,
-//                          toMeshHoles, 
-//                          nbEnforcedVertices, nbEnforcedNodes, 
-//                          enforcedEdges, enforcedTriangles,
-//                          toMakeGroupsOfDomains );
-                         
-    Ok = readGMFFile(aResultFileName.ToCString(),
-                     this,
-                     &helper, aNodeByGhs3dId, aFaceByGhs3dId, aNodeToGhs3dIdMap,
-                     aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
-                     groupsToRemove, toMakeGroupsOfDomains, toMeshHoles);
-
-    removeEmptyGroupsOfDomains( helper.GetMesh(), /*notEmptyAsWell =*/ !toMakeGroupsOfDomains );
-    //}
+  GHS3DPlugin_Hypothesis::TSetStrings groupsToRemove = GHS3DPlugin_Hypothesis::GetGroupsToRemove(_hyp);
+  bool toMeshHoles =
+    _hyp ? _hyp->GetToMeshHoles(true) : GHS3DPlugin_Hypothesis::DefaultMeshHoles();
+  const bool toMakeGroupsOfDomains = GHS3DPlugin_Hypothesis::GetToMakeGroupsOfDomains( _hyp );
 
+  helper.IsQuadraticSubMesh( theShape );
+  helper.SetElementsOnShape( false );
+
+  Ok = readGMFFile(&mgTetra,
+                   aResultFileName.ToCString(),
+                   this,
+                   &helper, aNodeByGhs3dId, aFaceByGhs3dId, aNodeToGhs3dIdMap,
+                   aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
+                   groupsToRemove, toMakeGroupsOfDomains, toMeshHoles);
+
+  removeEmptyGroupsOfDomains( helper.GetMesh(), /*notEmptyAsWell =*/ !toMakeGroupsOfDomains );
 
 
 
@@ -1933,13 +1793,19 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
     // if ( _hyp && _hyp->GetToMakeGroupsOfDomains() )
     //   error( COMPERR_WARNING, "'toMakeGroupsOfDomains' is ignored since the mesh is on shape" );
   }
-  else if ( OSD_File( aLogFileName ).Size() > 0 )
+  else if ( mgTetra.HasLog() )
   {
-    // get problem description from the log file
-    _Ghs2smdsConvertor conv( aNodeByGhs3dId, proxyMesh );
-    storeErrorDescription( aLogFileName, conv );
+    if( _computeCanceled )
+      error( "interruption initiated by user" );
+    else
+    {
+      // get problem description from the log file
+      _Ghs2smdsConvertor conv( aNodeByGhs3dId, proxyMesh );
+      error( getErrorDescription( _logInStandardOutput ? 0 : aLogFileName.ToCString(),
+                                  mgTetra.GetLog(), conv ));
+    }
   }
-  else
+  else if ( !errStr.empty() )
   {
     // the log file is empty
     removeFile( aLogFileName );
@@ -1948,7 +1814,7 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   }
 
   if ( !_keepFiles ) {
-    if (! Ok && _compute_canceled)
+    if (! Ok && _computeCanceled )
       removeFile( aLogFileName );
     removeFile( aGMFFileName );
     removeFile( aRequiredVerticesFileName );
@@ -1957,16 +1823,18 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
     removeFile( aResultFileName );
     removeFile( aSmdsToGhs3dIdMapFileName );
   }
-  std::cout << "<" << aResultFileName.ToCString() << "> MG-Tetra output file ";
-  if ( !Ok )
-    std::cout << "not ";
-  std::cout << "treated !" << std::endl;
-  std::cout << std::endl;
-
-  // _nbShape = 0;    // re-initializing _nbShape for the next Compute() method call
-  // delete [] tabShape;
-  // delete [] tabBox;
-
+  if ( mgTetra.IsExecutable() )
+  {
+    std::cout << "<" << aResultFileName.ToCString() << "> MG-Tetra output file ";
+    if ( !Ok )
+      std::cout << "not ";
+    std::cout << "treated !" << std::endl;
+    std::cout << std::endl;
+  }
+  else
+  {
+    std::cout << "MG-Tetra " << ( Ok ? "succeeded" : "failed") << std::endl;
+  }
   return Ok;
 }
 
@@ -1978,8 +1846,6 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
                                 SMESH_MesherHelper* theHelper)
 {
-  MESSAGE("GHS3DPlugin_GHS3D::Compute()");
-
   theHelper->IsQuadraticSubMesh( theHelper->GetSubShape() );
 
   // a unique working file name
@@ -1993,24 +1859,16 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   bool Ok;
 
   TCollection_AsciiString aGMFFileName, aRequiredVerticesFileName, aSolFileName, aResSolFileName;
-//#ifdef _DEBUG_
   aGMFFileName              = aGenericName + ".mesh"; // GMF mesh file
   aResultFileName           = aGenericName + "Vol.mesh"; // GMF mesh file
   aResSolFileName           = aGenericName + "Vol.sol"; // GMF mesh file
   aRequiredVerticesFileName = aGenericNameRequired + ".mesh"; // GMF required vertices mesh file
   aSolFileName              = aGenericNameRequired + ".sol"; // GMF solution file
-//#else
-//  aGMFFileName    = aGenericName + ".meshb"; // GMF mesh file
-//  aResultFileName = aGenericName + "Vol.meshb"; // GMF mesh file
-//  aRequiredVerticesFileName    = aGenericNameRequired + ".meshb"; // GMF required vertices mesh file
-//  aSolFileName    = aGenericNameRequired + ".solb"; // GMF solution file
-//#endif
 
   std::map <int, int> nodeID2nodeIndexMap;
   std::map<std::vector<double>, std::string> enfVerticesWithGroup;
   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues coordsSizeMap;
   TopoDS_Shape GeomShape;
-//   TopAbs_ShapeEnum GeomType;
   std::vector<double> coords;
   gp_Pnt aPnt;
   GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertex* enfVertex;
@@ -2021,70 +1879,32 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   for ( ; enfVerIt != enfVertices.end() ; ++enfVerIt)
   {
     enfVertex = (*enfVerIt);
-//     if (enfVertex->geomEntry.empty() && enfVertex->coords.size()) {
     if (enfVertex->coords.size()) {
       coordsSizeMap.insert(make_pair(enfVertex->coords,enfVertex->size));
       enfVerticesWithGroup.insert(make_pair(enfVertex->coords,enfVertex->groupName));
-//       MESSAGE("enfVerticesWithGroup.insert(make_pair(("<<enfVertex->coords[0]<<","<<enfVertex->coords[1]<<","<<enfVertex->coords[2]<<"),\""<<enfVertex->groupName<<"\"))");
     }
     else {
-//     if (!enfVertex->geomEntry.empty()) {
       GeomShape = entryToShape(enfVertex->geomEntry);
-//       GeomType = GeomShape.ShapeType();
-
-//       if (!enfVertex->isCompound) {
-// //       if (GeomType == TopAbs_VERTEX) {
-//         coords.clear();
-//         aPnt = BRep_Tool::Pnt(TopoDS::Vertex(GeomShape));
-//         coords.push_back(aPnt.X());
-//         coords.push_back(aPnt.Y());
-//         coords.push_back(aPnt.Z());
-//         if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
-//           coordsSizeMap.insert(make_pair(coords,enfVertex->size));
-//           enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
-//         }
-//       }
-//
-//       // Group Management
-//       else {
-//       if (GeomType == TopAbs_COMPOUND){
-        for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){
-          coords.clear();
-          if (it.Value().ShapeType() == TopAbs_VERTEX){
-            aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
-            coords.push_back(aPnt.X());
-            coords.push_back(aPnt.Y());
-            coords.push_back(aPnt.Z());
-            if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
-              coordsSizeMap.insert(make_pair(coords,enfVertex->size));
-              enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
-//               MESSAGE("enfVerticesWithGroup.insert(make_pair(("<<coords[0]<<","<<coords[1]<<","<<coords[2]<<"),\""<<enfVertex->groupName<<"\"))");
-            }
+      for (TopoDS_Iterator it (GeomShape); it.More(); it.Next()){
+        coords.clear();
+        if (it.Value().ShapeType() == TopAbs_VERTEX){
+          aPnt = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
+          coords.push_back(aPnt.X());
+          coords.push_back(aPnt.Y());
+          coords.push_back(aPnt.Z());
+          if (coordsSizeMap.find(coords) == coordsSizeMap.end()) {
+            coordsSizeMap.insert(make_pair(coords,enfVertex->size));
+            enfVerticesWithGroup.insert(make_pair(coords,enfVertex->groupName));
           }
         }
-//       }
+      }
     }
   }
 
-//   const SMDS_MeshNode* enfNode;
-  GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
-//   GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap::const_iterator enfNodeIt = enforcedNodes.begin();
-//   for ( ; enfNodeIt != enforcedNodes.end() ; ++enfNodeIt)
-//   {
-//     enfNode = enfNodeIt->first;
-//     coords.clear();
-//     coords.push_back(enfNode->X());
-//     coords.push_back(enfNode->Y());
-//     coords.push_back(enfNode->Z());
-//     if (enfVerticesWithGro
-//       enfVerticesWithGroup.insert(make_pair(coords,enfNodeIt->second));
-//   }
-
-
-  GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
+  GHS3DPlugin_Hypothesis::TIDSortedNodeGroupMap     enforcedNodes = GHS3DPlugin_Hypothesis::GetEnforcedNodes(_hyp);
+  GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap     enforcedEdges = GHS3DPlugin_Hypothesis::GetEnforcedEdges(_hyp);
   GHS3DPlugin_Hypothesis::TIDSortedElemGroupMap enforcedTriangles = GHS3DPlugin_Hypothesis::GetEnforcedTriangles(_hyp);
-//   TIDSortedElemSet enforcedQuadrangles = GHS3DPlugin_Hypothesis::GetEnforcedQuadrangles(_hyp);
-  GHS3DPlugin_Hypothesis::TID2SizeMap nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
+  GHS3DPlugin_Hypothesis::TID2SizeMap             nodeIDToSizeMap = GHS3DPlugin_Hypothesis::GetNodeIDToSizeMap(_hyp);
 
   std::string tmpStr;
 
@@ -2100,52 +1920,64 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   std::map<const SMDS_MeshNode*,int> aNodeToGhs3dIdMap;
   std::vector<std::string> aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId;
 
+
+  MG_Tetra_API mgTetra( _computeCanceled, _progress );
+
+  _isLibUsed = mgTetra.IsLibrary();
+  if ( theMesh.NbQuadrangles() > 0 )
+    _progressAdvance /= 10;
+
   // proxyMesh must live till readGMFFile() as a proxy face can be used by
   // MG-Tetra for domain indication
-  //{
-    SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
-    if ( theMesh.NbQuadrangles() > 0 )
-    {
-      StdMeshers_QuadToTriaAdaptor* aQuad2Trias = new StdMeshers_QuadToTriaAdaptor;
-      aQuad2Trias->Compute( theMesh );
-      proxyMesh.reset( aQuad2Trias );
-    }
+  SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
+  if ( theMesh.NbQuadrangles() > 0 )
+  {
+    StdMeshers_QuadToTriaAdaptor* aQuad2Trias = new StdMeshers_QuadToTriaAdaptor;
+    Ok = aQuad2Trias->Compute( theMesh );
+    proxyMesh.reset( aQuad2Trias );
+    if ( !Ok )
+      return false;
+  }
 
-    int anInvalidEnforcedFlags = 0;
-    Ok = writeGMFFile(aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(),
-                      *proxyMesh, *theHelper,
-                      aNodeByGhs3dId, aFaceByGhs3dId, aNodeToGhs3dIdMap,
-                      aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
-                      enforcedNodes, enforcedEdges, enforcedTriangles,
-                      enfVerticesWithGroup, coordsSizeMap, anInvalidEnforcedFlags);
-    //}
+  int anInvalidEnforcedFlags = 0;
+  Ok = writeGMFFile(&mgTetra,
+                    aGMFFileName.ToCString(), aRequiredVerticesFileName.ToCString(), aSolFileName.ToCString(),
+                    *proxyMesh, *theHelper,
+                    aNodeByGhs3dId, aFaceByGhs3dId, aNodeToGhs3dIdMap,
+                    aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
+                    enforcedNodes, enforcedEdges, enforcedTriangles,
+                    enfVerticesWithGroup, coordsSizeMap, anInvalidEnforcedFlags);
 
   // -----------------
   // run MG-Tetra mesher
   // -----------------
 
-  TCollection_AsciiString cmd = TCollection_AsciiString((char*)GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false ).c_str());
+  TCollection_AsciiString cmd = GHS3DPlugin_Hypothesis::CommandToRun( _hyp, false, mgTetra.IsExecutable() ).c_str();
 
-  cmd += TCollection_AsciiString(" --in ") + aGMFFileName;
-  if ( nbEnforcedVertices + nbEnforcedNodes)
-    cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired;
-  cmd += TCollection_AsciiString(" --out ") + aResultFileName;
+  if ( mgTetra.IsExecutable() )
+  {
+    cmd += TCollection_AsciiString(" --in ") + aGMFFileName;
+    if ( nbEnforcedVertices + nbEnforcedNodes)
+      cmd += TCollection_AsciiString(" --required_vertices ") + aGenericNameRequired;
+    cmd += TCollection_AsciiString(" --out ") + aResultFileName;
+  }
   if ( !_logInStandardOutput )
+  {
+    mgTetra.SetLogFile( aLogFileName.ToCString() );
     cmd += TCollection_AsciiString(" 1>" ) + aLogFileName;  // dump into file
-
+  }
   std::cout << std::endl;
   std::cout << "MG-Tetra execution..." << std::endl;
   std::cout << cmd << std::endl;
 
-  _compute_canceled = false;
-
-  int err = system( cmd.ToCString() ); // run
+  _computeCanceled = false;
 
   std::string errStr;
-  if ( err )
-    errStr = SMESH_Comment("system(mg-tetra.exe ...) command failed with error: ")
-      << strerror( errno );
-  else
+  Ok = mgTetra.Compute( cmd.ToCString(), errStr ); // run
+
+  if ( _logInStandardOutput && mgTetra.IsLibrary() )
+    std::cout << std::endl << mgTetra.GetLog() << std::endl;
+  if ( Ok )
     std::cout << std::endl << "End of MG-Tetra execution !" << std::endl;
 
   // --------------
@@ -2154,11 +1986,12 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   GHS3DPlugin_Hypothesis::TSetStrings groupsToRemove = GHS3DPlugin_Hypothesis::GetGroupsToRemove(_hyp);
   const bool toMakeGroupsOfDomains = GHS3DPlugin_Hypothesis::GetToMakeGroupsOfDomains( _hyp );
 
-  Ok = readGMFFile(aResultFileName.ToCString(),
-                   this,
-                   theHelper, aNodeByGhs3dId, aFaceByGhs3dId, aNodeToGhs3dIdMap,
-                   aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
-                   groupsToRemove, toMakeGroupsOfDomains);
+  Ok = Ok && readGMFFile(&mgTetra,
+                         aResultFileName.ToCString(),
+                         this,
+                         theHelper, aNodeByGhs3dId, aFaceByGhs3dId, aNodeToGhs3dIdMap,
+                         aNodeGroupByGhs3dId, anEdgeGroupByGhs3dId, aFaceGroupByGhs3dId,
+                         groupsToRemove, toMakeGroupsOfDomains);
 
   updateMeshGroups(theHelper->GetMesh(), groupsToRemove);
   removeEmptyGroupsOfDomains( theHelper->GetMesh(), /*notEmptyAsWell =*/ !toMakeGroupsOfDomains );
@@ -2182,11 +2015,17 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
     //if ( !toMakeGroupsOfDomains && _hyp && _hyp->GetToMakeGroupsOfDomains() )
     //error( COMPERR_WARNING, "'toMakeGroupsOfDomains' is ignored since 'toMeshHoles' is OFF." );
   }
-  else if ( OSD_File( aLogFileName ).Size() > 0 )
+  else if ( mgTetra.HasLog() )
   {
-    // get problem description from the log file
-    _Ghs2smdsConvertor conv( aNodeByGhs3dId, proxyMesh );
-    storeErrorDescription( aLogFileName, conv );
+    if( _computeCanceled )
+      error( "interruption initiated by user" );
+    else
+    {
+      // get problem description from the log file
+      _Ghs2smdsConvertor conv( aNodeByGhs3dId, proxyMesh );
+      error( getErrorDescription( _logInStandardOutput ? 0 : aLogFileName.ToCString(),
+                                  mgTetra.GetLog(), conv ));
+    }
   }
   else {
     // the log file is empty
@@ -2197,7 +2036,7 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
 
   if ( !_keepFiles )
   {
-    if (! Ok && _compute_canceled)
+    if (! Ok && _computeCanceled)
       removeFile( aLogFileName );
     removeFile( aGMFFileName );
     removeFile( aResultFileName );
@@ -2210,9 +2049,8 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
 
 void GHS3DPlugin_GHS3D::CancelCompute()
 {
-  _compute_canceled = true;
-#ifdef WIN32
-#else
+  _computeCanceled = true;
+#if !defined WIN32 && !defined __APPLE__
   std::string cmd = "ps xo pid,args | grep " + _genericName;
   //cmd += " | grep -e \"^ *[0-9]\\+ \\+" + GHS3DPlugin_Hypothesis::GetExeName() + "\"";
   cmd += " | awk '{print $1}' | xargs kill -9 > /dev/null 2>&1";
@@ -2542,30 +2380,17 @@ static char* getIds( char* ptr, int nbIds, vector<int>& ids )
  */
 //================================================================================
 
-bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& logFile,
-                                              const _Ghs2smdsConvertor &     toSmdsConvertor )
+SMESH_ComputeErrorPtr
+GHS3DPlugin_GHS3D::getErrorDescription(const char*                logFile,
+                                       const std::string&         log,
+                                       const _Ghs2smdsConvertor & toSmdsConvertor,
+                                       const bool                 isOk/* = false*/ )
 {
-  if(_compute_canceled)
-    return error(SMESH_Comment("interruption initiated by user"));
-  // open file
-#ifdef WIN32
-  int file = ::_open (logFile.ToCString(), _O_RDONLY|_O_BINARY);
-#else
-  int file = ::open (logFile.ToCString(), O_RDONLY);
-#endif
-  if ( file < 0 )
-    return error( SMESH_Comment("See ") << logFile << " for problem description");
+  SMESH_ComputeErrorPtr err = SMESH_ComputeError::New( COMPERR_ALGO_FAILED );
 
-  // get file size
-  off_t length = lseek( file, 0, SEEK_END);
-  lseek( file, 0, SEEK_SET);
+  char* ptr = const_cast<char*>( log.c_str() );
+  char* buf = ptr, * bufEnd = ptr + log.size();
 
-  // read file
-  vector< char > buf( length );
-  int nBytesRead = ::read (file, & buf[0], length);
-  ::close (file);
-  char* ptr = & buf[0];
-  char* bufEnd = ptr + nBytesRead;
 
   SMESH_Comment errDescription;
 
@@ -2599,7 +2424,7 @@ bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& log
     if ( strncmp( ptr, "ERR ", 4 ) != 0 )
       continue;
 
-    list<const SMDS_MeshElement*> badElems;
+    list<const SMDS_MeshElement*>& badElems = err->myBadElements;
     vector<int> nodeIds;
 
     ptr += 4;
@@ -2773,13 +2598,6 @@ bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& log
 //         continue; // not to report different types of errors with bad elements
 //     }
 
-    // store bad elements
-    //if ( allElemsOk ) {
-      list<const SMDS_MeshElement*>::iterator elem = badElems.begin();
-      for ( ; elem != badElems.end(); ++elem )
-        addBadInputElement( *elem );
-      //}
-
     // make error text
     string text = translateError( errNum );
     if ( errDescription.find( text ) == text.npos ) {
@@ -2804,12 +2622,20 @@ bool GHS3DPlugin_GHS3D::storeErrorDescription(const TCollection_AsciiString& log
     }
   }
 
-  if ( errDescription.empty() )
-    errDescription << "See " << logFile << " for problem description";
-  else
-    errDescription << "\nSee " << logFile << " for more information";
+  if ( !isOk && logFile && logFile[0] )
+  {
+    if ( errDescription.empty() )
+      errDescription << "See " << logFile << " for problem description";
+    else
+      errDescription << "\nSee " << logFile << " for more information";
+  }
+
+  err->myComment = errDescription;
 
-  return error( errDescription );
+  if ( err->myComment.empty() && err->myBadElements.empty() )
+    err = SMESH_ComputeError::New(); // OK
+
+  return err;
 }
 
 //================================================================================
@@ -2964,19 +2790,11 @@ bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
 
 bool GHS3DPlugin_GHS3D::importGMFMesh(const char* theGMFFileName, SMESH_Mesh& theMesh)
 {
-  SMESH_MesherHelper* helper  = new SMESH_MesherHelper(theMesh );
-  std::vector <const SMDS_MeshNode*> dummyNodeVector;
-  std::vector <const SMDS_MeshElement*> aFaceByGhs3dId;
-  std::map<const SMDS_MeshNode*,int> dummyNodeMap;
-  std::map<std::vector<double>, std::string> dummyEnfVertGroup;
-  std::vector<std::string> dummyElemGroup;
-  std::set<std::string> dummyGroupsToRemove;
-
-  bool ok = readGMFFile(theGMFFileName,
-                        this,
-                        helper, dummyNodeVector, aFaceByGhs3dId, dummyNodeMap, dummyElemGroup, dummyElemGroup, dummyElemGroup, dummyGroupsToRemove);
+  SMESH_ComputeErrorPtr err = theMesh.GMFToMesh( theGMFFileName, /*makeRequiredGroups =*/ true );
+
   theMesh.GetMeshDS()->Modified();
-  return ok;
+
+  return ( !err || err->IsOK());
 }
 
 namespace
@@ -3103,3 +2921,26 @@ void GHS3DPlugin_GHS3D::SetEventListener(SMESH_subMesh* subMesh)
 {
   subMesh->SetEventListener( new _GroupsOfDomainsRemover(), 0, subMesh );
 }
+
+//================================================================================
+/*!
+ * \brief If possible, returns progress of computation [0.,1.]
+ */
+//================================================================================
+
+double GHS3DPlugin_GHS3D::GetProgress() const
+{
+  if ( _isLibUsed )
+  {
+    // this->_progress is advanced by MG_Tetra_API according to messages from MG library
+    // but sharply. Advance it a bit to get smoother advancement.
+    GHS3DPlugin_GHS3D* me = const_cast<GHS3DPlugin_GHS3D*>( this );
+    if ( _progress < 0.1 ) // the first message is at 10%
+      me->_progress = GetProgressByTic();
+    else if ( _progress < 0.98 )
+      me->_progress += _progressAdvance;
+    return _progress;
+  }
+
+  return -1;
+}