-// Copyright (C) 2007-2016 CEA/DEN, EDF R&D
+// Copyright (C) 2007-2021 CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
//
#include "GHS3DPRLPlugin_GHS3DPRL.hxx"
#include "GHS3DPRLPlugin_Hypothesis.hxx"
+#include "MG_TetraHPC_API.hxx"
#include <SMESHDS_Mesh.hxx>
#include <SMESH_Gen.hxx>
+#include <SMESH_TypeDefs.hxx>
#include <SMESH_subMesh.hxx>
-
-#include <TopExp_Explorer.hxx>
-#include <OSD_File.hxx>
+#include <SMESH_MesherHelper.hxx>
#include "utilities.h"
-#ifndef WIN32
-#include <sys/sysinfo.h>
-#endif
-
-#ifdef _DEBUG_
-#define DUMP(txt) \
-// cout << txt
-#else
-#define DUMP(txt)
-#endif
-
#include <list>
#include <BRepGProp.hxx>
#include <GProp_GProps.hxx>
+#include <OSD_File.hxx>
#include <Standard_ProgramError.hxx>
#include <TCollection_AsciiString.hxx>
+#include <TopExp_Explorer.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
+#define GMFVERSION GmfDouble
+#define GMFDIMENSION 3
+
using namespace std;
static void removeFile( const TCollection_AsciiString& fileName )
try {
OSD_File( fileName ).Remove();
}
- catch ( Standard_ProgramError ) {
+ catch ( Standard_ProgramError& ) {
MESSAGE("Can't remove file: " << fileName.ToCString() << " ; file does not exist or permission denied");
}
}
//=============================================================================
-GHS3DPRLPlugin_GHS3DPRL::GHS3DPRLPlugin_GHS3DPRL(int hypId, int studyId, SMESH_Gen* gen)
- : SMESH_3D_Algo(hypId, studyId, gen)
+GHS3DPRLPlugin_GHS3DPRL::GHS3DPRLPlugin_GHS3DPRL(int hypId, SMESH_Gen* gen)
+ : SMESH_3D_Algo(hypId, gen)
{
MESSAGE("GHS3DPRLPlugin_GHS3DPRL::GHS3DPRLPlugin_GHS3DPRL");
_name = "MG-Tetra Parallel";
_shapeType = (1 << TopAbs_SHELL) | (1 << TopAbs_SOLID);// 1 bit /shape type
+ _onlyUnaryInput = false; // Compute() will be called on a compound of solids
_countSubMesh=0;
_nodeRefNumber=0;
_compatibleHypothesis.push_back(GHS3DPRLPlugin_Hypothesis::GetHypType());
+ _requireShape=false;
}
//=============================================================================
int nbHyp = hyps.size();
if (!nbHyp)
{
- aStatus = SMESH_Hypothesis::HYP_OK;
- return true; // can work with no hypothesis
+ aStatus = SMESH_Hypothesis::HYP_MISSING;
+ return false; // can't work with no hypothesis
}
itl = hyps.begin();
return aStatus == SMESH_Hypothesis::HYP_OK;
}
-//=======================================================================
-// static bool writeGHS3DPRLFiles (const TCollection_AsciiString & GHS3DPRL_In,
-// SMESHDS_Mesh * theMesh,
-// map <int,int> & theSmdsToGHS3DPRLIdMap,
-// map <int,const SMDS_MeshNode*> & theGHS3DPRLIdToNodeMap)
-// {
-// bool Ok;
-// int ifam=0;
-// TCollection_AsciiString namefile(GHS3DPRL_In);
-// namefile+=".points";
-// removeFile(namefile);
-// ofstream theFile;
-// theFile.open(namefile.ToCString(),ios::out);
-// #ifdef WIN32
-// Ok = theFile.is_open();
-// #else
-// Ok=theFile.rdbuf()->is_open();
-// #endif
-// if (!Ok)
-// {
-// INFOS("Can't write into "<<namefile.ToCString());
-// return false;
-// }
-// cout<<endl<<"writeGHS3DPRLFiles version tetra_hpc v2.1.11 "<<endl;
-// cout<<endl<<"Creating GHS3DPRL processed mesh file : "<<namefile<<endl;
-
-// int nbVertices=theMesh->NbNodes();
-// int nbFaces=theMesh->NbFaces(); //triangles or quadrangles
-// const char* space=" ";
-// //const int dummyint=1; //nrs,nsd,refnum=1 (for wrap)
-
-// // Writing SMESH points into GHS3DPRL File.points
-// theFile<<nbVertices<<endl;
-
-// int aSmdsNodeID=1;
-// const SMDS_MeshNode* node_2;
-// SMDS_NodeIteratorPtr itOnNode=theMesh->nodesIterator();
-// //int ifam=100;//test famille
-// theFile.precision(15); theFile.setf(ios::scientific,ios::floatfield);
-// //cout<<"set precision 15 on float\n";
-// while (itOnNode->more())
-// {
-// node_2 = itOnNode->next();
-// theSmdsToGHS3DPRLIdMap.insert(map <int,int>::value_type(node_2->GetID(),aSmdsNodeID));
-// theGHS3DPRLIdToNodeMap.insert(map <int,const SMDS_MeshNode*>::value_type(aSmdsNodeID,node_2));
-// theFile<<node_2->X()<<space<<node_2->Y()<<space<<node_2->Z()<<space<<ifam<<endl;
-// aSmdsNodeID++;
-// //if (aSmdsNodeID==11) ifam++;
-// }
-// //no specified points;
-// theFile.close();
-
-// namefile=GHS3DPRL_In+".faces";
-// removeFile(namefile);
-// theFile.open(namefile.ToCString(),ios::out);
-// #ifdef WIN32
-// Ok=theFile.is_open();
-// #else
-// Ok=theFile.rdbuf()->is_open();
-// #endif
-// if (!Ok)
-// {
-// INFOS("Can't write into "<<namefile.ToCString());
-// return false;
-// }
-// cout<<endl<<"Creating GHS3DPRL processed mesh file : "<<namefile<<endl;
-
-// // Writing SMESH faces into GHS3DPRL File.faces
-// theFile<<nbFaces<<" 0"<<endl; //NB_ELEMS DUMMY_INT
-// //" 0" is a reserved parameter
-
-// const SMDS_MeshElement* aFace;
-// map<int,int>::const_iterator itOnSmdsNode;
-// SMDS_ElemIteratorPtr itOnFaceNode;
-// SMDS_FaceIteratorPtr itOnSmdsFace = theMesh->facesIterator();
-// long nbNoTriangles=0;
-// int ifaces=0;
-// //ifam=300;
-// while (itOnSmdsFace->more())
-// {
-// aFace=itOnSmdsFace->next();
-// itOnFaceNode=aFace->nodesIterator();
-// const int nbNodes=aFace->NbNodes();
-// if (nbNodes!=3) nbNoTriangles++;
-// ifaces++;
-// theFile<<nbNodes<<space; // NB_NODES
-// while (itOnFaceNode->more())
-// {
-// aSmdsNodeID=itOnFaceNode->next()->GetID();
-// itOnSmdsNode=theSmdsToGHS3DPRLIdMap.find(aSmdsNodeID);
-// ASSERT(itOnSmdsNode!=theSmdsToGHS3DPRLIdMap.end());
-// theFile<<space<<(*itOnSmdsNode).second; //NODE_1 NODE_2 ...
-// }
-// //(NB_NODES+1) times: DUMMY_INT
-// //if (ifaces==11) ifam++;
-// theFile<<space<<ifam;
-// for ( int i=1; i<=nbNodes; i++) theFile<<space<<200+i;
-// theFile<<endl;
-// }
-// theFile.close();
-
-// cout<<"Processed mesh files created, they contains :\n";
-// cout<<" "<<nbVertices<<" vertices\n";
-// if (nbNoTriangles==0)
-// cout<<" "<<nbFaces<<" faces\n\n";
-// else
-// cout<<" "<<nbFaces<<" faces with "<<nbNoTriangles<<"faces no triangles\n\n";
-// return true;
-// }
-
-
-//=======================================================================
-
-#define GHS3DPRLPlugin_BUFLENGTH 256
-#define GHS3DPRLPlugin_ReadLine(aPtr,aBuf,aFile,aLineNb) \
-{ aPtr = fgets( aBuf, GHS3DPRLPlugin_BUFLENGTH - 2, aFile ); aLineNb++; DUMP(endl); }
-
-
//=============================================================================
// Pass parameters to GHS3DPRL
void GHS3DPRLPlugin_GHS3DPRL::SetParameters(const GHS3DPRLPlugin_Hypothesis* hyp)
return aTmpDir;
}
+//=============================================================================
+// Write a skin mesh into a GMF file or pass it to MG-TetraHPC API
+static void exportGMF(MG_TetraHPC_API* theTetraInput,
+ const char* theFile,
+ const SMESHDS_Mesh* theMeshDS)
+{
+ int meshID = theTetraInput->GmfOpenMesh( theFile, GmfWrite, GMFVERSION, GMFDIMENSION);
+
+ // nodes
+ int iN = 0, nbNodes = theMeshDS->NbNodes();
+ theTetraInput->GmfSetKwd( meshID, GmfVertices, nbNodes );
+ std::map< const SMDS_MeshNode*, int, TIDCompare > node2IdMap;
+ SMDS_NodeIteratorPtr nodeIt = theMeshDS->nodesIterator();
+ SMESH_TNodeXYZ n;
+ while ( nodeIt->more() )
+ {
+ n.Set( nodeIt->next() );
+ theTetraInput->GmfSetLin( meshID, GmfVertices, n.X(), n.Y(), n.Z(), n._node->getshapeId() );
+ node2IdMap.insert( node2IdMap.end(), std::make_pair( n._node, ++iN ));
+ }
+
+ // triangles
+ SMDS_ElemIteratorPtr elemIt = theMeshDS->elementGeomIterator( SMDSGeom_TRIANGLE );
+ if ( elemIt->more() )
+ {
+ int nbTria = theMeshDS->GetMeshInfo().NbElements( SMDSGeom_TRIANGLE );
+ theTetraInput->GmfSetKwd(meshID, GmfTriangles, nbTria );
+ for ( int gmfID = 1; elemIt->more(); ++gmfID )
+ {
+ const SMDS_MeshElement* tria = elemIt->next();
+ theTetraInput->GmfSetLin(meshID, GmfTriangles,
+ node2IdMap[ tria->GetNode( 0 )],
+ node2IdMap[ tria->GetNode( 1 )],
+ node2IdMap[ tria->GetNode( 2 )],
+ tria->getshapeId() );
+ }
+ }
+ theTetraInput->GmfCloseMesh( meshID );
+}
+
//=============================================================================
// Here we are going to use the GHS3DPRL mesher for tetra-hpc (formerly tepal in v3 (2014))
-bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh& theMesh,
- const TopoDS_Shape& theShape)
+bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& /*theShape*/)
+{
+ SMESH_MesherHelper helper( theMesh );
+ bool ok = Compute( theMesh, &helper );
+ return ok;
+}
+
+//=============================================================================
+// Here we are going to use the GHS3DPRL mesher for tetra-hpc (formerly tepal in v3 (2014))
+bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh& theMesh,
+ SMESH_MesherHelper* /*theHelper*/)
{
bool Ok=false;
TCollection_AsciiString pluginerror("ghs3dprl: ");
SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
- //cout<<"GetMeshDS done\n";
- if (_countSubMesh==0){
- MESSAGE("GHS3DPRLPlugin_GHS3DPRL::Compute for tetra-hpc");
- _countTotal=0;
- TopExp_Explorer expf(meshDS->ShapeToMesh(), TopAbs_SOLID);
- for ( ; expf.More(); expf.Next() ) _countTotal++;
- }
- _countSubMesh++;
- //cout<<"Compute _countSubMesh "<<_countSubMesh<<endl;
- //no stuff if multiples submesh, multiple call compute
- //mesh all in one pass tepal (the last)
- if (_countSubMesh != _countTotal ) return true;
+ if ( theMesh.NbTriangles() == 0 )
+ return error( COMPERR_BAD_INPUT_MESH, "No triangles in the mesh" );
- //stuff on last call
if (_hypothesis==NULL){
pluginerror += "No existing parameters/hypothesis for GHS3DPRL";
cout <<"\n"<<pluginerror<<"\n\n";
cout << " multithread = " << _Multithread << "\n\n";
cout << " adv. options = '" << _AdvOptions << "'\n\n";
- //string tmpDir=getTmpDir_new();
TCollection_AsciiString
tmpDir=getTmpDir(),
GHS3DPRL_In,
GHS3DPRL_Out,
+ GHS3DPRL_Out_Mesh,
GHS3DPRL_Outxml,
+ logFileName,
run_GHS3DPRL("tetrahpc2med "),
rm("rm -f "),
run_nokeep_files,
fileskinmesh(""),
path,
casenamemed; //_MEDName.c_str());
+ int res = 0; // 0 is OK
casenamemed += (char *)_MEDName.c_str();
int n=casenamemed.SearchFromEnd('/');
casenamemed=casenamemed.SubString(1,20);
cerr<<"MEDName truncated (no more 20 characters) = "<<casenamemed<<endl;
}
- //cout<<"path="<<path<<endl;
- //cout<<"casenamemed="<<casenamemed<<endl;
map <int,int> aSmdsToGHS3DPRLIdMap;
map <int,const SMDS_MeshNode*> aGHS3DPRLIdToNodeMap;
GHS3DPRL_In = path + "GHS3DPRL";
GHS3DPRL_Out = path + casenamemed;
+ GHS3DPRL_Out_Mesh = path + casenamemed + "_out.mesh";
GHS3DPRL_Outxml = path + casenamemed + ".xml"; //master file
+ logFileName = path + casenamemed + ".log"; // MG library output
NbPart=_NbPart;
Gradation=_Gradation;
MinSize=_MinSize;
system( run_nokeep_files.ToCString() ); //clean files
run_nokeep_files = rm + GHS3DPRL_In + "* ";
- cout<<"GHS3DPRL command :\n "<<run_GHS3DPRL.ToCString()<<endl;
fileskinmesh=path + "GHS3DPRL.mesh";
- cout<<" Write input file for tetra_hpc.exe "<<fileskinmesh<<"...";
GHS3DPRL_Out = path + casenamemed;
removeFile( GHS3DPRL_Outxml ); //only the master xml file
- //Ok=writeGHS3DPRLFiles(GHS3DPRL_In, meshDS, aSmdsToGHS3DPRLIdMap, aGHS3DPRLIdToNodeMap);
- bool toCreateGroups = false;
- theMesh.ExportGMF(fileskinmesh.ToCString(), meshDS, toCreateGroups );
- cout<<" ...done\n";
- //else {
- // cout<<" ...NOT done\n";
- // pluginerror = pluginerror + "problem writing input tepal files " + GHS3DPRL_In + ".mesh";
-
- //Ecriture dans un fichier MED ?v2.? meme si not Ok
- //create empty file -> avoid warning message
- //med_idt fid=MEDouvrir((const char *)fileskinmed.ToCString(),MED_CREATION);
- //med_err ret=MEDfermer(fid);
- //fileskinmed=fileskinmed + "cp /home/wambeke/empty.med "+ path + "GHS3DPRL_skin.med";
- //system( fileskinmed.ToCString() );
+
+ MG_TetraHPC_API mgTetraHPC( _computeCanceled, _progress );
+ bool useLib = ( mgTetraHPC.IsLibrary() && !_Background && _Multithread );
+ if ( !useLib )
+ mgTetraHPC.SetUseExecutable();
+
+ exportGMF( &mgTetraHPC, fileskinmesh.ToCString(), meshDS );
+
+ if ( useLib )
+ {
+ TCollection_AsciiString cmd = TCollection_AsciiString("mg-tetra_hpc.exe") +
+ " --number_of_subdomains=" + NbPart +
+ " --gradation=" + Gradation +
+ " --min_size=" + MinSize +
+ " --max_size=" + MaxSize +
+ " --verbose=3" +
+ " --out=" + GHS3DPRL_Out_Mesh +
+ " " + _AdvOptions.c_str();
+
+ cout << endl
+ << " Run mg-tetra_hpc as library. Creating a mesh file " << GHS3DPRL_Out_Mesh << endl
+ << " Creating a log file : " << logFileName << endl << endl;
+ mgTetraHPC.SetLogFile( logFileName.ToCString() );
+
+ mgTetraHPC.Compute( cmd.ToCString() );
+
+ std::string log = mgTetraHPC.GetLog();
+ if ( log.find(" Dlim " ) != std::string::npos ||
+ log.find(" license ") != std::string::npos )
+ return error("License problem");
+
+ // set --launchtetra=no
+ int yesPos = run_GHS3DPRL.Search("launchtetra") + sizeof("launchtetra");
+ run_GHS3DPRL.SetValue( yesPos+0, 'n' );
+ run_GHS3DPRL.SetValue( yesPos+1, 'o' );
+ run_GHS3DPRL.SetValue( yesPos+2, ' ' );
+ }
+ else
+ {
+ cout<<" Write input file for mg-tetra_hpc "<<fileskinmesh<<"...";
+ cout<<" ...done\n";
+ }
fileskinmed=path + "GHS3DPRL_skin.med";
cout<<" Write file "<<fileskinmed<<"...";
- theMesh.ExportMED(fileskinmed.ToCString(),"SKIN_INITIAL",true,1);
+ theMesh.ExportMED(fileskinmed.ToCString(),"SKIN_INITIAL",true);
cout<<" ...done\n\n";
-
+ cout<<"GHS3DPRL command :\n "<<run_GHS3DPRL.ToCString()<<endl;
//sometimes it is better to wait flushing files on slow filesystem...
system( "sleep 3" );
//launch tetrahpc2med which launch mg-tetra_hpc.py which launch mg-tetra_hpc(_mpi?).exe
- system( run_GHS3DPRL.ToCString() );
+ res = system( run_GHS3DPRL.ToCString() );
+ if (res > 0)
+ {
+ pluginerror = pluginerror + "PROBLEM tetrahpc2med command";
+ cout<<pluginerror<<endl;
+ error(COMPERR_ALGO_FAILED, pluginerror.ToCString());
+ return false; //but it is not a problem but if true my message is overwritten
+ }
system( "sleep 3" );
if (_Background) {
pluginerror = pluginerror + "backgrounding... plugin is not waiting for output files "+ casenamemed + "_*.med";
cout<<pluginerror<<endl;
- error(COMPERR_ALGO_FAILED, pluginerror.ToCString());
+ error(COMPERR_NO_MESH_ON_SHAPE, pluginerror.ToCString());
return false; //but it is not a problem but if true my message is overwritten
//return true; //but it is not a problem,
}
// read a result, GHS3DPRL_Out is the name of master file (previous xml format)
FILE * aResultFile = fopen( GHS3DPRL_Outxml.ToCString(), "r" );
if (aResultFile){
- //Ok = readResult( aResultFile, meshDS, theShape, aGHS3DPRLIdToNodeMap, GHS3DPRL_Out, _nodeRefNumber );
Ok = true;
- Ok = false; //but it is not a problem but if true my message is overwritten
fclose(aResultFile);
cout<<"GHS3DPRL OK output master file "<<casenamemed<<".xml exist !\n\n";
- pluginerror = pluginerror + "new tetraedra not in memory, but stored in files "+ casenamemed + "_*.med";
+ pluginerror = pluginerror + "MG-tetra_hpc mesh(es) not loaded in memory, are stored in files "+ casenamemed + "_*.med";
cout<<pluginerror<<endl;
- error(COMPERR_ALGO_FAILED, pluginerror.ToCString());
+ error(COMPERR_WARNING, pluginerror.ToCString() );
if (!_KeepFiles) system( run_nokeep_files.ToCString() );
}
else{
system( run_list_files.ToCString() );
cout<<endl;
}
- _countSubMesh=0;
-
return Ok;
}