Cleanup of parallel meshing + documentation

This commit is contained in:
Yoann Audouin 2023-03-09 16:32:55 +01:00
parent 483e992a6d
commit d328a1d7b8
30 changed files with 767 additions and 196 deletions

View File

@ -98,14 +98,22 @@ def run_test(nbox=2, boxsize=100):
"""
geom, seq_mesh, netgen_parameters = build_seq_mesh(nbox, boxsize, 0)
par_mesh = smesh.ParallelMesh(geom, netgen_parameters, 6, name="par_mesh")
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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View 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

View File

@ -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`.

View 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>`

View 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
*/

View 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

View 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

View 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"
@ -58,6 +57,10 @@
#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;
}

View 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;

View 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
}

View 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() {};
virtual void Lock(){};
virtual 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;};
virtual int GetNbThreads(){return 0;};
virtual void SetNbThreads(long nbThreads){(void) nbThreads;};
void InitPoolThreads(){};
void DeletePoolThreads(){};
void wait(){}
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;};
bool IsParallel(){return _NbThreads > 0;}
#else
void Lock() {_my_lock.lock();};
void Unlock() {_my_lock.unlock();};
virtual bool IsParallel(){std::cout << "Should not pass here: IsParallel" << std::endl;return false;};
int GetNbThreads(){return _NbThreads;};
void SetNbThreads(long nbThreads){_NbThreads=nbThreads;};
void InitPoolThreads(){_pool = new boost::asio::thread_pool(_NbThreads);};
void DeletePoolThreads(){delete _pool;};
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();

View File

@ -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);
}

View File

@ -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

View File

@ -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);
};

View File

@ -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

View 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()) {

View 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 ---

View File

@ -107,6 +107,8 @@
#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();

View 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 );

View 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();
}
//=============================================================================
/*!

View 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

View 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):
# 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 split_geom:
self._all_faces, self._solids = _split_geom(geompyD, geom)
self.UseExistingSegments()
self.UseExistingFaces()
self._algo2d = self.Triangle(geom=self._all_faces, algo="NETGEN_2D")
self._algo3d = []
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)
self._param = ParallelismSettings(self)
def GetParallelismSettings(self):
"""
Return class to set parameters for the parallelism
"""
return self._param
def AddGlobalHypothesis(self, hyp):
"""
Split hypothesis to apply it to all the submeshes:
- the 1D+2D
- each of the 3D solids
Parameters:
hyp: a hypothesis to assign
"""
if not isinstance(hyp, NETGENPlugin._objref_NETGENPlugin_Hypothesis):
raise ValueError("param must come from NETGENPlugin")
if nbThreads < 1:
raise ValueError("Number of threads must be stricly greater than 1")
param2d = self._algo2d.Parameters()
_copy_netgen_param(2, param2d, hyp)
# 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)
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')
super(ParallelMesh, self).__init__(smeshpyD, geompyD, geom, name)
self.mesh.SetNbThreads(nbThreads)
self.UseExistingSegments()
self.UseExistingFaces()
algo2d = self.Triangle(geom=all_faces, algo="NETGEN_2D")
param2d = algo2d.Parameters()
_copy_netgen_param(2, param2d, param)
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

View 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;

View 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

View 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 ),

View 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 );

View 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 );

View 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