]> SALOME platform Git repositories - plugins/netgenplugin.git/blob - src/NETGENPlugin/NETGENPlugin_NETGEN_3D.cxx
Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[plugins/netgenplugin.git] / src / NETGENPlugin / NETGENPlugin_NETGEN_3D.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS, L3S, LJLL, MENSI
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
8 //
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 //=============================================================================
21 // File      : NETGENPlugin_NETGEN_3D.cxx
22 //             Moved here from SMESH_NETGEN_3D.cxx
23 // Created   : lundi 27 Janvier 2003
24 // Author    : Nadir BOUHAMOU (CEA)
25 // Project   : SALOME
26 // Copyright : CEA 2003
27 // $Header$
28 //=============================================================================
29 #include "NETGENPlugin_NETGEN_3D.hxx"
30
31 #include "NETGENPlugin_Mesher.hxx"
32
33 #include "SMDS_MeshElement.hxx"
34 #include "SMDS_MeshNode.hxx"
35 #include "SMESHDS_Mesh.hxx"
36 #include "SMESH_Comment.hxx"
37 #include "SMESH_ControlsDef.hxx"
38 #include "SMESH_Gen.hxx"
39 #include "SMESH_Mesh.hxx"
40 #include "SMESH_MesherHelper.hxx"
41
42 #include <BRep_Tool.hxx>
43 #include <TopExp.hxx>
44 #include <TopExp_Explorer.hxx>
45 #include <TopoDS.hxx>
46
47 #include <Standard_Failure.hxx>
48 #include <Standard_ErrorHandler.hxx>
49
50 #include "utilities.h"
51
52 #include <list>
53 #include <vector>
54 #include <map>
55
56 /*
57   Netgen include files
58 */
59
60 namespace nglib {
61 #include <nglib.h>
62 }
63 using namespace nglib;
64
65 //=============================================================================
66 /*!
67  *  
68  */
69 //=============================================================================
70
71 NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D(int hypId, int studyId,
72                              SMESH_Gen* gen)
73   : SMESH_3D_Algo(hypId, studyId, gen)
74 {
75   MESSAGE("NETGENPlugin_NETGEN_3D::NETGENPlugin_NETGEN_3D");
76   _name = "NETGEN_3D";
77   _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
78   _compatibleHypothesis.push_back("MaxElementVolume");
79
80   _maxElementVolume = 0.;
81
82   _hypMaxElementVolume = NULL;
83 }
84
85 //=============================================================================
86 /*!
87  *  
88  */
89 //=============================================================================
90
91 NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D()
92 {
93   MESSAGE("NETGENPlugin_NETGEN_3D::~NETGENPlugin_NETGEN_3D");
94 }
95
96 //=============================================================================
97 /*!
98  *  
99  */
100 //=============================================================================
101
102 bool NETGENPlugin_NETGEN_3D::CheckHypothesis
103                          (SMESH_Mesh& aMesh,
104                           const TopoDS_Shape& aShape,
105                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
106 {
107   MESSAGE("NETGENPlugin_NETGEN_3D::CheckHypothesis");
108
109   _hypMaxElementVolume = NULL;
110   _maxElementVolume = DBL_MAX;
111
112   list<const SMESHDS_Hypothesis*>::const_iterator itl;
113   const SMESHDS_Hypothesis* theHyp;
114
115   const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
116   int nbHyp = hyps.size();
117   if (!nbHyp)
118   {
119     aStatus = SMESH_Hypothesis::HYP_OK;
120     //aStatus = SMESH_Hypothesis::HYP_MISSING;
121     return true;  // can work with no hypothesis
122   }
123
124   itl = hyps.begin();
125   theHyp = (*itl); // use only the first hypothesis
126
127   string hypName = theHyp->GetName();
128
129   bool isOk = false;
130
131   if (hypName == "MaxElementVolume")
132   {
133     _hypMaxElementVolume = static_cast<const StdMeshers_MaxElementVolume*> (theHyp);
134     ASSERT(_hypMaxElementVolume);
135     _maxElementVolume = _hypMaxElementVolume->GetMaxVolume();
136     isOk =true;
137     aStatus = SMESH_Hypothesis::HYP_OK;
138   }
139   else
140     aStatus = SMESH_Hypothesis::HYP_INCOMPATIBLE;
141
142   return isOk;
143 }
144
145 //=============================================================================
146 /*!
147  *Here we are going to use the NETGEN mesher
148  */
149 //=============================================================================
150
151 bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh&         aMesh,
152                                      const TopoDS_Shape& aShape)
153 {
154   MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);
155
156   SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
157
158   const int invalid_ID = -1;
159
160   SMESH::Controls::Area areaControl;
161   SMESH::Controls::TSequenceOfXYZ nodesCoords;
162
163   // -------------------------------------------------------------------
164   // get triangles on aShell and make a map of nodes to Netgen node IDs
165   // -------------------------------------------------------------------
166
167   SMESH_MesherHelper helper(aMesh);
168   SMESH_MesherHelper* myTool = &helper;
169   bool _quadraticMesh = myTool->IsQuadraticSubMesh(aShape);
170
171   typedef map< const SMDS_MeshNode*, int> TNodeToIDMap;
172   TNodeToIDMap nodeToNetgenID;
173   list< const SMDS_MeshElement* > triangles;
174   list< bool >                    isReversed; // orientation of triangles
175
176   // for the degeneraged edge: ignore all but one node on it;
177   // map storing ids of degen edges and vertices and their netgen id:
178   map< int, int* > degenShapeIdToPtrNgId;
179   map< int, int* >::iterator shId_ngId;
180   list< int > degenNgIds;
181
182   for (TopExp_Explorer exp(aShape,TopAbs_FACE);exp.More();exp.Next())
183   {
184     const TopoDS_Shape& aShapeFace = exp.Current();
185     const SMESHDS_SubMesh * aSubMeshDSFace = meshDS->MeshElements( aShapeFace );
186     if ( aSubMeshDSFace )
187     {
188       bool isRev = SMESH_Algo::IsReversedSubMesh( TopoDS::Face(aShapeFace), meshDS );
189
190       SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
191       while ( iteratorElem->more() ) // loop on elements on a face
192       {
193         // check element
194         const SMDS_MeshElement* elem = iteratorElem->next();
195         if ( !elem )
196           return error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
197         bool isTraingle = ( elem->NbNodes()==3 || (_quadraticMesh && elem->NbNodes()==6 ));
198         if ( !isTraingle )
199           return error( COMPERR_BAD_INPUT_MESH,
200                         SMESH_Comment("Not triangle element ")<<elem->GetID());
201         // keep a triangle
202         triangles.push_back( elem );
203         isReversed.push_back( isRev );
204         // put elem nodes to nodeToNetgenID map
205         SMDS_ElemIteratorPtr triangleNodesIt = elem->nodesIterator();
206         while ( triangleNodesIt->more() ) {
207           const SMDS_MeshNode * node =
208             static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
209           if(myTool->IsMedium(node))
210             continue;
211           nodeToNetgenID.insert( make_pair( node, invalid_ID ));
212         }
213 #ifdef _DEBUG_
214         // check if a trainge is degenerated
215         areaControl.GetPoints( elem, nodesCoords );
216         double area = areaControl.GetValue( nodesCoords );
217         if ( area <= DBL_MIN ) {
218           MESSAGE( "Warning: Degenerated " << elem );
219         }
220 #endif
221       }
222       // look for degeneraged edges and vetices
223       for (TopExp_Explorer expE(aShapeFace,TopAbs_EDGE);expE.More();expE.Next())
224       {
225         TopoDS_Edge aShapeEdge = TopoDS::Edge( expE.Current() );
226         if ( BRep_Tool::Degenerated( aShapeEdge ))
227         {
228           degenNgIds.push_back( invalid_ID );
229           int* ptrIdOnEdge = & degenNgIds.back();
230           // remember edge id
231           int edgeID = meshDS->ShapeToIndex( aShapeEdge );
232           degenShapeIdToPtrNgId.insert( make_pair( edgeID, ptrIdOnEdge ));
233           // remember vertex id
234           int vertexID = meshDS->ShapeToIndex( TopExp::FirstVertex( aShapeEdge ));
235           degenShapeIdToPtrNgId.insert( make_pair( vertexID, ptrIdOnEdge ));
236         }
237       }
238     }
239   }
240   // ---------------------------------
241   // Feed the Netgen with surface mesh
242   // ---------------------------------
243
244   int Netgen_NbOfNodes = 0;
245   int Netgen_param2ndOrder = 0;
246   double Netgen_paramFine = 1.;
247   double Netgen_paramSize = _maxElementVolume;
248
249   double Netgen_point[3];
250   int Netgen_triangle[3];
251   int Netgen_tetrahedron[4];
252
253   Ng_Init();
254
255   Ng_Mesh * Netgen_mesh = Ng_NewMesh();
256
257   // set nodes and remember thier netgen IDs
258   bool isDegen = false, hasDegen = !degenShapeIdToPtrNgId.empty();
259   TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
260   for ( ; n_id != nodeToNetgenID.end(); ++n_id )
261   {
262     const SMDS_MeshNode* node = n_id->first;
263
264     // ignore nodes on degenerated edge
265     if ( hasDegen ) {
266       int shapeId = node->GetPosition()->GetShapeId();
267       shId_ngId = degenShapeIdToPtrNgId.find( shapeId );
268       isDegen = ( shId_ngId != degenShapeIdToPtrNgId.end() );
269       if ( isDegen && *(shId_ngId->second) != invalid_ID ) {
270         n_id->second = *(shId_ngId->second);
271         continue;
272       }
273     }
274     Netgen_point [ 0 ] = node->X();
275     Netgen_point [ 1 ] = node->Y();
276     Netgen_point [ 2 ] = node->Z();
277     Ng_AddPoint(Netgen_mesh, Netgen_point);
278     n_id->second = ++Netgen_NbOfNodes; // set netgen ID
279
280     if ( isDegen ) // all nodes on a degen edge get one netgen ID
281       *(shId_ngId->second) = n_id->second;
282   }
283
284   // set triangles
285   list< const SMDS_MeshElement* >::iterator tria = triangles.begin();
286   list< bool >::iterator                 reverse = isReversed.begin();
287   for ( ; tria != triangles.end(); ++tria, ++reverse )
288   {
289     int i = 0;
290     SMDS_ElemIteratorPtr triangleNodesIt = (*tria)->nodesIterator();
291     while ( triangleNodesIt->more() ) {
292       const SMDS_MeshNode * node =
293         static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
294       if(myTool->IsMedium(node))
295         continue;
296       Netgen_triangle[ *reverse ? 2 - i : i ] = nodeToNetgenID[ node ];
297       ++i;
298     }
299     if ( !hasDegen ||
300          // ignore degenerated triangles, they have 2 or 3 same ids
301          (Netgen_triangle[0] != Netgen_triangle[1] &&
302           Netgen_triangle[0] != Netgen_triangle[2] &&
303           Netgen_triangle[2] != Netgen_triangle[1] ))
304       Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
305   }
306
307   // -------------------------
308   // Generate the volume mesh
309   // -------------------------
310
311   Ng_Meshing_Parameters Netgen_param;
312
313   Netgen_param.secondorder = Netgen_param2ndOrder;
314   Netgen_param.fineness = Netgen_paramFine;
315   Netgen_param.maxh = Netgen_paramSize;
316
317   Ng_Result status;
318
319   try {
320 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
321     OCC_CATCH_SIGNALS;
322 #endif
323     status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
324   }
325   catch (Standard_Failure& exc) {
326     error(COMPERR_OCC_EXCEPTION, exc.GetMessageString());
327     status = NG_VOLUME_FAILURE;
328   }
329   catch (...) {
330     error("Exception in Ng_GenerateVolumeMesh()");
331     status = NG_VOLUME_FAILURE;
332   }
333   if ( GetComputeError()->IsOK() ) {
334     switch ( status ) {
335     case NG_SURFACE_INPUT_ERROR:error( status, "NG_SURFACE_INPUT_ERROR");
336     case NG_VOLUME_FAILURE:     error( status, "NG_VOLUME_FAILURE");
337     case NG_STL_INPUT_ERROR:    error( status, "NG_STL_INPUT_ERROR");
338     case NG_SURFACE_FAILURE:    error( status, "NG_SURFACE_FAILURE");
339     case NG_FILE_NOT_FOUND:     error( status, "NG_FILE_NOT_FOUND");
340     };
341   }
342
343   int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
344
345   int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh);
346
347   MESSAGE("End of Volume Mesh Generation. status=" << status <<
348           ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes <<
349           ", nb tetra: " << Netgen_NbOfTetra);
350
351   // -------------------------------------------------------------------
352   // Feed back the SMESHDS with the generated Nodes and Volume Elements
353   // -------------------------------------------------------------------
354
355   bool isOK = ( /*status == NG_OK &&*/ Netgen_NbOfTetra > 0 );// get whatever built
356   if ( isOK )
357   {
358     // vector of nodes in which node index == netgen ID
359     vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 );
360     // insert old nodes into nodeVec
361     for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id ) {
362       nodeVec.at( n_id->second ) = n_id->first;
363     }
364     // create and insert new nodes into nodeVec
365     int nodeIndex = Netgen_NbOfNodes + 1;
366     int shapeID = meshDS->ShapeToIndex( aShape );
367     for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex )
368     {
369       Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point );
370       SMDS_MeshNode * node = meshDS->AddNode(Netgen_point[0],
371                                              Netgen_point[1],
372                                              Netgen_point[2]);
373       meshDS->SetNodeInVolume(node, shapeID);
374       nodeVec.at(nodeIndex) = node;
375     }
376
377     // create tetrahedrons
378     for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
379     {
380       Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron);
381       SMDS_MeshVolume * elt = myTool->AddVolume (nodeVec.at( Netgen_tetrahedron[0] ),
382                                                  nodeVec.at( Netgen_tetrahedron[1] ),
383                                                  nodeVec.at( Netgen_tetrahedron[2] ),
384                                                  nodeVec.at( Netgen_tetrahedron[3] ));
385       meshDS->SetMeshElementOnShape(elt, shapeID );
386     }
387   }
388
389   Ng_DeleteMesh(Netgen_mesh);
390   Ng_Exit();
391
392   NETGENPlugin_Mesher::RemoveTmpFiles();
393
394   return (status == NG_OK);
395 }
396
397 bool NETGENPlugin_NETGEN_3D::Compute(SMESH_Mesh& aMesh,
398                                      SMESH_MesherHelper* aHelper)
399 {
400   MESSAGE("NETGENPlugin_NETGEN_3D::Compute with maxElmentsize = " << _maxElementVolume);  
401   const int invalid_ID = -1;
402   bool _quadraticMesh = false;
403   typedef map< const SMDS_MeshNode*, int> TNodeToIDMap;
404   TNodeToIDMap nodeToNetgenID;
405   list< const SMDS_MeshElement* > triangles;
406   SMESHDS_Mesh* MeshDS = aHelper->GetMeshDS();
407
408   SMESH_MesherHelper::MType MeshType = aHelper->IsQuadraticMesh();
409   
410   if(MeshType == SMESH_MesherHelper::COMP)
411     return error( COMPERR_BAD_INPUT_MESH,
412                   SMESH_Comment("Mesh with linear and quadratic elements given."));
413   else if (MeshType == SMESH_MesherHelper::QUADRATIC)
414     _quadraticMesh = true;
415     
416   SMDS_FaceIteratorPtr iteratorFace = MeshDS->facesIterator();
417
418   while(iteratorFace->more())
419   {
420     // check element
421     const SMDS_MeshElement* elem = iteratorFace->next();
422     if ( !elem )
423       return error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
424     bool isTraingle = ( elem->NbNodes()==3 || (_quadraticMesh && elem->NbNodes()==6 ));
425     if ( !isTraingle )
426       return error( COMPERR_BAD_INPUT_MESH,
427                     SMESH_Comment("Not triangle element ")<<elem->GetID());
428     
429     // keep a triangle
430     triangles.push_back( elem );
431     // put elem nodes to nodeToNetgenID map
432     SMDS_ElemIteratorPtr triangleNodesIt = elem->nodesIterator();
433     while ( triangleNodesIt->more() ) {
434       const SMDS_MeshNode * node =
435         static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
436       if(aHelper->IsMedium(node))
437         continue;
438       
439       nodeToNetgenID.insert( make_pair( node, invalid_ID ));
440     }
441   }
442
443   // ---------------------------------
444   // Feed the Netgen with surface mesh
445   // ---------------------------------
446
447   int Netgen_NbOfNodes = 0;
448   int Netgen_param2ndOrder = 0;
449   double Netgen_paramFine = 1.;
450   double Netgen_paramSize = _maxElementVolume;
451   
452   double Netgen_point[3];
453   int Netgen_triangle[3];
454   int Netgen_tetrahedron[4];
455
456   Ng_Init();
457
458   Ng_Mesh * Netgen_mesh = Ng_NewMesh();
459
460     // set nodes and remember thier netgen IDs
461   
462   TNodeToIDMap::iterator n_id = nodeToNetgenID.begin();
463   for ( ; n_id != nodeToNetgenID.end(); ++n_id )
464   {
465     const SMDS_MeshNode* node = n_id->first;
466
467     Netgen_point [ 0 ] = node->X();
468     Netgen_point [ 1 ] = node->Y();
469     Netgen_point [ 2 ] = node->Z();
470     Ng_AddPoint(Netgen_mesh, Netgen_point);
471     n_id->second = ++Netgen_NbOfNodes; // set netgen ID
472
473   }
474
475   // set triangles
476   list< const SMDS_MeshElement* >::iterator tria = triangles.begin();
477   for ( ; tria != triangles.end(); ++tria)
478   {
479     int i = 0;
480     SMDS_ElemIteratorPtr triangleNodesIt = (*tria)->nodesIterator();
481     while ( triangleNodesIt->more() ) {
482       const SMDS_MeshNode * node =
483         static_cast<const SMDS_MeshNode *>(triangleNodesIt->next());
484       if(aHelper->IsMedium(node))
485         continue;
486       Netgen_triangle[ i ] = nodeToNetgenID[ node ];
487       ++i;
488     }
489     
490     Ng_AddSurfaceElement(Netgen_mesh, NG_TRIG, Netgen_triangle);
491   }
492
493   // -------------------------
494   // Generate the volume mesh
495   // -------------------------
496
497   Ng_Meshing_Parameters Netgen_param;
498
499   Netgen_param.secondorder = Netgen_param2ndOrder;
500   Netgen_param.fineness = Netgen_paramFine;
501   Netgen_param.maxh = Netgen_paramSize;
502
503   Ng_Result status;
504
505   try {
506 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
507     OCC_CATCH_SIGNALS;
508 #endif
509     status = Ng_GenerateVolumeMesh(Netgen_mesh, &Netgen_param);
510   }
511   catch (Standard_Failure& exc) {
512     error(COMPERR_OCC_EXCEPTION, exc.GetMessageString());
513     status = NG_VOLUME_FAILURE;
514   }
515   catch (...) {
516     error("Bad mesh input!!!");
517     status = NG_VOLUME_FAILURE;
518   }
519   if ( GetComputeError()->IsOK() ) {
520     error( status, "Bad mesh input!!!");
521   }
522
523   int Netgen_NbOfNodesNew = Ng_GetNP(Netgen_mesh);
524
525   int Netgen_NbOfTetra = Ng_GetNE(Netgen_mesh);
526
527   MESSAGE("End of Volume Mesh Generation. status=" << status <<
528           ", nb new nodes: " << Netgen_NbOfNodesNew - Netgen_NbOfNodes <<
529           ", nb tetra: " << Netgen_NbOfTetra);
530
531   // -------------------------------------------------------------------
532   // Feed back the SMESHDS with the generated Nodes and Volume Elements
533   // -------------------------------------------------------------------
534
535   bool isOK = ( Netgen_NbOfTetra > 0 );// get whatever built
536   if ( isOK )
537   {
538     // vector of nodes in which node index == netgen ID
539     vector< const SMDS_MeshNode* > nodeVec ( Netgen_NbOfNodesNew + 1 );
540     // insert old nodes into nodeVec
541     for ( n_id = nodeToNetgenID.begin(); n_id != nodeToNetgenID.end(); ++n_id ) {
542       nodeVec.at( n_id->second ) = n_id->first;
543     }
544     // create and insert new nodes into nodeVec
545     int nodeIndex = Netgen_NbOfNodes + 1;
546     
547     for ( ; nodeIndex <= Netgen_NbOfNodesNew; ++nodeIndex )
548     {
549       Ng_GetPoint( Netgen_mesh, nodeIndex, Netgen_point );
550       SMDS_MeshNode * node = aHelper->AddNode(Netgen_point[0],
551                                              Netgen_point[1],
552                                              Netgen_point[2]);
553       nodeVec.at(nodeIndex) = node;
554     }
555
556     // create tetrahedrons
557     for ( int elemIndex = 1; elemIndex <= Netgen_NbOfTetra; ++elemIndex )
558     {
559       Ng_GetVolumeElement(Netgen_mesh, elemIndex, Netgen_tetrahedron);
560       aHelper->AddVolume (nodeVec.at( Netgen_tetrahedron[0] ),
561                                                  nodeVec.at( Netgen_tetrahedron[1] ),
562                                                  nodeVec.at( Netgen_tetrahedron[2] ),
563                                                  nodeVec.at( Netgen_tetrahedron[3] ));
564     }
565   }
566
567   Ng_DeleteMesh(Netgen_mesh);
568   Ng_Exit();
569   
570   NETGENPlugin_Mesher::RemoveTmpFiles();
571   
572   return (status == NG_OK);
573 }