-// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2023 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
#include "NETGENPlugin_DriverParam.hxx"
#include "NETGENPlugin_Hypothesis.hxx"
+#include "StdMeshers_MaxElementVolume.hxx"
#include <SMESH_Gen.hxx>
#include <SMESH_Mesh.hxx>
#include <SMESHDS_Mesh.hxx>
+#ifdef WIN32
+#include <filesystem>
+namespace fs = std::filesystem;
+#else
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
+#endif
/*
Netgen include files
//=============================================================================
/*!
- *
+ * Constructor
*/
//=============================================================================
NETGENPlugin_NETGEN_3D_SA::NETGENPlugin_NETGEN_3D_SA()
- : NETGENPlugin_NETGEN_3D(0, _gen=new SMESH_Gen())
+ : NETGENPlugin_NETGEN_3D(0, new SMESH_Gen())
{
_name = "NETGEN_3D_SA";
}
//=============================================================================
/*!
- *
+ * Destructor
*/
//=============================================================================
delete _gen;
}
+/**
+ * @brief fill plugin hypothesis from the netgen_params structure
+ *
+ * @param aParams the structure
+ * @param gen SMESH_Gen associate with the SA
+ */
+void NETGENPlugin_NETGEN_3D_SA::fillHyp(netgen_params aParams)
+{
+ if(aParams.has_netgen_param){
+ NETGENPlugin_Hypothesis * hypParameters = new NETGENPlugin_Hypothesis(0, GetGen());
+
+ hypParameters->SetMaxSize(aParams.maxh);
+ hypParameters->SetMinSize(aParams.minh);
+ hypParameters->SetNbSegPerEdge(aParams.segmentsperedge);
+ hypParameters->SetGrowthRate(aParams.grading);
+ hypParameters->SetNbSegPerRadius(aParams.curvaturesafety);
+ hypParameters->SetSecondOrder(aParams.secondorder);
+ hypParameters->SetQuadAllowed(aParams.quad);
+ hypParameters->SetOptimize(aParams.optimize);
+ hypParameters->SetFineness((NETGENPlugin_Hypothesis::Fineness)aParams.fineness);
+ hypParameters->SetSurfaceCurvature(aParams.uselocalh);
+ hypParameters->SetFuseEdges(aParams.merge_solids);
+ hypParameters->SetChordalErrorEnabled(aParams.chordalError);
+ if(aParams.optimize){
+ hypParameters->SetNbSurfOptSteps(aParams.optsteps2d);
+ hypParameters->SetNbVolOptSteps(aParams.optsteps3d);
+ }
+ hypParameters->SetElemSizeWeight(aParams.elsizeweight);
+ hypParameters->SetWorstElemMeasure(aParams.opterrpow);
+ hypParameters->SetUseDelauney(aParams.delaunay);
+ hypParameters->SetCheckOverlapping(aParams.checkoverlap);
+ hypParameters->SetCheckChartBoundary(aParams.checkchartboundary);
+ hypParameters->SetMeshSizeFile(aParams.meshsizefilename);
+
+ _hypParameters = dynamic_cast< const NETGENPlugin_Hypothesis *> (hypParameters);
+ }
+ if(aParams.has_maxelementvolume_hyp){
+ _hypMaxElementVolume = new StdMeshers_MaxElementVolume(1, GetGen());
+ _maxElementVolume = aParams.maxElementVolume;
+ }
+ // TODO: Handle viscous layer
+}
+/**
+ * @brief Write a binary file containing information on the elements/nodes
+ * created by the mesher
+ *
+ * @param nodeVec mapping between the mesh id and the netgen structure id
+ * @param ngLib Wrapper on netgen library
+ * @param new_element_file Name of the output file
+ * @param Netgen_NbOfNodes Number of nodes in the netgen structure
+ * @return true if there are some error
+ */
bool NETGENPlugin_NETGEN_3D_SA::computeFillNewElementFile(
std::vector< const SMDS_MeshNode* > &nodeVec,
NETGENPlugin_NetgenLibWrapper &ngLib,
return false;
}
-
-bool NETGENPlugin_NETGEN_3D_SA::Compute(TopoDS_Shape &aShape, SMESH_Mesh& aMesh, netgen_params& aParams,
- std::string new_element_file, std::string element_orientation_file,
- bool output_mesh)
+/**
+ * @brief Compute mesh associated to shape
+ *
+ * @param aShape the shape
+ * @param aMesh the mesh
+ * @param aParams netgen_params structure
+ * @param new_element_file Name of the file containing new element
+ * @param output_mesh Name of the output mesh (if empty it will not be written)
+ * @return true if there are some error
+ */
+bool NETGENPlugin_NETGEN_3D_SA::Compute(
+ TopoDS_Shape &aShape,
+ SMESH_Mesh& aMesh,
+ netgen_params& aParams,
+ std::string new_element_file,
+ bool output_mesh)
{
// vector of nodes in which node index == netgen ID
vector< const SMDS_MeshNode* > nodeVec;
int endWith = netgen::MESHCONST_OPTVOLUME;
int Netgen_NbOfNodes=0;
- bool ret;
- ret = NETGENPlugin_NETGEN_3D::computeFillNgMesh(aMesh, aShape, nodeVec, ngLib, helper, aParams, Netgen_NbOfNodes);
- if(ret)
- return error( aParams._error, aParams._comment);
+ // Changing netgen log_file putting it next to new_element_file
+ fs::path netgen_log_file = fs::path(new_element_file).remove_filename() / fs::path("NETGEN.out");
- netgen::OCCGeometry occgeo;
- NETGENPlugin_NETGEN_3D::computePrepareParam(aMesh, ngLib, occgeo, helper, aParams, endWith);
+ ngLib.setOutputFile(netgen_log_file.string());
- ret = NETGENPlugin_NETGEN_3D::computeRunMesher(occgeo, nodeVec, ngLib._ngMesh, ngLib, aParams, startWith, endWith);
- if(ret){
- if(aParams._error)
- return error(aParams._error, aParams._comment);
+ NETGENPlugin_NETGEN_3D::computeFillNgMesh(aMesh, aShape, nodeVec, ngLib, helper, Netgen_NbOfNodes);
- error(aParams._comment);
- return true;
- }
+ netgen::OCCGeometry occgeo;
+ NETGENPlugin_NETGEN_3D::computePrepareParam(aMesh, ngLib, occgeo, helper, endWith);
+
+ NETGENPlugin_NETGEN_3D::computeRunMesher(occgeo, nodeVec, ngLib._ngMesh, ngLib, startWith, endWith);
computeFillNewElementFile(nodeVec, ngLib, new_element_file, Netgen_NbOfNodes);
return false;
}
+
+/**
+ * @brief Running the mesher on the given files
+ *
+ * @param input_mesh_file Mesh file (containing 2D elements)
+ * @param shape_file Shape file (BREP or STEP format)
+ * @param hypo_file Ascii file containing the netgen parameters
+ * @param element_orientation_file Binary file containing the orientation of surface elemnts
+ * @param new_element_file output file containing info the elements created by the mesher
+ * @param output_mesh_file output mesh file (if empty it will not be created)
+ * @return int
+ */
int NETGENPlugin_NETGEN_3D_SA::run(const std::string input_mesh_file,
const std::string shape_file,
const std::string hypo_file,
const std::string element_orientation_file,
const std::string new_element_file,
- const std::string output_mesh_file,
- int nbThreads)
+ const std::string output_mesh_file)
{
_element_orientation_file = element_orientation_file;
- // Importing mesh
- SMESH_Gen gen;
- std::unique_ptr<SMESH_Mesh> myMesh(gen.CreateMesh(false));
+ std::unique_ptr<SMESH_Mesh> myMesh(_gen->CreateMesh(false));
- importMesh(input_mesh_file, *myMesh);
+ SMESH_DriverMesh::importMesh(input_mesh_file, *myMesh);
// Importing shape
TopoDS_Shape myShape;
- importShape(shape_file, myShape);
+ SMESH_DriverShape::importShape(shape_file, myShape);
// Importing hypothesis
netgen_params myParams;
- importNetgenParams(hypo_file, myParams, &gen);
- // Setting number of threads for netgen
- myParams.nbThreads = nbThreads;
+ importNetgenParams(hypo_file, myParams);
+ fillHyp(myParams);
- std::cout << "Meshing with netgen3d" << std::endl;
+ MESSAGE("Meshing with netgen3d");
int ret = Compute(myShape, *myMesh, myParams,
- new_element_file, element_orientation_file,
+ new_element_file,
!output_mesh_file.empty());
if(ret){
- std::cout << "Meshing failed" << std::endl;
+ std::cerr << "Meshing failed" << std::endl;
return ret;
}
if(!output_mesh_file.empty()){
- exportMesh(output_mesh_file, *myMesh, mesh_name);
+ std::string meshName = "MESH";
+ SMESH_DriverMesh::exportMesh(output_mesh_file, *myMesh, meshName);
}
return ret;
}
-
+/**
+ * @brief Compute the list of already meshed Surface elements and info
+ * on their orientation and if they are internal
+ *
+ * @param aMesh Global Mesh
+ * @param aShape Shape associated to the mesh
+ * @param proxyMesh pointer to mesh used fo find the elements
+ * @param internals information on internal sub shapes
+ * @param helper helper associated to the mesh
+ * @param listElements map of surface element associated with
+ * their orientation and internal status
+ * @return true if their was some error
+ */
bool NETGENPlugin_NETGEN_3D_SA::getSurfaceElements(
SMESH_Mesh& aMesh,
const TopoDS_Shape& aShape,
SMESH_ProxyMesh::Ptr proxyMesh,
NETGENPlugin_Internals &internals,
SMESH_MesherHelper &helper,
- netgen_params &aParams,
- std::map<const SMDS_MeshElement*, tuple<bool, bool>>& listElements
+ std::map<const SMDS_MeshElement*, tuple<bool, bool>, TIDCompare>& listElements
)
{
+ // To remove compilation warnings
+ (void) aShape;
+ (void) proxyMesh;
+ (void) internals;
+ (void) helper;
SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
// Get list of elements + their orientation from element_orientation file
{
// Setting all element orientation to false if there no element orientation file
if(_element_orientation_file.empty()){
- std::cout << "No element orientation file" << std::endl;
+ MESSAGE("No element orientation file");
SMDS_ElemIteratorPtr iteratorElem = meshDS->elementsIterator(SMDSAbs_Face);
while ( iteratorElem->more() ) // loop on elements on a geom face
elemOrientation[elem->GetID()] = false;
}
} else {
- std::cout << "Reading from elements from file: " << _element_orientation_file << std::endl;
+ MESSAGE("Reading from elements from file: " << _element_orientation_file);
std::ifstream df(_element_orientation_file, ios::binary|ios::in);
int nbElement;
bool orient;
// Adding elements from Mesh
SMDS_ElemIteratorPtr iteratorElem = meshDS->elementsIterator(SMDSAbs_Face);
bool isRev;
- bool isInternalFace = false;
bool isIn;
// check mesh face
const SMDS_MeshElement* elem = iteratorElem->next();
if ( !elem ){
- aParams._error = COMPERR_BAD_INPUT_MESH;
- aParams._comment = "Null element encounters";
- return true;
+ return error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
}
if ( elem->NbCornerNodes() != 3 ){
- aParams._error = COMPERR_BAD_INPUT_MESH;
- aParams._comment = "Not triangle element encounters";
- return true;
+ return error( COMPERR_BAD_INPUT_MESH, "Not triangle element encounters");
}
// Keeping only element that are in the element orientation file
isIn = elemOrientation.count(elem->GetID())==1;