1 //=============================================================================
2 // File : NETGENPlugin_NETGEN_3D.cxx
3 // Moved here from SMESH_NETGEN_3D.cxx
4 // Created : lundi 27 Janvier 2003
5 // Author : Nadir BOUHAMOU (CEA)
7 // Copyright : CEA 2003
9 //=============================================================================
12 #include "NETGENPlugin_NETGEN_3D.hxx"
14 #include "SMESH_Gen.hxx"
15 #include "SMESH_Mesh.hxx"
16 #include "SMESH_ControlsDef.hxx"
17 #include "SMESHDS_Mesh.hxx"
18 #include "SMDS_MeshElement.hxx"
19 #include "SMDS_MeshNode.hxx"
23 #include "utilities.h"
35 //=============================================================================
39 //=============================================================================
41 NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, int studyId,
43 : SMESH_3D_Algo(hypId, studyId, gen)
45 MESSAGE("NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D");
47 // _shapeType = TopAbs_SOLID;
48 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
49 // MESSAGE("_shapeType octal " << oct << _shapeType);
50 _compatibleHypothesis.push_back("MaxElementVolume");
52 _maxElementVolume = 0.;
54 _hypMaxElementVolume = NULL;
57 //=============================================================================
61 //=============================================================================
63 NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D()
65 MESSAGE("NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D");
68 //=============================================================================
72 //=============================================================================
74 bool NETGENPlugin_NETGEN_3D::CheckHypothesis
76 const TopoDS_Shape& aShape,
77 SMESH_Hypothesis::Hypothesis_Status& aStatus)
79 MESSAGE("NETGENPlugin_NETGEN_3D::CheckHypothesis");
81 _hypMaxElementVolume = NULL;
82 _maxElementVolume = DBL_MAX;
84 list<const SMESHDS_Hypothesis*>::const_iterator itl;
85 const SMESHDS_Hypothesis* theHyp;
87 const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
88 int nbHyp = hyps.size();
91 aStatus = SMESH_Hypothesis::HYP_OK;
92 //aStatus = SMESH_Hypothesis::HYP_MISSING;
93 return true; // can work with no hypothesis
97 theHyp = (*itl); // use only the first hypothesis
99 string hypName = theHyp->GetName();
103 if (hypName == "MaxElementVolume")
105 _hypMaxElementVolume = static_cast<const StdMeshers_MaxElementVolume*> (theHyp);
106 ASSERT(_hypMaxElementVolume);
107 _maxElementVolume = _hypMaxElementVolume->GetMaxVolume();
109 aStatus = SMESH_Hypothesis::HYP_OK;
112 aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
117 //=============================================================================
119 *Here we are going to use the NETGEN mesher
121 //=============================================================================
123 bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh,
124 const TopoDS_Shape& aShape)
126 MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);
128 SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
130 // -------------------------------------------------------------------
131 // get triangles on aShell and make a map of nodes to Netgen node IDs
132 // -------------------------------------------------------------------
134 typedef map< const SMDS_MeshNode*, int> TNodeToIDMap;
135 TNodeToIDMap nodeToNetgenID;
136 list< const SMDS_MeshElement* > triangles;
137 list< bool > isReversed; // orientation of triangles
139 SMESH::Controls::Area areaControl;
140 SMESH::Controls::TSequenceOfXYZ nodesCoords;
142 for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next())
144 TopoDS_Shape aShapeFace = exp.Current();
145 int faceID = meshDS->ShapeToIndex( aShapeFace );
146 TopoDS_Shape aMeshedFace = meshDS->IndexToShape( faceID );
147 const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( faceID );
148 if ( aSubMeshDSFace )
150 bool isRev = ( aShapeFace.Orientation() != aMeshedFace.Orientation() );
151 SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
152 while ( iteratorElem->more() ) // loop on elements on a face
155 const SMDS_MeshElement* elem = iteratorElem->next();
156 if ( !elem || elem->NbNodes() != 3 ) {
157 INFOS( "NETGENPlugin_NETGEN_3D::Compute(), bad mesh");
161 triangles.push_back( elem );
162 isReversed.push_back( isRev );
163 // put elem nodes to nodeToNetgenID map
164 SMDS_ElemIteratorPtr triangleNodesIt = elem->nodesIterator();
165 while ( triangleNodesIt->more() ) {
166 const SMDS_MeshNode * node =
167 static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
168 nodeToNetgenID.insert( make_pair( node, 0 ));
171 // check if a trainge is degenerated
172 areaControl.GetPoints( elem, nodesCoords );
173 double area = areaControl.GetValue( nodesCoords );
174 if ( area <= DBL_MIN ) {
175 MESSAGE( "Warning: Degenerated " << elem );
181 // ---------------------------------
182 // Feed the Netgen with surface mesh
183 // ---------------------------------
185 int Netgen_NbOfNodes = nodeToNetgenID.size();
186 int Netgen_param2ndOrder = 0;
187 double Netgen_paramFine = 1.;
188 double Netgen_paramSize = _maxElementVolume;
190 double Netgen_point[3];
191 int Netgen_triangle[3];
192 int Netgen_tetrahedron[4];
196 Ng_Mesh * Netgen_mesh = Ng_NewMesh();
198 // set nodes and remember thier netgen IDs
199 TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
200 for ( int id = 0; n_id != nodeToNetgenID.end(); ++n_id )
202 const SMDS_MeshNode* node = n_id->first;
203 Netgen_point [ 0 ] = node->X();
204 Netgen_point [ 1 ] = node->Y();
205 Netgen_point [ 2 ] = node->Z();
207 Ng_AddPoint(Netgen_mesh, Netgen_point);
210 list< const SMDS_MeshElement* >::iterator tria = triangles.begin();
211 list< bool >::iterator reverse = isReversed.begin();
212 for ( ; tria != triangles.end(); ++tria, ++reverse )
215 SMDS_ElemIteratorPtr triangleNodesIt = (*tria)->nodesIterator();
216 while ( triangleNodesIt->more() ) {
217 const SMDS_MeshNode * node =
218 static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
219 Netgen_triangle[ *reverse ? 2 - i : i ] = nodeToNetgenID[ node ];
222 Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
225 // -------------------------
226 // Generate the volume mesh
227 // -------------------------
229 Ng_Meshing_Parameters Netgen_param;
231 Netgen_param.secondorder = Netgen_param2ndOrder;
232 Netgen_param.fineness = Netgen_paramFine;
233 Netgen_param.maxh = Netgen_paramSize;
238 status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
240 MESSAGE("An exception has been caught during the Volume Mesh Generation ...");
241 status = NG_VOLUME_FAILURE;
244 int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
246 int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh);
248 MESSAGE("End of Volume Mesh Generation. status=" << status <<
249 ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes <<
250 ", nb tetra: " << Netgen_NbOfTetra);
252 // -------------------------------------------------------------------
253 // Feed back the SMESHDS with the generated Nodes and Volume Elements
254 // -------------------------------------------------------------------
256 bool isOK = ( status == NG_OK && Netgen_NbOfTetra > 0 );
259 // vector of nodes in which node index == netgen ID
260 vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 );
261 // insert old nodes into nodeVec
262 for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id )
263 nodeVec[ n_id->second ] = n_id->first;
264 // create and insert new nodes into nodeVec
265 int nodeIndex = Netgen_NbOfNodes + 1;
266 int shapeID = meshDS->ShapeToIndex( aShape );
267 for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex )
269 Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point );
270 SMDS_MeshNode * node = meshDS->AddNode(Netgen_point[0],
273 meshDS->SetNodeInVolume(node, shapeID);
274 nodeVec[nodeIndex] = node;
277 // create tetrahedrons
278 for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
280 Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron);
281 SMDS_MeshVolume * elt = meshDS->AddVolume (nodeVec[ Netgen_tetrahedron[0] ],
282 nodeVec[ Netgen_tetrahedron[1] ],
283 nodeVec[ Netgen_tetrahedron[2] ],
284 nodeVec[ Netgen_tetrahedron[3] ]);
285 meshDS->SetMeshElementOnShape(elt, shapeID );
289 Ng_DeleteMesh(Netgen_mesh);
295 //=============================================================================
299 //=============================================================================
301 ostream & NETGENPlugin_NETGEN_3D::SaveTo(ostream & save)
306 //=============================================================================
310 //=============================================================================
312 istream & NETGENPlugin_NETGEN_3D::LoadFrom(istream & load)
317 //=============================================================================
321 //=============================================================================
323 ostream & operator << (ostream & save, NETGENPlugin_NETGEN_3D & hyp)
325 return hyp.SaveTo( save );
328 //=============================================================================
332 //=============================================================================
334 istream & operator >> (istream & load, NETGENPlugin_NETGEN_3D & hyp)
336 return hyp.LoadFrom( load );