Salome HOME
Creating Remote and SA NETGEN_3D plugins
[plugins/netgenplugin.git] / src / NETGENPlugin / NETGENPlugin_NETGEN_3D.cxx
index caa026822593ba126d8a9efdb4bd8aec01aa97c5..8180d0bb3a71b01de788e82d26c53cc1a1d3c277 100644 (file)
 #include "NETGENPlugin_NETGEN_3D.hxx"
 
 #include "NETGENPlugin_Hypothesis.hxx"
-#include "NETGENPlugin_Provider.hxx"
 
-#include "DriverStep.hxx"
-#include "DriverMesh.hxx"
-#include "netgen_param.hxx"
+// TODO: remove use of netgen_param
+#include "NETGENPlugin_DriverParam.hxx"
 
 #include <SMDS_MeshElement.hxx>
 #include <SMDS_MeshNode.hxx>
@@ -52,6 +50,7 @@
 #include <StdMeshers_ViscousLayers.hxx>
 #include <SMESH_subMesh.hxx>
 
+
 #include <BRepGProp.hxx>
 #include <BRep_Tool.hxx>
 #include <GProp_GProps.hxx>
@@ -70,8 +69,6 @@
 #include <map>
 
 #include <cstdlib>
-#include <boost/filesystem.hpp>
-namespace fs = boost::filesystem;
 
 /*
   Netgen include files
@@ -95,6 +92,7 @@ namespace nglib {
 namespace netgen {
 
   NETGENPLUGIN_DLL_HEADER
+  extern MeshingParameters mparam;
 
   NETGENPLUGIN_DLL_HEADER
   extern volatile multithreadt multithread;
@@ -196,58 +194,39 @@ bool NETGENPlugin_NETGEN_3D::CheckHypothesis (SMESH_Mesh&         aMesh,
 }
 
 
-void NETGENPlugin_NETGEN_3D::FillParameters(const NETGENPlugin_Hypothesis* hyp, netgen_params &aParams)
-{
-  aParams.maxh               = hyp->GetMaxSize();
-  aParams.minh               = hyp->GetMinSize();
-  aParams.segmentsperedge    = hyp->GetNbSegPerEdge();
-  aParams.grading            = hyp->GetGrowthRate();
-  aParams.curvaturesafety    = hyp->GetNbSegPerRadius();
-  aParams.secondorder        = hyp->GetSecondOrder() ? 1 : 0;
-  aParams.quad               = hyp->GetQuadAllowed() ? 1 : 0;
-  aParams.optimize           = hyp->GetOptimize();
-  aParams.fineness           = hyp->GetFineness();
-  aParams.uselocalh          = hyp->GetSurfaceCurvature();
-  aParams.merge_solids       = hyp->GetFuseEdges();
-  aParams.chordalError       = hyp->GetChordalErrorEnabled() ? hyp->GetChordalError() : -1.;
-  aParams.optsteps2d         = aParams.optimize ? hyp->GetNbSurfOptSteps() : 0;
-  aParams.optsteps3d         = aParams.optimize ? hyp->GetNbVolOptSteps()  : 0;
-  aParams.elsizeweight       = hyp->GetElemSizeWeight();
-  aParams.opterrpow          = hyp->GetWorstElemMeasure();
-  aParams.delaunay           = hyp->GetUseDelauney();
-  aParams.checkoverlap       = hyp->GetCheckOverlapping();
-  aParams.checkchartboundary = hyp->GetCheckChartBoundary();
-#ifdef NETGEN_V6
-  // std::string
-  aParams.meshsizefilename = hyp->GetMeshSizeFile();
-#else
-  // const char*
-  aParams.meshsizefilename = hyp->GetMeshSizeFile().empty() ? 0 : hyp->GetMeshSizeFile().c_str();
-#endif
-#ifdef NETGEN_V6
-  aParams.closeedgefac = 2;
-#else
-  aParams.closeedgefac = 0;
-#endif
-}
 
-void NETGENPlugin_NETGEN_3D::exportElementOrientation(SMESH_Mesh& aMesh,
-                                                      const TopoDS_Shape& aShape,
-                                                      netgen_params& aParams,
-                                                      const std::string output_file)
+//=============================================================================
+/*!
+ *Here we are going to use the NETGEN mesher
+ */
+//=============================================================================
+
+/**
+ * @brief Get an iterator on the Surface element with their orientation
+ *
+ */
+
+bool NETGENPlugin_NETGEN_3D::getSurfaceElements(
+    SMESH_Mesh&         aMesh,
+    const TopoDS_Shape& aShape,
+    SMESH_ProxyMesh::Ptr proxyMesh,
+    NETGENPlugin_Internals &internals,
+    SMESH_MesherHelper &helper,
+    netgen_params &aParams,
+    std::map<const SMDS_MeshElement*, tuple<bool, bool>>& listElements
+)
 {
-  SMESH_MesherHelper helper(aMesh);
-  NETGENPlugin_Internals internals( aMesh, aShape, /*is3D=*/true );
-  SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( aMesh ));
-  std::map<vtkIdType, bool> elemOrientation;
+  SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
+  TopAbs_ShapeEnum mainType = aMesh.GetShapeToMesh().ShapeType();
+  bool checkReverse = ( mainType == TopAbs_COMPOUND || mainType == TopAbs_COMPSOLID );
 
   for ( TopExp_Explorer exFa( aShape, TopAbs_FACE ); exFa.More(); exFa.Next())
   {
     const TopoDS_Shape& aShapeFace = exFa.Current();
-    int faceID = aMesh.GetMeshDS()->ShapeToIndex( aShapeFace );
+    int faceID = meshDS->ShapeToIndex( aShapeFace );
     bool isInternalFace = internals.isInternalShape( faceID );
     bool isRev = false;
-    if ( !isInternalFace &&
+    if ( checkReverse && !isInternalFace &&
           helper.NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 )
       // IsReversedSubMesh() can work wrong on strongly curved faces,
       // so we use it as less as possible
@@ -266,19 +245,100 @@ void NETGENPlugin_NETGEN_3D::exportElementOrientation(SMESH_Mesh& aMesh,
 
       iteratorElem = aSubMeshDSFace->GetElements();
     }
-    while ( iteratorElem->more() ) // loop on elements on a geom face
-    {
-      // check mesh face
+    while(iteratorElem->more()){
       const SMDS_MeshElement* elem = iteratorElem->next();
-      if ( !elem )
-        error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
-      if ( elem->NbCornerNodes() != 3 )
-        error( COMPERR_BAD_INPUT_MESH, "Not triangle element encounters");
-      elemOrientation[elem->GetID()] = isRev;
+      // check mesh face
+      if ( !elem ){
+        aParams._error = COMPERR_BAD_INPUT_MESH;
+        aParams._comment = "Null element encounters";
+        return true;
+      }
+      if ( elem->NbCornerNodes() != 3 ){
+        aParams._error = COMPERR_BAD_INPUT_MESH;
+        aParams._comment = "Not triangle element encounters";
+        return true;
+      }
+      listElements[elem] = tuple(isRev, isInternalFace);
+    }
+  }
+
+  return false;
+}
+
+
+bool NETGENPlugin_NETGEN_3D::computeFillNgMesh(
+  SMESH_Mesh&         aMesh,
+  const TopoDS_Shape& aShape,
+  vector< const SMDS_MeshNode* > &nodeVec,
+  NETGENPlugin_NetgenLibWrapper &ngLib,
+  SMESH_MesherHelper &helper,
+  netgen_params &aParams,
+  int &Netgen_NbOfNodes)
+{
+  netgen::multithread.terminate = 0;
+  netgen::multithread.task = "Volume meshing";
+  aParams._progressByTic = -1.;
+
+  SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
+
+  aParams._quadraticMesh = helper.IsQuadraticSubMesh(aShape);
+  helper.SetElementsOnShape( true );
+
+  Netgen_NbOfNodes = 0;
+  double Netgen_point[3];
+  int Netgen_triangle[3];
+
+  Ng_Mesh * Netgen_mesh = (Ng_Mesh*)ngLib._ngMesh;
+
+  {
+    const int invalid_ID = -1;
+
+    SMESH::Controls::Area areaControl;
+    SMESH::Controls::TSequenceOfXYZ nodesCoords;
+
+    // maps nodes to ng ID
+    typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap;
+    typedef TNodeToIDMap::value_type                     TN2ID;
+    TNodeToIDMap nodeToNetgenID;
+
+    // find internal shapes
+    NETGENPlugin_Internals internals( aMesh, aShape, /*is3D=*/true );
+
+    // ---------------------------------
+    // Feed the Netgen with surface mesh
+    // ---------------------------------
+    bool isRev=false;
+    bool isInternalFace=false;
+
+    SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( aMesh ));
+    if ( aParams._viscousLayersHyp )
+    {
+      netgen::multithread.percent = 3;
+      proxyMesh = aParams._viscousLayersHyp->Compute( aMesh, aShape );
+      if ( !proxyMesh )
+        return false;
+    }
+    if ( aMesh.NbQuadrangles() > 0 )
+    {
+      netgen::multithread.percent = 6;
+      StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor;
+      Adaptor->Compute(aMesh,aShape,proxyMesh.get());
+      proxyMesh.reset( Adaptor );
+    }
+
+    std::map<const SMDS_MeshElement*, tuple<bool, bool>> listElements;
+    bool ret = getSurfaceElements(aMesh, aShape, proxyMesh, internals, helper, aParams, listElements);
+    if(ret)
+      return ret;
+
+    for ( auto const& [elem, info] : listElements ) // loop on elements on a geom face
+    {
+      isRev = get<0>(info);
+      isInternalFace = get<1>(info);
       // Add nodes of triangles and triangles them-selves to netgen mesh
 
       // add three nodes of triangle
-/*      bool hasDegen = false;
+      bool hasDegen = false;
       for ( int iN = 0; iN < 3; ++iN )
       {
         const SMDS_MeshNode* node = elem->GetNode( iN );
@@ -314,430 +374,248 @@ void NETGENPlugin_NETGEN_3D::exportElementOrientation(SMESH_Mesh& aMesh,
       {
         swap( Netgen_triangle[1], Netgen_triangle[2] );
         Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
-      }*/
+      }
     } // loop on elements on a face
-  } // loop on faces of a SOLID or SHELL
 
-  std::ofstream df(output_file, ios::out|ios::binary);
-  int size=elemOrientation.size();
-  std::cout << size<< std::endl;
-  std::cout << "vtkIdType " << sizeof(vtkIdType) << std::endl;
+    // insert old nodes into nodeVec
+    nodeVec.resize( nodeToNetgenID.size() + 1, 0 );
+    TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
+    for ( ; n_id != nodeToNetgenID.end(); ++n_id )
+      nodeVec[ n_id->second ] = n_id->first;
+    nodeToNetgenID.clear();
 
-  df.write((char*)&size, sizeof(int));
-  for(auto const& [id, orient]:elemOrientation){
-    df.write((char*)&id, sizeof(vtkIdType));
-    df.write((char*)&orient, sizeof(bool));
+    if ( internals.hasInternalVertexInSolid() )
+    {
+      netgen::OCCGeometry occgeo;
+      NETGENPlugin_Mesher::AddIntVerticesInSolids( occgeo,
+                                                   (netgen::Mesh&) *Netgen_mesh,
+                                                   nodeVec,
+                                                   internals);
+    }
   }
-  df.close();
-  // for(auto const& [id, orient] : elemOrientation)
-  //   {
-  //     std::cout << id << " : " << orient << ", ";
-  //   }
+  Netgen_NbOfNodes = Ng_GetNP( Netgen_mesh );
+  return false;
 }
 
-int NETGENPlugin_NETGEN_3D::ParallelCompute(SMESH_Mesh&         aMesh,
-                                             const TopoDS_Shape& aShape)
-{
-  aMesh.Lock();
-  SMESH_Hypothesis::Hypothesis_Status hypStatus;
-  CheckHypothesis(aMesh, aShape, hypStatus);
-
-  // Temporary folder for run
-  fs::path tmp_folder = aMesh.tmp_folder / fs::unique_path(fs::path("Volume-%%%%-%%%%"));
-  fs::create_directories(tmp_folder);
-  // Using MESH2D generated after all triangles where created.
-  fs::path mesh_file=aMesh.tmp_folder / fs::path("Mesh2D.med");
-  fs::path element_orientation_file=tmp_folder / fs::path("element_orientation.dat");
-  fs::path new_element_file=tmp_folder / fs::path("new_elements.dat");
-  fs::path tmp_mesh_file=tmp_folder / fs::path("tmp_mesh.med");
-  // TODO: Remove that file we do not use it
-  fs::path output_mesh_file=tmp_folder / fs::path("output_mesh.med");
-  fs::path shape_file=tmp_folder / fs::path("shape.step");
-  fs::path param_file=tmp_folder / fs::path("netgen3d_param.txt");
-  fs::path log_file=tmp_folder / fs::path("run_mesher.log");
-  //TODO: Handle variable mesh_name
-  std::string mesh_name = "Maillage_1";
-
-  //Writing Shape
-  export_shape(shape_file.string(), aShape);
-  //Writing hypo
-  netgen_params aParams;
-  FillParameters(_hypParameters, aParams);
-
-  export_netgen_params(param_file.string(), aParams);
-
-  // Exporting element orientation
-  exportElementOrientation(aMesh, aShape, aParams, element_orientation_file.string());
-
-  aMesh.Unlock();
-  // Calling run_mesher
-  std::string cmd;
-  // TODO: Add run_meher to bin
-  std::string run_mesher_exe = "/home/B61570/work_in_progress/ssmesh/run_mesher/build/src/run_mesher";
-  cmd = run_mesher_exe +
-                  " NETGEN3D " + mesh_file.string() + " "
-                               + shape_file.string() + " "
-                               + param_file.string() + " "
-                               + element_orientation_file.string() + " "
-                               + new_element_file.string() + " "
-                               + output_mesh_file.string() +
-                               " >> " + log_file.string();
-
-  std::cout << "Running command: " << std::endl;
-  std::cout << cmd << std::endl;
-
-  // Writing command in log
-  std::ofstream flog(log_file.string());
-  flog << cmd << endl;
-  flog.close();
-
-  int ret = system(cmd.c_str());
-
-  // TODO: error handling
-  if(ret != 0){
-    // Run crahed
-    //throw Exception("Meshing failed");
-    std::cerr << "Issue with command: " << std::endl;
-    std::cerr << cmd << std::endl;
-    return false;
-  }
+bool NETGENPlugin_NETGEN_3D::computePrepareParam(
+  SMESH_Mesh&         aMesh,
+  NETGENPlugin_NetgenLibWrapper &ngLib,
+  netgen::OCCGeometry &occgeo,
+  SMESH_MesherHelper &helper,
+  netgen_params &aParams,
+  int &endWith)
 
+{
+  netgen::multithread.terminate = 0;
 
-  aMesh.Lock();
-  std::ifstream df(new_element_file.string(), ios::binary);
-
+  netgen::Mesh* ngMesh = ngLib._ngMesh;
 
-  int Netgen_NbOfNodes;
-  int Netgen_NbOfNodesNew;
-  int Netgen_NbOfTetra;
-  double Netgen_point[3];
-  int    Netgen_tetrahedron[4];
-  int nodeID;
+  NETGENPlugin_Mesher aMesher( &aMesh, helper.GetSubShape(), /*isVolume=*/true );
 
-  SMESH_MesherHelper helper(aMesh);
-  // This function
-  int _quadraticMesh = helper.IsQuadraticSubMesh(aShape);
-  helper.SetElementsOnShape( true );
 
-  // Filling nodevec (correspondence netgen numbering mesh numbering)
-  // Number of nodes
-  df.read((char*) &Netgen_NbOfNodes, sizeof(int));
-  df.read((char*) &Netgen_NbOfNodesNew, sizeof(int));
+  if ( aParams._hypParameters )
+  {
+    aMesher.SetParameters( aParams._hypParameters );
 
-  vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 );
+    if ( !aParams._hypParameters->GetLocalSizesAndEntries().empty() ||
+         !aParams._hypParameters->GetMeshSizeFile().empty() )
+    {
+      if ( ! &ngMesh->LocalHFunction() )
+      {
+        netgen::Point3d pmin, pmax;
+        ngMesh->GetBox( pmin, pmax, 0 );
+        ngMesh->SetLocalH( pmin, pmax, aParams._hypParameters->GetGrowthRate() );
+      }
+      aMesher.SetLocalSize( occgeo, *ngMesh );
 
-  for (int nodeIndex = 1 ; nodeIndex <= Netgen_NbOfNodes; ++nodeIndex )
-  {
-    //Id of the point
-    df.read((char*) &nodeID, sizeof(int));
-    // std::cout << "Old Node " << nodeIndex << ": " << nodeID << std::endl;
-    // TODO: do stuff to fill nodeVec ??
-    nodeVec.at(nodeIndex) = nullptr;
-    SMDS_NodeIteratorPtr iteratorNode = aMesh.GetMeshDS()->nodesIterator();
-    while(iteratorNode->more()){
-      const SMDS_MeshNode* node = iteratorNode->next();
-      if(node->GetID() == nodeID){
-        nodeVec.at(nodeIndex) = node;
-        break;
+      try {
+        ngMesh->LoadLocalMeshSize( netgen::mparam.meshsizefilename );
+      } catch (netgen::NgException & ex) {
+        aParams._error = COMPERR_BAD_PARMETERS;
+        aParams._comment = ex.What();
+        return false;
       }
     }
-    if(nodeVec.at(nodeIndex) == nullptr){
-      std::cout << "Error could not identify id";
-      return false;
-    }
+    if ( !aParams._hypParameters->GetOptimize() )
+      endWith = netgen::MESHCONST_MESHVOLUME;
   }
-
-  // Writing info on new points
-  for (int nodeIndex = Netgen_NbOfNodes +1 ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex )
+  else if ( aParams._hypMaxElementVolume )
   {
-    // Coordinates of the point
-    df.read((char *) &Netgen_point, sizeof(double)*3);
-    // std::cout << "Node " << nodeIndex << ": ";
-    // for(auto coord:Netgen_point){
-    //   std::cout << coord << " ";
-    // }
-    // std::cout << std::endl;
-    nodeVec.at(nodeIndex) = helper.AddNode(Netgen_point[0],
-                                           Netgen_point[1],
-                                           Netgen_point[2]);
-
+    netgen::mparam.maxh = pow( 72, 1/6. ) * pow( aParams.maxElementVolume, 1/3. );
+    // limitVolumeSize( ngMesh, mparam.maxh ); // result is unpredictable
   }
-
-  // create tetrahedrons
-  df.read((char*) &Netgen_NbOfTetra, sizeof(int));
-  for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
+  else if ( aMesh.HasShapeToMesh() )
   {
-    df.read((char*) &Netgen_tetrahedron, sizeof(int)*4);
-    // std::cout << "Element " << elemIndex << ": ";
-    // for(auto elem:Netgen_tetrahedron){
-    //   std::cout << elem << " ";
-    // }
-    // std::cout << std::endl;
-    // TODO: Add tetra
-    helper.AddVolume (nodeVec.at( Netgen_tetrahedron[0] ),
-                      nodeVec.at( Netgen_tetrahedron[1] ),
-                      nodeVec.at( Netgen_tetrahedron[2] ),
-                      nodeVec.at( Netgen_tetrahedron[3] ));
+    aMesher.PrepareOCCgeometry( occgeo, helper.GetSubShape(), aMesh );
+    netgen::mparam.maxh = occgeo.GetBoundingBox().Diam()/2;
+  }
+  else
+  {
+    netgen::Point3d pmin, pmax;
+    ngMesh->GetBox (pmin, pmax);
+    netgen::mparam.maxh = Dist(pmin, pmax)/2;
   }
-  df.close();
-
-  aMesh.Unlock();
 
-  return true;
+  if ( !aParams._hypParameters && aMesh.HasShapeToMesh() )
+  {
+    netgen::mparam.minh = aMesher.GetDefaultMinSize( helper.GetSubShape(), netgen::mparam.maxh );
+  }
+  return false;
 }
 
-//=============================================================================
-/*!
- *Here we are going to use the NETGEN mesher
- */
-//=============================================================================
-
-bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
-                                     const TopoDS_Shape& aShape)
+bool NETGENPlugin_NETGEN_3D::computeRunMesher(
+  netgen::OCCGeometry &occgeo,
+  vector< const SMDS_MeshNode* > &nodeVec,
+  netgen::Mesh* ngMesh,
+  NETGENPlugin_NetgenLibWrapper &ngLib,
+  netgen_params &aParams,
+  int &startWith, int &endWith)
 {
+  int err = 1;
 
-  return ParallelCompute(aMesh, aShape);
-  aMesh.Lock();
-  SMESH_Hypothesis::Hypothesis_Status hypStatus;
-  CheckHypothesis(aMesh, aShape, hypStatus);
-  aMesh.Unlock();
-
-  //netgen::multithread.terminate = 0;
-  //netgen::multithread.task = "Volume meshing";
-  _progressByTic = -1.;
-
-  SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
-
-  SMESH_MesherHelper *helper = new SMESH_MesherHelper(aMesh);
-  _quadraticMesh = helper->IsQuadraticSubMesh(aShape);
-  helper->SetElementsOnShape( true );
-
-  int Netgen_NbOfNodes = 0;
-  double Netgen_point[3];
-  int Netgen_triangle[3];
+  try
+  {
+    OCC_CATCH_SIGNALS;
 
-  NETGENPlugin_NetgenLibWrapper *ngLib;
-  int id_nglib = nglib_provider.take(&ngLib);
-  Ng_Mesh * Netgen_mesh = (Ng_Mesh*)ngLib->_ngMesh;
+    ngLib.CalcLocalH(ngMesh);
+    err = ngLib.GenerateMesh(occgeo, startWith, endWith);
 
-  // vector of nodes in which node index == netgen ID
-  vector< const SMDS_MeshNode* > nodeVec;
-  aMesh.Lock();
+    if(netgen::multithread.terminate)
+      return false;
+    if ( err ){
+      aParams._comment = SMESH_Comment("Error in netgen::OCCGenerateMesh() at ") << netgen::multithread.task;
+      return true;
+    }
+  }
+  catch (Standard_Failure& ex)
   {
-    const int invalid_ID = -1;
+    SMESH_Comment str("Exception in  netgen::OCCGenerateMesh()");
+    str << " at " << netgen::multithread.task
+        << ": " << ex.DynamicType()->Name();
+    if ( ex.GetMessageString() && strlen( ex.GetMessageString() ))
+      str << ": " << ex.GetMessageString();
+    aParams._comment = str;
+    return true;
+  }
+  catch (netgen::NgException& exc)
+  {
+    SMESH_Comment str("NgException");
+    if ( strlen( netgen::multithread.task ) > 0 )
+      str << " at " << netgen::multithread.task;
+    str << ": " << exc.What();
+    aParams._comment = str;
+    return true;
+  }
+  catch (...)
+  {
+    SMESH_Comment str("Exception in  netgen::OCCGenerateMesh()");
+    if ( strlen( netgen::multithread.task ) > 0 )
+      str << " at " << netgen::multithread.task;
+    aParams._comment = str;
+    return true;
+  }
 
-    SMESH::Controls::Area areaControl;
-    SMESH::Controls::TSequenceOfXYZ nodesCoords;
+  if ( err )
+  {
+    SMESH_ComputeErrorPtr ce = NETGENPlugin_Mesher::ReadErrors(nodeVec);
+    if ( ce && ce->HasBadElems() ){
+      aParams._error = ce->myName;
+      aParams._comment = ce->myComment;
+      return true;
+    }
+  }
 
-    // maps nodes to ng ID
-    typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap;
-    typedef TNodeToIDMap::value_type                     TN2ID;
-    TNodeToIDMap nodeToNetgenID;
+  return false;
+}
 
-    // find internal shapes
-    NETGENPlugin_Internals internals( aMesh, aShape, /*is3D=*/true );
+bool NETGENPlugin_NETGEN_3D::computeFillMesh(
+  vector< const SMDS_MeshNode* > &nodeVec,
+  NETGENPlugin_NetgenLibWrapper &ngLib,
+  SMESH_MesherHelper &helper,
+  int &Netgen_NbOfNodes
+  )
+{
+  Ng_Mesh* Netgen_mesh = ngLib.ngMesh();
 
-    // ---------------------------------
-    // Feed the Netgen with surface mesh
-    // ---------------------------------
+  int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
+  int Netgen_NbOfTetra    = Ng_GetNE(Netgen_mesh);
 
-    TopAbs_ShapeEnum mainType = aMesh.GetShapeToMesh().ShapeType();
-    bool checkReverse = ( mainType == TopAbs_COMPOUND || mainType == TopAbs_COMPSOLID );
+  bool isOK = ( /*status == NG_OK &&*/ Netgen_NbOfTetra > 0 );// get whatever built
+  if ( isOK )
+  {
+    double Netgen_point[3];
+    int    Netgen_tetrahedron[4];
 
-    SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( aMesh ));
-    if ( _viscousLayersHyp )
-    {
-      //netgen::multithread.percent = 3;
-      proxyMesh = _viscousLayersHyp->Compute( aMesh, aShape );
-      if ( !proxyMesh )
-        return false;
-    }
-    if ( aMesh.NbQuadrangles() > 0 )
+    // create and insert new nodes into nodeVec
+    nodeVec.resize( Netgen_NbOfNodesNew + 1, 0 );
+    int nodeIndex = Netgen_NbOfNodes + 1;
+    for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex )
     {
-      //netgen::multithread.percent = 6;
-      StdMeshers_QuadToTriaAdaptor* Adaptor = new StdMeshers_QuadToTriaAdaptor;
-      Adaptor->Compute(aMesh,aShape,proxyMesh.get());
-      proxyMesh.reset( Adaptor );
+      Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point );
+      nodeVec.at(nodeIndex) = helper.AddNode(Netgen_point[0], Netgen_point[1], Netgen_point[2]);
     }
 
-    for ( TopExp_Explorer exFa( aShape, TopAbs_FACE ); exFa.More(); exFa.Next())
+    // create tetrahedrons
+    for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
     {
-      const TopoDS_Shape& aShapeFace = exFa.Current();
-      int faceID = meshDS->ShapeToIndex( aShapeFace );
-      bool isInternalFace = internals.isInternalShape( faceID );
-      bool isRev = false;
-      if ( checkReverse && !isInternalFace &&
-           helper->NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 )
-        // IsReversedSubMesh() can work wrong on strongly curved faces,
-        // so we use it as less as possible
-        isRev = helper->IsReversedSubMesh( TopoDS::Face( aShapeFace ));
-
-      const SMESHDS_SubMesh * aSubMeshDSFace = proxyMesh->GetSubMesh( aShapeFace );
-      if ( !aSubMeshDSFace ) continue;
-
-      SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
-      if ( _quadraticMesh &&
-           dynamic_cast< const SMESH_ProxyMesh::SubMesh*>( aSubMeshDSFace ))
+      Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron);
+      try
       {
-        // add medium nodes of proxy triangles to helper (#16843)
-        while ( iteratorElem->more() )
-          helper->AddTLinks( static_cast< const SMDS_MeshFace* >( iteratorElem->next() ));
-
-        iteratorElem = aSubMeshDSFace->GetElements();
+        helper.AddVolume (nodeVec.at( Netgen_tetrahedron[0] ),
+                          nodeVec.at( Netgen_tetrahedron[1] ),
+                          nodeVec.at( Netgen_tetrahedron[2] ),
+                          nodeVec.at( Netgen_tetrahedron[3] ));
       }
-      while ( iteratorElem->more() ) // loop on elements on a geom face
+      catch (...)
       {
-        // check mesh face
-        const SMDS_MeshElement* elem = iteratorElem->next();
-        if ( !elem )
-          return error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
-        if ( elem->NbCornerNodes() != 3 )
-          return error( COMPERR_BAD_INPUT_MESH, "Not triangle element encounters");
-
-        // Add nodes of triangles and triangles them-selves to netgen mesh
-
-        // add three nodes of triangle
-        bool hasDegen = false;
-        for ( int iN = 0; iN < 3; ++iN )
-        {
-          const SMDS_MeshNode* node = elem->GetNode( iN );
-          const int shapeID = node->getshapeId();
-          if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_EDGE &&
-               helper->IsDegenShape( shapeID ))
-          {
-            // ignore all nodes on degeneraged edge and use node on its vertex instead
-            TopoDS_Shape vertex = TopoDS_Iterator( meshDS->IndexToShape( shapeID )).Value();
-            node = SMESH_Algo::VertexNode( TopoDS::Vertex( vertex ), meshDS );
-            hasDegen = true;
-          }
-          int& ngID = nodeToNetgenID.insert(TN2ID( node, invalid_ID )).first->second;
-          if ( ngID == invalid_ID )
-          {
-            ngID = ++Netgen_NbOfNodes;
-            Netgen_point [ 0 ] = node->X();
-            Netgen_point [ 1 ] = node->Y();
-            Netgen_point [ 2 ] = node->Z();
-            Ng_AddPoint(Netgen_mesh, Netgen_point);
-          }
-          Netgen_triangle[ isRev ? 2-iN : iN ] = ngID;
-        }
-        // add triangle
-        if ( hasDegen && (Netgen_triangle[0] == Netgen_triangle[1] ||
-                          Netgen_triangle[0] == Netgen_triangle[2] ||
-                          Netgen_triangle[2] == Netgen_triangle[1] ))
-          continue;
-
-        Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
+      }
+    }
+  }
+  return false;
+}
 
-        if ( isInternalFace && !proxyMesh->IsTemporary( elem ))
-        {
-          swap( Netgen_triangle[1], Netgen_triangle[2] );
-          Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
-        }
-      } // loop on elements on a face
-    } // loop on faces of a SOLID or SHELL
+bool NETGENPlugin_NETGEN_3D::Compute(
+  SMESH_Mesh&         aMesh,
+  const TopoDS_Shape& aShape)
+{
+  // vector of nodes in which node index == netgen ID
+  vector< const SMDS_MeshNode* > nodeVec;
+  NETGENPlugin_NetgenLibWrapper ngLib;
+  SMESH_MesherHelper helper(aMesh);
+  int startWith = netgen::MESHCONST_MESHVOLUME;
+  int endWith   = netgen::MESHCONST_OPTVOLUME;
+  int Netgen_NbOfNodes;
 
-    // insert old nodes into nodeVec
-    nodeVec.resize( nodeToNetgenID.size() + 1, 0 );
-    TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
-    for ( ; n_id != nodeToNetgenID.end(); ++n_id )
-      nodeVec[ n_id->second ] = n_id->first;
-    nodeToNetgenID.clear();
+  netgen_params aParams;
 
-    // TODO: Handle internal vertex
-    if ( internals.hasInternalVertexInSolid() )
-    {
-      netgen::OCCGeometry occgeo;
-      NETGENPlugin_Mesher::AddIntVerticesInSolids( occgeo,
-                                                   (netgen::Mesh&) *Netgen_mesh,
-                                                   nodeVec,
-                                                   internals);
-    }
+  aParams._hypParameters = const_cast<NETGENPlugin_Hypothesis*>(_hypParameters);
+  aParams._hypMaxElementVolume = const_cast<StdMeshers_MaxElementVolume*>(_hypMaxElementVolume);
+  aParams.maxElementVolume = _maxElementVolume;
+  aParams._progressByTic = _progressByTic;
+  aParams._quadraticMesh = _quadraticMesh;
+  aParams._viscousLayersHyp = const_cast<StdMeshers_ViscousLayers*>(_viscousLayersHyp);
+
+  bool ret;
+  ret = computeFillNgMesh(aMesh, aShape, nodeVec, ngLib, helper, aParams, Netgen_NbOfNodes);
+  if(ret)
+    return error( aParams._error, aParams._comment);
+
+  netgen::OCCGeometry occgeo;
+  computePrepareParam(aMesh, ngLib, occgeo, helper, aParams, endWith);
+  ret = computeRunMesher(occgeo, nodeVec, ngLib._ngMesh, ngLib, aParams, startWith, endWith);
+  if(ret){
+    if(aParams._error)
+      return error(aParams._error, aParams._comment);
+
+    error(aParams._comment);
+    return true;
   }
-  aMesh.Unlock();
+  computeFillMesh(nodeVec, ngLib, helper, Netgen_NbOfNodes);
 
-  // -------------------------
-  // Generate the volume mesh
-  // -------------------------
-  ngLib->_isComputeOk = compute( aMesh, *helper, nodeVec, *ngLib );
-  bool ret = ngLib->_isComputeOk;
-  nglib_provider.release(id_nglib, true);
+  return false;
 
-  return ret;
 }
 
-// namespace
-// {
-//   void limitVolumeSize( netgen::Mesh* ngMesh,
-//                         double        maxh )
-//   {
-//     // get average h of faces
-//     double faceh = 0;
-//     int nbh = 0;
-//     for (int i = 1; i <= ngMesh->GetNSE(); i++)
-//     {
-//       const netgen::Element2d& face = ngMesh->SurfaceElement(i);
-//       for (int j=1; j <= face.GetNP(); ++j)
-//       {
-//         const netgen::PointIndex & i1 = face.PNumMod(j);
-//         const netgen::PointIndex & i2 = face.PNumMod(j+1);
-//         if ( i1 < i2 )
-//         {
-//           const netgen::Point3d & p1 = ngMesh->Point( i1 );
-//           const netgen::Point3d & p2 = ngMesh->Point( i2 );
-//           faceh += netgen::Dist2( p1, p2 );
-//           nbh++;
-//         }
-//       }
-//     }
-//     faceh = Sqrt( faceh / nbh );
-
-//     double compareh;
-//     if      ( faceh < 0.5 * maxh ) compareh = -1;
-//     else if ( faceh > 1.5 * maxh ) compareh = 1;
-//     else                           compareh = 0;
-//     // cerr << "faceh " << faceh << endl;
-//     // cerr << "init maxh " << maxh << endl;
-//     // cerr << "compareh " << compareh << endl;
-
-//     if ( compareh > 0 )
-//       maxh *= 1.2;
-//     else
-//       maxh *= 0.8;
-//     // cerr << "maxh " << maxh << endl;
-
-//     // get bnd box
-//     netgen::Point3d pmin, pmax;
-//     ngMesh->GetBox( pmin, pmax, 0 );
-//     const double dx = pmax.X() - pmin.X();
-//     const double dy = pmax.Y() - pmin.Y();
-//     const double dz = pmax.Z() - pmin.Z();
-
-//     if ( ! & ngMesh->LocalHFunction() )
-//       ngMesh->SetLocalH( pmin, pmax, compareh <= 0 ? 0.1 : 0.5 );
-
-//     // adjusted by SALOME_TESTS/Grids/smesh/bugs_08/I8
-//     const int nbX = Max( 2, int( dx / maxh * 2 ));
-//     const int nbY = Max( 2, int( dy / maxh * 2 ));
-//     const int nbZ = Max( 2, int( dz / maxh * 2 ));
-
-//     netgen::Point3d p;
-//     for ( int i = 0; i <= nbX; ++i )
-//     {
-//       p.X() = pmin.X() +  i * dx / nbX;
-//       for ( int j = 0; j <= nbY; ++j )
-//       {
-//         p.Y() = pmin.Y() +  j * dy / nbY;
-//         for ( int k = 0; k <= nbZ; ++k )
-//         {
-//           p.Z() = pmin.Z() +  k * dz / nbZ;
-//           ngMesh->RestrictLocalH( p, maxh );
-//         }
-//       }
-//     }
-//   }
-// }
-
 //================================================================================
 /*!
  * \brief set parameters and generate the volume mesh
@@ -749,7 +627,9 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
                                      vector< const SMDS_MeshNode* >& nodeVec,
                                      NETGENPlugin_NetgenLibWrapper&  ngLib)
 {
-  //netgen::multithread.terminate = 0;
+  auto time0 = std::chrono::high_resolution_clock::now();
+
+  netgen::multithread.terminate = 0;
 
   netgen::Mesh* ngMesh = ngLib._ngMesh;
   Ng_Mesh* Netgen_mesh = ngLib.ngMesh();
@@ -760,15 +640,11 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
   int err = 1;
 
   NETGENPlugin_Mesher aMesher( &aMesh, helper.GetSubShape(), /*isVolume=*/true );
-  netgen::OCCGeometry *occgeo;
-  int id_occgeo = occgeom_provider.take(&occgeo);
-  netgen::MeshingParameters mparam;
-  int id_mparam = mparam_provider.take(mparam);
-  aMesher.SetDefaultParameters(mparam);
+  netgen::OCCGeometry occgeo;
 
   if ( _hypParameters )
   {
-    aMesher.SetParameters( _hypParameters, mparam );
+    aMesher.SetParameters( _hypParameters );
 
     if ( !_hypParameters->GetLocalSizesAndEntries().empty() ||
          !_hypParameters->GetMeshSizeFile().empty() )
@@ -779,10 +655,10 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
         ngMesh->GetBox( pmin, pmax, 0 );
         ngMesh->SetLocalH( pmin, pmax, _hypParameters->GetGrowthRate() );
       }
-      aMesher.SetLocalSize( *occgeo, *ngMesh );
+      aMesher.SetLocalSize( occgeo, *ngMesh );
 
       try {
-        ngMesh->LoadLocalMeshSize( mparam.meshsizefilename );
+        ngMesh->LoadLocalMeshSize( netgen::mparam.meshsizefilename );
       } catch (netgen::NgException & ex) {
         return error( COMPERR_BAD_PARMETERS, ex.What() );
       }
@@ -792,32 +668,33 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
   }
   else if ( _hypMaxElementVolume )
   {
-    mparam.maxh = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. );
+    netgen::mparam.maxh = pow( 72, 1/6. ) * pow( _maxElementVolume, 1/3. );
     // limitVolumeSize( ngMesh, mparam.maxh ); // result is unpredictable
   }
   else if ( aMesh.HasShapeToMesh() )
   {
-    aMesher.PrepareOCCgeometry( *occgeo, helper.GetSubShape(), aMesh );
-    mparam.maxh = occgeo->GetBoundingBox().Diam()/2;
+    aMesher.PrepareOCCgeometry( occgeo, helper.GetSubShape(), aMesh );
+    netgen::mparam.maxh = occgeo.GetBoundingBox().Diam()/2;
   }
   else
   {
     netgen::Point3d pmin, pmax;
     ngMesh->GetBox (pmin, pmax);
-    mparam.maxh = Dist(pmin, pmax)/2;
+    netgen::mparam.maxh = Dist(pmin, pmax)/2;
   }
 
   if ( !_hypParameters && aMesh.HasShapeToMesh() )
   {
-    mparam.minh = aMesher.GetDefaultMinSize( helper.GetSubShape(), mparam.maxh );
+    netgen::mparam.minh = aMesher.GetDefaultMinSize( helper.GetSubShape(), netgen::mparam.maxh );
   }
 
   try
   {
     OCC_CATCH_SIGNALS;
+    auto time0 = std::chrono::high_resolution_clock::now();
 
     ngLib.CalcLocalH(ngMesh);
-    err = ngLib.GenerateMesh(*occgeo, startWith, endWith, ngMesh, mparam);
+    err = ngLib.GenerateMesh(occgeo, startWith, endWith);
 
     if(netgen::multithread.terminate)
       return false;
@@ -848,6 +725,9 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
       str << " at " << netgen::multithread.task;
     error(str);
   }
+  auto time1 = std::chrono::high_resolution_clock::now();
+  auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(time1-time0);
+  std::cout << "Time for seq:compute: " << elapsed.count() * 1e-9 << std::endl;
 
   int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
   int Netgen_NbOfTetra    = Ng_GetNE(Netgen_mesh);
@@ -863,10 +743,6 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
       error( ce );
   }
 
-  mparam_provider.release(id_mparam);
-  occgeom_provider.release(id_occgeo, true);
-
-  aMesh.Lock();
   bool isOK = ( /*status == NG_OK &&*/ Netgen_NbOfTetra > 0 );// get whatever built
   if ( isOK )
   {
@@ -898,7 +774,9 @@ bool NETGENPlugin_NETGEN_3D::compute(SMESH_Mesh&                     aMesh,
       }
     }
   }
-  aMesh.Unlock();
+  auto time2 = std::chrono::high_resolution_clock::now();
+  elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(time2-time1);
+  std::cout << "Time for seq:compute: " << elapsed.count() * 1e-9 << std::endl;
 
 
   return !err;