Salome HOME
Split of seq/par compute in gen
[modules/smesh.git] / src / SMESH / SMESH_Gen.cxx
index ef42e33e05069ebd2b649227a67b2525c28ac5c6..f2e4e0d9f6e9a3b493f37cc481698a85925490f0 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "SMESH_Gen.hxx"
 
+#include "SMESH_DriverMesh.hxx"
 #include "SMDS_Mesh.hxx"
 #include "SMDS_MeshElement.hxx"
 #include "SMDS_MeshNode.hxx"
@@ -47,6 +48,7 @@
 #include <TopoDS_Iterator.hxx>
 
 #include "memoire.h"
+#include <functional>
 
 #ifdef WIN32
   #include <windows.h>
@@ -55,6 +57,9 @@
 #include <Basics_Utils.hxx>
 
 using namespace std;
+#include <boost/filesystem.hpp>
+#include <boost/asio.hpp>
+namespace fs = boost::filesystem;
 
 // Environment variable separator
 #ifdef WIN32
@@ -155,6 +160,41 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(bool theIsEmbeddedMode)
   return aMesh;
 }
 
+//=============================================================================
+/*
+ * Parallel compute of a submesh
+ * This function is used to pass to thread_pool
+ */
+//=============================================================================
+const std::function<void(int,
+                         SMESH_subMesh*,
+                         SMESH_subMesh::compute_event,
+                         SMESH_subMesh*,
+                         bool,
+                         TopTools_IndexedMapOfShape *,
+                         TSetOfInt*)>
+     compute_function([&] (int id,
+                          SMESH_subMesh* sm,
+                          SMESH_subMesh::compute_event event,
+                          SMESH_subMesh *shapeSM,
+                          bool aShapeOnly,
+                          TopTools_IndexedMapOfShape *allowedSubShapes,
+                          TSetOfInt*                  aShapesId) -> void
+{
+  if (sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
+  {
+    sm->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
+    setCurrentSubMesh( sm );
+    sm->ComputeStateEngine(event);
+    setCurrentSubMesh( nullptr );
+    sm->SetAllowedSubShapes( nullptr );
+  }
+
+  if ( aShapesId )
+    aShapesId->insert( sm->GetId() );
+
+});
+
 //=============================================================================
 /*
  * Compute a mesh
@@ -182,6 +222,10 @@ bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
   const bool complexShapeFirst = true;
   const int  globalAlgoDim = 100;
 
+  // Pool of thread for computation
+  if(aMesh.IsParallel())
+    aMesh.InitPoolThreads();
+
   SMESH_subMeshIteratorPtr smIt;
 
   // Fix of Issue 22150. Due to !BLSURF->OnlyUnaryInput(), BLSURF computes edges
@@ -202,6 +246,11 @@ bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
     // Mesh all the sub-shapes starting from vertices
     // ===============================================
 
+    TopAbs_ShapeEnum previousShapeType = TopAbs_VERTEX;
+    int nbThreads = aMesh.GetNbThreads();
+    MESSAGE("Running mesh with threads: " << nbThreads << " mesher: " << aMesh.GetMesherNbThreads());
+
+
     smIt = shapeSM->getDependsOnIterator(includeSelf, !complexShapeFirst);
     while ( smIt->more() )
     {
@@ -212,6 +261,39 @@ bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
       const TopAbs_ShapeEnum shapeType = shape.ShapeType();
       if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX )
         continue;
+      if(shapeType==TopAbs_FACE||shapeType==TopAbs_EDGE)
+        aMesh.SetNbThreads(0);
+      else
+        aMesh.SetNbThreads(nbThreads);
+      if ((aMesh.IsParallel()||nbThreads!=0) && shapeType != previousShapeType) {
+        // Waiting for all threads for the previous type to end
+        aMesh.wait();
+
+        std::string file_name;
+        switch(previousShapeType){
+          case TopAbs_FACE:
+            file_name = "Mesh2D.med";
+            break;
+          case TopAbs_EDGE:
+            file_name = "Mesh1D.med";
+            break;
+          case TopAbs_VERTEX:
+            file_name = "Mesh0D.med";
+            break;
+          case TopAbs_SOLID:
+          default:
+            file_name = "";
+            break;
+        }
+        if(file_name != "")
+        {
+          fs::path mesh_file = fs::path(aMesh.tmp_folder) / fs::path(file_name);
+          exportMesh(mesh_file.string(), aMesh, "MESH");
+
+        }
+        //Resetting threaded pool info
+        previousShapeType = shapeType;
+      }
 
       // check for preview dimension limitations
       if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
@@ -221,37 +303,42 @@ bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
         smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
         continue;
       }
-
-      if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
+      if(aMesh.IsParallel())
       {
-        if (_compute_canceled)
-          return false;
-        smToCompute->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
-        setCurrentSubMesh( smToCompute );
-        smToCompute->ComputeStateEngine( computeEvent );
-        setCurrentSubMesh( nullptr );
-        smToCompute->SetAllowedSubShapes( nullptr );
+        boost::asio::post(*(aMesh._pool), std::bind(compute_function, 1, smToCompute, computeEvent,
+                          shapeSM, aShapeOnly, allowedSubShapes,
+                          aShapesId));
+      } else {
+        compute_function(1 ,smToCompute, computeEvent,
+                         shapeSM, aShapeOnly, allowedSubShapes,
+                         aShapesId);
+
+        if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE &&
+           ( shapeType != TopAbs_EDGE || !SMESH_Algo::isDegenerated( TopoDS::Edge( shape ))))
+          ret = false;
+        else if ( aShapesId )
+          aShapesId->insert( smToCompute->GetId() );
       }
+    }
 
-      // we check all the sub-meshes here and detect if any of them failed to compute
-      if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE &&
-          ( shapeType != TopAbs_EDGE || !SMESH_Algo::isDegenerated( TopoDS::Edge( shape ))))
-        ret = false;
-      else if ( aShapesId )
-        aShapesId->insert( smToCompute->GetId() );
+    // TODO: Check error handling in parallel mode
+    if(aMesh.IsParallel()){
+      // Waiting for the thread for Solids to finish
+      aMesh.wait();
     }
-    //aMesh.GetMeshDS()->Modified();
+
+    aMesh.GetMeshDS()->Modified();
+
     return ret;
   }
   else
   {
     // ================================================================
-    // Apply algos that do NOT require discreteized boundaries
+    // Apply algos that do NOT require discretized boundaries
     // ("all-dimensional") and do NOT support sub-meshes, starting from
     // the most complex shapes and collect sub-meshes with algos that
     // DO support sub-meshes
     // ================================================================
-
     list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes[4]; // for each dim
 
     // map to sort sm with same dim algos according to dim of
@@ -448,6 +535,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
           sm->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
           setCurrentSubMesh( sm );
           sm->ComputeStateEngine( computeEvent );
+
           setCurrentSubMesh( NULL );
           sm->SetAllowedSubShapes( nullptr );
           if ( aShapesId )
@@ -460,6 +548,7 @@ bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
     // mesh the rest sub-shapes starting from vertices
     // -----------------------------------------------
     ret = Compute( aMesh, aShape, aFlags | UPWARD, aDim, aShapesId, allowedSubShapes );
+
   }
 
   MEMOSTAT;
@@ -603,7 +692,7 @@ bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
       const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
       const int aShapeDim = GetShapeDim( aSubShape );
       if ( aShapeDim < 1 ) break;
-      
+
       SMESH_Algo* algo = GetAlgo( smToCompute );
       if ( algo && !algo->NeedDiscreteBoundary() ) {
         if ( algo->SupportSubmeshes() ) {