1 //=============================================================================
2 // File : GHS3DPlugin_GHS3D.cxx
4 // Author : Edward AGAPOV
6 // Copyright : CEA 2003
8 //=============================================================================
11 #include "GHS3DPlugin_GHS3D.hxx"
12 #include "SMESH_Gen.hxx"
13 #include "SMESH_Mesh.hxx"
15 #include "SMDS_MeshElement.hxx"
16 #include "SMDS_MeshNode.hxx"
18 #include <TopExp_Explorer.hxx>
19 #include <OSD_File.hxx>
21 #include "utilities.h"
24 #include <sys/sysinfo.h>
35 //=============================================================================
39 //=============================================================================
41 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
42 : SMESH_3D_Algo(hypId, studyId, gen)
44 MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
46 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
49 //=============================================================================
53 //=============================================================================
55 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
57 MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
60 //=============================================================================
64 //=============================================================================
66 bool GHS3DPlugin_GHS3D::CheckHypothesis
68 const TopoDS_Shape& aShape,
69 SMESH_Hypothesis::Hypothesis_Status& aStatus)
71 // MESSAGE("GHS3DPlugin_GHS3D::CheckHypothesis");
72 aStatus = SMESH_Hypothesis::HYP_OK;
76 //=======================================================================
77 //function : writeFaces
79 //=======================================================================
81 static bool writeFaces (ofstream & theFile,
82 SMESHDS_Mesh * theMesh,
83 const TopoDS_Shape& theShape,
84 const map <int,int> & theSmdsToGhs3dIdMap)
89 // Loop from 1 to NB_ELEMS
90 // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
92 // get all faces bound to theShape
94 list< const SMDS_MeshElement* > faces;
95 TopExp_Explorer fExp( theShape, TopAbs_FACE );
96 for ( ; fExp.More(); fExp.Next() ) {
97 SMESHDS_SubMesh* sm = theMesh->MeshElements( fExp.Current() );
99 SMDS_ElemIteratorPtr eIt = sm->GetElements();
100 while ( eIt->more() ) {
101 faces.push_back( eIt->next() );
110 const char* space = " ";
111 const int dummyint = 0;
113 // NB_ELEMS DUMMY_INT
114 theFile << space << nbFaces << space << dummyint << endl;
116 // Loop from 1 to NB_ELEMS
117 list< const SMDS_MeshElement* >::iterator f = faces.begin();
118 for ( ; f != faces.end(); ++f )
121 const SMDS_MeshElement* elem = *f;
122 const int nbNodes = elem->NbNodes();
123 theFile << space << nbNodes;
125 // NODE_NB_1 NODE_NB_2 ...
126 SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
127 while ( nodeIt->more() )
130 int aSmdsID = nodeIt->next()->GetID();
131 map<int,int>::const_iterator it = theSmdsToGhs3dIdMap.find( aSmdsID );
132 ASSERT( it != theSmdsToGhs3dIdMap.end() );
133 theFile << space << (*it).second;
136 // (NB_NODES + 1) times: DUMMY_INT
137 for ( int i=0; i<=nbNodes; i++)
138 theFile << space << dummyint;
146 //=======================================================================
147 //function : writePoints
149 //=======================================================================
151 static bool writePoints (ofstream & theFile,
152 SMESHDS_Mesh * theMesh,
153 map <int,int> & theSmdsToGhs3dIdMap,
154 map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap)
159 // Loop from 1 to NB_NODES
162 int nbNodes = theMesh->NbNodes();
166 const char* space = " ";
167 const int dummyint = 0;
170 theFile << space << nbNodes << endl;
172 // Loop from 1 to NB_NODES
174 SMDS_NodeIteratorPtr it = theMesh->nodesIterator();
177 const SMDS_MeshNode* node = it->next();
178 theSmdsToGhs3dIdMap.insert( map <int,int>::value_type( node->GetID(), aGhs3dID ));
179 theGhs3dIdToNodeMap.insert (map <int,const SMDS_MeshNode*>::value_type( aGhs3dID, node ));
184 << space << node->X()
185 << space << node->Y()
186 << space << node->Z()
187 << space << dummyint;
195 //=======================================================================
198 //=======================================================================
200 static bool getInt( int & theValue, char * & theLine )
203 theValue = strtol( theLine, &ptr, 10 );
204 if ( ptr == theLine ||
205 // there must not be neither '.' nor ',' nor 'E' ...
206 (*ptr != ' ' && *ptr != '\n' && *ptr != '\0'))
209 DUMP( " " << theValue );
214 //=======================================================================
215 //function : getDouble
217 //=======================================================================
219 static bool getDouble( double & theValue, char * & theLine )
222 theValue = strtod( theLine, &ptr );
223 if ( ptr == theLine )
226 DUMP( " " << theValue );
231 //=======================================================================
232 //function : readLine
234 //=======================================================================
236 #define GHS3DPlugin_BUFLENGTH 256
237 #define GHS3DPlugin_ReadLine(aPtr,aBuf,aFile,aLineNb) \
238 { aPtr = fgets( aBuf, GHS3DPlugin_BUFLENGTH - 2, aFile ); aLineNb++; DUMP(endl); }
240 //=======================================================================
241 //function : readResult
243 //=======================================================================
245 static bool readResult(FILE * theFile,
246 SMESHDS_Mesh * theMesh,
247 const TopoDS_Shape& theShape,
248 map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap)
253 // NB_ELEMENTS NB_NODES NB_INPUT_NODES (14 DUMMY_INT)
255 // (NB_ELEMENTS * 4) node nbs
257 // (NB_NODES) node XYZ
259 char aBuffer[ GHS3DPlugin_BUFLENGTH ];
263 // get shell to set nodes in
264 TopExp_Explorer exp( theShape, TopAbs_SHELL );
265 TopoDS_Shell aShell = TopoDS::Shell( exp.Current() );
266 if ( aShell.IsNull() )
269 // ----------------------------------------
271 // read nb of generated elements and nodes
272 // ----------------------------------------
273 int nbElems = 0 , nbNodes = 0, nbInputNodes = 0;
274 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
276 !getInt( nbElems, aPtr ) ||
277 !getInt( nbNodes, aPtr ) ||
278 !getInt( nbInputNodes, aPtr))
281 // -------------------------------------------
283 // read element nodes and create tetrahedrons
284 // -------------------------------------------
285 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
286 for (int iElem = 0; iElem < nbElems; iElem++)
289 const SMDS_MeshNode * node[4];
290 for (int iNode = 0; iNode < 4; iNode++)
292 // read Ghs3d node ID
294 if (!aPtr || ! getInt ( ID, aPtr ))
296 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
297 if (!aPtr || ! getInt ( ID, aPtr ))
299 MESSAGE( "Cant read " << (iNode+1) << "-th node on line " << aLineNb );
303 // find/create a node with ID
304 map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
305 if ( IdNode == theGhs3dIdToNodeMap.end())
307 // ID is not yet in theGhs3dIdToNodeMap
308 ASSERT ( ID > nbInputNodes ); // it should be a new one
309 SMDS_MeshNode * aNewNode = theMesh->AddNode( 0.,0.,0. ); // read XYZ later
310 theMesh->SetNodeInVolume( aNewNode, aShell );
311 theGhs3dIdToNodeMap.insert
312 ( map <int,const SMDS_MeshNode*>::value_type( ID, aNewNode ));
313 node[ iNode ] = aNewNode;
317 node[ iNode ] = (*IdNode).second;
320 // create a tetrahedron with orientation as for MED
321 SMDS_MeshElement* aTet = theMesh->AddVolume( node[1], node[0], node[2], node[3] );
322 theMesh->SetMeshElementOnShape( aTet, theShape );
325 // ------------------------
327 // read and set nodes' XYZ
328 // ------------------------
329 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
330 for (int iNode = 0; iNode < nbNodes; iNode++)
332 // read 3 coordinates
334 for (int iCoord = 0; iCoord < 3; iCoord++)
336 if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
338 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
339 if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
341 MESSAGE( "Cant read " << (iCoord+1) << "-th node coord on line " << aLineNb );
346 // do not move old nodes
348 if (ID <= nbInputNodes)
351 map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
352 ASSERT ( IdNode != theGhs3dIdToNodeMap.end());
353 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*> ( (*IdNode).second );
356 theMesh->MoveNode( node, coord[0], coord[1], coord[2] );
362 //=======================================================================
363 //function : getTmpDir
365 //=======================================================================
367 static TCollection_AsciiString getTmpDir()
369 TCollection_AsciiString aTmpDir;
371 char *Tmp_dir = getenv("SALOME_TMP_DIR");
372 if(Tmp_dir != NULL) {
375 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
377 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
382 aTmpDir = TCollection_AsciiString("C:\\");
384 aTmpDir = TCollection_AsciiString("/tmp/");
390 //=============================================================================
392 *Here we are going to use the GHS3D mesher
394 //=============================================================================
396 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
397 const TopoDS_Shape& theShape)
399 MESSAGE("GHS3DPlugin_GHS3D::Compute");
401 SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
403 // make a unique working file name
404 // to avoid access to the same files by eg different users
406 TCollection_AsciiString aGenericName, aTmpDir = getTmpDir();
407 aGenericName = aTmpDir + "GHS3D_";
409 aGenericName += GetCurrentProcessId();
411 aGenericName += getpid();
414 aGenericName += meshDS->ShapeToIndex( theShape );
416 TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
417 TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
418 aFacesFileName = aGenericName + ".faces"; // in faces
419 aPointsFileName = aGenericName + ".points"; // in points
420 aResultFileName = aGenericName + ".noboite";// out points and volumes
421 aBadResFileName = aGenericName + ".boite"; // out bad result
422 aBbResFileName = aGenericName + ".bb"; // out vertex stepsize
423 aLogFileName = aGenericName + ".log"; // log
429 ofstream aFacesFile ( aFacesFileName.ToCString() , ios::out);
430 ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
433 aFacesFile->is_open() && aPointsFile->is_open();
435 aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
439 INFOS( "Can't write into " << aTmpDir.ToCString());
442 map <int,int> aSmdsToGhs3dIdMap;
443 map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
446 (writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) &&
447 writeFaces ( aFacesFile, meshDS, theShape, aSmdsToGhs3dIdMap ));
453 if ( !getenv("GHS3D_KEEP_FILES") ) {
454 OSD_File( aFacesFileName ).Remove();
455 OSD_File( aPointsFileName ).Remove();
461 // run ghs3d mesher WIN32???
464 // ghs3d need to know amount of memory it may use (MB).
465 // Default memory is defined at ghs3d installation but it may be not enough,
466 // so allow to use about all available memory
467 TCollection_AsciiString memory;
470 int err = sysinfo( &si );
473 memory += int ( 0.8 * ( si.freeram + si.freeswap ) * si.mem_unit / 1024 / 1024 );
477 TCollection_AsciiString cmd( "ghs3d " ); // command to run
480 " -f " + aGenericName + // file to read
481 " 1>" + aLogFileName; // dump into file
483 system( cmd.ToCString() ); // run
489 FILE * aResultFile = fopen( aResultFileName.ToCString(), "r" );
492 Ok = readResult( aResultFile, meshDS, theShape, aGhs3dIdToNodeMap );
498 // ---------------------
499 // remove working files
500 // ---------------------
503 OSD_File( aLogFileName ).Remove();
505 else if ( OSD_File( aLogFileName ).Size() > 0 ) {
506 INFOS( "GHS3D Error: see " << aLogFileName.ToCString() );
509 OSD_File( aLogFileName ).Remove();
510 INFOS( "GHS3D Error: command '" << cmd.ToCString() << "' failed" );
513 if ( !getenv("GHS3D_KEEP_FILES") )
515 OSD_File( aFacesFileName ).Remove();
516 OSD_File( aPointsFileName ).Remove();
517 OSD_File( aResultFileName ).Remove();
518 OSD_File( aBadResFileName ).Remove();
519 OSD_File( aBbResFileName ).Remove();
526 //=============================================================================
530 //=============================================================================
532 ostream & GHS3DPlugin_GHS3D::SaveTo(ostream & save)
537 //=============================================================================
541 //=============================================================================
543 istream & GHS3DPlugin_GHS3D::LoadFrom(istream & load)
548 //=============================================================================
552 //=============================================================================
554 ostream & operator << (ostream & save, GHS3DPlugin_GHS3D & hyp)
556 return hyp.SaveTo( save );
559 //=============================================================================
563 //=============================================================================
565 istream & operator >> (istream & load, GHS3DPlugin_GHS3D & hyp)
567 return hyp.LoadFrom( load );