# contains function to compute a mesh in parallel
+from platform import java_ver
+import sys
+try:
+ from tkinter import W
+except:
+ print("warning: could not import tkinter")
+
import salome
+import time
+
+
salome.salome_init()
import salome_notebook
notebook = salome_notebook.NoteBook()
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()
-nbox = 2
-boxsize = 100
-offset = 0
-# 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')
-
-rubik_cube = geompy.MakeGlueEdges(all_boxes, 1e-07)
-geompy.addToStudy(all_boxes, 'rubik_cube')
+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):
-smesh = smeshBuilder.New()
-print("Creating Parallel Mesh")
-par_mesh = smesh.ParallelMesh(rubik_cube, name="par_mesh")
-
-print("Creating hypoehtesis for netgen")
-NETGEN_3D_Parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters',
- 'NETGENEngine', 34.641, 0 )
-print("Adding hypothesis")
-par_mesh.AddGlobalHypothesis(NETGEN_3D_Parameters_1)
-
-print("Setting parallelism method")
-par_mesh.SetParallelismMethod(smeshBuilder.MULTITHREAD)
-
-print("Setting parallelism options")
-param = par_mesh.GetParallelismSettings()
-param.SetNbThreads(6)
-
-print("Starting parallel compute")
-is_done = par_mesh.Compute()
-if not is_done:
- raise Exception("Error when computing Mesh")
-
-print(" Tetrahedron: ", par_mesh.NbTetras())
-print(" Triangle: ", par_mesh.NbTriangles())
-print(" edge: ", par_mesh.NbEdges())
-
-assert par_mesh.NbTetras() > 0
-assert par_mesh.NbTriangles() > 0
-assert par_mesh.NbEdges() > 0
+ 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()
+ if not is_done:
+ raise Exception("Error when computing Mesh")
+
+ stop = time.monotonic()
+ time_seq = stop-start
+
+ print("Starting parallel compute")
+ start = time.monotonic()
+ is_done = par_mesh.Compute()
+ if not is_done:
+ raise Exception("Error when computing Mesh")
+
+ 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()
You follow the same principle as the creation of a sequential Mesh.
-1. First you create the mesh:
-
+#. First you create the mesh:
.. code-block:: python
- par_mesh = smesh.ParallelMesh(my_geom, name="par_mesh")
+ par_mesh = smesh.ParallelMesh(geom, name="par_mesh")
-2. Define the Global Hypothesis that will be split into an hypothesis for the
+#. 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
+ .. code-block:: python
NETGEN_3D_Parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters',
'NETGENEngine', 34.641, 0 )
- par_mesh.AddGlobalHypothesis(NETGEN_3D_Parameters_1)
-
-3. Set the method for the parallelisation:
-
- You have two methods for parallelisation:
-
- * Multihtreading: Will run the computation on your computer using the processors on your computer.
-
- .. code-block:: python
-
- par_mesh.SetParallelismMethod(smeshBuilder.MULTITHREAD)
-
-
- * MultiNodal: Will run the computation on a remote resource (cluster) that is defined in your salome catalog.
-
- .. code-block:: python
-
- par_mesh.SetParallelismMethod(smeshBuilder.MULTINODE)
-
-
-4. Set the parameters for the parallelism:
-
- * Multithread:
+ par_mesh.AddGlobalHypothesis(netgen_parameters)
+#. Set the parameters for the parallelisation:
.. code-block:: python
param = par_mesh.GetParallelismSettings()
param.SetNbThreads(6)
- * Multinode:
-
- .. code-block:: python
-
- param = par_mesh.GetParallelismSettings()
- param.SetResource("cronos")
- param.SetNbProc(nbox**3)
- param.SetNbProcPerNode(2)
- param.SetNbNode(6)
- param.SetWcKey("P11N0:SALOME_COFEE")
-
-5. Compute the mesh:
+#. Compute the mesh:
.. code-block:: python
- is_done = par_mesh.Compute()
- if not is_done:
- raise Exception("Error when computing Mesh")
+ mesh.Compute()
**See Also** a sample script of :ref:`tui_create_parallel_mesh`.
* with TopoDS_Shapes
* The mesh is a parallel one
*/
- SMESH_ParallelMesh CreateParallelMesh( in GEOM::GEOM_Object theObject )
+ SMESH_Mesh CreateParallelMesh( in GEOM::GEOM_Object theObject )
raises ( SALOME::SALOME_Exception );
/*!
* Create an empty mesh object
*/
boolean SetMeshOrder(in submesh_array_array theSubMeshArray);
+ /*!
+ * \brief Set Number of Threads
+ */
+ void SetNbThreads(in long nbThreads);
+ /*!
+ /*!
+ * \brief Get Number of Threads
+ */
+ long GetNbThreads();
+ /*!
+
/*!
* Get mesh description
*/
};
interface SMESH_SequentialMesh:SMESH_Mesh{};
- interface SMESH_ParallelMesh:SMESH_Mesh{
-
- // Parallism method
- long GetParallelismMethod();
- void SetParallelismMethod(in long aMethod);
-
- // Parameters for MutliThreading
- long GetNbThreads();
- void SetNbThreads(in long nbThreads);
-
- // Parameters for MultiNode
- string GetResource();
- void SetResource(in string aResource);
-
- long GetNbProc();
- void SetNbProc(in long nbProc);
-
- long GetNbProcPerNode();
- void SetNbProcPerNode(in long nbProcPerNode);
-
- long GetNbNode();
- void SetNbNode(in long nbNode);
-
- string GetWcKey();
- void SetWcKey(in string wcKey);
- };
+ interface SMESH_ParallelMesh:SMESH_Mesh{};
};
# --- options ---
# additional include directories
INCLUDE_DIRECTORIES(
- ${QT_INCLUDES}
${KERNEL_INCLUDE_DIRS}
${GEOM_INCLUDE_DIRS}
${OpenCASCADE_INCLUDE_DIR}
MeshDriverGMF
${DriverCGNS_LIB}
${MEDCoupling_medloader}
- Qt5::Core
)
# --- headers ---
#include "memoire.h"
#include <functional>
-#include <QString>
-#include <QProcess>
-
#ifdef WIN32
#include <windows.h>
#endif
*/
//=============================================================================
-SMESH_ParallelMesh* SMESH_Gen::CreateParallelMesh(bool theIsEmbeddedMode)
+SMESH_Mesh* SMESH_Gen::CreateParallelMesh(bool theIsEmbeddedMode)
{
Unexpect aCatch(SalomeException);
// create a new SMESH_mesh object
- SMESH_ParallelMesh *aMesh = new SMESH_ParallelMesh(
+ SMESH_Mesh *aMesh = new SMESH_ParallelMesh(
_localId++,
this,
theIsEmbeddedMode,
const bool complexShapeFirst,
const bool aShapeOnly)
{
- MESSAGE("Sequential Compute of submeshes");
+ MESSAGE("Compute submeshes sequentialy");
bool ret = true;
});
-//=============================================================================
-/*
- * Copy a file on remote resource
- */
-//=============================================================================
-
-void SMESH_Gen::send_mesh(SMESH_Mesh& aMesh, std::string file_name)
-{
- SMESH_ParallelMesh& aParMesh = dynamic_cast<SMESH_ParallelMesh&>(aMesh);
- // Calling run_mesher
- // Path to mesher script
- fs::path send_files = fs::path(std::getenv("SMESH_ROOT_DIR"))/
- fs::path("bin")/
- fs::path("salome")/
- fs::path("send_files.py");
-
- std::string s_program="python3";
- std::list<std::string> params;
- params.push_back(send_files.string());
- params.push_back(file_name);
- params.push_back("--resource="+aParMesh.GetResource());
-
- // log file
- fs::path log_file=aParMesh.GetTmpFolder() / fs::path("copy.log");
- QString out_file = log_file.string().c_str();
-
- // Building arguments for QProcess
- QString program = QString::fromStdString(s_program);
- QStringList arguments;
- for(auto arg : params){
- arguments << arg.c_str();
- }
-
- std::string cmd = "";
- cmd += s_program;
- for(auto arg: params){
- cmd += " " + arg;
- }
- MESSAGE("Send files command: ");
- MESSAGE(cmd);
-
- QProcess myProcess;
- myProcess.setProcessChannelMode(QProcess::MergedChannels);
- myProcess.setStandardOutputFile(out_file);
-
- myProcess.start(program, arguments);
- // Waiting for process to finish (argument -1 make it wait until the end of
- // the process otherwise it just waits 30 seconds)
- bool finished = myProcess.waitForFinished(-1);
- int ret = myProcess.exitCode();
-
- if(ret != 0 || !finished){
- // Run crahed
- std::string msg = "Issue with send_files: \n";
- msg += "See log for more details: " + log_file.string() + "\n";
- msg += cmd + "\n";
- throw SALOME_Exception(msg);
- }
-}
-
//=============================================================================
/*!
* Algo to run the computation of all the submeshes of a mesh in parallel
SMESH_subMeshIteratorPtr smIt;
SMESH_subMesh *shapeSM = aMesh.GetSubMesh(aShape);
- SMESH_ParallelMesh &aParMesh = dynamic_cast<SMESH_ParallelMesh&>(aMesh);
TopAbs_ShapeEnum previousShapeType = TopAbs_VERTEX;
- MESSAGE("Parallel Compute of submeshes");
+ int nbThreads = aMesh.GetNbThreads();
+ MESSAGE("Compute submeshes with threads: " << nbThreads);
smIt = shapeSM->getDependsOnIterator(includeSelf, !complexShapeFirst);
// 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
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_EDGE:
+ file_name = "Mesh1D.med";
+ break;
+ case TopAbs_VERTEX:
+ file_name = "Mesh0D.med";
+ break;
case TopAbs_SOLID:
default:
file_name = "";
}
if(file_name != "")
{
- fs::path mesh_file = fs::path(aParMesh.GetTmpFolder()) / fs::path(file_name);
+ fs::path mesh_file = fs::path(aMesh.GetTmpFolder()) / fs::path(file_name);
SMESH_DriverMesh::exportMesh(mesh_file.string(), aMesh, "MESH");
- if (aParMesh.GetParallelismMethod() == ParallelismMethod::MultiNode) {
- this->send_mesh(aMesh, mesh_file.string());
- }
}
//Resetting threaded pool info
previousShapeType = shapeType;
smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
continue;
}
- // Parallelism is only for 3D parts
- if(shapeType!=TopAbs_SOLID){
- compute_function(smToCompute, computeEvent,
+ boost::asio::post(*(aMesh.GetPool()), std::bind(compute_function, smToCompute, computeEvent,
shapeSM, aShapeOnly, allowedSubShapes,
- aShapesId);
- }else{
- boost::asio::post(*(aParMesh.GetPool()), std::bind(compute_function, smToCompute, computeEvent,
- shapeSM, aShapeOnly, allowedSubShapes,
- aShapesId));
- }
+ aShapesId));
}
// Waiting for the thread for Solids to finish
if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
continue;
sm->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
-
setCurrentSubMesh( sm );
sm->ComputeStateEngine( computeEvent );
class SMESHDS_Document;
class SMESH_Algo;
class SMESH_Mesh;
-class SMESH_ParallelMesh;
class TopoDS_Shape;
~SMESH_Gen();
SMESH_Mesh* CreateMesh(bool theIsEmbeddedMode);
- SMESH_ParallelMesh* CreateParallelMesh(bool theIsEmbeddedMode);
+ SMESH_Mesh* CreateParallelMesh(bool theIsEmbeddedMode);
enum ComputeFlags
{
int GetANewId();
public:
- void send_mesh(SMESH_Mesh & aMesh, std::string filename);
-
bool parallelComputeSubMeshes(
SMESH_Mesh & aMesh,
const TopoDS_Shape & aShape,
#ifndef WIN32
#include <boost/filesystem.hpp>
+#include <boost/asio/thread_pool.hpp>
#endif
#include <boost/thread.hpp>
virtual void Lock(){};
virtual void Unlock(){};
- virtual void wait(){};
+ virtual int GetNbThreads(){return 0;};
+ virtual void SetNbThreads(long nbThreads){(void) nbThreads;};
- virtual bool IsParallel(){throw SALOME_Exception("Calling SMESH_Mesh::IsParallel");return false;};
+ 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;};
+
+ virtual bool IsParallel(){std::cout << "Should not pass here: IsParallel" << std::endl;return false;};
+
+#ifndef WIN32
+ virtual boost::filesystem::path GetTmpFolder() {return "";};
+ virtual boost::asio::thread_pool* GetPool() {return NULL;};
+#endif
virtual bool ComputeSubMeshes(
SMESH_Gen* gen,
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;throw SALOME_Exception("Calling SMESH_Mesh::ComputeSubMeshes");return false;};
+ 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:
// 2) to forget not loaded mesh data at hyp modification
TCallUp* _callUp;
+ // Mutex for multhitreading write in SMESH_Mesh
+#ifndef WIN32
+ boost::mutex _my_lock;
+#endif
+ int _NbThreads=-1;
+
protected:
SMESH_Mesh();
SMESH_Mesh(const SMESH_Mesh&) {};
theDocument)
{
MESSAGE("SMESH_ParallelMesh::SMESH_ParallelMesh(int localId)");
+#ifndef WIN32
+ _NbThreads = std::thread::hardware_concurrency();
+#else
+ _NbThreads = 0;
+#endif
CreateTmpFolder();
};
#endif
}
-//=============================================================================
-/*!
- * \brief Get the number of Threads to be used for the pool of Threads
- */
-//=============================================================================
-int SMESH_ParallelMesh::GetPoolNbThreads()
-{
- int nbThreads = -1;
-
- if(_method == ParallelismMethod::MultiThread){
- nbThreads = _NbThreads;
- }else if( _method == ParallelismMethod::MultiNode){
- //TODO: Check of that is the right way
- nbThreads = std::max(_nbProc, _nbNode*_nbProcPerNode);
- } else {
- throw SALOME_Exception("Unknown method "+std::to_string(_method));
- }
-
- return nbThreads;
-}
-
-//=============================================================================
-/*!
- * \brief Set Number of thread for multithread run
- */
-//=============================================================================
-void SMESH_ParallelMesh::SetNbThreads(long nbThreads)
-{
- if(nbThreads < 1)
- throw SALOME_Exception("Number of threads should be higher than 1");
- _NbThreads=nbThreads;
-};
-
bool SMESH_ParallelMesh::ComputeSubMeshes(
SMESH_Gen* gen,
SMESH_Mesh & aMesh,
#include "SMESH_Mesh.hxx"
-#ifndef WIN32
-#include <boost/asio.hpp>
-#endif
-
#include "SMESH_Gen.hxx"
#include "SMESH_subMesh.hxx"
-enum ParallelismMethod {MultiThread, MultiNode};
-
class SMESH_EXPORT SMESH_ParallelMesh: public SMESH_Mesh
{
public:
virtual ~SMESH_ParallelMesh();
- // Locking mechanism
+#ifndef WIN32
void Lock() override {_my_lock.lock();};
void Unlock() override {_my_lock.unlock();};
- // We need to recreate the pool afterthe join
- void wait() override {_pool->join(); DeletePoolThreads(); InitPoolThreads(); };
- // Thread Pool
- void InitPoolThreads() {_pool = new boost::asio::thread_pool(GetPoolNbThreads());};
- void DeletePoolThreads() {delete _pool;};
- boost::asio::thread_pool* GetPool() {return _pool;};
- int GetPoolNbThreads();
+ int GetNbThreads() override{return _NbThreads;};
+ void SetNbThreads(long nbThreads) override{_NbThreads=nbThreads;};
- // Temporary folder
- void CreateTmpFolder();
- void DeleteTmpFolder();
- boost::filesystem::path GetTmpFolder() {return tmp_folder;};
+ void InitPoolThreads() override {_pool = new boost::asio::thread_pool(_NbThreads);};
+ void DeletePoolThreads() override {delete _pool;};
- //
- bool IsParallel() override {return true;};
+ void wait() override {_pool->join(); DeletePoolThreads(); InitPoolThreads(); };
- // Parallelims paramaters
- int GetParallelismMethod() {return _method;};
- void SetParallelismMethod(int aMethod) {_method = aMethod;};
+ bool IsParallel() override {return _NbThreads > 0;};
- // Mutlithreading parameters
- int GetNbThreads() {return _NbThreads;};
- void SetNbThreads(long nbThreads);
+ void CreateTmpFolder();
+ void DeleteTmpFolder();
- // Multinode parameters
- std::string GetResource() {return _resource;};
- void SetResource(std::string aResource) {_resource = aResource;};
+ boost::filesystem::path GetTmpFolder() override {return tmp_folder;};
+ boost::asio::thread_pool* GetPool() override {return _pool;};
+#else
+ void Lock() override {};
+ void Unlock() override {};
- int GetNbProc() {return _nbProc;};
- void SetNbProc(long nbProc) {_nbProc = nbProc;};
+ int GetNbThreads() override {return 0;};
+ void SetNbThreads(long nbThreads) {(void) nbThreads;};
- int GetNbProcPerNode() {return _nbProcPerNode;};
- void SetNbProcPerNode(long nbProcPerNodes) {_nbProcPerNode = nbProcPerNodes;};
+ void InitPoolThreads() override {};
+ void DeletePoolThreads() override {};
+ void wait() override {};
- int GetNbNode() {return _nbNode;};
- void SetNbNode(long nbNodes) {_nbNode = nbNodes;};
+ bool IsParallel() override {return false;};
- std::string GetWcKey() {return _wcKey;};
- void SetWcKey(std::string wcKey) {_wcKey = wcKey;};
+ void CreateTmpFolder();
+ void DeleteTmpFolder();
+#endif
- // Parallel computation
bool ComputeSubMeshes(
SMESH_Gen* gen,
SMESH_Mesh & aMesh,
SMESH_ParallelMesh():SMESH_Mesh() {};
SMESH_ParallelMesh(const SMESH_ParallelMesh& aMesh):SMESH_Mesh(aMesh) {};
private:
- // Mutex for multhitreading write in SMESH_Mesh
#ifndef WIN32
- boost::mutex _my_lock;
-#endif
boost::filesystem::path tmp_folder;
- // thread pool for computation
- boost::asio::thread_pool * _pool = nullptr;
-
- int _method = ParallelismMethod::MultiThread;
-
- int _NbThreads = std::thread::hardware_concurrency();
-
- int _nbProc = 1;
- int _nbProcPerNode = 1;
- int _nbNode = 1;
- std::string _resource = "";
- std::string _wcKey = "P11N0:SALOME";
+ boost::asio::thread_pool * _pool = nullptr; //thread pool for computation
+#endif
};
#endif
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;};
// check submeshes needed
// 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() || shape.ShapeType() != TopAbs_SOLID )) {
+ if (_father->HasShapeToMesh() && !_father->IsParallel()) {
bool subComputed = false, subFailed = false;
if (!algo->OnlyUnaryInput()) {
// --- commented for bos#22320 to compute all sub-shapes at once if possible;
{
SMESH_subMesh* subMesh = smIt->next();
const TopoDS_Shape& S = subMesh->_subShape;
-
- if ( S.ShapeType() != this->_subShape.ShapeType() ){
+ if ( S.ShapeType() != this->_subShape.ShapeType() )
continue;
- }
- if ( _allowedSubShapes && !_allowedSubShapes->IsEmpty() && !_allowedSubShapes->Contains( S )){
+ if ( _allowedSubShapes && !_allowedSubShapes->IsEmpty() && !_allowedSubShapes->Contains( S ))
continue;
- }
if ( subMesh == this )
{
aBuilder.Add( aCompound, S );
else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
{
SMESH_Algo* anAlgo = subMesh->GetAlgo();
-
if (( anAlgo->IsSameName( *theAlgo )) && // same algo
( anAlgo->GetUsedHypothesis( *_father, S, skipAuxHyps ) == usedHyps ) && // same hyps
( anAlgo->GetAssignedShapes() == assiShapes ) && // on same sub-shapes
SMESH_PreMeshInfo.cxx
MG_ADAPT_i.cxx
SMESH_Homard_i.cxx
- SMESH_ParallelMesh_i.cxx
)
# --- rules ---
#include "SMESH_Hypothesis.hxx"
#include "SMESH_Hypothesis_i.hxx"
#include "SMESH_Mesh.hxx"
-#include "SMESH_ParallelMesh.hxx"
#include "SMESH_MeshEditor.hxx"
#include "SMESH_Mesh_i.hxx"
-#include <SMESH_SequentialMesh_i.hxx>
-#include "SMESH_ParallelMesh_i.hxx"
#include "SMESH_PreMeshInfo.hxx"
#include "SMESH_PythonDump.hxx"
#include "SMESH_ControlsDef.hxx"
*/
//=============================================================================
-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" );
SMESH_Mesh_i* meshServant = new SMESH_Mesh_i( GetPOA(), this );
// create a new mesh object
MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
- SMESH_Mesh* myImpl = dynamic_cast<SMESH_Mesh*>(myGen.CreateMesh( myIsEmbeddedMode ));
- if(myImpl == NULL )
- THROW_SALOME_CORBA_EXCEPTION( "Could not cast SequentialMesh as Mesh", SALOME::INTERNAL_ERROR );
- meshServant->SetImpl(myImpl);
+ 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() );
return SMESH::SMESH_Mesh::_nil();
}
-//=============================================================================
-/*!
- * SMESH_Gen_i::createParallelMesh
- *
- * Create empty parallel mesh on shape
- */
-//=============================================================================
-SMESH::SMESH_ParallelMesh_ptr SMESH_Gen_i::createParallelMesh()
-{
- Unexpect aCatch(SALOME_SalomeException);
- MESSAGE( "SMESH_Gen_i::createParallelMesh" );
-
- // Get or create the GEOM_Client instance
- try {
- // create a new mesh object servant, store it in a map in study context
- SMESH_ParallelMesh_i* meshServant = new SMESH_ParallelMesh_i( GetPOA(), this );
- // create a new mesh object
- MESSAGE("myIsEmbeddedMode " << myIsEmbeddedMode);
- SMESH_Mesh* myImpl = dynamic_cast<SMESH_Mesh*>(myGen.CreateParallelMesh( myIsEmbeddedMode ));
- if(myImpl == NULL )
- THROW_SALOME_CORBA_EXCEPTION( "Could not cast ParallelMesh as Mesh", SALOME::INTERNAL_ERROR );
- meshServant->SetImpl(myImpl);
-
- // activate the CORBA servant of Mesh
- SMESH::SMESH_ParallelMesh_var mesh = SMESH::SMESH_ParallelMesh::_narrow( meshServant->_this() );
- int nextId = RegisterObject( mesh );
- MESSAGE( "Add mesh to map with id = "<< nextId);
-
- return mesh._retn();
- }
- catch (SALOME_Exception& S_ex) {
- THROW_SALOME_CORBA_EXCEPTION( S_ex.what(), SALOME::BAD_PARAM );
- }
- return SMESH::SMESH_ParallelMesh::_nil();
-}
-
//=============================================================================
/*!
* SMESH_Gen_i::GetShapeReader
*/
//=============================================================================
-SMESH::SMESH_ParallelMesh_ptr SMESH_Gen_i::CreateParallelMesh( GEOM::GEOM_Object_ptr theShapeObject )
+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_ParallelMesh_var mesh = this->createParallelMesh();
+ SMESH::SMESH_Mesh_var mesh = this->createMesh(true);
// set shape
- SMESH_ParallelMesh_i* meshServant = SMESH::DownCast<SMESH_ParallelMesh_i*>( mesh );
+ SMESH_Mesh_i* meshServant = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
ASSERT( meshServant );
meshServant->SetShape( theShapeObject );
aStudyBuilder->CommitCommand();
if ( !aSO->_is_nil() ) {
// Update Python script
- TPythonDump(this) << aSO << " = " << this << ".CreateParallelMesh(" << theShapeObject << ")";
+ TPythonDump(this) << aSO << " = " << this << ".CreateMesh(" << theShapeObject << ")";
}
}
SMESH::SMESH_Mesh_ptr CreateMesh( GEOM::GEOM_Object_ptr theShapeObject );
// Create empty parallel mesh on a shape
- SMESH::SMESH_ParallelMesh_ptr CreateParallelMesh( GEOM::GEOM_Object_ptr theShapeObject );
+ SMESH::SMESH_Mesh_ptr CreateParallelMesh( GEOM::GEOM_Object_ptr theShapeObject );
// Create empty mesh
SMESH::SMESH_Mesh_ptr CreateEmptyMesh();
SMESH::SMESH_Hypothesis_ptr createHypothesis( const char* theHypName,
const char* theLibName);
// Create empty mesh on shape
- SMESH::SMESH_Mesh_ptr createMesh();
- SMESH::SMESH_ParallelMesh_ptr createParallelMesh();
+ SMESH::SMESH_Mesh_ptr createMesh(bool parallel=false);
// Check mesh icon
bool isGeomModifIcon( SMESH::SMESH_Mesh_ptr mesh );
return res;
}
+//=============================================================================
+/*!
+ * \brief Set the number of threads for a parallel computation
+ */
+//=============================================================================
+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();
+}
+
//=============================================================================
/*!
SMESH::submesh_array_array& theSubMeshOrder,
const bool theIsDump);
+ /*!
+ * Parallelims informations
+ */
+ void SetNbThreads(CORBA::Long nbThreads);
+ CORBA::Long GetNbThreads();
+
/*!
* \brief Finds concurrent sub-meshes
*/
TListOfListOfInt findConcurrentSubMeshes();
- protected:
- ::SMESH_Mesh* _impl; // :: force no namespace here
private:
static int _idGenerator;
+ ::SMESH_Mesh* _impl; // :: force no namespace here
SMESH_Gen_i* _gen_i;
int _id; // id given by creator (unique within the creator instance)
int _nbInvalidHypos;
// Module : SMESH
#include "SMESH_ParallelMesh_i.hxx"
-#include "SMESH_Mesh_i.hxx"
#include "SMESH_Gen_i.hxx"
+#ifdef _DEBUG_
+static int MYDEBUG = 0;
+#else
+static int MYDEBUG = 0;
+#endif
+
+//=============================================================================
+/*!
+ * Constructor
+ */
+//=============================================================================
+
+SMESH_ParallelMesh_i::SMESH_ParallelMesh_i( PortableServer::POA_ptr thePOA,
+ SMESH_Gen_i* gen_i )
+: SMESH_Mesh_i(thePOA, gen_i)
+{
+}
+
//=============================================================================
namespace
{
};
}
-::SMESH_ParallelMesh* SMESH_ParallelMesh_i::DownCast()
-{
- ::SMESH_ParallelMesh* myImpl = dynamic_cast<::SMESH_ParallelMesh*>(_impl);
- if (myImpl == NULL)
- THROW_SALOME_CORBA_EXCEPTION("Could not cast as ParallelMesh", SALOME::INTERNAL_ERROR);
-
- return myImpl;
-}
-
-//=============================================================================
+//================================================================================
/*!
- * \brief Get the parallellism method
+ * \brief Set mesh implementation
*/
-//=============================================================================
-
-CORBA::Long SMESH_ParallelMesh_i::GetParallelismMethod(){
- return DownCast()->GetParallelismMethod();
-}
-
-//=============================================================================
-/*!
- * \brief Set the parallellism method
- */
-//=============================================================================
-void SMESH_ParallelMesh_i::SetParallelismMethod(CORBA::Long aMethod){
- DownCast()->SetParallelismMethod(aMethod);
-}
+//================================================================================
-//=============================================================================
-/*!
- * \brief Get the number of threads for a parallel computation
- */
-//=============================================================================
-CORBA::Long SMESH_ParallelMesh_i::GetNbThreads(){
- return DownCast()->GetNbThreads();
-}
-
-//=============================================================================
-/*!
- * \brief Set the number of threads for a parallel computation
- */
-//=============================================================================
-void SMESH_ParallelMesh_i::SetNbThreads(CORBA::Long nbThreads){
- DownCast()->SetNbThreads(nbThreads);
-}
-
-//=============================================================================
-/*!
- * \brief Get the ressource to connect to
- */
-//=============================================================================
-char* SMESH_ParallelMesh_i::GetResource(){
- return CORBA::string_dup(DownCast()->GetResource().c_str());
-}
-
-//=============================================================================
-/*!
- * \brief Set the ressource to connect to
- */
-//=============================================================================
-void SMESH_ParallelMesh_i::SetResource(const char* aResource){
- DownCast()->SetResource(std::string(aResource));
-}
-
-//=============================================================================
-/*!
- * \brief Get the number of processor to use on ressource
- */
-//=============================================================================
-CORBA::Long SMESH_ParallelMesh_i::GetNbProc(){
- return DownCast()->GetNbProc();
-}
-
-//=============================================================================
-/*!
- * \brief Set the number of processor to use on ressource
- */
-//=============================================================================
-void SMESH_ParallelMesh_i::SetNbProc(CORBA::Long nbProcs){
- DownCast()->SetNbProc(nbProcs);
-}
-
-//=============================================================================
-/*!
- * \brief Get the number of processor per node to use on ressource
- */
-//=============================================================================
-CORBA::Long SMESH_ParallelMesh_i::GetNbProcPerNode(){
- return DownCast()->GetNbProcPerNode();
-}
-
-//=============================================================================
-/*!
- * \brief Set the number of processor per node to use on ressource
- */
-//=============================================================================
-void SMESH_ParallelMesh_i::SetNbProcPerNode(CORBA::Long nbProcPerNodes){
- DownCast()->SetNbProcPerNode(nbProcPerNodes);
-}
-
-//=============================================================================
-/*!
- * \brief Get the number of node to use on ressource
- */
-//=============================================================================
-CORBA::Long SMESH_ParallelMesh_i::GetNbNode(){
- return DownCast()->GetNbNode();
-}
-
-//=============================================================================
-/*!
- * \brief Set the number of node to use on ressource
- */
-//=============================================================================
-void SMESH_ParallelMesh_i::SetNbNode(CORBA::Long nbNodes){
- DownCast()->SetNbNode(nbNodes);
+void SMESH_ParallelMesh_i::SetImpl(::SMESH_ParallelMesh * impl)
+{
+ if(MYDEBUG) MESSAGE("SMESH_ParallelMesh_i::SetImpl");
+ _impl = impl;
+ if ( _impl )
+ _impl->SetCallUp( new TCallUp_i(this));
}
//=============================================================================
/*!
- * \brief Get the wckey to use on ressource
+ * Return a mesh implementation
*/
//=============================================================================
-char* SMESH_ParallelMesh_i::GetWcKey(){
- return CORBA::string_dup(DownCast()->GetWcKey().c_str());
-}
-//=============================================================================
-/*!
- * \brief Set the wckey to use on ressource
- */
-//=============================================================================
-void SMESH_ParallelMesh_i::SetWcKey(const char* wcKey){
- DownCast()->SetWcKey(std::string(wcKey));
-}
+::SMESH_ParallelMesh & SMESH_ParallelMesh_i::GetImpl()
+{
+ if(MYDEBUG) MESSAGE("SMESH_ParallelMesh_i::GetImpl()");
+ return *_impl;
+}
\ No newline at end of file
#include "SMESH_Hypothesis.hxx"
#include "SMESH_Mesh_i.hxx"
-#include "SMESH_ParallelMesh.hxx"
#include <SALOME_GenericObj_i.hh>
#include <SALOMEconfig.h>
public virtual POA_SMESH::SMESH_ParallelMesh,
public virtual SMESH_Mesh_i
{
- SMESH_ParallelMesh_i();
- SMESH_ParallelMesh_i(const SMESH_ParallelMesh_i&);
- public:
SMESH_ParallelMesh_i( PortableServer::POA_ptr thePOA,
SMESH_Gen_i* myGen_i ):SMESH_Mesh_i(thePOA, myGen_i){};
virtual ~SMESH_ParallelMesh_i(){};
- CORBA::Long GetParallelismMethod();
- void SetParallelismMethod(CORBA::Long aMethod);
-
- CORBA::Long GetNbThreads();
- void SetNbThreads(CORBA::Long nbThreads);
-
- char* GetResource();
- void SetResource(const char* aResource);
-
- CORBA::Long GetNbProc();
- void SetNbProc(CORBA::Long nbProcs);
-
- CORBA::Long GetNbProcPerNode();
- void SetNbProcPerNode(CORBA::Long nbProcPerNodes);
-
- CORBA::Long GetNbNode();
- void SetNbNode(CORBA::Long nbNodes);
-
- char* GetWcKey();
- void SetWcKey(const char* wcKey);
-
- private:
- ::SMESH_ParallelMesh* DownCast();
};
#endif
SMESH_SequentialMesh_i( PortableServer::POA_ptr thePOA,
SMESH_Gen_i* myGen_i ):SMESH_Mesh_i(thePOA, myGen_i){};
- virtual ~SMESH_SequentialMesh_i();
+ virtual ~SMESH_SequentialMesh_i(){};
};
smesh_tools.py
)
-SET(smesh_exe_SCRIPTS
- mesher_launcher.py
- send_files.py
-)
-
SET(StdMeshers_SCRIPTS
__init__.py
StdMeshersBuilder.py
install(TARGETS _SMeshHelper DESTINATION ${SALOME_INSTALL_LIBS})
install(FILES ${SMeshHelper_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
SALOME_INSTALL_SCRIPTS("${_swig_SCRIPTS}" ${SALOME_INSTALL_BINS} EXTRA_DPYS "${SWIG_MODULE_SMeshHelper_REAL_NAME}")
-SALOME_INSTALL_SCRIPTS("${smesh_exe_SCRIPTS}" ${SALOME_INSTALL_BINS})
# --- rules ---
SALOME_INSTALL_SCRIPTS("${smesh_SCRIPTS}" ${SALOME_INSTALL_PYTHON}/salome/smesh DEF_PERMS)
+++ /dev/null
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-## Copyright (C) 2021-2023 CEA/DEN, EDF R&D, OPEN CASCADE
-##
-## 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 to run mesher from command line
-"""
-#TODO: Make the execution path independant (output files are written in current directory)
-from os import environ, path
-import sys
-import subprocess as sp
-
-from argparse import ArgumentParser
-import pydefx
-import pylauncher
-
-MESHER_HANDLED = ["NETGEN3D"]
-
-CMD_TEMPLATE = \
-"""{runner} {mesher} {mesh_file} {shape_file} {param_file} {elem_orientation_file} {new_element_file} {output_mesh_file} > {log_file} 2>&1"""
-
-PYTHON_CODE = \
-"""
-import subprocess as sp
-def _exec(cmd):
- error_code = -1
- try:
- output = sp.check_output(cmd, shell=True)
- error_code = 0
- except sp.CalledProcessError as e:
- print('Code crash')
- print(e.output)
- error_code = e.returncode
- raise e
- return error_code
-"""
-
-def create_launcher():
- """ Initialise pylauncher
- """
- launcher = pylauncher.Launcher_cpp()
- launcher.SetResourcesManager(create_resources_manager())
- return launcher
-
-def create_resources_manager():
- """ Look for the catalog file and create a ressource manager with it """
- # localhost is defined anyway, even if the catalog file does not exist.
- catalog_path = environ.get("USER_CATALOG_RESOURCES_FILE", "")
- if not path.isfile(catalog_path):
- salome_path = environ.get("ROOT_SALOME_INSTALL", "")
- catalog_path = path.join(salome_path, "CatalogResources.xml")
- if not path.isfile(catalog_path):
- catalog_path = ""
-
- return pylauncher.ResourcesManager_cpp(catalog_path)
-
-def create_job_parameters():
- """ Initialsie JobParameters """
- jparam = pylauncher.JobParameters_cpp()
- jparam.resource_required = create_resource_parameters()
- return jparam
-
-def create_resource_parameters():
- """ Init resourceParams """
- return pylauncher.resourceParams()
-
-def get_runner(mesher):
- """
- Get path to exe for mesher
-
- Arguments:
- mesher: Name of the mesher (NETGEN2D/NETGEN3D...)
-
- retuns (string) Path to the exe
- """
- if sys.platform.startswith('win'):
- ext = ".exe"
- else:
- ext = ""
-
- if mesher in ['NETGEN3D']:
- exe_path = path.join("${NETGENPLUGIN_ROOT_DIR}",
- "bin",
- "salome",
- "NETGENPlugin_Runner"+ext)
- else:
- raise Exception("Mesher {mesher} is not handled".format(mesher=mesher))
-
- return exe_path
-
-def run_local(args):
- """ Simple Local run """
- print("Local run")
- #TODO: Check on how to handle log for windows (through sp.check_output)
- cmd = CMD_TEMPLATE.format(\
- runner=get_runner(args.mesher),
- mesher=args.mesher,
- mesh_file=args.input_mesh_file,
- shape_file=args.shape_file,
- param_file=args.hypo_file,
- elem_orientation_file=args.elem_orient_file,
- new_element_file=args.new_element_file,
- log_file=path.join(path.dirname(args.shape_file), "run.log"),
- output_mesh_file=args.output_mesh_file)
- print("Executing:")
- print(cmd)
- sp.check_output(cmd, shell=True, cwd=path.dirname(args.shape_file))
-
-def run_pylauncher(args):
- """ Run exe throuhg pylauncher """
- import time
- print("Cluster run")
-
- cmd = CMD_TEMPLATE.format(\
- runner=get_runner(args.mesher),
- mesher=args.mesher,
- mesh_file="../"+path.basename(args.input_mesh_file),
- shape_file=path.basename(args.shape_file),
- param_file=path.basename(args.hypo_file),
- elem_orientation_file=path.basename(args.elem_orient_file),
- new_element_file=path.basename(args.new_element_file),
- log_file="run.log",
- output_mesh_file=path.basename(args.output_mesh_file))
-
- print("Cmd: ", cmd)
-
- # salome launcher
- launcher = create_launcher()
-
- # See SALOME_Launcher documentation for parameters
- job_params = create_job_parameters()
- # different type are:
- # command Shell out of salome session
- # command_salome Shell in salome shell
- # python_salome Python script
- # yacs_file
- job_params.job_type = "command_salome" # creates CatalogResources.xml
-
- job_params.wckey = args.wc_key
- job_params.resource_required.nb_proc = args.nb_proc
- job_params.resource_required.nb_proc_per_node = args.nb_proc_per_node
- job_params.resource_required.nb_node = args.nb_node
-
- # job_params.pre_command = pre_command # command to run on frontal
- # script to run in batch mode
- run_script = path.join(path.dirname(args.shape_file), "run.sh")
- with open(run_script, "w") as f:
- f.write("#!/bin/bash\n")
- f.write(cmd)
- job_params.job_file = run_script
-
- local_dir = path.dirname(args.shape_file)
-
- # files to copy to remote working dir
- # Directories are copied recursively.
- # job_file script is automaticaly copied.
- job_params.in_files = [args.shape_file,
- args.hypo_file,
- args.elem_orient_file]
-
- print("in_files", job_params.in_files)
- # local path for in_files
- job_params.local_directory = local_dir
- # result files you want to bring back with getJobResults
- # TODO: replace run.log by argument ? by path
- out_files = ["run.log"]
- if args.new_element_file != "NONE":
- out_files.append(path.relpath(args.new_element_file, local_dir))
- if args.output_mesh_file != "NONE":
- out_files.append(path.relpath(args.output_mesh_file, local_dir))
- job_params.out_files = out_files
- print("out_files", job_params.out_files)
- # local path where to copy out_files
- job_params.result_directory = local_dir
-
- job_params.job_name = "SMESH_parallel"
- job_params.resource_required.name = args.resource
-
- # Extra parameters
- # String that is directly added to the job submission file
- # job_params.extra_params = "#SBATCH --nodes=2"
-
- # remote job directory
- # Retrieve working dir from catalog
- res_manager = create_resources_manager()
- res_params = res_manager.GetResourceDefinition(args.resource)
- job_params.work_directory = path.join(\
- res_params.working_directory,
- path.basename(path.dirname(path.dirname(args.shape_file))),
- path.basename(path.dirname(args.shape_file)))
- print("work directory", job_params.work_directory)
-
- job_id = launcher.createJob(job_params) #SALOME id of the job
- launcher.launchJob(job_id) # copy files, run pre_command, submit job
-
- # wait for the end of the job
- job_state = launcher.getJobState(job_id)
- print("Job %d state: %s" % (job_id, job_state))
- while job_state not in ["FINISHED", "FAILED"]:
- time.sleep(3)
- job_state = launcher.getJobState(job_id)
-
- if job_state == "FAILED":
- raise Exception("Job failed")
- else:
- # verify the return code of the execution
- if(launcher.getJobWorkFile(job_id,
- "logs/exit_code.log",
- job_params.result_directory)):
- exit_code_file = path.join(job_params.result_directory,
- "exit_code.log")
- exit_code = ""
- if path.isfile(exit_code_file):
- with open(exit_code_file) as myfile:
- exit_code = myfile.read()
- exit_code = exit_code.strip()
- if exit_code != "0":
- raise Exception(\
- "An error occured during the execution of the job.")
- else:
- raise Exception("Failed to get the exit code of the job.")
-
- # Retrieve result files
- launcher.getJobResults(job_id, "")
-
- # Delete remote working dir
- launcher.clearJobWorkingDir(job_id)
-
-def def_arg():
- """ Define and parse arguments for the script """
- parser = ArgumentParser()
- parser.add_argument("mesher",
- choices=MESHER_HANDLED,
- help="mesher to use from ("+",".join(MESHER_HANDLED)+")")
- parser.add_argument("input_mesh_file",\
- help="MED File containing lower-dimension-elements already meshed")
- parser.add_argument("shape_file",
- help="STEP file containing the shape to mesh")
- parser.add_argument("hypo_file",
- help="Ascii file containint the list of parameters")
- parser.add_argument("--elem-orient-file",\
- help="binary file containing the list of elements from "\
- "INPUT_MESH_FILE associated to the shape and their orientation")
- # Output file parameters
- output = parser.add_argument_group("Output files", "Possible output files")
- output.add_argument("--new-element-file",
- default="NONE",
- help="contains elements and nodes added by the meshing")
- output.add_argument(\
- "--output-mesh-file",
- default="NONE",
- help="MED File containing the mesh after the run of the mesher")
-
- # Run parameters
- run_param = parser.add_argument_group(\
- "Run parameters",
- "Parameters for the run of the mesher")
- run_param.add_argument("--method",
- default="local",
- choices=["local", "cluster"],
- help="Running method (default: local)")
-
- run_param.add_argument("--resource",
- help="resource from SALOME Catalog")
- run_param.add_argument("--nb-proc",
- default=1,
- type=int,
- help="Number of processors")
- run_param.add_argument("--nb-proc-per-node",
- default=1,
- type=int,
- help="Number of processeor per node")
- run_param.add_argument("--nb-node",
- default=1,
- type=int,
- help="Number of node")
- run_param.add_argument("--wc-key",
- default="P11N0:SALOME",
- help="wc-key for job submission (default P11N0:SALOME)")
-
- args = parser.parse_args()
-
- return args
-
-def main():
- """ Main function """
- args = def_arg()
- if args.method == "local":
- run_local(args)
- elif args.method == "cluster":
- run_pylauncher(args)
- else:
- raise Exception("Unknown method {}".format(args.method))
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-#!/usr/bin/env python3
-# -*- coding: utf-8 -*-
-## Copyright (C) 2021-2023 CEA/DEN, EDF R&D, OPEN CASCADE
-##
-## 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 to send files on remote ressource
-"""
-from os import environ, path
-
-from argparse import ArgumentParser
-import pydefx
-import pylauncher
-
-def create_launcher():
- """ Initialise pylauncher
- """
- launcher = pylauncher.Launcher_cpp()
- launcher.SetResourcesManager(create_resources_manager())
- return launcher
-
-def create_resources_manager():
- """ Look for the catalog file and create a ressource manager with it """
- # localhost is defined anyway, even if the catalog file does not exist.
- catalog_path = environ.get("USER_CATALOG_RESOURCES_FILE", "")
- if not path.isfile(catalog_path):
- salome_path = environ.get("ROOT_SALOME_INSTALL", "")
- catalog_path = path.join(salome_path, "CatalogResources.xml")
- if not path.isfile(catalog_path):
- catalog_path = ""
-
- return pylauncher.ResourcesManager_cpp(catalog_path)
-
-def create_job_parameters():
- """ Initialsie JobParameters """
- jparam = pylauncher.JobParameters_cpp()
- jparam.resource_required = create_resource_parameters()
- return jparam
-
-def create_resource_parameters():
- """ Init resourceParams """
- return pylauncher.resourceParams()
-
-def send_file(args):
- """ job to send a file to the cluster """
- # salome launcher
- launcher = create_launcher()
-
- # See SALOME_Launcher documentation for parameters
- job_params = create_job_parameters()
- job_params.job_type = "command_salome" # creates CatalogResources.xml
-
- local_dir = path.dirname(args.input_file)
-
- # job_params.pre_command = pre_command # command to run on frontal
- # script to run in batch mode
- run_script = path.join(path.dirname(args.input_file), "run.sh")
- with open(run_script, "w") as f:
- f.write("#!/bin/bash\n")
- job_params.job_file = run_script
- job_params.resource_required.nb_proc = 1
-
- # files to copy to remote working dir
- # Directories are copied recursively.
- # job_file script is automaticaly copied.
- job_params.in_files = [args.input_file]
- print("in_files", job_params.in_files)
- # local path where to copy out_files
- job_params.result_directory = local_dir
-
- job_params.job_name = "SMESH_transfer"
- job_params.resource_required.name = args.resource
-
- # remote job directory
- # Retrieve working dir from catalog
- res_manager = create_resources_manager()
- res_params = res_manager.GetResourceDefinition(args.resource)
- job_params.work_directory = path.join(\
- res_params.working_directory,
- path.basename(path.dirname(args.input_file)))
-
- print("work_directory", job_params.work_directory)
-
- job_id = launcher.createJob(job_params) #SALOME id of the job
- launcher.exportInputFiles(job_id)
-
-
-def def_arg():
- """ Define and parse arguments for the script """
- parser = ArgumentParser()
- parser.add_argument("input_file",\
- help="file to copy")
-
- # Run parameters
-
- parser.add_argument("--resource",
- help="resource from SALOME Catalog")
-
- args = parser.parse_args()
-
- return args
-
-def main():
- """ Main function """
- args = def_arg()
- send_file(args)
-
-if __name__ == "__main__":
- main()
geo_name = "%s_%s to mesh"%(self.geom.GetShapeType(), id(self.geom)%100)
geompyD.addToStudy( self.geom, geo_name )
if parallel and isinstance(self, ParallelMesh):
- mymesh = self.smeshpyD.CreateParallelMesh(self.geom)
- mymesh2 = mymesh._narrow(SMESH._objref_SMESH_Mesh)
- self.SetMesh( mymesh )
+ self.SetMesh( self.smeshpyD.CreateParallelMesh(self.geom) )
else:
self.SetMesh( self.smeshpyD.CreateMesh(self.geom) )
toCopyAll,toCreateAllElements,groups)
if mesh: mesh = self.smeshpyD.Mesh(mesh)
return nb, mesh, group
-
+
def MakeBoundaryElements(self, dimension=SMESH.BND_2DFROM3D, groupName="", meshName="",
toCopyAll=False, groups=[]):
"""
Create 1D/2D/3D netgen parameters from a NETGEN 1D2D3D parameter
"""
if dim==1:
- #TODO: Try to identify why we need to substract 1 to have same results
+ #TODO: Try to identify why we need to substract 1
local_param.NumberOfSegments(int(global_param.GetNbSegPerEdge())-1)
elif dim==2:
local_param.SetMaxSize(global_param.GetMaxSize())
local_param.SetFineness(global_param.GetFineness())
local_param.SetNbSegPerEdge(global_param.GetNbSegPerEdge())
local_param.SetNbSegPerRadius(global_param.GetNbSegPerRadius())
- #TODO: Why the 0.9 to have same results
local_param.SetGrowthRate(global_param.GetGrowthRate()*0.9)
local_param.SetChordalError(global_param.GetChordalError())
local_param.SetChordalErrorEnabled(global_param.GetChordalErrorEnabled())
local_param.SetGrowthRate(global_param.GetGrowthRate())
local_param.SetNbThreads(global_param.GetNbThreads())
-
-def _shaperstudy2geom(geompyD, shaper_obj):
- """
- Convertion of shaper object to geom object
-
- Parameters:
- geompyD: geomBuilder instance
- shaper_obj: Shaper study object
-
- Returns:
- geom object
-
- """
- import tempfile
- #Writing shaperstudy object into a brep file
- fid, tmp_file = tempfile.mkstemp(suffix='.brep')
- with open(fid, 'wb') as f:
- f.write(shaper_obj.GetShapeStream())
- # Reimporting brep file into geom
- real_geom = geompyD.ImportBREP(tmp_file)
- os.remove(tmp_file)
-
- return real_geom
-
-
def _split_geom(geompyD, geom):
"""
Splitting geometry into n solids and a 2D/1D compound
geompyD: geomBuilder instance
geom: geometrical object for meshing
- Returns:
- compound containing all the 1D,2D elements
- list of solids
"""
-
# Splitting geometry into 3D elements and all the 2D/1D into one compound
object_solids = geompyD.ExtractShapes(geom, geompyD.ShapeType["SOLID"],
True)
'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)
return all_faces, solids
-
-MULTITHREAD, MULTINODE = range(2)
class ParallelismSettings:
"""
Defines the parameters for the parallelism of ParallelMesh
self._mesh = mesh
-
-class MTParallelismSettings(ParallelismSettings):
- """
- Defines the parameters for the parallelism of ParallelMesh using MultiThreading
- """
- def __init__(self, mesh):
- ParallelismSettings.__init__(self, mesh)
-
- # Multithreading methods
def SetNbThreads(self, nbThreads):
- """ Set the number of threads for multithread """
+ """
+ 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 """
+ """
+ Get Number of threads
+ """
return self._mesh.mesh.GetNbThreads()
- def __str__(self):
- """ str conversion """
- string = "\nParameter for MultiThreading parallelism:\n"
- string += "NbThreads: {}\n".format(self.GetNbThreads())
-
- return string
-
-
-class MNParallelismSettings(ParallelismSettings):
- """
- Defines the parameters for the parallelism of ParallelMesh using MultiNodal
- """
- def __init__(self, mesh):
- ParallelismSettings.__init__(self, mesh)
-
- def GetResource(self):
- """ Get the resource on which to run """
- return self._mesh.mesh.GetResource()
-
- def SetResource(self, resource):
- """ Set the resource on which to run """
- self._mesh.mesh.SetResource(resource)
-
- def SetNbProc(self, nbProc):
- """ Set the number of Processor for multinode """
- if nbProc < 1:
- raise ValueError("Number of Proc must be stricly greater than 1")
- self._mesh.mesh.SetNbProc(nbProc)
-
- def GetNbProc(self):
- """ Get Number of Processor """
- return self._mesh.mesh.GetNbProc()
-
- def SetNbProcPerNode(self, nbProcPerNode):
- """ Set the number of Processor Per Node for multinode """
- if nbProcPerNode < 1:
- raise ValueError("Number of Processor Per Node must be stricly greater than 1")
-
- self._mesh.mesh.SetNbProcPerNode(nbProcPerNode)
-
- def GetNbProcPerNode(self):
- """ Get Number of Processor Per Node """
- return self._mesh.mesh.GetNbProcPerNode()
-
- def SetNbNode(self, nbNode):
- """ Set the number of Node for multinode """
- if nbNode < 1:
- raise ValueError("Number of Node must be stricly greater than 1")
- self._mesh.mesh.SetNbNode(nbNode)
-
- def GetNbNode(self):
- """ Get Number of Node """
- return self._mesh.mesh.GetNbNode()
-
- def SetWcKey(self, wcKey):
- """ Set the number of Node for multinode """
- self._mesh.mesh.SetWcKey(wcKey)
-
- def GetWcKey(self):
- """ Get Number of Node """
- return self._mesh.mesh.GetWcKey()
-
- def __str__(self):
- """ str conversion """
- string = "\nParameter for MultiNode parallelism:\n"
- string += "Reource: {}\n".format(self.GetResource())
- string += "NbProc: {}\n".format(self.GetNbProc())
- string += "NbProcPerNode: {}\n".format(self.GetNbProcPerNode())
- string += "NbNode: {}\n".format(self.GetNbNode())
- string += "WcKey: {}\n".format(self.GetWcKey())
-
- return string
-
-
class ParallelMesh(Mesh):
"""
Surcharge on Mesh for parallel computation of a mesh
if not isinstance(geom, geomBuilder.GEOM._objref_GEOM_Object):
raise ValueError("geom argument must be a geometry")
- import SHAPERSTUDY
- import shaperBuilder
- # If we have a shaper object converting it into geom (temporary solution)
- if isinstance(geom, SHAPERSTUDY.SHAPERSTUDY_ORB._objref_SHAPER_Object):
- geom_obj = _shaperstudy2geom(geompyD, geom)
- else:
- geom_obj = geom
-
# Splitting geometry into one geom containing 1D and 2D elements and a
# list of 3D elements
- super(ParallelMesh, self).__init__(smeshpyD, geompyD, geom_obj, name, parallel=True)
+ super(ParallelMesh, self).__init__(smeshpyD, geompyD, geom, name, parallel=True)
if split_geom:
- self._all_faces, self._solids = _split_geom(geompyD, geom_obj)
+ self._all_faces, self._solids = _split_geom(geompyD, geom)
- order = []
- self._algo2d = self.Triangle(geom=geom_obj, algo="NETGEN_2D")
+ 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 = None
-
+ self._param = ParallelismSettings(self)
- def GetNbSolids(self):
- """
- Return the number of 3D solids
- """
- return len(self._solids)
-
- def GetParallelismMethod(self):
- """ Get the parallelims method """
- return self.mesh.GetParallelismMethod()
-
- def SetParallelismMethod(self, method):
- """ Set the parallelims method """
- if method not in [MULTITHREAD , MULTINODE]:
- raise ValueError("Parallelism method can only be 0:MultiThread or 1:MultiNode")
-
- self.mesh.SetParallelismMethod(method)
-
- if method == MULTITHREAD:
- self._param = MTParallelismSettings(self)
- else:
- self._param = MNParallelismSettings(self)
def GetParallelismSettings(self):
"""
Return class to set parameters for the parallelism
"""
- if self._param is None:
- raise Exception("You need to set Parallelism method first (SetParallelismMethod)")
return self._param
def AddGlobalHypothesis(self, hyp):
pass # End of ParallelMesh
+
class meshProxy(SMESH._objref_SMESH_Mesh):
"""
Private class used to compensate change of CORBA API of SMESH_Mesh for backward compatibility
if len( args ) == 1:
args += True,
return SMESH._objref_SMESH_Mesh.ExportDAT(self, *args)
-
+ pass
omniORB.registerObjref(SMESH._objref_SMESH_Mesh._NP_RepositoryId, meshProxy)
-class parallelMeshProxy(SMESH._objref_SMESH_ParallelMesh):
- def __init__(self,*args):
- SMESH._objref_SMESH_ParallelMesh.__init__(self,*args)
- def __deepcopy__(self, memo=None):
- new = self.__class__(self)
- return new
-omniORB.registerObjref(SMESH._objref_SMESH_ParallelMesh._NP_RepositoryId, parallelMeshProxy)
-
-
-
class submeshProxy(SMESH._objref_SMESH_subMesh):
"""