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 ];
262 int shapeID = theMesh->ShapeToIndex( theShape );
264 // ----------------------------------------
266 // read nb of generated elements and nodes
267 // ----------------------------------------
268 int nbElems = 0 , nbNodes = 0, nbInputNodes = 0;
269 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
271 !getInt( nbElems, aPtr ) ||
272 !getInt( nbNodes, aPtr ) ||
273 !getInt( nbInputNodes, aPtr))
276 // -------------------------------------------
278 // read element nodes and create tetrahedrons
279 // -------------------------------------------
280 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
281 for (int iElem = 0; iElem < nbElems; iElem++)
284 const SMDS_MeshNode * node[4];
285 for (int iNode = 0; iNode < 4; iNode++)
287 // read Ghs3d node ID
289 if (!aPtr || ! getInt ( ID, aPtr ))
291 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
292 if (!aPtr || ! getInt ( ID, aPtr ))
294 MESSAGE( "Cant read " << (iNode+1) << "-th node on line " << aLineNb );
298 // find/create a node with ID
299 map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
300 if ( IdNode == theGhs3dIdToNodeMap.end())
302 // ID is not yet in theGhs3dIdToNodeMap
303 ASSERT ( ID > nbInputNodes ); // it should be a new one
304 SMDS_MeshNode * aNewNode = theMesh->AddNode( 0.,0.,0. ); // read XYZ later
305 theMesh->SetNodeInVolume( aNewNode, shapeID );
306 theGhs3dIdToNodeMap.insert ( make_pair( ID, aNewNode ));
307 node[ iNode ] = aNewNode;
311 node[ iNode ] = IdNode->second;
314 // create a tetrahedron with orientation as for MED
315 SMDS_MeshElement* aTet = theMesh->AddVolume( node[1], node[0], node[2], node[3] );
316 theMesh->SetMeshElementOnShape( aTet, shapeID );
319 // ------------------------
321 // read and set nodes' XYZ
322 // ------------------------
323 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
324 for (int iNode = 0; iNode < nbNodes; iNode++)
326 // read 3 coordinates
328 for (int iCoord = 0; iCoord < 3; iCoord++)
330 if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
332 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
333 if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
335 MESSAGE( "Cant read " << (iCoord+1) << "-th node coord on line " << aLineNb );
340 // do not move old nodes
342 if (ID <= nbInputNodes)
345 map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
346 ASSERT ( IdNode != theGhs3dIdToNodeMap.end());
347 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*> ( (*IdNode).second );
350 theMesh->MoveNode( node, coord[0], coord[1], coord[2] );
356 //=======================================================================
357 //function : getTmpDir
359 //=======================================================================
361 static TCollection_AsciiString getTmpDir()
363 TCollection_AsciiString aTmpDir;
365 char *Tmp_dir = getenv("SALOME_TMP_DIR");
366 if(Tmp_dir != NULL) {
369 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
371 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
376 aTmpDir = TCollection_AsciiString("C:\\");
378 aTmpDir = TCollection_AsciiString("/tmp/");
384 //=============================================================================
386 *Here we are going to use the GHS3D mesher
388 //=============================================================================
390 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
391 const TopoDS_Shape& theShape)
393 MESSAGE("GHS3DPlugin_GHS3D::Compute");
395 SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
397 // make a unique working file name
398 // to avoid access to the same files by eg different users
400 TCollection_AsciiString aGenericName, aTmpDir = getTmpDir();
401 aGenericName = aTmpDir + "GHS3D_";
403 aGenericName += GetCurrentProcessId();
405 aGenericName += getpid();
408 aGenericName += meshDS->ShapeToIndex( theShape );
410 TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
411 TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
412 aFacesFileName = aGenericName + ".faces"; // in faces
413 aPointsFileName = aGenericName + ".points"; // in points
414 aResultFileName = aGenericName + ".noboite";// out points and volumes
415 aBadResFileName = aGenericName + ".boite"; // out bad result
416 aBbResFileName = aGenericName + ".bb"; // out vertex stepsize
417 aLogFileName = aGenericName + ".log"; // log
423 ofstream aFacesFile ( aFacesFileName.ToCString() , ios::out);
424 ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
427 aFacesFile->is_open() && aPointsFile->is_open();
429 aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
433 INFOS( "Can't write into " << aTmpDir.ToCString());
436 map <int,int> aSmdsToGhs3dIdMap;
437 map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
440 (writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) &&
441 writeFaces ( aFacesFile, meshDS, theShape, aSmdsToGhs3dIdMap ));
447 if ( !getenv("GHS3D_KEEP_FILES") ) {
448 OSD_File( aFacesFileName ).Remove();
449 OSD_File( aPointsFileName ).Remove();
455 // run ghs3d mesher WIN32???
458 // ghs3d need to know amount of memory it may use (MB).
459 // Default memory is defined at ghs3d installation but it may be not enough,
460 // so allow to use about all available memory
461 TCollection_AsciiString memory;
464 int err = sysinfo( &si );
467 memory += int ( 0.8 * ( si.freeram + si.freeswap ) * si.mem_unit / 1024 / 1024 );
471 TCollection_AsciiString cmd( "ghs3d " ); // command to run
474 " -f " + aGenericName + // file to read
475 " 1>" + aLogFileName; // dump into file
477 system( cmd.ToCString() ); // run
483 FILE * aResultFile = fopen( aResultFileName.ToCString(), "r" );
486 Ok = readResult( aResultFile, meshDS, theShape, aGhs3dIdToNodeMap );
492 // ---------------------
493 // remove working files
494 // ---------------------
497 OSD_File( aLogFileName ).Remove();
499 else if ( OSD_File( aLogFileName ).Size() > 0 ) {
500 INFOS( "GHS3D Error: see " << aLogFileName.ToCString() );
503 OSD_File( aLogFileName ).Remove();
504 INFOS( "GHS3D Error: command '" << cmd.ToCString() << "' failed" );
507 if ( !getenv("GHS3D_KEEP_FILES") )
509 OSD_File( aFacesFileName ).Remove();
510 OSD_File( aPointsFileName ).Remove();
511 OSD_File( aResultFileName ).Remove();
512 OSD_File( aBadResFileName ).Remove();
513 OSD_File( aBbResFileName ).Remove();
520 //=============================================================================
524 //=============================================================================
526 ostream & GHS3DPlugin_GHS3D::SaveTo(ostream & save)
531 //=============================================================================
535 //=============================================================================
537 istream & GHS3DPlugin_GHS3D::LoadFrom(istream & load)
542 //=============================================================================
546 //=============================================================================
548 ostream & operator << (ostream & save, GHS3DPlugin_GHS3D & hyp)
550 return hyp.SaveTo( save );
553 //=============================================================================
557 //=============================================================================
559 istream & operator >> (istream & load, GHS3DPlugin_GHS3D & hyp)
561 return hyp.LoadFrom( load );