Splitting gen compute seq/para + clean up + remove int argument + solve bug (commented notifyevent)

This commit is contained in:
Yoann Audouin 2022-09-29 16:25:05 +02:00
parent d5617f4801
commit c9a5231c32
6 changed files with 205 additions and 97 deletions

View File

@ -52,7 +52,7 @@ The mesh can include the following entities:
* **Node** - a mesh entity defining a position in 3D space with coordinates (x, y, z). * **Node** - a mesh entity defining a position in 3D space with coordinates (x, y, z).
* **Edge** (or segment) - 1D mesh element linking two nodes. * **Edge** (or segment) - 1D mesh element linking two nodes.
* **Face** - 2D mesh element representing a part of surface bound by links between face nodes. A face can be a triangle, quadrangle or polygon. * **Face** - 2D mesh element representing a part of surface bound by links between face nodes. A face can be a triangle, quadrangle or polygon.
* **Volume** - 3D mesh element representing a part of 3D space bound by volume facets. Nodes of a volume describing each facet are defined by the :ref:`connectivity convention <connectivity_page>`. A volume can be a tetrahedron, hexahedron, pentahedron, pyramid, hexagonal prism or polyhedron. * **Volume** - 3D mesh element representing a part of 3D space bound by volume facets. Nodes of a volume describing each facet are defined by the :ref:`connectivity convention <connectivity_page>`. A volume can be a tetrahedron, hexahedron, pentahedron, pyramid, hexagonal or polyhedron.
* **0D** element - mesh element defined by one node. * **0D** element - mesh element defined by one node.
* **Ball** element - discrete mesh element defined by a node and a diameter. * **Ball** element - discrete mesh element defined by a node and a diameter.

View File

@ -160,21 +160,82 @@ SMESH_Mesh* SMESH_Gen::CreateMesh(bool theIsEmbeddedMode)
return aMesh; return aMesh;
} }
bool SMESH_Gen::sequentialComputeSubMeshes(
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)
{
MESSAGE("Compute submeshes sequentialy");
bool ret = true;
SMESH_subMeshIteratorPtr smIt;
SMESH_subMesh *shapeSM = aMesh.GetSubMesh(aShape);
smIt = shapeSM->getDependsOnIterator(includeSelf, !complexShapeFirst);
while ( smIt->more() )
{
SMESH_subMesh* smToCompute = smIt->next();
// do not mesh vertices of a pseudo shape
const TopoDS_Shape& shape = smToCompute->GetSubShape();
const TopAbs_ShapeEnum shapeType = shape.ShapeType();
if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX )
continue;
// check for preview dimension limitations
if ( aShapesId && 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;
}
if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
{
if (_compute_canceled)
return false;
smToCompute->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
setCurrentSubMesh( smToCompute );
smToCompute->ComputeStateEngine( computeEvent );
setCurrentSubMesh( nullptr );
smToCompute->SetAllowedSubShapes( nullptr );
}
// 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() );
}
//aMesh.GetMeshDS()->Modified();
return ret;
};
//============================================================================= //=============================================================================
/* /*
* Parallel compute of a submesh * Parallel compute of a submesh
* This function is used to pass to thread_pool * This function is used to pass to thread_pool
*/ */
//============================================================================= //=============================================================================
const std::function<void(int, const std::function<void(SMESH_subMesh*,
SMESH_subMesh*,
SMESH_subMesh::compute_event, SMESH_subMesh::compute_event,
SMESH_subMesh*, SMESH_subMesh*,
bool, bool,
TopTools_IndexedMapOfShape *, TopTools_IndexedMapOfShape *,
TSetOfInt*)> TSetOfInt*)>
compute_function([&] (int id, compute_function([&] (SMESH_subMesh* sm,
SMESH_subMesh* sm,
SMESH_subMesh::compute_event event, SMESH_subMesh::compute_event event,
SMESH_subMesh *shapeSM, SMESH_subMesh *shapeSM,
bool aShapeOnly, bool aShapeOnly,
@ -184,9 +245,9 @@ const std::function<void(int,
if (sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE) if (sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
{ {
sm->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes )); sm->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
setCurrentSubMesh( sm ); //setCurrentSubMesh( sm );
sm->ComputeStateEngine(event); sm->ComputeStateEngine(event);
setCurrentSubMesh( nullptr ); //setCurrentSubMesh( nullptr );
sm->SetAllowedSubShapes( nullptr ); sm->SetAllowedSubShapes( nullptr );
} }
@ -195,6 +256,101 @@ const std::function<void(int,
}); });
bool SMESH_Gen::parallelComputeSubMeshes(
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)
{
bool ret = true;
SMESH_subMeshIteratorPtr smIt;
SMESH_subMesh *shapeSM = aMesh.GetSubMesh(aShape);
// Pool of thread for computation
// TODO: move when parallelMesh created
aMesh.InitPoolThreads();
TopAbs_ShapeEnum previousShapeType = TopAbs_VERTEX;
int nbThreads = aMesh.GetNbThreads();
MESSAGE("Compute submeshes with threads: " << nbThreads << " mesher: " << aMesh.GetMesherNbThreads());
smIt = shapeSM->getDependsOnIterator(includeSelf, !complexShapeFirst);
while ( smIt->more() )
{
SMESH_subMesh* smToCompute = smIt->next();
// do not mesh vertices of a pseudo shape
const TopoDS_Shape& shape = smToCompute->GetSubShape();
const TopAbs_ShapeEnum shapeType = shape.ShapeType();
// Not doing in parallel 1D and 2D meshes
if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX )
continue;
if(shapeType==TopAbs_FACE||shapeType==TopAbs_EDGE)
aMesh.SetNbThreads(0);
else
aMesh.SetNbThreads(nbThreads);
if (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 )
{
// 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,
shapeSM, aShapeOnly, allowedSubShapes,
aShapesId));
}
// Waiting for the thread for Solids to finish
aMesh.wait();
aMesh.GetMeshDS()->Modified();
return ret;
};
//============================================================================= //=============================================================================
/* /*
* Compute a mesh * Compute a mesh
@ -222,10 +378,6 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh,
const bool complexShapeFirst = true; const bool complexShapeFirst = true;
const int globalAlgoDim = 100; const int globalAlgoDim = 100;
// Pool of thread for computation
if(aMesh.IsParallel())
aMesh.InitPoolThreads();
SMESH_subMeshIteratorPtr smIt; SMESH_subMeshIteratorPtr smIt;
// Fix of Issue 22150. Due to !BLSURF->OnlyUnaryInput(), BLSURF computes edges // Fix of Issue 22150. Due to !BLSURF->OnlyUnaryInput(), BLSURF computes edges
@ -245,89 +397,22 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh,
// =============================================== // ===============================================
// Mesh all the sub-shapes starting from vertices // Mesh all the sub-shapes starting from vertices
// =============================================== // ===============================================
if (aMesh.IsParallel())
TopAbs_ShapeEnum previousShapeType = TopAbs_VERTEX; ret = parallelComputeSubMeshes(
int nbThreads = aMesh.GetNbThreads(); aMesh, aShape, aDim,
MESSAGE("Running mesh with threads: " << nbThreads << " mesher: " << aMesh.GetMesherNbThreads()); aShapesId, allowedSubShapes,
computeEvent,
includeSelf,
smIt = shapeSM->getDependsOnIterator(includeSelf, !complexShapeFirst); complexShapeFirst,
while ( smIt->more() ) aShapeOnly);
{ else
SMESH_subMesh* smToCompute = smIt->next(); ret = sequentialComputeSubMeshes(
aMesh, aShape, aDim,
// do not mesh vertices of a pseudo shape aShapesId, allowedSubShapes,
const TopoDS_Shape& shape = smToCompute->GetSubShape(); computeEvent,
const TopAbs_ShapeEnum shapeType = shape.ShapeType(); includeSelf,
if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX ) complexShapeFirst,
continue; aShapeOnly);
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 )
{
// 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;
}
if(aMesh.IsParallel())
{
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() );
}
}
// TODO: Check error handling in parallel mode
if(aMesh.IsParallel()){
// Waiting for the thread for Solids to finish
aMesh.wait();
}
aMesh.GetMeshDS()->Modified();
return ret; return ret;
} }

View File

@ -34,6 +34,7 @@
#include "SMESH_Algo.hxx" #include "SMESH_Algo.hxx"
#include "SMESH_ComputeError.hxx" #include "SMESH_ComputeError.hxx"
#include "SMESH_subMesh.hxx"
#include <map> #include <map>
#include <list> #include <list>
@ -49,7 +50,7 @@ class SMESHDS_Document;
class SMESH_Algo; class SMESH_Algo;
class SMESH_Mesh; class SMESH_Mesh;
class TopoDS_Shape; class TopoDS_Shape;
class SMESH_subMesh;
typedef SMESH_Hypothesis::Hypothesis_Status TAlgoStateErrorName; typedef SMESH_Hypothesis::Hypothesis_Status TAlgoStateErrorName;
@ -168,6 +169,28 @@ public:
private: private:
bool parallelComputeSubMeshes(
SMESH_Mesh & aMesh,
const TopoDS_Shape & aShape,
const ::MeshDimension aDim,
TSetOfInt* aShapesId,
TopTools_IndexedMapOfShape* allowedSubShapes,
SMESH_subMesh::compute_event &computeEvent,
const bool includeSelf,
const bool complexShapeFirst,
const bool aShapeOnly);
bool sequentialComputeSubMeshes(
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);
int _localId; // unique Id of created objects, within SMESH_Gen entity int _localId; // unique Id of created objects, within SMESH_Gen entity
StudyContextStruct* _studyContext; StudyContextStruct* _studyContext;

View File

@ -5588,5 +5588,6 @@ void SMESH_MesherHelper::WriteShape(const TopoDS_Shape& s)
{ {
const char* name = "/tmp/shape.brep"; const char* name = "/tmp/shape.brep";
BRepTools::Write( s, name ); BRepTools::Write( s, name );
MESSAGE(name);
} }

View File

@ -1907,7 +1907,7 @@ bool SMESH_subMesh::ComputeStateEngine(compute_event event)
break; break;
} }
//notifyListenersOnEvent( event, COMPUTE_EVENT ); notifyListenersOnEvent( event, COMPUTE_EVENT );
return ret; return ret;
} }

View File

@ -1898,7 +1898,6 @@ class Mesh(metaclass = MeshMeta):
a last total re-compute and that may prevent successful partial re-compute, a last total re-compute and that may prevent successful partial re-compute,
then the mesh is cleaned before Compute() then the mesh is cleaned before Compute()
refresh: if *True*, Object Browser is automatically updated (when running in GUI) refresh: if *True*, Object Browser is automatically updated (when running in GUI)
nbThreads: Number of threads to use for a parallel computation
Returns: Returns:
True or False True or False