1 // Copyright (C) 2005 CEA/DEN, EDF R&D, OPEN CASCADE, PRINCIPIA R&D
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.
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/
19 //=============================================================================
20 // File : GHS3DPlugin_GHS3D.cxx
22 // Author : Edward AGAPOV
24 // Copyright : CEA 2003
26 //=============================================================================
29 #include "GHS3DPlugin_GHS3D.hxx"
30 #include "SMESH_Gen.hxx"
31 #include "SMESH_Mesh.hxx"
33 #include "SMDS_MeshElement.hxx"
34 #include "SMDS_MeshNode.hxx"
36 #include <TopExp_Explorer.hxx>
37 #include <OSD_File.hxx>
39 #include "utilities.h"
42 #include <sys/sysinfo.h>
53 //=============================================================================
57 //=============================================================================
59 GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D(int hypId, int studyId, SMESH_Gen* gen)
60 : SMESH_3D_Algo(hypId, studyId, gen)
62 MESSAGE("GHS3DPlugin_GHS3D::GHS3DPlugin_GHS3D");
64 _shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
67 //=============================================================================
71 //=============================================================================
73 GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D()
75 MESSAGE("GHS3DPlugin_GHS3D::~GHS3DPlugin_GHS3D");
78 //=============================================================================
82 //=============================================================================
84 bool GHS3DPlugin_GHS3D::CheckHypothesis
86 const TopoDS_Shape& aShape,
87 SMESH_Hypothesis::Hypothesis_Status& aStatus)
89 // MESSAGE("GHS3DPlugin_GHS3D::CheckHypothesis");
90 aStatus = SMESH_Hypothesis::HYP_OK;
94 //=======================================================================
95 //function : writeFaces
97 //=======================================================================
99 static bool writeFaces (ofstream & theFile,
100 SMESHDS_Mesh * theMesh,
101 const TopoDS_Shape& theShape,
102 const map <int,int> & theSmdsToGhs3dIdMap)
106 // NB_ELEMS DUMMY_INT
107 // Loop from 1 to NB_ELEMS
108 // NB_NODES NODE_NB_1 NODE_NB_2 ... (NB_NODES + 1) times: DUMMY_INT
110 // get all faces bound to theShape
112 list< const SMDS_MeshElement* > faces;
113 TopExp_Explorer fExp( theShape, TopAbs_FACE );
114 for ( ; fExp.More(); fExp.Next() ) {
115 SMESHDS_SubMesh* sm = theMesh->MeshElements( fExp.Current() );
117 SMDS_ElemIteratorPtr eIt = sm->GetElements();
118 while ( eIt->more() ) {
119 faces.push_back( eIt->next() );
128 const char* space = " ";
129 const int dummyint = 0;
131 // NB_ELEMS DUMMY_INT
132 theFile << space << nbFaces << space << dummyint << endl;
134 // Loop from 1 to NB_ELEMS
135 list< const SMDS_MeshElement* >::iterator f = faces.begin();
136 for ( ; f != faces.end(); ++f )
139 const SMDS_MeshElement* elem = *f;
140 const int nbNodes = elem->NbNodes();
141 theFile << space << nbNodes;
143 // NODE_NB_1 NODE_NB_2 ...
144 SMDS_ElemIteratorPtr nodeIt = elem->nodesIterator();
145 while ( nodeIt->more() )
148 int aSmdsID = nodeIt->next()->GetID();
149 map<int,int>::const_iterator it = theSmdsToGhs3dIdMap.find( aSmdsID );
150 ASSERT( it != theSmdsToGhs3dIdMap.end() );
151 theFile << space << (*it).second;
154 // (NB_NODES + 1) times: DUMMY_INT
155 for ( int i=0; i<=nbNodes; i++)
156 theFile << space << dummyint;
164 //=======================================================================
165 //function : writePoints
167 //=======================================================================
169 static bool writePoints (ofstream & theFile,
170 SMESHDS_Mesh * theMesh,
171 map <int,int> & theSmdsToGhs3dIdMap,
172 map <int,const SMDS_MeshNode*> & theGhs3dIdToNodeMap)
177 // Loop from 1 to NB_NODES
180 int nbNodes = theMesh->NbNodes();
184 const char* space = " ";
185 const int dummyint = 0;
188 theFile << space << nbNodes << endl;
190 // Loop from 1 to NB_NODES
192 SMDS_NodeIteratorPtr it = theMesh->nodesIterator();
195 const SMDS_MeshNode* node = it->next();
196 theSmdsToGhs3dIdMap.insert( map <int,int>::value_type( node->GetID(), aGhs3dID ));
197 theGhs3dIdToNodeMap.insert (map <int,const SMDS_MeshNode*>::value_type( aGhs3dID, node ));
202 << space << node->X()
203 << space << node->Y()
204 << space << node->Z()
205 << space << dummyint;
213 //=======================================================================
216 //=======================================================================
218 static bool getInt( int & theValue, char * & theLine )
221 theValue = strtol( theLine, &ptr, 10 );
222 if ( ptr == theLine ||
223 // there must not be neither '.' nor ',' nor 'E' ...
224 (*ptr != ' ' && *ptr != '\n' && *ptr != '\0'))
227 DUMP( " " << theValue );
232 //=======================================================================
233 //function : getDouble
235 //=======================================================================
237 static bool getDouble( double & theValue, char * & theLine )
240 theValue = strtod( theLine, &ptr );
241 if ( ptr == theLine )
244 DUMP( " " << theValue );
249 //=======================================================================
250 //function : readLine
252 //=======================================================================
254 #define GHS3DPlugin_BUFLENGTH 256
255 #define GHS3DPlugin_ReadLine(aPtr,aBuf,aFile,aLineNb) \
256 { aPtr = fgets( aBuf, GHS3DPlugin_BUFLENGTH - 2, aFile ); aLineNb++; DUMP(endl); }
258 //=======================================================================
259 //function : readResult
261 //=======================================================================
263 static bool readResult(FILE * theFile,
264 SMESHDS_Mesh * theMesh,
265 const TopoDS_Shape& theShape,
266 map <int,const SMDS_MeshNode*>& theGhs3dIdToNodeMap)
271 // NB_ELEMENTS NB_NODES NB_INPUT_NODES (14 DUMMY_INT)
273 // (NB_ELEMENTS * 4) node nbs
275 // (NB_NODES) node XYZ
277 char aBuffer[ GHS3DPlugin_BUFLENGTH ];
280 int shapeID = theMesh->ShapeToIndex( theShape );
282 // ----------------------------------------
284 // read nb of generated elements and nodes
285 // ----------------------------------------
286 int nbElems = 0 , nbNodes = 0, nbInputNodes = 0;
287 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
289 !getInt( nbElems, aPtr ) ||
290 !getInt( nbNodes, aPtr ) ||
291 !getInt( nbInputNodes, aPtr))
294 // -------------------------------------------
296 // read element nodes and create tetrahedrons
297 // -------------------------------------------
298 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
299 for (int iElem = 0; iElem < nbElems; iElem++)
302 const SMDS_MeshNode * node[4];
303 for (int iNode = 0; iNode < 4; iNode++)
305 // read Ghs3d node ID
307 if (!aPtr || ! getInt ( ID, aPtr ))
309 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
310 if (!aPtr || ! getInt ( ID, aPtr ))
312 MESSAGE( "Cant read " << (iNode+1) << "-th node on line " << aLineNb );
316 // find/create a node with ID
317 map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
318 if ( IdNode == theGhs3dIdToNodeMap.end())
320 // ID is not yet in theGhs3dIdToNodeMap
321 ASSERT ( ID > nbInputNodes ); // it should be a new one
322 SMDS_MeshNode * aNewNode = theMesh->AddNode( 0.,0.,0. ); // read XYZ later
323 theMesh->SetNodeInVolume( aNewNode, shapeID );
324 theGhs3dIdToNodeMap.insert ( make_pair( ID, aNewNode ));
325 node[ iNode ] = aNewNode;
329 node[ iNode ] = IdNode->second;
332 // create a tetrahedron with orientation as for MED
333 SMDS_MeshElement* aTet = theMesh->AddVolume( node[1], node[0], node[2], node[3] );
334 theMesh->SetMeshElementOnShape( aTet, shapeID );
337 // ------------------------
339 // read and set nodes' XYZ
340 // ------------------------
341 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
342 for (int iNode = 0; iNode < nbNodes; iNode++)
344 // read 3 coordinates
346 for (int iCoord = 0; iCoord < 3; iCoord++)
348 if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
350 GHS3DPlugin_ReadLine( aPtr, aBuffer, theFile, aLineNb );
351 if (!aPtr || ! getDouble ( coord[ iCoord ], aPtr ))
353 MESSAGE( "Cant read " << (iCoord+1) << "-th node coord on line " << aLineNb );
358 // do not move old nodes
360 if (ID <= nbInputNodes)
363 map <int,const SMDS_MeshNode*>::iterator IdNode = theGhs3dIdToNodeMap.find( ID );
364 ASSERT ( IdNode != theGhs3dIdToNodeMap.end());
365 SMDS_MeshNode* node = const_cast<SMDS_MeshNode*> ( (*IdNode).second );
368 theMesh->MoveNode( node, coord[0], coord[1], coord[2] );
374 //=======================================================================
375 //function : getTmpDir
377 //=======================================================================
379 static TCollection_AsciiString getTmpDir()
381 TCollection_AsciiString aTmpDir;
383 char *Tmp_dir = getenv("SALOME_TMP_DIR");
384 if(Tmp_dir != NULL) {
387 if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
389 if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
394 aTmpDir = TCollection_AsciiString("C:\\");
396 aTmpDir = TCollection_AsciiString("/tmp/");
402 //=============================================================================
404 *Here we are going to use the GHS3D mesher
406 //=============================================================================
408 bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
409 const TopoDS_Shape& theShape)
411 MESSAGE("GHS3DPlugin_GHS3D::Compute");
413 SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
415 // make a unique working file name
416 // to avoid access to the same files by eg different users
418 TCollection_AsciiString aGenericName, aTmpDir = getTmpDir();
419 aGenericName = aTmpDir + "GHS3D_";
421 aGenericName += GetCurrentProcessId();
423 aGenericName += getpid();
426 aGenericName += meshDS->ShapeToIndex( theShape );
428 TCollection_AsciiString aFacesFileName, aPointsFileName, aResultFileName;
429 TCollection_AsciiString aBadResFileName, aBbResFileName, aLogFileName;
430 aFacesFileName = aGenericName + ".faces"; // in faces
431 aPointsFileName = aGenericName + ".points"; // in points
432 aResultFileName = aGenericName + ".noboite";// out points and volumes
433 aBadResFileName = aGenericName + ".boite"; // out bad result
434 aBbResFileName = aGenericName + ".bb"; // out vertex stepsize
435 aLogFileName = aGenericName + ".log"; // log
441 ofstream aFacesFile ( aFacesFileName.ToCString() , ios::out);
442 ofstream aPointsFile ( aPointsFileName.ToCString() , ios::out);
445 aFacesFile->is_open() && aPointsFile->is_open();
447 aFacesFile.rdbuf()->is_open() && aPointsFile.rdbuf()->is_open();
451 INFOS( "Can't write into " << aTmpDir.ToCString());
454 map <int,int> aSmdsToGhs3dIdMap;
455 map <int,const SMDS_MeshNode*> aGhs3dIdToNodeMap;
458 (writePoints( aPointsFile, meshDS, aSmdsToGhs3dIdMap, aGhs3dIdToNodeMap ) &&
459 writeFaces ( aFacesFile, meshDS, theShape, aSmdsToGhs3dIdMap ));
465 if ( !getenv("GHS3D_KEEP_FILES") ) {
466 OSD_File( aFacesFileName ).Remove();
467 OSD_File( aPointsFileName ).Remove();
473 // run ghs3d mesher WIN32???
476 // ghs3d need to know amount of memory it may use (MB).
477 // Default memory is defined at ghs3d installation but it may be not enough,
478 // so allow to use about all available memory
479 TCollection_AsciiString memory;
482 int err = sysinfo( &si );
485 memory += int ( 0.8 * ( si.freeram + si.freeswap ) * si.mem_unit / 1024 / 1024 );
489 TCollection_AsciiString cmd( "ghs3d " ); // command to run
492 " -f " + aGenericName + // file to read
493 " 1>" + aLogFileName; // dump into file
495 system( cmd.ToCString() ); // run
501 FILE * aResultFile = fopen( aResultFileName.ToCString(), "r" );
504 Ok = readResult( aResultFile, meshDS, theShape, aGhs3dIdToNodeMap );
510 // ---------------------
511 // remove working files
512 // ---------------------
515 OSD_File( aLogFileName ).Remove();
517 else if ( OSD_File( aLogFileName ).Size() > 0 ) {
518 INFOS( "GHS3D Error: see " << aLogFileName.ToCString() );
521 OSD_File( aLogFileName ).Remove();
522 INFOS( "GHS3D Error: command '" << cmd.ToCString() << "' failed" );
525 if ( !getenv("GHS3D_KEEP_FILES") )
527 OSD_File( aFacesFileName ).Remove();
528 OSD_File( aPointsFileName ).Remove();
529 OSD_File( aResultFileName ).Remove();
530 OSD_File( aBadResFileName ).Remove();
531 OSD_File( aBbResFileName ).Remove();
538 //=============================================================================
542 //=============================================================================
544 ostream & GHS3DPlugin_GHS3D::SaveTo(ostream & save)
549 //=============================================================================
553 //=============================================================================
555 istream & GHS3DPlugin_GHS3D::LoadFrom(istream & load)
560 //=============================================================================
564 //=============================================================================
566 ostream & operator << (ostream & save, GHS3DPlugin_GHS3D & hyp)
568 return hyp.SaveTo( save );
571 //=============================================================================
575 //=============================================================================
577 istream & operator >> (istream & load, GHS3DPlugin_GHS3D & hyp)
579 return hyp.LoadFrom( load );