Salome HOME
Cleanup of parallel meshing + documentation
authorYoann Audouin <yoann.audouin@edf.fr>
Thu, 9 Mar 2023 15:32:55 +0000 (16:32 +0100)
committerYoann Audouin <yoann.audouin@edf.fr>
Wed, 22 Mar 2023 16:24:14 +0000 (17:24 +0100)
31 files changed:
doc/examples/creating_parallel_mesh.py [new file with mode: 0644]
doc/examples/tests.set
doc/gui/images/diagram_parallel_mesh.png [new file with mode: 0644]
doc/gui/input/about_meshes.rst
doc/gui/input/parallel_compute.rst [new file with mode: 0644]
doc/gui/input/tui_creating_meshes.rst
idl/SMESH_Gen.idl
idl/SMESH_Mesh.idl
src/SMESH/CMakeLists.txt
src/SMESH/SMESH_Gen.cxx
src/SMESH/SMESH_Gen.hxx
src/SMESH/SMESH_Mesh.cxx
src/SMESH/SMESH_Mesh.hxx
src/SMESH/SMESH_ParallelMesh.cxx [new file with mode: 0644]
src/SMESH/SMESH_ParallelMesh.hxx [new file with mode: 0644]
src/SMESH/SMESH_SequentialMesh.cxx [new file with mode: 0644]
src/SMESH/SMESH_SequentialMesh.hxx [new file with mode: 0644]
src/SMESH/SMESH_subMesh.cxx
src/SMESH_I/CMakeLists.txt
src/SMESH_I/SMESH_Gen_i.cxx
src/SMESH_I/SMESH_Gen_i.hxx
src/SMESH_I/SMESH_Mesh_i.cxx
src/SMESH_I/SMESH_Mesh_i.hxx
src/SMESH_SWIG/smeshBuilder.py
src/StdMeshers/StdMeshers_Prism_3D.cxx
src/StdMeshers/StdMeshers_Prism_3D.hxx
src/StdMeshers/StdMeshers_Projection_2D.cxx
src/StdMeshers/StdMeshers_QuadFromMedialAxis_1D2D.cxx
src/StdMeshers/StdMeshers_RadialQuadrangle_1D2D.cxx
test/SMESH_ParallelCompute.py [deleted file]
test/tests.set

diff --git a/doc/examples/creating_parallel_mesh.py b/doc/examples/creating_parallel_mesh.py
new file mode 100644 (file)
index 0000000..e837fc9
--- /dev/null
@@ -0,0 +1,141 @@
+# contains function to compute a mesh in parallel
+from platform import java_ver
+import sys
+from tkinter import W
+import salome
+
+import time
+
+
+salome.salome_init()
+import salome_notebook
+notebook = salome_notebook.NoteBook()
+
+###
+### GEOM component
+###
+
+import GEOM
+from salome.geom import geomBuilder
+from salome.smesh import smeshBuilder
+import math
+import SALOMEDS
+
+import numpy as np
+
+geompy = geomBuilder.New()
+
+smesh = smeshBuilder.New()
+
+
+def build_seq_mesh(nbox, boxsize, offset):
+    # Create 3D faces
+    boxes = []
+    # First creating all the boxes
+    for i in range(nbox):
+        for j in range(nbox):
+            for k in range(nbox):
+
+                x_orig = i*(boxsize+offset)
+                y_orig = j*(boxsize+offset)
+                z_orig = k*(boxsize+offset)
+
+                tmp_box = geompy.MakeBoxDXDYDZ(boxsize, boxsize, boxsize)
+
+                if not i == j == k == 0:
+                    box = geompy.MakeTranslation(tmp_box, x_orig,
+                                                 y_orig, z_orig)
+                else:
+                    box = tmp_box
+
+                geompy.addToStudy(box, 'box_{}:{}:{}'.format(i, j, k))
+
+                boxes.append(box)
+
+    # Create fuse of all boxes
+    all_boxes = geompy.MakeCompound(boxes)
+    geompy.addToStudy(all_boxes, 'Compound_1')
+
+    # Removing duplicates faces and edges
+    all_boxes = geompy.MakeGlueFaces(all_boxes, 1e-07)
+    geompy.addToStudy(all_boxes, 'Glued_Faces_1')
+
+    all_boxes = geompy.MakeGlueEdges(all_boxes, 1e-07)
+    geompy.addToStudy(all_boxes, 'rubik_cube')
+
+
+    # Building sequetial mesh
+    print("Creating mesh")
+    all_box_mesh = smesh.Mesh(all_boxes, "seq_mesh")
+
+    print("Adding algo")
+    algo3d = all_box_mesh.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D)
+
+    netgen_parameters = algo3d.Parameters()
+    netgen_parameters.SetMaxSize(34.641)
+    netgen_parameters.SetMinSize(0.141421)
+    netgen_parameters.SetOptimize(1)
+    netgen_parameters.SetCheckOverlapping(0)
+    netgen_parameters.SetCheckChartBoundary(0)
+    netgen_parameters.SetFineness(5)
+    netgen_parameters.SetNbSegPerEdge(16*(boxsize//100))
+    netgen_parameters.SetNbSegPerRadius(1.5)
+    netgen_parameters.SetGrowthRate(0.15)
+    netgen_parameters.SetChordalError(-1)
+    netgen_parameters.SetChordalErrorEnabled(0)
+    netgen_parameters.SetUseSurfaceCurvature(1)
+    netgen_parameters.SetQuadAllowed(0)
+    netgen_parameters.SetCheckOverlapping(False)
+    netgen_parameters.SetNbThreads(2)
+
+    return all_boxes, all_box_mesh, netgen_parameters
+
+def run_test(nbox=2, boxsize=100):
+    """ Run sequential mesh and parallel version of it
+
+    nbox: NUmber of boxes
+    boxsize: Size of each box
+    """
+    geom, seq_mesh, netgen_parameters = build_seq_mesh(nbox, boxsize, 0)
+
+    print("Creating Parallel Mesh")
+    par_mesh = smesh.ParallelMesh(geom, name="par_mesh")
+    par_mesh.AddGlobalHypothesis(netgen_parameters)
+    param = par_mesh.GetParallelismSettings()
+    param.SetNbThreads(6)
+
+    assert param.GetNbThreads() == 6, param.GetNbThreads()
+
+    print("Starting sequential compute")
+    start = time.monotonic()
+    is_done = seq_mesh.Compute()
+    assert is_done
+    stop = time.monotonic()
+    time_seq = stop-start
+
+    print("Starting parallel compute")
+    start = time.monotonic()
+    is_done = par_mesh.Compute()
+    assert is_done
+    stop = time.monotonic()
+    time_par = stop-start
+
+    print("  Tetrahedron: ", seq_mesh.NbTetras(), par_mesh.NbTetras())
+    print("  Triangle: ", seq_mesh.NbTriangles(), par_mesh.NbTriangles())
+    print("  edge: ", seq_mesh.NbEdges(), par_mesh.NbEdges())
+
+    assert  par_mesh.NbTetras() > 0
+    assert  par_mesh.NbTriangles() > 0
+    assert  par_mesh.NbEdges() > 0
+
+    print("Time elapsed (seq, par): ", time_seq, time_par)
+
+def main():
+    if sys.platform == "win32":
+        print("Test disabled on Windows")
+        return
+    nbox = 2
+    boxsize = 100
+    run_test(nbox, boxsize)
+
+main()
index df39d9dd9c7f9954548fb893a5685a4e0e5aae6e..e051ca01cafc7251ec2cf61ee0564225eea764ef 100644 (file)
@@ -129,6 +129,7 @@ SET(BAD_TESTS
   viewing_meshes_ex01.py
   radial_prism_3d_algo.py
   create_dual_mesh.py
+  creating_parallel_mesh.py
   )
 IF(NOT WIN32)
   LIST(APPEND BAD_TESTS
diff --git a/doc/gui/images/diagram_parallel_mesh.png b/doc/gui/images/diagram_parallel_mesh.png
new file mode 100644 (file)
index 0000000..466b29b
Binary files /dev/null and b/doc/gui/images/diagram_parallel_mesh.png differ
index 619bd799f8918412f9a40d33d71d29794f1263aa..6350eea4b7cd37e7a67d50af1b2409221d19daad 100644 (file)
@@ -71,6 +71,8 @@ Quadratic mesh can be obtained in three ways:
 * Using :ref:`convert_to_from_quadratic_mesh_page` operation.
 * Using an appropriate option of some meshing algorithms, which generate elements of several dimensions starting from mesh segments.
 
+A work in progress allow you to compute your mesh in parralle :ref:`Parallel Computing<parallel_compute>`
+
 
 **Table of Contents**
 
@@ -86,3 +88,4 @@ Quadratic mesh can be obtained in three ways:
    copy_mesh.rst
    create_dual_mesh.rst
    connectivity.rst
+   parallel_compute.rst
diff --git a/doc/gui/input/parallel_compute.rst b/doc/gui/input/parallel_compute.rst
new file mode 100644 (file)
index 0000000..fecbf2f
--- /dev/null
@@ -0,0 +1,70 @@
+.. _parallel_compute_page:
+
+******************
+Parallel Computing
+******************
+
+
+.. warning::
+  This functionality is a work in progress.
+
+  It is only available for NETGEN.
+
+  It is only available in TUI.
+
+
+The goal here is to speed up computation by running sub-meshes in parallel
+(multi-threading).
+
+*******
+Concept
+*******
+
+.. image:: ../images/diagram_parallel_mesh.png
+
+In order to parallelise the computation of the mesh we split the geometry into:
+
+  * A 1D+2D compound
+  * A list of 3D solids
+
+Then create a sub-mesh for each of those geometry.
+And associate Hypothesis to the mesh using a hypothesis on the whole geometry
+
+We will first compute sequentially the 1D+2D compound with NETGEN_1D2D.
+
+Then we will compute all the solids in parallel. Having done the 1D+2D first
+ensure that all the solids can be computed without any concurrency.
+
+
+******
+How to
+******
+
+You follow the same principle as the creation of a sequential Mesh.
+
+
+#. First you create the mesh:
+       .. code-block:: python
+
+               par_mesh = smesh.ParallelMesh(geom, name="par_mesh")
+
+#. Define the Global Hypothesis that will be split into an hypothesis for the
+   1D+2D compound and one for each of the 3D solids:
+       .. code-block:: python
+
+               NETGEN_3D_Parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters',
+                                                 'NETGENEngine', 34.641, 0 )
+               par_mesh.AddGlobalHypothesis(netgen_parameters)
+
+#. Set the parameters for the parallelisation:
+       .. code-block:: python
+
+               param = par_mesh.GetParallelismSettings()
+               param.SetNbThreads(6)
+
+#. Compute the mesh:
+       .. code-block:: python
+
+               mesh.Compute()
+
+**See Also** a sample script of :ref:`tui_create_parallel_mesh`.
index 253fbf260da44b54e688065df9882113fe7a3545..67e14d358a530d9c4d811f5076b5a4e6470a97bf 100644 (file)
@@ -117,3 +117,12 @@ Creating Dual Mesh
 
 :download:`Download this script <../../examples/create_dual_mesh.py>`
 
+.. _tui_create_parallel_mesh:
+
+Creating Parallel Mesh
+======================
+
+.. literalinclude:: ../../examples/creating_parallel_mesh.py
+    :language: python
+
+:download:`Download this script <../../examples/creating_parallel_mesh.py>`
index a5b48aaa6bf75f81c3e09fd8a28488e0f9a5b8ae..a36e30d3e39457945b8fad057832747472adb85c 100644 (file)
@@ -242,6 +242,16 @@ module SMESH
     SMESH_Mesh CreateMesh( in GEOM::GEOM_Object theObject )
       raises ( SALOME::SALOME_Exception );
 
+    /*!
+     * Create a Mesh object, given a geometry shape.
+     * Mesh is created empty (no points, no elements).
+     * Shape is explored via GEOM_Client to create local copies.
+     * of TopoDS_Shapes and bind CORBA references of shape & subshapes
+     * with TopoDS_Shapes
+     * The mesh is a parallel one
+     */
+    SMESH_Mesh CreateParallelMesh( in GEOM::GEOM_Object theObject )
+      raises ( SALOME::SALOME_Exception );
     /*!
      * Create an empty mesh object
      */
index 7b86361d83a2604744924452312f18e7dd354ca2..88152274ef2a4a354fd7b40a32ead57e0647d462 100644 (file)
@@ -904,6 +904,11 @@ module SMESH
      */
     void SetNbThreads(in long nbThreads);
     /*!
+    /*!
+     * \brief Get Number of Threads
+     */
+    long GetNbThreads();
+    /*!
 
     /*!
      * Get mesh description
@@ -1108,6 +1113,9 @@ module SMESH
     long GetId();
   };
 
+  interface SMESH_SequentialMesh:SMESH_Mesh{};
+  interface SMESH_ParallelMesh:SMESH_Mesh{};
+
 };
 
 #endif
index 88d42d87573ac1155c820392a0ca6b14c0da542c..ec3761798b01547b12843ec60558c7b8e9a81592 100644 (file)
@@ -77,6 +77,8 @@ SET(_link_LIBRARIES
 SET(SMESHimpl_HEADERS
   SMESH_Gen.hxx
   SMESH_Mesh.hxx
+  SMESH_SequentialMesh.hxx
+  SMESH_ParallelMesh.hxx
   SMESH_subMesh.hxx
   SMESH_subMeshEventListener.hxx
   SMESH_Hypothesis.hxx
@@ -102,6 +104,8 @@ SET(SMESHimpl_SOURCES
   memoire.h
   SMESH_Gen.cxx
   SMESH_Mesh.cxx
+  SMESH_SequentialMesh.cxx
+  SMESH_ParallelMesh.cxx
   SMESH_subMesh.cxx
   SMESH_Hypothesis.cxx
   SMESH_Algo.cxx
index bd8098302799dd02da9a79d535955a57b4cef769..4a020890e93a29e92dd8c2cb91c4cf7642b045ad 100644 (file)
@@ -27,9 +27,6 @@
 //
 //#define CHRONODEF
 //
-#ifndef WIN32
-#include <boost/asio.hpp>
-#endif
 #include "SMESH_Gen.hxx"
 
 #include "SMESH_DriverMesh.hxx"
@@ -39,6 +36,8 @@
 #include "SMESHDS_Document.hxx"
 #include "SMESH_HypoFilter.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_SequentialMesh.hxx"
+#include "SMESH_ParallelMesh.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_subMesh.hxx"
 
 
 #include <Basics_Utils.hxx>
 
+#ifndef WIN32
+#include <boost/asio.hpp>
+#endif
+
 using namespace std;
 #ifndef WIN32
 #include <boost/filesystem.hpp>
@@ -154,7 +157,8 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(bool theIsEmbeddedMode)
   Unexpect aCatch(SalomeException);
 
   // create a new SMESH_mesh object
-  SMESH_Mesh *aMesh = new SMESH_Mesh(_localId++,
+  SMESH_Mesh *aMesh = new SMESH_SequentialMesh(
+                                     _localId++,
                                      this,
                                      theIsEmbeddedMode,
                                      _studyContext->myDocument);
@@ -163,6 +167,27 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(bool theIsEmbeddedMode)
   return aMesh;
 }
 
+//=============================================================================
+/*!
+ * Creates a parallel mesh in a study.
+ * if (theIsEmbeddedMode) { mesh modification commands are not logged }
+ */
+//=============================================================================
+
+SMESH_Mesh* SMESH_Gen::CreateParallelMesh(bool theIsEmbeddedMode)
+{
+  Unexpect aCatch(SalomeException);
+
+  // create a new SMESH_mesh object
+  SMESH_Mesh *aMesh = new SMESH_ParallelMesh(
+                                     _localId++,
+                                     this,
+                                     theIsEmbeddedMode,
+                                     _studyContext->myDocument);
+  _studyContext->mapMesh[_localId-1] = aMesh;
+
+  return aMesh;
+}
 
 //=============================================================================
 /*!
@@ -200,7 +225,7 @@ bool SMESH_Gen::sequentialComputeSubMeshes(
       continue;
 
     // check for preview dimension limitations
-    if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
+    if ( aShapesId && SMESH_Gen::GetShapeDim( shapeType ) > (int)aDim )
     {
       // clear compute state not to show previous compute errors
       //  if preview invoked less dimension less than previous
@@ -264,6 +289,7 @@ const std::function<void(SMESH_subMesh*,
 
 });
 
+
 //=============================================================================
 /*!
  * Algo to run the computation of all the submeshes of a mesh in parallel
@@ -290,11 +316,6 @@ bool SMESH_Gen::parallelComputeSubMeshes(
   SMESH_subMeshIteratorPtr smIt;
   SMESH_subMesh *shapeSM = aMesh.GetSubMesh(aShape);
 
-  // Pool of thread for computation
-  // TODO: move when parallelMesh created
-  aMesh.InitPoolThreads();
-  aMesh.CreateTmpFolder();
-
   TopAbs_ShapeEnum previousShapeType = TopAbs_VERTEX;
   int nbThreads = aMesh.GetNbThreads();
   MESSAGE("Compute submeshes with threads: " << nbThreads);
@@ -339,23 +360,22 @@ bool SMESH_Gen::parallelComputeSubMeshes(
       }
       if(file_name != "")
       {
-        fs::path mesh_file = fs::path(aMesh.tmp_folder) / fs::path(file_name);
-       SMESH_DriverMesh::exportMesh(mesh_file.string(), aMesh, "MESH");
-
+        fs::path mesh_file = fs::path(aMesh.GetTmpFolder()) / fs::path(file_name);
+             SMESH_DriverMesh::exportMesh(mesh_file.string(), aMesh, "MESH");
       }
       //Resetting threaded pool info
       previousShapeType = shapeType;
     }
 
     // check for preview dimension limitations
-    if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
+    if ( aShapesId && SMESH_Gen::GetShapeDim( shapeType ) > (int)aDim )
     {
       // clear compute state not to show previous compute errors
       //  if preview invoked less dimension less than previous
       smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
       continue;
     }
-    boost::asio::post(*(aMesh._pool), std::bind(compute_function, smToCompute, computeEvent,
+    boost::asio::post(*(aMesh.GetPool()), std::bind(compute_function, smToCompute, computeEvent,
                       shapeSM, aShapeOnly, allowedSubShapes,
                       aShapesId));
   }
@@ -364,7 +384,6 @@ bool SMESH_Gen::parallelComputeSubMeshes(
   aMesh.wait();
 
   aMesh.GetMeshDS()->Modified();
-  aMesh.DeleteTmpFolder();
 
   return ret;
 #endif
@@ -416,22 +435,14 @@ bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
     // ===============================================
     // Mesh all the sub-shapes starting from vertices
     // ===============================================
-    if (aMesh.IsParallel())
-      ret = parallelComputeSubMeshes(
-              aMesh, aShape, aDim,
-              aShapesId, allowedSubShapes,
-              computeEvent,
-              includeSelf,
-              complexShapeFirst,
-              aShapeOnly);
-    else
-      ret = sequentialComputeSubMeshes(
-              aMesh, aShape, aDim,
-              aShapesId, allowedSubShapes,
-              computeEvent,
-              includeSelf,
-              complexShapeFirst,
-              aShapeOnly);
+    ret = aMesh.ComputeSubMeshes(
+            this,
+            aMesh, aShape, aDim,
+            aShapesId, allowedSubShapes,
+            computeEvent,
+            includeSelf,
+            complexShapeFirst,
+            aShapeOnly);
 
     return ret;
   }
index 94058184e5e83a7af853b3a8b13884bb0484c6e6..40e92ca37e146e330d1a282626b74cda22edc590 100644 (file)
@@ -70,6 +70,7 @@ public:
   ~SMESH_Gen();
 
   SMESH_Mesh* CreateMesh(bool theIsEmbeddedMode);
+  SMESH_Mesh* CreateParallelMesh(bool theIsEmbeddedMode);
 
   enum ComputeFlags
   {
@@ -167,9 +168,7 @@ public:
 
   int GetANewId();
 
-private:
-
-
+public:
   bool parallelComputeSubMeshes(
           SMESH_Mesh & aMesh,
           const TopoDS_Shape & aShape,
@@ -191,6 +190,11 @@ private:
           const bool includeSelf,
           const bool complexShapeFirst,
           const bool aShapeOnly);
+
+private:
+
+
+
   int _localId;                         // unique Id of created objects, within SMESH_Gen entity
   StudyContextStruct* _studyContext;
 
index 82ce58633fcc36522ec25f523508ac49456f694e..ad3d733f07d4525c7565688fa994ef8b1782aee5 100644 (file)
@@ -232,8 +232,6 @@ SMESH_Mesh::~SMESH_Mesh()
     int result=pthread_create(&thread, NULL, deleteMeshDS, (void*)_meshDS);
 #endif
   }
-  if(_pool)
-    DeletePoolThreads();
 }
 
 //================================================================================
@@ -2564,30 +2562,3 @@ void SMESH_Mesh::getAncestorsSubMeshes (const TopoDS_Shape&            theSubSha
   // sort submeshes according to stored mesh order
   SortByMeshOrder( theSubMeshes );
 }
-
-
-//=============================================================================
-/*!
- * \brief Build folder for parallel computation
- */
-//=============================================================================
-void SMESH_Mesh::CreateTmpFolder()
-{
-#ifndef WIN32
-  // Temporary folder that will be used by parallel computation
-  tmp_folder = fs::temp_directory_path()/fs::unique_path(fs::path("SMESH_%%%%-%%%%"));
-  fs::create_directories(tmp_folder);
-#endif
-}
-//
-//=============================================================================
-/*!
- * \brief Delete temporary folder used for parallel computation
- */
-//=============================================================================
-void SMESH_Mesh::DeleteTmpFolder()
-{
-#ifndef WIN32
-    fs::remove_all(tmp_folder);
-#endif
-}
index 9c96064996fe21fe54f6e930fc65db21e0c6169d..c0cbb37b66c88b0694a366f6da9ba77be5118650 100644 (file)
@@ -33,6 +33,7 @@
 #include "SMESH_ComputeError.hxx"
 #include "SMESH_Controls.hxx"
 #include "SMESH_Hypothesis.hxx"
+#include "SMESH_subMesh.hxx"
 #include "SMDS_Iterator.hxx"
 
 #include "Utils_SALOME_Exception.hxx"
@@ -72,6 +73,7 @@ class TopoDS_Solid;
 
 class DriverMED_W_SMESHDS_Mesh;
 
+typedef std::set<int> TSetOfInt;
 typedef std::list<int> TListOfInt;
 typedef std::list<TListOfInt> TListOfListOfInt;
 
@@ -390,45 +392,32 @@ class SMESH_EXPORT SMESH_Mesh
 
   // Parallel computation functions
 
-#ifdef WIN32
-  void Lock() {};
-  void Unlock() {};
-
-  int GetNbThreads(){return _NbThreads;};
-  void SetNbThreads(long nbThreads){std::cout << "Warning Parallel Meshing is disabled on Windows it will behave as a slower normal compute" << std::endl;_NbThreads=nbThreads;};
-
-  void InitPoolThreads(){};
-  void DeletePoolThreads(){};
-  void wait(){}
+  virtual void Lock(){};
+  virtual void Unlock(){};
 
-  bool IsParallel(){return _NbThreads > 0;}
-#else
-  void Lock() {_my_lock.lock();};
-  void Unlock() {_my_lock.unlock();};
+  virtual int GetNbThreads(){return 0;};
+  virtual void SetNbThreads(long nbThreads){(void) nbThreads;};
 
-  int GetNbThreads(){return _NbThreads;};
-  void SetNbThreads(long nbThreads){_NbThreads=nbThreads;};
+  virtual void InitPoolThreads(){std::cout << "Should not pass here: InitPoolThread" << std::endl;};
+  virtual void DeletePoolThreads(){std::cout << "Should not pass here: DeletePoolThread" << std::endl;};
+  virtual void wait(){std::cout << "Should not pass here: wait" << std::endl;};
 
-  void InitPoolThreads(){_pool = new boost::asio::thread_pool(_NbThreads);};
-  void DeletePoolThreads(){delete _pool;};
+  virtual bool IsParallel(){std::cout << "Should not pass here: IsParallel" << std::endl;return false;};
 
-  void wait(){_pool->join(); DeletePoolThreads(); InitPoolThreads(); }
-
-  bool IsParallel(){return _NbThreads > 0;}
-#endif
-
-  void CreateTmpFolder();
-  void DeleteTmpFolder();
-
-  // Temporary folder used during parallel Computation
-#ifndef WIN32
-  boost::filesystem::path tmp_folder;
-  boost::asio::thread_pool *     _pool = nullptr; //thread pool for computation
-#else
-  std::string tmp_folder;
-  bool _pool = false;
-#endif
+  virtual boost::filesystem::path GetTmpFolder() {return "";};
+  virtual boost::asio::thread_pool* GetPool() {return NULL;};
 
+  virtual bool ComputeSubMeshes(
+            SMESH_Gen* gen,
+            SMESH_Mesh & aMesh,
+            const TopoDS_Shape & aShape,
+            const ::MeshDimension       aDim,
+            TSetOfInt*                  aShapesId /*=0*/,
+            TopTools_IndexedMapOfShape* allowedSubShapes,
+            SMESH_subMesh::compute_event &computeEvent,
+            const bool includeSelf,
+            const bool complexShapeFirst,
+            const bool aShapeOnly){(void) gen;(void) aMesh;(void) aShape;(void) aDim;(void) aShapesId;(void) allowedSubShapes;(void) computeEvent;(void) includeSelf;(void) complexShapeFirst;(void) aShapeOnly;std::cout << "Should not pass here: computesubmesh" << std::endl;return false;};
 
 private:
 
@@ -480,7 +469,7 @@ protected:
 #ifndef WIN32
   boost::mutex _my_lock;
 #endif
-  int _NbThreads=0;
+  int _NbThreads=-1;
 
 protected:
   SMESH_Mesh();
diff --git a/src/SMESH/SMESH_ParallelMesh.cxx b/src/SMESH/SMESH_ParallelMesh.cxx
new file mode 100644 (file)
index 0000000..4b9f83c
--- /dev/null
@@ -0,0 +1,120 @@
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  File   : SMESH_ParallelMesh.cxx
+//  Author : Yoann AUDOUIN, EDF
+//  Module : SMESH
+//
+#include "SMESH_ParallelMesh.hxx"
+
+#include "SMESH_Gen.hxx"
+
+#ifdef WIN32
+  #include <windows.h>
+#endif
+
+#ifndef WIN32
+#include <boost/filesystem.hpp>
+namespace fs=boost::filesystem;
+#endif
+
+#ifndef WIN32
+#include <boost/asio.hpp>
+#endif
+
+#include <utilities.h>
+
+#ifdef _DEBUG_
+static int MYDEBUG = 1;
+#else
+static int MYDEBUG = 0;
+#endif
+
+SMESH_ParallelMesh::SMESH_ParallelMesh(int               theLocalId,
+                       SMESH_Gen*        theGen,
+                       bool              theIsEmbeddedMode,
+                       SMESHDS_Document* theDocument) :SMESH_Mesh(theLocalId,
+                                                                  theGen,
+                                                                  theIsEmbeddedMode,
+                                                                  theDocument)
+{
+  MESSAGE("SMESH_ParallelMesh::SMESH_ParallelMesh(int localId)");
+  _NbThreads = std::thread::hardware_concurrency();
+  CreateTmpFolder();
+};
+
+SMESH_ParallelMesh::~SMESH_ParallelMesh()
+{
+  DeletePoolThreads();
+  if(!MYDEBUG)
+    DeleteTmpFolder();
+};
+
+
+
+//=============================================================================
+/*!
+ * \brief Build folder for parallel computation
+ */
+//=============================================================================
+void SMESH_ParallelMesh::CreateTmpFolder()
+{
+#ifndef WIN32
+  // Temporary folder that will be used by parallel computation
+  tmp_folder = fs::temp_directory_path()/fs::unique_path(fs::path("SMESH_%%%%-%%%%"));
+  fs::create_directories(tmp_folder);
+#endif
+}
+//
+//=============================================================================
+/*!
+ * \brief Delete temporary folder used for parallel computation
+ */
+//=============================================================================
+void SMESH_ParallelMesh::DeleteTmpFolder()
+{
+#ifndef WIN32
+    fs::remove_all(tmp_folder);
+#endif
+}
+
+bool SMESH_ParallelMesh::ComputeSubMeshes(
+          SMESH_Gen* gen,
+          SMESH_Mesh & aMesh,
+          const TopoDS_Shape & aShape,
+          const ::MeshDimension       aDim,
+          TSetOfInt*                  aShapesId /*=0*/,
+          TopTools_IndexedMapOfShape* allowedSubShapes,
+          SMESH_subMesh::compute_event &computeEvent,
+          const bool includeSelf,
+          const bool complexShapeFirst,
+          const bool   aShapeOnly)
+{
+  InitPoolThreads();
+  return gen->parallelComputeSubMeshes(
+            aMesh, aShape, aDim,
+            aShapesId, allowedSubShapes,
+            computeEvent,
+            includeSelf,
+            complexShapeFirst,
+            aShapeOnly);
+}
diff --git a/src/SMESH/SMESH_ParallelMesh.hxx b/src/SMESH/SMESH_ParallelMesh.hxx
new file mode 100644 (file)
index 0000000..09a5206
--- /dev/null
@@ -0,0 +1,83 @@
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  File   : SMESH_ParallelMesh.hxx
+//  Author : Yoann AUDOUIN, EDF
+//  Module : SMESH
+//
+#ifndef _SMESH_PARALLELMESH_HXX_
+#define _SMESH_PARALLELMESH_HXX_
+
+#include "SMESH_Mesh.hxx"
+
+#include "SMESH_Gen.hxx"
+#include "SMESH_subMesh.hxx"
+
+class SMESH_EXPORT SMESH_ParallelMesh: public SMESH_Mesh
+{
+ public:
+  SMESH_ParallelMesh(int               theLocalId,
+                       SMESH_Gen*        theGen,
+                       bool              theIsEmbeddedMode,
+                       SMESHDS_Document* theDocument);
+
+  virtual ~SMESH_ParallelMesh();
+
+  void Lock() override {_my_lock.lock();};
+  void Unlock() override {_my_lock.unlock();};
+
+  int GetNbThreads() override{return _NbThreads;};
+  void SetNbThreads(long nbThreads) override{_NbThreads=nbThreads;};
+
+  void InitPoolThreads() override {_pool = new boost::asio::thread_pool(_NbThreads);};
+  void DeletePoolThreads() override {delete _pool;};
+
+  void wait() override {_pool->join(); DeletePoolThreads(); InitPoolThreads(); };
+
+  bool IsParallel() override {return _NbThreads > 0;};
+
+  void CreateTmpFolder();
+  void DeleteTmpFolder();
+
+  boost::filesystem::path GetTmpFolder() override {return tmp_folder;};
+  boost::asio::thread_pool* GetPool() override {return _pool;};
+
+  bool ComputeSubMeshes(
+            SMESH_Gen* gen,
+            SMESH_Mesh & aMesh,
+            const TopoDS_Shape & aShape,
+            const ::MeshDimension       aDim,
+            TSetOfInt*                  aShapesId /*=0*/,
+            TopTools_IndexedMapOfShape* allowedSubShapes,
+            SMESH_subMesh::compute_event &computeEvent,
+            const bool includeSelf,
+            const bool complexShapeFirst,
+            const bool   aShapeOnly) override;
+
+ protected:
+  SMESH_ParallelMesh():SMESH_Mesh() {};
+  SMESH_ParallelMesh(const SMESH_ParallelMesh& aMesh):SMESH_Mesh(aMesh) {};
+ private:
+  boost::filesystem::path tmp_folder;
+  boost::asio::thread_pool *     _pool = nullptr; //thread pool for computation
+};
+#endif
diff --git a/src/SMESH/SMESH_SequentialMesh.cxx b/src/SMESH/SMESH_SequentialMesh.cxx
new file mode 100644 (file)
index 0000000..35023ae
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  File   : SMESH_SequentialMesh.cxx
+//  Author : Yoann AUDOUIN, EDF
+//  Module : SMESH
+//
+#include "SMESH_SequentialMesh.hxx"
+
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Iterator.hxx>
+
+#include <utilities.h>
+
+SMESH_SequentialMesh::SMESH_SequentialMesh(int               theLocalId,
+                       SMESH_Gen*        theGen,
+                       bool              theIsEmbeddedMode,
+                       SMESHDS_Document* theDocument) :SMESH_Mesh(theLocalId,
+                                                                  theGen,
+                                                                  theIsEmbeddedMode,
+                                                                  theDocument)
+{
+  MESSAGE("SMESH_SequentialMesh::SMESH_SequentialMesh(int localId)");
+};
+
+SMESH_SequentialMesh::~SMESH_SequentialMesh()
+{
+};
+
+bool SMESH_SequentialMesh::ComputeSubMeshes(
+          SMESH_Gen* gen,
+          SMESH_Mesh & aMesh,
+          const TopoDS_Shape & aShape,
+          const ::MeshDimension       aDim,
+          TSetOfInt*                  aShapesId /*=0*/,
+          TopTools_IndexedMapOfShape* allowedSubShapes,
+          SMESH_subMesh::compute_event &computeEvent,
+          const bool includeSelf,
+          const bool complexShapeFirst,
+          const bool   aShapeOnly)
+{
+    return gen->sequentialComputeSubMeshes(
+            aMesh, aShape, aDim,
+            aShapesId, allowedSubShapes,
+            computeEvent,
+            includeSelf,
+            complexShapeFirst,
+            aShapeOnly);
+};
diff --git a/src/SMESH/SMESH_SequentialMesh.hxx b/src/SMESH/SMESH_SequentialMesh.hxx
new file mode 100644 (file)
index 0000000..90cf904
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright (C) 2007-2022  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  File   : SMESH_SequentialMesh.hxx
+//  Author : Yoann AUDOUIN, EDF
+//  Module : SMESH
+//
+#ifndef _SMESH_SEQUENTIALMESH_HXX_
+#define _SMESH_SEQUENTIALMESH_HXX_
+
+#include "SMESH_Mesh.hxx"
+
+#include "SMESH_Gen.hxx"
+#include "SMESH_subMesh.hxx"
+
+class SMESH_EXPORT SMESH_SequentialMesh: public SMESH_Mesh
+{
+ public:
+  SMESH_SequentialMesh(int               theLocalId,
+                       SMESH_Gen*        theGen,
+                       bool              theIsEmbeddedMode,
+                       SMESHDS_Document* theDocument);
+
+  virtual ~SMESH_SequentialMesh();
+
+  void Lock() override {};
+  void Unlock() override {};
+
+  int GetNbThreads() override {return 0;};
+  void SetNbThreads(long nbThreads) {(void) nbThreads;};
+
+  void InitPoolThreads() override {};
+  void DeletePoolThreads() override {};
+  void wait() override {};
+
+  bool IsParallel() override {return false;};
+
+  bool ComputeSubMeshes (
+            SMESH_Gen* gen,
+            SMESH_Mesh & aMesh,
+            const TopoDS_Shape & aShape,
+            const ::MeshDimension       aDim,
+            TSetOfInt*                  aShapesId /*=0*/,
+            TopTools_IndexedMapOfShape* allowedSubShapes,
+            SMESH_subMesh::compute_event &computeEvent,
+            const bool includeSelf,
+            const bool complexShapeFirst,
+            const bool   aShapeOnly) override;
+
+ protected:
+  SMESH_SequentialMesh():SMESH_Mesh() {};
+  SMESH_SequentialMesh(const SMESH_SequentialMesh& aMesh):SMESH_Mesh(aMesh) {};
+};
+#endif
index 76dfb83e1478c38ae5faecbd3388717e79feb9a1..bc3aa8792e0dfa6789bd966c8cfa0298d2ca9c5e 100644 (file)
@@ -1515,7 +1515,8 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event)
         TopoDS_Shape shape = _subShape;
         algo->setSubMeshesToCompute(this);
         // check submeshes needed
-        // In parallel there would be no submesh to check
+        // When computing in parallel mode we do not have a additional layer of submesh
+        // The check should not be done in parallel as that check is not thread-safe
         if (_father->HasShapeToMesh() && !_father->IsParallel()) {
           bool subComputed = false, subFailed = false;
           if (!algo->OnlyUnaryInput()) {
index 218cb915e7cdf100cb4716e669479b8f6357b097..f525f022c7a69ddcb0f036c14766e6252353f3a5 100644 (file)
@@ -67,7 +67,7 @@ SET(_link_LIBRARIES
   ${KERNEL_Registry}
   ${KERNEL_SalomeHDFPersist}
   ${KERNEL_SalomeLifeCycleCORBA}
-  ${KERNEL_TOOLSDS}  
+  ${KERNEL_TOOLSDS}
   ${KERNEL_SalomeGenericObj}
   ${KERNEL_SalomeIDLKERNEL}
   ${KERNEL_SALOMELocalTrace}
@@ -115,6 +115,8 @@ SET(SMESHEngine_HEADERS
   SMESH.hxx
   MG_ADAPT_i.hxx
   SMESH_Homard_i.hxx
+  SMESH_SequentialMesh_i.hxx
+  SMESH_ParallelMesh_i.hxx
 )
 
 # --- sources ---
index 32265c51435a7f721af90321bdb6021d7707d6a3..0bf885f358646514d07c98d008a06ca944a979aa 100644 (file)
 #include "SMESH_PythonDump.hxx"
 #include "SMESH_ControlsDef.hxx"
 #include <SMESH_BoostTxtArchive.hxx>
+#include <SMESH_SequentialMesh_i.hxx>
+#include <SMESH_ParallelMesh_i.hxx>
 
 // to pass CORBA exception through SMESH_TRY
 #define SMY_OWN_CATCH catch( SALOME::SALOME_Exception& se ) { throw se; }
@@ -560,7 +562,7 @@ SMESH::SMESH_Hypothesis_ptr SMESH_Gen_i::createHypothesis(const char* theHypName
  */
 //=============================================================================
 
-SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
+SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh(bool parallel /*=false*/)
 {
   Unexpect aCatch(SALOME_SalomeException);
   MESSAGE( "SMESH_Gen_i::createMesh" );
@@ -571,7 +573,11 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::createMesh()
     SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this );
     // create a new mesh object
     MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
-    meshServant->SetImpl( myGen.CreateMesh( myIsEmbeddedMode ));
+    if(parallel) {
+      meshServant->SetImpl( dynamic_cast<SMESH_Mesh*>(myGen.CreateParallelMesh( myIsEmbeddedMode )));
+    }else{
+      meshServant->SetImpl( dynamic_cast<SMESH_Mesh*>(myGen.CreateMesh( myIsEmbeddedMode )));
+    }
 
     // activate the CORBA servant of Mesh
     SMESH::SMESH_Mesh_var mesh = SMESH::SMESH_Mesh::_narrow( meshServant->_this() );
@@ -1198,7 +1204,7 @@ char* SMESH_Gen_i::GetOption(const char* name)
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObject )
 {
   Unexpect aCatch(SALOME_SalomeException);
-  MESSAGE( "SMESH_Gen_i::CreateMesh" );
+  MESSAGE( "SMESH_Gen_i::CreateMesh(GEOM_Object_ptr)" );
   // create mesh
   SMESH::SMESH_Mesh_var mesh = this->createMesh();
   // set shape
@@ -1221,6 +1227,40 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObj
   return mesh._retn();
 }
 
+//=============================================================================
+/*!
+ *  SMESH_Gen_i::CreateParallelMesh
+ *
+ *  Create empty parallel mesh on a shape and publish it in the study
+ */
+//=============================================================================
+
+SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateParallelMesh( GEOM::GEOM_Object_ptr theShapeObject )
+{
+  Unexpect aCatch(SALOME_SalomeException);
+  MESSAGE( "SMESH_Gen_i::CreateParallelMesh" );
+  // create mesh
+  SMESH::SMESH_Mesh_var mesh = this->createMesh(true);
+  // set shape
+  SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
+  ASSERT( meshServant );
+  meshServant->SetShape( theShapeObject );
+
+  // publish mesh in the study
+  if ( CanPublishInStudy( mesh ) ) {
+    SALOMEDS::StudyBuilder_var aStudyBuilder = getStudyServant()->NewBuilder();
+    aStudyBuilder->NewCommand();  // There is a transaction
+    SALOMEDS::SObject_wrap aSO = PublishMesh( mesh.in() );
+    aStudyBuilder->CommitCommand();
+    if ( !aSO->_is_nil() ) {
+      // Update Python script
+      TPythonDump(this) << aSO << " = " << this << ".CreateMesh(" << theShapeObject << ")";
+    }
+  }
+
+  return mesh._retn();
+}
+
 //=============================================================================
 /*!
  *  SMESH_Gen_i::CreateEmptyMesh
@@ -1232,7 +1272,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMesh( GEOM::GEOM_Object_ptr theShapeObj
 SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateEmptyMesh()
 {
   Unexpect aCatch(SALOME_SalomeException);
-  MESSAGE( "SMESH_Gen_i::CreateMesh" );
+  MESSAGE( "SMESH_Gen_i::CreateEmptyMesh" );
   // create mesh
   SMESH::SMESH_Mesh_var mesh = this->createMesh();
 
index 822e71f2e51c96ca2a0cf6cdd6d8e9f38e2f8b1f..f793d4f1bb613cc478404639a80835868a966763 100644 (file)
@@ -231,6 +231,9 @@ public:
   // Create empty mesh on a shape
   SMESH::SMESH_Mesh_ptr CreateMesh( GEOM::GEOM_Object_ptr theShapeObject );
 
+  // Create empty parallel mesh on a shape
+  SMESH::SMESH_Mesh_ptr CreateParallelMesh( GEOM::GEOM_Object_ptr theShapeObject );
+
   // Create empty mesh
   SMESH::SMESH_Mesh_ptr CreateEmptyMesh();
 
@@ -631,7 +634,7 @@ private:
   SMESH::SMESH_Hypothesis_ptr createHypothesis( const char* theHypName,
                                                 const char* theLibName);
   // Create empty mesh on shape
-  SMESH::SMESH_Mesh_ptr createMesh();
+  SMESH::SMESH_Mesh_ptr createMesh(bool parallel=false);
 
   // Check mesh icon
   bool isGeomModifIcon( SMESH::SMESH_Mesh_ptr mesh );
index 7d4bcb4181a5d280d1b33c3853cb4d793aa6cc7a..d101f14dcd2a34feae7e61230b910071771eb45a 100644 (file)
@@ -7037,6 +7037,15 @@ void SMESH_Mesh_i::SetNbThreads(CORBA::Long nbThreads){
   _impl->SetNbThreads(nbThreads);
 }
 
+//=============================================================================
+/*!
+ * \brief Get the number of threads for a parallel computation
+ */
+//=============================================================================
+CORBA::Long SMESH_Mesh_i::GetNbThreads(){
+  return _impl->GetNbThreads();
+}
+
 
 //=============================================================================
 /*!
index 45928272db5698acf20ae64909c9e07f0617850d..d9a82e3c6f0ecd00c1acb528eb7e6024d04c97c6 100644 (file)
@@ -673,7 +673,11 @@ private:
                         SMESH::submesh_array_array& theSubMeshOrder,
                         const bool                  theIsDump);
 
+  /*!
+   * Parallelims informations
+   */
   void SetNbThreads(CORBA::Long nbThreads);
+  CORBA::Long GetNbThreads();
 
   /*!
    * \brief Finds concurrent sub-meshes
index 972a4507cfd320f06247840433c9b4a1116cc7b9..8d0a81ac5693dab47b5ca5898b616a07c1cb8df8 100644 (file)
@@ -462,20 +462,21 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
             obj,name = name,obj
         return Mesh(self, self.geompyD, obj, name)
 
-    def ParallelMesh(self, obj, param, nbThreads, name=0):
+    def ParallelMesh(self, obj, name=0, split_geom=True):
         """
         Create a parallel mesh.
 
         Parameters:
             obj: geometrical object for meshing
             name: the name for the new mesh.
-            param: full mesh parameters
-            nbThreads: Number of threads for parallelisation.
+            split_geom: If True split the geometry and create the assoicated
+            sub meshes
 
         Returns:
             an instance of class :class:`ParallelMesh`.
         """
-        return ParallelMesh(self, self.geompyD, obj, param, nbThreads, name)
+        return ParallelMesh(self, self.geompyD, obj,
+                            split_geom=split_geom, name=name)
 
     def RemoveMesh( self, mesh ):
         """
@@ -1592,7 +1593,7 @@ class Mesh(metaclass = MeshMeta):
     mesh = 0
     editor = 0
 
-    def __init__(self, smeshpyD, geompyD, obj=0, name=0):
+    def __init__(self, smeshpyD, geompyD, obj=0, name=0, parallel=False):
 
         """
         Constructor
@@ -1625,7 +1626,10 @@ class Mesh(metaclass = MeshMeta):
                     else:
                         geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
                     geompyD.addToStudy( self.geom, geo_name )
-                self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
+                if parallel and isinstance(self, ParallelMesh):
+                    self.SetMesh( self.smeshpyD.CreateParallelMesh(self.geom) )
+                else:
+                    self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
 
             elif isinstance(obj, SMESH._objref_SMESH_Mesh):
                 self.SetMesh(obj)
@@ -7501,6 +7505,9 @@ class Mesh(metaclass = MeshMeta):
 
 
 def _copy_netgen_param(dim, local_param, global_param):
+    """
+    Create 1D/2D/3D netgen parameters from a NETGEN 1D2D3D parameter
+    """
     if dim==1:
         #TODO: Try to identify why we need to substract 1
         local_param.NumberOfSegments(int(global_param.GetNbSegPerEdge())-1)
@@ -7532,19 +7539,95 @@ def _copy_netgen_param(dim, local_param, global_param):
         local_param.SetGrowthRate(global_param.GetGrowthRate())
         local_param.SetNbThreads(global_param.GetNbThreads())
 
+def _split_geom(geompyD, geom):
+    """
+    Splitting geometry into n solids and a 2D/1D compound
+
+    Parameters:
+        geompyD: geomBuilder instance
+        geom: geometrical object for meshing
+
+    """
+    # Splitting geometry into 3D elements and all the 2D/1D into one compound
+    object_solids = geompyD.ExtractShapes(geom, geompyD.ShapeType["SOLID"],
+                                          True)
+
+    solids = []
+    isolid = 0
+    for solid in object_solids:
+        isolid += 1
+        geompyD.addToStudyInFather( geom, solid, 'Solid_{}'.format(isolid) )
+        solids.append(solid)
+    # If geom is a solid ExtractShapes will return nothin in that case geom is the solids
+    if isolid == 0:
+       solids = [geom]
+
+    faces = []
+    iface = 0
+    for isolid, solid in enumerate(solids):
+        solid_faces = geompyD.ExtractShapes(solid, geompyD.ShapeType["FACE"],
+                                            True)
+        for face in solid_faces:
+            faces.append(face)
+            iface += 1
+            geompyD.addToStudyInFather(solid, face,
+                                       'Face_{}'.format(iface))
+
+    # Creating submesh for edges 1D/2D part
+
+    all_faces = geompyD.MakeCompound(faces)
+    geompyD.addToStudy(all_faces, 'Compound_1')
+    all_faces = geompyD.MakeGlueEdges(all_faces, 1e-07)
+    all_faces = geompyD.MakeGlueFaces(all_faces, 1e-07)
+    geompyD.addToStudy(all_faces, 'global2D')
+
+    return all_faces, solids
+
+class ParallelismSettings:
+    """
+    Defines the parameters for the parallelism of ParallelMesh
+    """
+    def __init__(self, mesh):
+        """
+        Construsctor
+
+        Parameters:
+        mesh: Instance of ParallelMesh
+        """
+        if not(isinstance(mesh, ParallelMesh)):
+            raise ValueError("mesh should be a ParallelMesh")
+
+        self._mesh = mesh
+
+    def SetNbThreads(self, nbThreads):
+        """
+        Set the number of threads for multithreading
+        """
+        if nbThreads < 1:
+            raise ValueError("Number of threads must be stricly greater than 1")
+
+        self._mesh.mesh.SetNbThreads(nbThreads)
+
+    def GetNbThreads(self):
+        """
+        Get Number of threads
+        """
+        return self._mesh.mesh.GetNbThreads()
+
 class ParallelMesh(Mesh):
     """
     Surcharge on Mesh for parallel computation of a mesh
     """
-
-    def __init__(self, smeshpyD, geompyD, geom, param, nbThreads, name=0):
+    def __init__(self, smeshpyD, geompyD, geom, split_geom=True, name=0):
         """
         Create a parallel mesh.
 
         Parameters:
+            smeshpyD: instance of smeshBuilder
+            geompyD: instance of geomBuilder
             geom: geometrical object for meshing
-            param: full mesh parameters
-            nbThreads: Number of threads for parallelisation.
+            split_geom: If true will divide geometry on solids and 1D/2D
+            coumpound and create the associated submeshes
             name: the name for the new mesh.
 
         Returns:
@@ -7554,63 +7637,56 @@ class ParallelMesh(Mesh):
         if not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
             raise ValueError("geom argument must be a geometry")
 
-        if not isinstance(param, NETGENPlugin._objref_NETGENPlugin_Hypothesis):
-            raise ValueError("param must come from NETGENPlugin")
+        # Splitting geometry into one geom containing 1D and 2D elements and a
+        # list of 3D elements
+        super(ParallelMesh, self).__init__(smeshpyD, geompyD, geom, name, parallel=True)
 
-        if nbThreads < 1:
-            raise ValueError("Number of threads must be stricly greater than 1")
+        if split_geom:
+            self._all_faces, self._solids = _split_geom(geompyD, geom)
 
-        # Splitting geometry into 3D elements and all the 2D/1D into one compound
-        object_solids = geompyD.ExtractShapes(geom, geompyD.ShapeType["SOLID"],
-                                              True)
+            self.UseExistingSegments()
+            self.UseExistingFaces()
 
-        solids = []
-        isolid = 0
-        for solid in object_solids:
-            isolid += 1
-            geompyD.addToStudyInFather( geom, solid, 'Solid_{}'.format(isolid) )
-            solids.append(solid)
+            self._algo2d = self.Triangle(geom=self._all_faces, algo="NETGEN_2D")
+            self._algo3d = []
 
-        faces = []
-        iface = 0
-        for isolid, solid in enumerate(solids):
-            solid_faces = geompyD.ExtractShapes(solid, geompyD.ShapeType["FACE"],
-                                                True)
-            for face in solid_faces:
-                faces.append(face)
-                iface += 1
-                geompyD.addToStudyInFather(solid, face,
-                                           'Face_{}'.format(iface))
+            for solid_id, solid in enumerate(self._solids):
+                name = "Solid_{}".format(solid_id)
+                self.UseExistingSegments(geom=solid)
+                self.UseExistingFaces(geom=solid)
+                algo3d = self.Tetrahedron(geom=solid, algo="NETGEN_3D_Remote")
+                self._algo3d.append(algo3d)
 
-        # Creating submesh for edges 1D/2D part
+        self._param = ParallelismSettings(self)
 
-        all_faces = geompyD.MakeCompound(faces)
-        geompyD.addToStudy(all_faces, 'Compound_1')
-        all_faces = geompyD.MakeGlueEdges(all_faces, 1e-07)
-        all_faces = geompyD.MakeGlueFaces(all_faces, 1e-07)
-        geompyD.addToStudy(all_faces, 'global2D')
 
-        super(ParallelMesh, self).__init__(smeshpyD, geompyD, geom, name)
+    def GetParallelismSettings(self):
+        """
+        Return class to set parameters for the parallelism
+        """
+        return self._param
 
-        self.mesh.SetNbThreads(nbThreads)
+    def AddGlobalHypothesis(self, hyp):
+        """
+        Split hypothesis to apply it to all the submeshes:
+        - the 1D+2D
+        - each of the 3D solids
 
-        self.UseExistingSegments()
-        self.UseExistingFaces()
+        Parameters:
+                hyp: a hypothesis to assign
 
-        algo2d = self.Triangle(geom=all_faces, algo="NETGEN_2D")
-        param2d = algo2d.Parameters()
+        """
+        if not isinstance(hyp, NETGENPlugin._objref_NETGENPlugin_Hypothesis):
+            raise ValueError("param must come from NETGENPlugin")
 
-        _copy_netgen_param(2, param2d, param)
+        param2d = self._algo2d.Parameters()
+        _copy_netgen_param(2, param2d, hyp)
 
-        for solid_id, solid in enumerate(solids):
-            name = "Solid_{}".format(solid_id)
-            self.UseExistingSegments(geom=solid)
-            self.UseExistingFaces(geom=solid)
-            algo3d = self.Tetrahedron(geom=solid, algo="NETGEN_3D_Remote")
+        for algo3d in self._algo3d:
 
             param3d = algo3d.Parameters()
+            _copy_netgen_param(3, param3d, hyp)
 
-            _copy_netgen_param(3, param3d, param)
 
     pass # End of ParallelMesh
 
index 4caad58b43aaa79517f4c162762aff64768c5c42..005be9abb3132684055d5684cfe040079fd309b5 100644 (file)
@@ -95,7 +95,7 @@ namespace
   /*!
    * \brief Auxiliary mesh
    */
-  struct TmpMesh: public SMESH_Mesh
+  struct TmpMesh: public SMESH_SequentialMesh
   {
     TmpMesh() {
       _isShapeToMesh = (_id = 0);
@@ -5075,7 +5075,7 @@ void StdMeshers_PrismAsBlock::THorizontalEdgeAdaptor::dumpNodes(int nbNodes) con
 {
   if (!SALOME::VerbosityActivated())
     return;
-    
+
   // Not bedugged code. Last node is sometimes incorrect
   const TSideFace* side = mySide;
   double u = 0;
index d2bea83f431f09a5781b030de3442f9e8d4ef224..9a7398e916b6432606dca38bfbcf4e8f77cc0c62 100644 (file)
@@ -33,6 +33,7 @@
 #include "SMESH_Block.hxx"
 #include "SMESH_Comment.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_SequentialMesh.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_TypeDefs.hxx"
 #include "SMESH_subMesh.hxx"
@@ -117,7 +118,7 @@ namespace Prism_3D
 
 // ===============================================================
 /*!
- * \brief Tool analyzing and giving access to a prism geometry 
+ * \brief Tool analyzing and giving access to a prism geometry
  *  treating it like a block, i.e. the four side faces are
  *  emulated by division/uniting of missing/excess faces.
  *  It also manage associations between block sub-shapes and a mesh.
@@ -200,7 +201,7 @@ class STDMESHERS_EXPORT StdMeshers_PrismAsBlock: public SMESH_Block
    */
   bool GetLayersTransformation(std::vector<gp_Trsf> &      trsf,
                                const Prism_3D::TPrismTopo& prism) const;
-  
+
   /*!
    * \brief Return pointer to mesh
     * \retval SMESH_Mesh - mesh
@@ -389,7 +390,7 @@ private:
   SMESH_ComputeErrorPtr myError;
 
   // container of 4 side faces
-  TSideFace*            mySide; 
+  TSideFace*            mySide;
   // node columns for each base edge
   std::vector< TParam2ColumnMap >                       myParam2ColumnMaps;
   // to find a column for a node by edge SMESHDS Index
index 589112b47490f72c42db225a1aa59697bc6964ae..f3e01a338f34c4e883f1d1be8a89f9383f268b1c 100644 (file)
@@ -45,6 +45,7 @@
 #include <SMESH_Comment.hxx>
 #include <SMESH_Gen.hxx>
 #include <SMESH_Mesh.hxx>
+#include <SMESH_SequentialMesh.hxx>
 #include <SMESH_MeshAlgos.hxx>
 #include <SMESH_MeshEditor.hxx>
 #include <SMESH_MesherHelper.hxx>
@@ -324,7 +325,7 @@ namespace {
       break;
     }
     case TopAbs_EDGE: {
-      
+
       // Get submeshes of sub-vertices
       const map< int, SMESH_subMesh * >& subSM = sm->DependsOn();
       if ( subSM.size() != 2 )
@@ -711,7 +712,7 @@ namespace {
     while ( elemIt->more() ) // loop on all mesh faces on srcFace
     {
       const SMDS_MeshElement* elem = elemIt->next();
-      const int nbN = elem->NbCornerNodes(); 
+      const int nbN = elem->NbCornerNodes();
       tgtNodes.resize( nbN );
       helper->SetElementsOnShape( false );
       for ( int i = 0; i < nbN; ++i ) // loop on nodes of the source element
@@ -1096,7 +1097,7 @@ namespace {
    */
   //================================================================================
 
-  struct QuadMesh : public SMESH_Mesh
+  struct QuadMesh : public SMESH_SequentialMesh
   {
     ObjectPool< TriaCoordSys > _traiLCSPool;
     SMESH_ElementSearcher*     _elemSearcher;
@@ -1428,7 +1429,7 @@ namespace {
     //   const SMDS_MeshElement* elem = elemIt->next();
     //   TFaceConn& tgtNodes = newFacesVec[ iFaceSrc++ ];
 
-    //   const int nbN = elem->NbCornerNodes(); 
+    //   const int nbN = elem->NbCornerNodes();
     //   tgtNodes.resize( nbN );
     //   for ( int i = 0; i < nbN; ++i ) // loop on nodes of the source element
     //   {
@@ -1442,7 +1443,7 @@ namespace {
     //       {
     //         tgtNodeOrXY.first = srcN_tgtN->second; // tgt node exists
     //       }
-    //       else 
+    //       else
     //       {
     //         // find XY of src node within the quadrilateral srcFace
     //         if ( !block.ComputeParameters( SMESH_TNodeXYZ( srcNode ),
index 5cdf93f2bbef8a33d920aff261ab54975655d3ac..a14c5137777a2761d20215c888705f3eccb7ee72 100644 (file)
@@ -30,6 +30,7 @@
 #include "SMESH_Gen.hxx"
 #include "SMESH_MAT2d.hxx"
 #include "SMESH_Mesh.hxx"
+#include "SMESH_SequentialMesh.hxx"
 #include "SMESH_MeshEditor.hxx"
 #include "SMESH_MesherHelper.hxx"
 #include "SMESH_ProxyMesh.hxx"
@@ -144,7 +145,7 @@ public:
     return true;
   }
 };
+
 //================================================================================
 /*!
  * \brief Constructor sets algo features
@@ -203,7 +204,7 @@ bool StdMeshers_QuadFromMedialAxis_1D2D::CheckHypothesis(SMESH_Mesh&         aMe
 namespace
 {
   typedef map< const SMDS_MeshNode*, list< const SMDS_MeshNode* > > TMergeMap;
-  
+
   //================================================================================
   /*!
    * \brief Sinuous face
@@ -236,7 +237,7 @@ namespace
   /*!
    * \brief Temporary mesh
    */
-  struct TmpMesh : public SMESH_Mesh
+  struct TmpMesh : public SMESH_SequentialMesh
   {
     TmpMesh()
     {
@@ -506,7 +507,7 @@ namespace
     theSinuEdges[1].clear();
     theShortEdges[0].clear();
     theShortEdges[1].clear();
-   
+
     vector<TopoDS_Edge> & allEdges = theSinuFace._edges;
     const size_t nbEdges = allEdges.size();
     if ( nbEdges < 4 && theSinuFace._nbWires == 1 )
@@ -841,7 +842,7 @@ namespace
 
 
     // Find 1D algo to mesh branchEdge
-  
+
     // look for a most local 1D hyp assigned to the FACE
     int mostSimpleShape = -1, maxShape = TopAbs_EDGE;
     TopoDS_Edge edge;
@@ -1450,7 +1451,7 @@ namespace
       nIn = nodeParams.rbegin()->second;
     else
       nIn = u2n->second;
-    
+
     // find position of distant nodes in uvsOut and uvsIn
     size_t iDistOut, iDistIn;
     for ( iDistOut = 0; iDistOut < uvsOut.size(); ++iDistOut )
@@ -2151,6 +2152,7 @@ bool StdMeshers_QuadFromMedialAxis_1D2D::computeQuads( SMESH_MesherHelper& theHe
 bool StdMeshers_QuadFromMedialAxis_1D2D::Compute(SMESH_Mesh&         theMesh,
                                                  const TopoDS_Shape& theShape)
 {
+  std::cout << "helper_quad " << theMesh.IsParallel() << std::endl;
   SMESH_MesherHelper helper( theMesh );
   helper.SetSubShape( theShape );
 
index ff5906d53344e51b150f7562ce4135e70ffce33b..a97f274a21506a9910403e66441e7ef234a95b46 100644 (file)
@@ -70,7 +70,7 @@ using namespace std;
 
 //=======================================================================
 //function : StdMeshers_RadialQuadrangle_1D2D
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 StdMeshers_RadialQuadrangle_1D2D::StdMeshers_RadialQuadrangle_1D2D(int        hypId,
@@ -103,7 +103,7 @@ StdMeshers_RadialQuadrangle_1D2D::~StdMeshers_RadialQuadrangle_1D2D()
 
 //=======================================================================
 //function : CheckHypothesis
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool StdMeshers_RadialQuadrangle_1D2D::CheckHypothesis
@@ -111,7 +111,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::CheckHypothesis
                             const TopoDS_Shape&                  aShape,
                             SMESH_Hypothesis::Hypothesis_Status& aStatus)
 {
-  // check aShape 
+  // check aShape
   myNbLayerHypo = 0;
   myDistributionHypo = 0;
 
@@ -271,7 +271,7 @@ namespace
         sideEdges.splice( sideEdges.end(), edges, edges.begin() );
 
       StdMeshers_FaceSidePtr side;
-      if ( aMesh ) 
+      if ( aMesh )
         side = StdMeshers_FaceSide::New( face, sideEdges, aMesh,
                                          /*isFwd=*/true, /*skipMedium=*/ true, helper );
       sides.push_back( side );
@@ -355,7 +355,7 @@ namespace
         }
     }
 
-    int iCirc = deviation2sideInd.rbegin()->second; 
+    int iCirc = deviation2sideInd.rbegin()->second;
     aCircSide = sides[ iCirc ];
     aLinSide1 = sides[( iCirc + 1 ) % sides.size() ];
     if ( sides.size() > 2 )
@@ -958,7 +958,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Compute(SMESH_Mesh&         aMesh,
     centerUV   = nodes.back().UV();
   }
   // ------------------------------------------------------------------------------------------
-  else // nbSides == 3 
+  else // nbSides == 3
   {
     // one curve must be a part of ellipse and 2 other curves must be segments of line
 
@@ -1082,7 +1082,7 @@ int StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(StdMeshers_FaceSideP
     if ( !TNodeDistributor::GetDistributor(*mesh)->Compute( positions, linSide->Edge(0),
                                                             *curve, f, l, *mesh, hyp1D ))
     {
-      if ( myDistributionHypo ) { // bad hyp assigned 
+      if ( myDistributionHypo ) { // bad hyp assigned
         return error( TNodeDistributor::GetDistributor(*mesh)->GetComputeError() );
       }
       else {
@@ -1090,7 +1090,7 @@ int StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(StdMeshers_FaceSideP
       }
     }
   }
-  
+
   if ( positions.empty() ) // try to use nb of layers
   {
     if ( !nbLayers )
@@ -1132,7 +1132,7 @@ int StdMeshers_RadialQuadrangle_1D2D::computeLayerPositions(StdMeshers_FaceSideP
 
 //=======================================================================
 //function : Evaluate
-//purpose  : 
+//purpose  :
 //=======================================================================
 
 bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
@@ -1193,7 +1193,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
       return false;
   }
   // ------------------------------------------------------------------------------------------
-  else // nbSides == 3 
+  else // nbSides == 3
   {
     if ( !computeLayerPositions(( linSide1->Length() > linSide2->Length() ) ? linSide1 : linSide2,
                                  layerPositions ))
@@ -1217,7 +1217,7 @@ bool StdMeshers_RadialQuadrangle_1D2D::Evaluate(SMESH_Mesh&         aMesh,
     if ( SMDSEntity_Quad_Edge < (int) nbElems.size() )
       nbCircSegments += ( nbElems[ SMDSEntity_Edge ] + nbElems[ SMDSEntity_Quad_Edge ]);
   }
-  
+
   smIdType nbQuads = nbCircSegments * ( layerPositions.size() - 1 );
   smIdType nbTria  = nbCircSegments;
   smIdType nbNodes = ( nbCircSegments - 1 ) * ( layerPositions.size() - 2 );
diff --git a/test/SMESH_ParallelCompute.py b/test/SMESH_ParallelCompute.py
deleted file mode 100644 (file)
index fccec13..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-# contains function to compute a mesh in parallel
-from platform import java_ver
-import sys
-from tkinter import W
-import salome
-
-import time
-
-
-salome.salome_init()
-import salome_notebook
-notebook = salome_notebook.NoteBook()
-
-###
-### GEOM component
-###
-
-import GEOM
-from salome.geom import geomBuilder
-from salome.smesh import smeshBuilder
-import math
-import SALOMEDS
-
-import numpy as np
-
-geompy = geomBuilder.New()
-
-smesh = smeshBuilder.New()
-
-
-def build_seq_mesh(nbox, boxsize, offset):
-    # Create 3D faces
-    boxes = []
-    # First creating all the boxes
-    for i in range(nbox):
-        for j in range(nbox):
-            for k in range(nbox):
-
-                x_orig = i*(boxsize+offset)
-                y_orig = j*(boxsize+offset)
-                z_orig = k*(boxsize+offset)
-
-                tmp_box = geompy.MakeBoxDXDYDZ(boxsize, boxsize, boxsize)
-
-                if not i == j == k == 0:
-                    box = geompy.MakeTranslation(tmp_box, x_orig,
-                                                 y_orig, z_orig)
-                else:
-                    box = tmp_box
-
-                geompy.addToStudy(box, 'box_{}:{}:{}'.format(i, j, k))
-
-                boxes.append(box)
-
-    # Create fuse of all boxes
-    all_boxes = geompy.MakeCompound(boxes)
-    geompy.addToStudy(all_boxes, 'Compound_1')
-
-    # Removing duplicates faces and edges
-    all_boxes = geompy.MakeGlueFaces(all_boxes, 1e-07)
-    geompy.addToStudy(all_boxes, 'Glued_Faces_1')
-
-    all_boxes = geompy.MakeGlueEdges(all_boxes, 1e-07)
-    geompy.addToStudy(all_boxes, 'rubik_cube')
-
-
-    # Building sequetial mesh
-    print("Creating mesh")
-    all_box_mesh = smesh.Mesh(all_boxes, "seq_mesh")
-
-    print("Adding algo")
-    algo3d = all_box_mesh.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D)
-
-    netgen_parameters = algo3d.Parameters()
-    netgen_parameters.SetMaxSize(34.641)
-    netgen_parameters.SetMinSize(0.141421)
-    netgen_parameters.SetOptimize(1)
-    netgen_parameters.SetCheckOverlapping(0)
-    netgen_parameters.SetCheckChartBoundary(0)
-    netgen_parameters.SetFineness(5)
-    netgen_parameters.SetNbSegPerEdge(16*(boxsize//100))
-    netgen_parameters.SetNbSegPerRadius(1.5)
-    netgen_parameters.SetGrowthRate(0.15)
-    netgen_parameters.SetChordalError(-1)
-    netgen_parameters.SetChordalErrorEnabled(0)
-    netgen_parameters.SetUseSurfaceCurvature(1)
-    netgen_parameters.SetQuadAllowed(0)
-    netgen_parameters.SetCheckOverlapping(False)
-    netgen_parameters.SetNbThreads(2)
-
-    return all_boxes, all_box_mesh, netgen_parameters
-
-def run_test(nbox=2, boxsize=100):
-    """ Run sequential mesh and parallel version of it
-
-    nbox: NUmber of boxes
-    boxsize: Size of each box
-    """
-    geom, seq_mesh, netgen_parameters = build_seq_mesh(nbox, boxsize, 0)
-
-    par_mesh = smesh.ParallelMesh(geom, netgen_parameters, 6, name="par_mesh")
-
-    start = time.monotonic()
-    is_done = seq_mesh.Compute()
-    assert is_done
-    stop = time.monotonic()
-    time_seq = stop-start
-
-    start = time.monotonic()
-    is_done = par_mesh.Compute()
-    assert is_done
-    stop = time.monotonic()
-    time_par = stop-start
-
-    print("  Tetrahedron: ", seq_mesh.NbTetras(), par_mesh.NbTetras())
-    print("  Triangle: ", seq_mesh.NbTriangles(), par_mesh.NbTriangles())
-    print("  edge: ", seq_mesh.NbEdges(), par_mesh.NbEdges())
-
-    assert  par_mesh.NbTetras() > 0
-    assert  par_mesh.NbTriangles() > 0
-    assert  par_mesh.NbEdges() > 0
-
-    print("Time elapsed (seq, par): ", time_seq, time_par)
-
-def main():
-    if sys.platform == "win32":
-        print("Test disabled on Windows")
-        return
-    nbox = 2
-    boxsize = 100
-    run_test(nbox, boxsize)
-
-main()
index 0035933fe45ed6fdb3368283e211c9cea94dbb1a..b14e7c2004c7d6067fbc75834ed4ce781c19040e 100644 (file)
@@ -65,7 +65,6 @@ SET(BAD_TESTS
   SMESH_create_dual_mesh_adapt.py
   SMESH_create_dual_mesh_tpipe.py
   netgen_runner.py
-  SMESH_ParallelCompute.py
   )
 IF(NOT WIN32)
   LIST(APPEND BAD_TESTS