Salome HOME
updated copyright message
[plugins/ghs3dplugin.git] / src / GHS3DPlugin / GHS3DPlugin_GHS3D.cxx
index 0a1091f00204b3b4ca41e670c9b81a80075829ea..601f8b231e50ac64bbfd45e39df2b7475d752f30 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2004-2016  CEA/DEN, EDF R&D
+// Copyright (C) 2004-2023  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include <algorithm>
 #include <errno.h>
 
+#include <boost/filesystem.hpp>
+
+namespace boofs = boost::filesystem;
+
 #ifdef _DEBUG_
 //#define _MY_DEBUG_
 #endif
@@ -112,6 +116,13 @@ static std::string flagsToErrorStr( int anInvalidEnforcedFlags )
   return str;
 }
 
+// change results files permissions to user only (using boost to be used without C++17)
+static void chmodUserOnly(const char* filename)
+{
+  if (boofs::exists(filename))
+    boofs::permissions(filename, boofs::remove_perms | boofs::group_all | boofs::others_all );
+}
+
 typedef const list<const SMDS_MeshFace*> TTriaList;
 
 static const char theDomainGroupNamePrefix[] = "Domain_";
@@ -132,10 +143,9 @@ static void removeFile( const TCollection_AsciiString& fileName )
  */
 //=============================================================================
 
-GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
-  : SMESH_3D_Algo(hypId, studyId, gen), _isLibUsed( false )
+GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, SMESH_Gen* gen)
+  : SMESH_3D_Algo(hypId, 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
@@ -143,18 +153,7 @@ 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
-
-  _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);
-  if (!_study->_is_nil())
-    MESSAGE("_study->StudyId() = " << _study->StudyId());
+  _requireShape = false; // can work without shape
   
   _computeCanceled = false;
   _progressAdvance = 1e-4;
@@ -162,18 +161,17 @@ GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
 
 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
 {
-  MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
 }
 
 //=============================================================================
 /*!
- *  
+ *
  */
 //=============================================================================
 
@@ -201,8 +199,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();
   }
 
@@ -220,26 +218,27 @@ bool GHS3DPlugin_GHS3D::CheckHypothesis ( SMESH_Mesh&         aMesh,
 
 TopoDS_Shape GHS3DPlugin_GHS3D::entryToShape(std::string entry)
 {
-  MESSAGE("GHS3DPlugin_GHS3D::entryToShape "<<entry );
-  if ( _study->_is_nil() )
+  if ( SMESH_Gen_i::GetSMESHGen()->getStudyServant()->_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 = _study->FindObjectID( entry.c_str() );
+  SALOMEDS::SObject_var aSObj = SMESH_Gen_i::GetSMESHGen()->getStudyServant()->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 = SMESH_Gen_i::GetSMESHGen()->GeomObjectToShape( aGeomObj.in() );
   return S;
 }
 
 //================================================================================
 /*!
- * \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
  */
 //================================================================================
 
@@ -251,26 +250,40 @@ 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 // nbNodes == 6
+      {
+        int i1 = vol->GetNodeIndex( node1 );
+        if (( i1 == 5 && i2 == 4 && i3 == 3 ) ||
+            ( i1 == 4 && i2 == 3 && i3 == 5 ) ||
+            ( i1 == 3 && i2 == 5 && i3 == 4 ))
+          return HOLE_ID;
+        else
+          return vol->getshapeId(); // triangle is a prism top
+      }
     }
   }
   return HOLE_ID;
@@ -302,7 +315,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
@@ -438,7 +451,7 @@ static int findShapeID(SMESH_Mesh&          mesh,
 static void addElemInMeshGroup(SMESH_Mesh*             theMesh,
                                const SMDS_MeshElement* anElem,
                                std::string&            groupName,
-                               std::set<std::string>&  groupsToRemove)
+                               std::set<std::string>&  /*groupsToRemove*/)
 {
   if ( !anElem ) return; // issue 0021776
 
@@ -453,19 +466,16 @@ 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;
     }
   }
   
   if (!groupDone)
   {
-    int groupId;
-    SMESH_Group* aGroup = theMesh->AddGroup(anElem->GetType(), groupName.c_str(), groupId);
+    SMESH_Group* aGroup = theMesh->AddGroup(anElem->GetType(), groupName.c_str());
     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)
@@ -489,7 +499,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());
     }
   }
@@ -559,13 +568,12 @@ static void makeDomainGroups( std::vector< std::vector< const SMDS_MeshElement*
     }
     // create and fill the groups
     size_t iElem = 0;
-    int groupID;
     do
     {
       SMESH_Group* group = groupOfType[ elems[ iElem ]->GetType() ];
       if ( !group )
         group = theHelper->GetMesh()->AddGroup( elems[ iElem ]->GetType(),
-                                                domainName.c_str(), groupID );
+                                                domainName.c_str() );
       SMDS_MeshGroup& groupDS =
         static_cast< SMESHDS_Group* >( group->GetGroupDS() )->SMDSGroup();
 
@@ -587,7 +595,7 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
                         SMESH_MesherHelper*             theHelper,
                         std::vector <const SMDS_MeshNode*> &    theNodeByGhs3dId,
                         std::vector <const SMDS_MeshElement*> & theFaceByGhs3dId,
-                        map<const SMDS_MeshNode*,int> & theNodeToGhs3dIdMap,
+                        map<const SMDS_MeshNode*,int> & /*theNodeToGhs3dIdMap*/,
                         std::vector<std::string> &      aNodeGroupByGhs3dId,
                         std::vector<std::string> &      anEdgeGroupByGhs3dId,
                         std::vector<std::string> &      aFaceGroupByGhs3dId,
@@ -599,17 +607,15 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
   SMESHDS_Mesh* theMeshDS = theHelper->GetMeshDS();
   const bool hasGeom = ( theHelper->GetMesh()->HasShapeToMesh() );
 
-  int nbInitialNodes = theNodeByGhs3dId.size();
-  int nbMeshNodes = theMeshDS->NbNodes();
+  int nbInitialNodes = (int) theNodeByGhs3dId.size();
   
+#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
   
@@ -620,7 +626,7 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
   int nbElem = 0, nbRef = 0;
   int aGMFNodeID = 0;
   std::vector< const SMDS_MeshNode*> GMFNode;
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
   std::map<int, std::set<int> > subdomainId2tetraId;
 #endif
   std::map <GmfKwdCod,int> tabRef;
@@ -637,11 +643,9 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
   tabRef[GmfHexahedra]      = 8;
 
   int ver, dim;
-  MESSAGE("Read " << theFile << " file");
   int InpMsh = MGOutput->GmfOpenMesh( theFile, GmfRead, &ver, &dim);
   if (!InpMsh)
     return false;
-  MESSAGE("Done ");
 
   // Read ids of domains
   vector< int > solidIDByDomain;
@@ -678,7 +682,7 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
             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 ] );
@@ -698,7 +702,7 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
   std::vector< const SMDS_MeshElement* > foundVolumes;
   if ( !hasGeom && theHelper->GetMesh()->NbVolumes() > 0 )
     elemSearcher = SMESH_MeshAlgos::GetElementSearcher( *theMeshDS );
-  auto_ptr< SMESH_ElementSearcher > elemSearcherDeleter( elemSearcher );
+  unique_ptr< SMESH_ElementSearcher > elemSearcherDeleter( elemSearcher );
 
   // IMP 0022172: [CEA 790] create the groups corresponding to domains
   std::vector< std::vector< const SMDS_MeshElement* > > elemsOfDomain;
@@ -808,7 +812,7 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
       (nbElem <= 1) ? tmpStr = " Tetrahedron" : tmpStr = " Tetrahedra";
       for ( int iElem = 0; iElem < nbElem; 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]);
-#ifdef _DEBUG_
+#ifdef _MY_DEBUG_
         subdomainId2tetraId[dummy].insert(iElem+1);
 #endif
       }
@@ -954,6 +958,20 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
         default: continue;
         } // switch (token)
 
+        // care about medium nodes
+        if ( aCreatedElem &&
+             aCreatedElem->IsQuadratic() &&
+             ( solidID = aCreatedElem->getshapeId() ) > 0 )
+        {
+          int iN = aCreatedElem->NbCornerNodes(), nbN = aCreatedElem->NbNodes();
+          for ( ; iN < nbN; ++iN )
+          {
+            const SMDS_MeshNode* n = aCreatedElem->GetNode(iN);
+            if ( n->getshapeId() < 1 )
+              theMeshDS->SetNodeInVolume( n, solidID );
+          }
+        }
+
         if ( aCreatedElem && toMakeGroupsOfDomains )
         {
           if ( domainID[iElem] >= (int) elemsOfDomain.size() )
@@ -981,8 +999,7 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
   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";
@@ -992,7 +1009,6 @@ static bool readGMFFile(MG_Tetra_API*                   MGOutput,
   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) {
@@ -1026,7 +1042,6 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
                          GHS3DPlugin_Hypothesis::TGHS3DEnforcedVertexCoordsValues & theEnforcedVertices,
                          int &                                           theInvalidEnforcedFlags)
 {
-  MESSAGE("writeGMFFile w/o geometry");
   std::string tmpStr;
   int idx, idxRequired = 0, idxSol = 0;
   const int dummyint = 0;
@@ -1048,11 +1063,11 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
   SMESHUtils::Deleter< SMESH_ElementSearcher > pntCls
     ( SMESH_MeshAlgos::GetElementSearcher(*theMesh->GetMeshDS()));
   
-  int nbEnforcedVertices = theEnforcedVertices.size();
+  int nbEnforcedVertices = (int) theEnforcedVertices.size();
   theInvalidEnforcedFlags = 0;
 
   // count faces
-  int nbFaces = theProxyMesh.NbFaces();
+  smIdType nbFaces = theProxyMesh.NbFaces();
   int nbNodes;
   theFaceByGhs3dId.reserve( nbFaces );
   
@@ -1081,13 +1096,21 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
     {
       // find MG-Tetra ID
       const SMDS_MeshNode* node = castToNode( nodeIt->next() );
-      int newId = aNodeToGhs3dIdMap.size() + 1; // MG-Tetra ids count from 1
+      int newId = (int) aNodeToGhs3dIdMap.size() + 1; // MG-Tetra ids count from 1
       aNodeToGhs3dIdMap.insert( make_pair( node, newId ));
     }
   }
-  
+  if ( !anElemSet.empty() &&
+       (*anElemSet.begin())->IsQuadratic() &&
+       theProxyMesh.NbProxySubMeshes() > 0 )
+  {
+    // add medium nodes of proxy triangles to theHelper (#16843)
+    for ( elemSetIt = anElemSet.begin(); elemSetIt != anElemSet.end(); ++elemSetIt )
+      theHelper.AddTLinks( static_cast< const SMDS_MeshFace* >( *elemSetIt ));
+  }
+
   /* EDGES ========================== */
-  
+
   // Iterate over the enforced edges
   for(elemIt = theEnforcedEdges.begin() ; elemIt != theEnforcedEdges.end() ; ++elemIt) {
     elem = elemIt->first;
@@ -1122,7 +1145,7 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
 #endif
         if (nbFoundElems ==0) {
           if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) {
-            newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // MG-Tetra ids count from 1
+            newId = int( aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1 ); // MG-Tetra ids count from 1
             anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
           }
         }
@@ -1179,7 +1202,7 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
 #endif
         if (nbFoundElems ==0) {
           if ((*aNodeToTopAbs_StateMap.find(node)).second == TopAbs_IN) {
-            newId = aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1; // MG-Tetra ids count from 1
+            newId = int( aNodeToGhs3dIdMap.size() + anEnforcedNodeToGhs3dIdMap.size() + 1 ); // MG-Tetra ids count from 1
             anEnforcedNodeToGhs3dIdMap.insert( make_pair( node, newId ));
           }
         }
@@ -1375,7 +1398,7 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
 //     theOrderedNodes.push_back(node);
     theRequiredNodes.push_back(node);
   }
-  int requiredNodes = theRequiredNodes.size();
+  int requiredNodes = (int) theRequiredNodes.size();
   
   int solSize = 0;
   std::vector<std::vector<double> > ReqVerTab;
@@ -1411,7 +1434,7 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
   // GmfVertices
   std::cout << "Begin writting required nodes in GmfVertices" << std::endl;
   std::cout << "Nb vertices: " << theOrderedNodes.size() << std::endl;
-  MGInput->GmfSetKwd( idx, GmfVertices, theOrderedNodes.size()/*+solSize*/);
+  MGInput->GmfSetKwd( idx, GmfVertices, int( theOrderedNodes.size()/*+solSize*/));
   for (ghs3dNodeIt = theOrderedNodes.begin();ghs3dNodeIt != theOrderedNodes.end();++ghs3dNodeIt) {
     MGInput->GmfSetLin( idx, GmfVertices, (*ghs3dNodeIt)->X(), (*ghs3dNodeIt)->Y(), (*ghs3dNodeIt)->Z(), dummyint);
   }
@@ -1470,7 +1493,7 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
 //    idxRequired = MGInput->GmfOpenMesh( theRequiredFileName, GmfWrite, GMFVERSION, GMFDIMENSION);
 //    if (!idxRequired)
 //      return false;
-    MGInput->GmfSetKwd( idx, GmfEdges, theKeptEnforcedEdges.size());
+    MGInput->GmfSetKwd( idx, GmfEdges, (int) theKeptEnforcedEdges.size());
 //    MGInput->GmfSetKwd( idxRequired, GmfEdges, theKeptEnforcedEdges.size());
     for(elemSetIt = theKeptEnforcedEdges.begin() ; elemSetIt != theKeptEnforcedEdges.end() ; ++elemSetIt) {
       elem = (*elemSetIt);
@@ -1507,7 +1530,7 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
   int usedEnforcedTriangles = 0;
   if (anElemSet.size()+theKeptEnforcedTriangles.size()) {
     aFaceGroupByGhs3dId.resize( anElemSet.size()+theKeptEnforcedTriangles.size() );
-    MGInput->GmfSetKwd( idx, GmfTriangles, anElemSet.size()+theKeptEnforcedTriangles.size());
+    MGInput->GmfSetKwd( idx, GmfTriangles, int( anElemSet.size()+theKeptEnforcedTriangles.size() ));
     int k=0;
     for(elemSetIt = anElemSet.begin() ; elemSetIt != anElemSet.end() ; ++elemSetIt,++k) {
       elem = (*elemSetIt);
@@ -1556,24 +1579,32 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
   if (usedEnforcedTriangles) {
     MGInput->GmfSetKwd( idx, GmfRequiredTriangles, usedEnforcedTriangles);
     for (int enfID=1;enfID<=usedEnforcedTriangles;enfID++)
-      MGInput->GmfSetLin( idx, GmfRequiredTriangles, anElemSet.size()+enfID);
+      MGInput->GmfSetLin( idx, GmfRequiredTriangles, int( anElemSet.size()+enfID ));
   }
 
+  // close input files and change results files permissions to user only
   MGInput->GmfCloseMesh(idx);
+  chmodUserOnly(theMeshFileName);
   if (idxRequired)
-    MGInput->GmfCloseMesh(idxRequired);
+    {
+      MGInput->GmfCloseMesh(idxRequired);
+      chmodUserOnly(theRequiredFileName);
+    }
   if (idxSol)
-    MGInput->GmfCloseMesh(idxSol);
+    {
+      MGInput->GmfCloseMesh(idxSol);
+      chmodUserOnly(theRequiredFileName);
+    }
 
   return true;
 }
 
+
 //=============================================================================
 /*!
  *Here we are going to use the MG-Tetra mesher with geometry
  */
 //=============================================================================
-
 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
                                 const TopoDS_Shape& theShape)
 {
@@ -1633,8 +1664,8 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
       }
     }
   }
-  int nbEnforcedVertices = coordsSizeMap.size();
-  int nbEnforcedNodes = enforcedNodes.size();
+  size_t nbEnforcedVertices = coordsSizeMap.size();
+  size_t nbEnforcedNodes = enforcedNodes.size();
 
   std::string tmpStr;
   (nbEnforcedNodes <= 1) ? tmpStr = "node" : "nodes";
@@ -1662,8 +1693,8 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   // MG-Tetra for domain indication
   SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( theMesh ));
 
-  // make prisms on quadrangles
-  if ( theMesh.NbQuadrangles() > 0 )
+  // make prisms on quadrangles and viscous layers
+  if ( theMesh.NbQuadrangles() > 0 || _viscousLayersHyp )
   {
     vector<SMESH_ProxyMesh::Ptr> components;
     for (expBox.ReInit(); expBox.More(); expBox.Next())
@@ -1673,22 +1704,27 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
         proxyMesh = _viscousLayersHyp->Compute( theMesh, expBox.Current() );
         if ( !proxyMesh )
           return false;
+        if ( theMesh.NbQuadrangles() == 0 )
+          components.push_back( proxyMesh );
+      }
+      if ( theMesh.NbQuadrangles() > 0 )
+      {
+        StdMeshers_QuadToTriaAdaptor* q2t = new StdMeshers_QuadToTriaAdaptor;
+        Ok = q2t->Compute( theMesh, expBox.Current(), proxyMesh.get() );
+        components.push_back( SMESH_ProxyMesh::Ptr( q2t ));
+        if ( !Ok )
+          return false;
       }
-      StdMeshers_QuadToTriaAdaptor* q2t = new StdMeshers_QuadToTriaAdaptor;
-      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;
-  }
+  // else if ( _viscousLayersHyp )
+  // {
+  //   proxyMesh = _viscousLayersHyp->Compute( theMesh, theShape );
+  //   if ( !proxyMesh )
+  //     return false;
+  // }
 
   int anInvalidEnforcedFlags = 0;
   Ok = writeGMFFile(&mgTetra,
@@ -1705,20 +1741,21 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   TCollection_AsciiString aSmdsToGhs3dIdMapFileName;
   aSmdsToGhs3dIdMapFileName = aGenericName + ".ids";  // ids relation
   ofstream aIdsFile  ( aSmdsToGhs3dIdMapFileName.ToCString()  , ios::out);
-  Ok = aIdsFile.rdbuf()->is_open();
-  if (!Ok) {
+  if ( !aIdsFile.rdbuf()->is_open() ) {
     INFOS( "Can't write into " << aSmdsToGhs3dIdMapFileName);
-    return error(SMESH_Comment("Can't write into ") << aSmdsToGhs3dIdMapFileName);
+    //return error(SMESH_Comment("Can't write into ") << aSmdsToGhs3dIdMapFileName);
   }
-  INFOS( "Writing ids relation into " << aSmdsToGhs3dIdMapFileName);
-  aIdsFile << "Smds MG-Tetra" << std::endl;
-  map <int,int>::const_iterator myit;
-  for (myit=aSmdsToGhs3dIdMap.begin() ; myit != aSmdsToGhs3dIdMap.end() ; ++myit) {
-    aIdsFile << myit->first << " " << myit->second << std::endl;
+  else
+  {
+    INFOS( "Writing ids relation into " << aSmdsToGhs3dIdMapFileName);
+    aIdsFile << "Smds MG-Tetra" << std::endl;
+    map <int,int>::const_iterator myit;
+    for (myit=aSmdsToGhs3dIdMap.begin() ; myit != aSmdsToGhs3dIdMap.end() ; ++myit) {
+      aIdsFile << myit->first << " " << myit->second << std::endl;
+    }
   }
-
   aIdsFile.close();
-
+  chmodUserOnly(aSmdsToGhs3dIdMapFileName.ToCString());
   if ( ! Ok ) {
     if ( !_keepFiles ) {
       removeFile( aGMFFileName );
@@ -1748,19 +1785,34 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
     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;
+
+  BRIEF_INFOS("")
+  BRIEF_INFOS("MG-Tetra execution...")
+  BRIEF_INFOS(cmd)
 
   _computeCanceled = false;
 
   std::string errStr;
   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;
+  if ( _logInStandardOutput && mgTetra.IsLibrary() ) {
+    BRIEF_INFOS("");
+    BRIEF_INFOS(mgTetra.GetLog());
+    BRIEF_INFOS("")
+  }
+  if ( Ok ) {
+    BRIEF_INFOS("");
+    BRIEF_INFOS("End of MG-Tetra execution !");
+    BRIEF_INFOS("")
+  }
+
+  // change results files permissions to user only
+  chmodUserOnly(aLogFileName.ToCString());
+  if (Ok)
+    {
+      chmodUserOnly(aResultFileName.ToCString());
+      chmodUserOnly(aResSolFileName.ToCString());
+    }
 
   // --------------
   // read a result
@@ -1800,10 +1852,15 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   }
   else if ( mgTetra.HasLog() )
   {
-    // get problem description from the log file
-    _Ghs2smdsConvertor conv( aNodeByGhs3dId, proxyMesh );
-    storeErrorDescription( _logInStandardOutput ? 0 : aLogFileName.ToCString(),
-                           mgTetra.GetLog(), 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 if ( !errStr.empty() )
   {
@@ -1843,11 +1900,10 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
  *Here we are going to use the MG-Tetra mesher w/o geometry
  */
 //=============================================================================
+
 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
                                 SMESH_MesherHelper* theHelper)
 {
-  MESSAGE("GHS3DPlugin_GHS3D::Compute()");
-
   theHelper->IsQuadraticSubMesh( theHelper->GetSubShape() );
 
   // a unique working file name
@@ -1910,8 +1966,8 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
 
   std::string tmpStr;
 
-  int nbEnforcedVertices = coordsSizeMap.size();
-  int nbEnforcedNodes = enforcedNodes.size();
+  size_t nbEnforcedVertices = coordsSizeMap.size();
+  size_t    nbEnforcedNodes = enforcedNodes.size();
   (nbEnforcedNodes <= 1) ? tmpStr = "node" : tmpStr = "nodes";
   std::cout << nbEnforcedNodes << " enforced " << tmpStr << " from hypo" << std::endl;
   (nbEnforcedVertices <= 1) ? tmpStr = "vertex" : tmpStr = "vertices";
@@ -1968,19 +2024,26 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
     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;
+
+  BRIEF_INFOS("")
+  BRIEF_INFOS("MG-Tetra execution...")
+  BRIEF_INFOS(cmd)
 
   _computeCanceled = false;
 
   std::string errStr;
   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;
+  if ( _logInStandardOutput && mgTetra.IsLibrary() ) {
+    BRIEF_INFOS("");
+    BRIEF_INFOS(mgTetra.GetLog());
+    BRIEF_INFOS("")
+  }
+  if ( Ok ) {
+    BRIEF_INFOS("");
+    BRIEF_INFOS("End of MG-Tetra execution !");
+    BRIEF_INFOS("")
+  }
 
   // --------------
   // read a result
@@ -2019,10 +2082,15 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   }
   else if ( mgTetra.HasLog() )
   {
-    // get problem description from the log file
-    _Ghs2smdsConvertor conv( aNodeByGhs3dId, proxyMesh );
-    storeErrorDescription( _logInStandardOutput ? 0 : aLogFileName.ToCString(),
-                           mgTetra.GetLog(), 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
@@ -2047,8 +2115,7 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
 void GHS3DPlugin_GHS3D::CancelCompute()
 {
   _computeCanceled = true;
-#ifdef WIN32
-#else
+#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";
@@ -2365,7 +2432,7 @@ static char* getIds( char* ptr, int nbIds, vector<int>& ids )
   {
     while ( !isdigit( *ptr )) ++ptr;
     if ( ptr[-1] == '-' ) --ptr;
-    ids.push_back( strtol( ptr, &ptr, 10 ));
+    ids.push_back((int) strtol( ptr, &ptr, 10 ));
     --nbIds;
   }
   return ptr;
@@ -2378,17 +2445,15 @@ static char* getIds( char* ptr, int nbIds, vector<int>& ids )
  */
 //================================================================================
 
-bool GHS3DPlugin_GHS3D::storeErrorDescription(const char*                logFile,
-                                              const std::string&         log,
-                                              const _Ghs2smdsConvertor & toSmdsConvertor )
+SMESH_ComputeErrorPtr
+GHS3DPlugin_GHS3D::getErrorDescription(const char*                logFile,
+                                       const std::string&         log,
+                                       const _Ghs2smdsConvertor & toSmdsConvertor,
+                                       const bool                 isOk/* = false*/ )
 {
-  if(_computeCanceled)
-    return error(SMESH_Comment("interruption initiated by user"));
-
-  // read file
-  // SMESH_File file( logFile.ToCString() );
-  // if ( file.size() == 0 )
-  //   return error( SMESH_Comment("See ") << logFile << " for problem description");
+  SMESH_BadInputElements* badElemsErr =
+    new SMESH_BadInputElements( toSmdsConvertor.getMesh(), COMPERR_ALGO_FAILED );
+  SMESH_ComputeErrorPtr err( badElemsErr );
 
   char* ptr = const_cast<char*>( log.c_str() );
   char* buf = ptr, * bufEnd = ptr + log.size();
@@ -2426,12 +2491,12 @@ bool GHS3DPlugin_GHS3D::storeErrorDescription(const char*                logFile
     if ( strncmp( ptr, "ERR ", 4 ) != 0 )
       continue;
 
-    list<const SMDS_MeshElement*> badElems;
+    list<const SMDS_MeshElement*>& badElems = badElemsErr->myBadElements;
     vector<int> nodeIds;
 
     ptr += 4;
     char* errBeg = ptr;
-    int   errNum = strtol(ptr, &ptr, 10) + versionAddition;
+    int   errNum = int( strtol(ptr, &ptr, 10) + versionAddition );
     // we treat errors enumerated in [SALOME platform 0019316] issue
     // and all errors from a new (Release 1.1) MeshGems User Manual
     switch ( errNum ) {
@@ -2600,13 +2665,6 @@ bool GHS3DPlugin_GHS3D::storeErrorDescription(const char*                logFile
 //         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 ) {
@@ -2620,9 +2678,12 @@ bool GHS3DPlugin_GHS3D::storeErrorDescription(const char*                logFile
   if ( errDescription.empty() ) { // no errors found
     char msgLic1[] = "connection to server failed";
     char msgLic2[] = " Dlim ";
+    char msgLic3[] = "license is not valid";
     if ( search( &buf[0], bufEnd, msgLic1, msgLic1 + strlen(msgLic1)) != bufEnd ||
          search( &buf[0], bufEnd, msgLic2, msgLic2 + strlen(msgLic2)) != bufEnd )
-      errDescription << "Licence problems.";
+      errDescription << "Network license problem.";
+    else if ( search( &buf[0], bufEnd, msgLic3, msgLic3 + strlen(msgLic3)) != bufEnd )
+      errDescription << "License is not valid.";
     else
     {
       char msg2[] = "SEGMENTATION FAULT";
@@ -2631,14 +2692,20 @@ bool GHS3DPlugin_GHS3D::storeErrorDescription(const char*                logFile
     }
   }
 
-  if ( logFile && logFile[0] )
+  if ( !isOk && logFile && logFile[0] )
   {
     if ( errDescription.empty() )
       errDescription << "See " << logFile << " for problem description";
     else
       errDescription << "\nSee " << logFile << " for more information";
   }
-  return error( errDescription );
+
+  err->myComment = errDescription;
+
+  if ( err->myComment.empty() && !err->HasBadElems() )
+    err = SMESH_ComputeError::New(); // OK
+
+  return err;
 }
 
 //================================================================================
@@ -2710,6 +2777,16 @@ const SMDS_MeshElement* _Ghs2smdsConvertor::getElement(const vector<int>& ghsNod
   return 0;
 }
 
+//================================================================================
+/*!
+ * \brief Return a mesh
+ */
+//================================================================================
+
+const SMDS_Mesh* _Ghs2smdsConvertor::getMesh() const
+{
+  return _mesh->GetMeshDS();
+}
 
 //=============================================================================
 /*!
@@ -2720,7 +2797,7 @@ bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
                                  const TopoDS_Shape& aShape,
                                  MapShapeNbElems& aResMap)
 {
-  int nbtri = 0, nbqua = 0;
+  smIdType nbtri = 0, nbqua = 0;
   double fullArea = 0.0;
   for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
     TopoDS_Face F = TopoDS::Face( exp.Current() );
@@ -2732,9 +2809,9 @@ bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
                                             "Submesh can not be evaluated",this));
       return false;
     }
-    std::vector<int> aVec = (*anIt).second;
-    nbtri += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
-    nbqua += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
+    std::vector<smIdType> aVec = (*anIt).second;
+    nbtri += std::max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
+    nbqua += std::max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
     GProp_GProps G;
     BRepGProp::SurfaceProperties(F,G);
     double anArea = G.Mass();
@@ -2742,7 +2819,7 @@ bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
   }
 
   // collect info from edges
-  int nb0d_e = 0, nb1d_e = 0;
+  smIdType nb0d_e = 0, nb1d_e = 0;
   bool IsQuadratic = false;
   bool IsFirst = true;
   TopTools_MapOfShape tmpMap;
@@ -2753,9 +2830,9 @@ bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
     tmpMap.Add(E);
     SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
     MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
-    std::vector<int> aVec = (*anIt).second;
+    std::vector<smIdType> aVec = (*anIt).second;
     nb0d_e += aVec[SMDSEntity_Node];
-    nb1d_e += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
+    nb1d_e += std::max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
     if(IsFirst) {
       IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
       IsFirst = false;
@@ -2763,18 +2840,18 @@ bool GHS3DPlugin_GHS3D::Evaluate(SMESH_Mesh& aMesh,
   }
   tmpMap.Clear();
 
-  double ELen = sqrt(2.* ( fullArea/(nbtri+nbqua*2) ) / sqrt(3.0) );
+  double ELen = sqrt(2.* ( fullArea/double(nbtri+nbqua*2) ) / sqrt(3.0) );
 
   GProp_GProps G;
   BRepGProp::VolumeProperties(aShape,G);
   double aVolume = G.Mass();
   double tetrVol = 0.1179*ELen*ELen*ELen;
   double CoeffQuality = 0.9;
-  int nbVols = int(aVolume/tetrVol/CoeffQuality);
-  int nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
-  int nb1d_in = (int) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
-  std::vector<int> aVec(SMDSEntity_Last);
-  for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0;
+  smIdType nbVols = smIdType(aVolume/tetrVol/CoeffQuality);
+  smIdType nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
+  smIdType nb1d_in = (smIdType) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
+  std::vector<smIdType> aVec(SMDSEntity_Last);
+  for(smIdType i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aVec[i]=0;
   if( IsQuadratic ) {
     aVec[SMDSEntity_Node] = nb1d_in/6 + 1 + nb1d_in;
     aVec[SMDSEntity_Quad_Tetra] = nbVols - nbqua*2;
@@ -2825,9 +2902,9 @@ namespace
      */
     void ProcessEvent(const int                       event,
                       const int                       eventType,
-                      SMESH_subMesh*                  subMesh,
+                      SMESH_subMesh*                  /*subMesh*/,
                       SMESH_subMeshEventListenerData* data,
-                      const SMESH_Hypothesis*         hyp)
+                      const SMESH_Hypothesis*         /*hyp*/)
     {
       if ( SMESH_subMesh::SUBMESH_LOADED == event &&
            SMESH_subMesh::COMPUTE_EVENT  == eventType &&
@@ -2867,11 +2944,11 @@ namespace
     /*!
      * \brief Treat events of the subMesh
      */
-    void ProcessEvent(const int                       event,
+    void ProcessEvent(const int                       /*event*/,
                       const int                       eventType,
                       SMESH_subMesh*                  subMesh,
-                      SMESH_subMeshEventListenerData* data,
-                      const SMESH_Hypothesis*         hyp)
+                      SMESH_subMeshEventListenerData* /*data*/,
+                      const SMESH_Hypothesis*         /*hyp*/)
     {
       if (SMESH_subMesh::ALGO_EVENT == eventType &&
           !subMesh->GetAlgo() )
@@ -2936,7 +3013,7 @@ double GHS3DPlugin_GHS3D::GetProgress() const
   if ( _isLibUsed )
   {
     // this->_progress is advanced by MG_Tetra_API according to messages from MG library
-    // but sharply. Advanced it a bit to get smoother advancement.
+    // 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();