1 // Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // NETGENPlugin : C++ implementation
21 // File : NETGENPlugin_NETGEN_2D3D_SA.cxx
22 // Author : Cesar Conopoima (OCC)
25 //=============================================================================
28 #include "NETGENPlugin_DriverParam.hxx"
29 #include "NETGENPlugin_Hypothesis.hxx"
30 #include "NETGENPlugin_SimpleHypothesis_3D.hxx"
32 #include "NETGENPlugin_NETGEN_2D.hxx"
33 #include "NETGENPlugin_NETGEN_1D2D3D_SA.hxx"
35 #include <SMESHDS_Mesh.hxx>
36 #include <SMESH_ControlsDef.hxx>
37 #include <SMESH_Gen.hxx>
38 #include <SMESH_Mesh.hxx>
39 #include <SMESH_MesherHelper.hxx>
40 #include <SMESH_DriverShape.hxx>
41 #include <SMESH_DriverMesh.hxx>
42 #include <utilities.h>
49 #include <meshing.hpp>
51 using namespace nglib;
53 //=============================================================================
57 //=============================================================================
59 NETGENPlugin_NETGEN_1D2D3D_SA::NETGENPlugin_NETGEN_1D2D3D_SA()
60 : NETGENPlugin_NETGEN_2D3D(0, new SMESH_Gen())
62 _name = "NETGEN_1D2D3D_SA";
65 //=============================================================================
69 //=============================================================================
71 NETGENPlugin_NETGEN_1D2D3D_SA::~NETGENPlugin_NETGEN_1D2D3D_SA()
76 * @brief Check presence and content of orientation file. Implemented for completness and future reference.
78 * @param element_orientation_file Binary file containing the orientation of surface elemnts
81 bool NETGENPlugin_NETGEN_1D2D3D_SA::checkOrientationFile( const std::string element_orientation_file )
83 if(element_orientation_file.empty()){
84 MESSAGE("No element orientation file");
87 MESSAGE("Reading from elements from file: " << element_orientation_file);
88 // By construction the orientation file written by Remote version has a zero written to mark no need of orientation in 2D meshing
90 std::ifstream df(element_orientation_file, ios::binary|ios::in);
91 df.read((char*)&nbElement, sizeof(int));
93 return (nbElement == 0);
98 * @brief fill plugin hypothesis from the netgen_params structure
100 * @param aParams the structure
102 void NETGENPlugin_NETGEN_1D2D3D_SA::fillHyp(netgen_params aParams)
104 if( aParams.myType == hypoType::Hypo )
106 NETGENPlugin_Hypothesis * hypParameters = new NETGENPlugin_Hypothesis(0, GetGen());
108 hypParameters->SetMaxSize(aParams.maxh);
109 hypParameters->SetMinSize(aParams.minh);
110 hypParameters->SetNbSegPerEdge(aParams.segmentsperedge);
111 hypParameters->SetGrowthRate(aParams.grading);
112 hypParameters->SetNbSegPerRadius(aParams.curvaturesafety);
113 hypParameters->SetSecondOrder(aParams.secondorder);
114 hypParameters->SetQuadAllowed(aParams.quad);
115 hypParameters->SetOptimize(aParams.optimize);
116 hypParameters->SetFineness((NETGENPlugin_Hypothesis::Fineness)aParams.fineness);
117 hypParameters->SetSurfaceCurvature(aParams.uselocalh);
118 hypParameters->SetFuseEdges(aParams.merge_solids);
119 hypParameters->SetChordalErrorEnabled(aParams.chordalError);
120 if(aParams.optimize){
121 hypParameters->SetNbSurfOptSteps(aParams.optsteps2d);
122 hypParameters->SetNbVolOptSteps(aParams.optsteps3d);
124 hypParameters->SetElemSizeWeight(aParams.elsizeweight);
125 hypParameters->SetWorstElemMeasure(aParams.opterrpow);
126 hypParameters->SetUseDelauney(aParams.delaunay);
127 hypParameters->SetCheckOverlapping(aParams.checkoverlap);
128 hypParameters->SetCheckChartBoundary(aParams.checkchartboundary);
129 hypParameters->SetMeshSizeFile(aParams.meshsizefilename);
131 _hypothesis = dynamic_cast< const NETGENPlugin_Hypothesis *> (hypParameters);
133 else if ( aParams.myType == hypoType::Simple2D )
135 NETGENPlugin_SimpleHypothesis_2D * hypParameters = new NETGENPlugin_SimpleHypothesis_2D(0, GetGen());
137 // mandatory to fill in this branch case!
138 // Number of segments (int)
139 // localLenght (double)
140 // maxElement area (double)
141 // GetAllowQuadrangles (bool)
142 hypParameters->SetNumberOfSegments( aParams.numberOfSegments );
143 if ( !aParams.numberOfSegments )
144 hypParameters->SetLocalLength( aParams.localLength );
145 hypParameters->SetMaxElementArea( aParams.maxElementArea );
146 hypParameters->SetAllowQuadrangles( aParams.allowQuadrangles );
147 _hypothesis = dynamic_cast< const NETGENPlugin_SimpleHypothesis_2D *> (hypParameters);
149 else if ( aParams.myType == hypoType::Simple3D )
151 NETGENPlugin_SimpleHypothesis_3D * hypParameters = new NETGENPlugin_SimpleHypothesis_3D(0, GetGen());
153 // mandatory to fill in this branch case!
154 // Number of segments (int)
155 // localLenght (double)
156 // maxElement area (double)
157 // maxElement volume (double)
158 // GetAllowQuadrangles (bool)
159 hypParameters->SetNumberOfSegments( aParams.numberOfSegments );
160 if ( !aParams.numberOfSegments )
161 hypParameters->SetLocalLength( aParams.localLength );
162 hypParameters->SetMaxElementArea( aParams.maxElementArea );
163 hypParameters->SetMaxElementVolume( aParams.maxElementVol );
164 hypParameters->SetAllowQuadrangles( aParams.allowQuadrangles );
166 _hypothesis = dynamic_cast< const NETGENPlugin_SimpleHypothesis_3D *> (hypParameters);
171 * @brief Write a binary file containing information on the elements/nodes
172 * created by the netgen mesher
174 * @param nodeVec mapping between the mesh id and the netgen structure id
175 * @param ngLib Wrapper on netgen library
176 * @param new_element_file Name of the output file
177 * @param NumOfPremeshedNodes Number of nodes in the netgen structure
178 * @return true if there are some error
180 bool NETGENPlugin_NETGEN_1D2D3D_SA::FillNewElementFile( std::vector< const SMDS_MeshNode* > &nodeVec, NETGENPlugin_NetgenLibWrapper &ngLib,
181 std::string new_element_file, const NETGENPlugin_Mesher::DIM dim )
184 // Particularities: As submeshing is not supported nodeVect is empty and NumberOfPremeshedNodes is also zero
185 Ng_Mesh* NetgenMesh = ngLib.ngMesh();
186 int NetgenNodes = Ng_GetNP(NetgenMesh);
187 int NetgenSeg2D = Ng_GetNSeg_2D( NetgenMesh );
188 int NetgenFaces = Ng_GetNSE(NetgenMesh);
189 int NetgenVols = Ng_GetNE(NetgenMesh);
191 bool isOK = ( NetgenNodes > 0 && NetgenSeg2D > 0 );
192 if ( isOK && !new_element_file.empty() )
194 MESSAGE("Writting new elements")
195 std::ofstream df(new_element_file, ios::out|ios::binary);
197 double NetgenPoint[3];
198 int NetgenSegment[2];
199 int NetgenSurface[8];
200 int NetgenVolumens[10];
202 // Writing nodevec (correspondence netgen numbering mesh numbering)
204 const int NumOfPremeshedNodes = nodeVec.size();
205 df.write((char*) &NumOfPremeshedNodes, sizeof(int));
206 df.write((char*) &NetgenNodes, sizeof(int));
208 for (int nodeIndex = 1 ; nodeIndex <= NumOfPremeshedNodes; ++nodeIndex )
211 int id = nodeVec.at(nodeIndex)->GetID();
212 df.write((char*) &id, sizeof(int));
215 // Writing all new points
216 for (int nodeIndex = NumOfPremeshedNodes + 1; nodeIndex <= NetgenNodes; ++nodeIndex )
218 Ng_GetPoint( NetgenMesh, nodeIndex, NetgenPoint );
219 // Coordinates of the point
220 df.write((char *) &NetgenPoint, sizeof(double)*3);
223 if ( dim >= NETGENPlugin_Mesher::D1 )
225 // create segments at boundaries.
226 df.write((char*) &NetgenSeg2D, sizeof(int));
227 for ( int elemIndex = 1; elemIndex <= NetgenSeg2D; ++elemIndex )
229 Ng_GetSegment_2D( NetgenMesh, elemIndex, NetgenSegment, &segmentId );
230 df.write((char*) &NetgenSegment, sizeof(int) * 2 );
233 if ( dim >= NETGENPlugin_Mesher::D2 )
235 // create surface elements.
236 df.write((char*) &NetgenFaces, sizeof(int));
237 for ( int elemIndex = 1; elemIndex <= NetgenFaces; ++elemIndex )
239 nglib::Ng_Surface_Element_Type elemType = Ng_GetSurfaceElement( NetgenMesh, elemIndex, NetgenSurface );
244 df.write((char*) &NetgenSurface, sizeof(int) * 3 );
249 df.write((char*) &NetgenSurface, sizeof(int) * 4 );
252 case nglib::NG_TRIG6:
254 df.write((char*) &NetgenSurface, sizeof(int) * 6 );
257 case nglib::NG_QUAD8:
259 df.write((char*) &NetgenSurface, sizeof(int) * 8 );
267 if ( dim >= NETGENPlugin_Mesher::D3 )
269 // create volume elements.
270 df.write((char*) &NetgenVols, sizeof(int));
271 for ( int elemIndex = 1; elemIndex <= NetgenVols; ++elemIndex )
273 nglib::Ng_Volume_Element_Type elemType = Ng_GetVolumeElement( NetgenMesh, elemIndex, NetgenVolumens );
278 df.write((char*) &NetgenVolumens, sizeof(int) * 4 );
281 case nglib::NG_PYRAMID:
283 df.write((char*) &NetgenVolumens, sizeof(int) * 5 );
286 case nglib::NG_PRISM:
288 df.write((char*) &NetgenVolumens, sizeof(int) * 6 );
291 case nglib::NG_TET10:
293 df.write((char*) &NetgenVolumens, sizeof(int) * 10 );
307 * @brief Compute the mesh based on the
309 * @param aMesh the read Mesh
310 * @param aShape the loaded shape
311 * @param new_element_file output file containing info the elements created by the mesher
312 * @param output_mesh whether or not write the created elements into the mesh
313 * @param dim the dimension to be meshed.
314 * @return negation of mesh fail: true, false
316 bool NETGENPlugin_NETGEN_1D2D3D_SA::Compute(SMESH_Mesh& aMesh, TopoDS_Shape &aShape, std::string new_element_file, bool output_mesh, NETGENPlugin_Mesher::DIM dim )
319 netgen::multithread.terminate = 0;
320 NETGENPlugin_Mesher mesher(&aMesh, aShape, /*is3D = */ false );
321 mesher.SetParameters(dynamic_cast<const NETGENPlugin_Hypothesis*>(_hypothesis));
322 if ( dim == NETGENPlugin_Mesher::D3 )
323 mesher.SetParameters(dynamic_cast<const NETGENPlugin_SimpleHypothesis_3D*>(_hypothesis));
325 mesher.SetParameters(dynamic_cast<const NETGENPlugin_SimpleHypothesis_2D*>(_hypothesis));
326 NETGENPlugin_NetgenLibWrapper ngLib;
327 vector< const SMDS_MeshNode* > nodeVec;
328 bool err = mesher.Compute( ngLib, nodeVec, output_mesh, dim );
329 FillNewElementFile( nodeVec, ngLib, new_element_file, dim );
334 * @brief Running the mesher on the given files
336 * @param input_mesh_file Mesh file (containing 2D elements)
337 * @param shape_file Shape file (BREP or STEP format)
338 * @param hypo_file Ascii file containing the netgen parameters
339 * @param element_orientation_file Binary file containing the orientation of surface elemnts
340 * @param new_element_file output file containing info the elements created by the mesher
341 * @param output_mesh_file output mesh file (if empty it will not be created)
342 * @return negation of mesh fail: true, false
344 int NETGENPlugin_NETGEN_1D2D3D_SA::run(const std::string input_mesh_file,
345 const std::string shape_file,
346 const std::string hypo_file,
347 const std::string element_orientation_file,
348 const std::string new_element_file,
349 const std::string output_mesh_file,
350 const NETGENPlugin_Mesher::DIM dim )
353 // _element_orientation_file = element_orientation_file;
355 std::unique_ptr<SMESH_Mesh> myMesh(_gen->CreateMesh(false));
358 SMESH_DriverMesh::importMesh(input_mesh_file, *myMesh);
360 TopoDS_Shape myShape;
361 SMESH_DriverShape::importShape(shape_file, myShape);
362 // Importing hypothesis
363 netgen_params myParams;
364 importNetgenParams(hypo_file, myParams);
368 if ( checkOrientationFile(element_orientation_file) )
370 ret = Compute( *myMesh, myShape, new_element_file, !output_mesh_file.empty(), dim );
372 std::cerr << "Meshing failed" << std::endl;
376 if(!output_mesh_file.empty()){
377 std::string meshName = "MESH";
378 SMESH_DriverMesh::exportMesh(output_mesh_file, *myMesh, meshName);
382 std::cerr << "For NETGENPlugin_NETGEN_1D2D3D_SA, orientation file should be market with 0 or be empty!" << std::endl;