#include "GHS3DPlugin_GHS3D.hxx"
#include "GHS3DPlugin_Hypothesis.hxx"
#include "MG_Tetra_API.hxx"
+#include "MG_TetraHPC_API.hxx"
#include <SMDS_FaceOfNodes.hxx>
#include <SMDS_LinearEdge.hxx>
return true;
}
+
//=============================================================================
/*!
*Here we are going to use the MG-Tetra mesher with geometry
*/
//=============================================================================
-
bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
- const TopoDS_Shape& theShape)
+ const TopoDS_Shape& theShape )
+{
+ bool isMGTetra = _hyp->GetAlgorithm() == GHS3DPlugin_Hypothesis::MGTetra;
+
+ if ( isMGTetra )
+ return ComputeMGTetra( theMesh, theShape );
+ else
+ return ComputeMGTetraHPC( theMesh, theShape );
+}
+
+bool GHS3DPlugin_GHS3D::ComputeMGTetra(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& theShape)
{
bool Ok(false);
TopExp_Explorer expBox ( theShape, TopAbs_SOLID );
return Ok;
}
+bool GHS3DPlugin_GHS3D::ComputeMGTetraHPC(SMESH_Mesh& theMesh,
+ const TopoDS_Shape& /*theShape*/)
+{
+ SMESH_MesherHelper helper( theMesh );
+ bool ok = ComputeMGTetraHPC( theMesh, &helper );
+ return ok;
+}
+
//=============================================================================
/*!
*Here we are going to use the MG-Tetra mesher w/o geometry
*/
-//=============================================================================
+//================================0=============================================
bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh& theMesh,
- SMESH_MesherHelper* theHelper)
+ SMESH_MesherHelper* theHelper )
+{
+ bool isMGTetra = _hyp->GetAlgorithm() == GHS3DPlugin_Hypothesis::MGTetra;
+
+ if ( isMGTetra )
+ return ComputeMGTetra( theMesh, theHelper );
+ else
+ return ComputeMGTetraHPC( theMesh, theHelper );
+
+}
+
+bool GHS3DPlugin_GHS3D::ComputeMGTetra(SMESH_Mesh& theMesh,
+ SMESH_MesherHelper* theHelper)
{
theHelper->IsQuadraticSubMesh( theHelper->GetSubShape() );
return Ok;
}
+//=============================================================================
+// Write a skin mesh into a GMF file or pass it to MG-TetraHPC API
+static void exportGMFHPC( 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 );
+}
+
+
+//=======================================================================
+//before launching salome
+//SALOME_TMP_DIR (for keep tepal intermediates files) could be set in user's directories
+static TCollection_AsciiString getTmpDir()
+{
+ TCollection_AsciiString aTmpDir;
+ char *Tmp_dir = getenv("SALOME_TMP_DIR");
+ if (Tmp_dir == NULL) Tmp_dir = getenv("TMP");
+ if(Tmp_dir != NULL)
+ {
+ aTmpDir = Tmp_dir;
+#ifdef WIN32
+ if(aTmpDir.Value(aTmpDir.Length()) != '\\') aTmpDir+='\\';
+#else
+ if(aTmpDir.Value(aTmpDir.Length()) != '/') aTmpDir+='/';
+#endif
+ }
+ else
+ {
+#ifdef WIN32
+ aTmpDir = TCollection_AsciiString("C:\\");
+#else
+ aTmpDir = TCollection_AsciiString("/tmp/");
+#endif
+ }
+ return aTmpDir;
+}
+
+bool GHS3DPlugin_GHS3D::ComputeMGTetraHPC(SMESH_Mesh& theMesh,
+ SMESH_MesherHelper* /*theHelper*/)
+{
+ bool Ok=false;
+ TCollection_AsciiString pluginerror("MG-TETRA_HPC: ");
+ SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
+ if ( theMesh.NbTriangles() == 0 )
+ return error( COMPERR_BAD_INPUT_MESH, "From MGTetra-HPC. No triangles in the mesh" );
+
+ if (_hyp == NULL){
+ pluginerror += "No existing parameters/hypothesis for MG-TETRA_HPC";
+ cout <<"\n"<<pluginerror<<"\n\n";
+ error(COMPERR_ALGO_FAILED, pluginerror.ToCString() );
+ return false;
+ }
+
+ // Not changing values
+ std::string _MEDName = "DOMAIN\0";
+ bool verbose = _hyp ? !_hyp->HasOptionDefined("verbose") : true;
+ bool proximity = _hyp->GetUseVolumeProximity();
+ bool _Multithread = _hyp->GetUseNumOfThreads();
+ double minSize = _hyp->GetMinSize();
+ double maxSize = _hyp->GetMaxSize();
+
+ TCollection_AsciiString
+ tmpDir = getTmpDir(),
+ GHS3DPRL_In,
+ GHS3DPRL_Out,
+ GHS3DPRL_Out_Mesh,
+ GHS3DPRL_Outxml,
+ logFileName,
+ rm("rm -f "),
+ run_nokeep_files,
+ NbPart,
+ fileskinmed(""),
+ path,
+ casenamemed; //_MEDName.c_str());
+
+ casenamemed += (char *)_MEDName.c_str();
+ int n = casenamemed.SearchFromEnd('/');
+
+ if (n>0) {
+ path=casenamemed.SubString(1,n);
+ casenamemed=casenamemed.SubString(n+1,casenamemed.Length());
+ }
+ else
+ path=tmpDir;
+
+ if (casenamemed.Length()>20){
+ casenamemed=casenamemed.SubString(1,20);
+ cerr<<"MEDName truncated (no more 20 characters) = "<<casenamemed<<endl;
+ }
+
+ _genericName = GHS3DPlugin_Hypothesis::GetFileNameHPC(_hyp);
+ TCollection_AsciiString aGenericName((char*) _genericName.c_str() );
+ GHS3DPRL_In = aGenericName + ".mesh";
+ GHS3DPRL_Out = path + casenamemed;
+ GHS3DPRL_Out_Mesh = aGenericName + "_out.mesh";
+ GHS3DPRL_Outxml = path + casenamemed + ".xml"; //master file
+ logFileName = aGenericName + ".log"; // MG library output
+ NbPart = 8;
+
+ run_nokeep_files = rm + GHS3DPRL_In + "* " + path + "tetrahpc.log";
+ system( run_nokeep_files.ToCString() ); //clean files
+ run_nokeep_files = rm + GHS3DPRL_In + "* ";
+ removeFile( GHS3DPRL_Outxml ); //only the master xml file
+
+ MG_TetraHPC_API mgTetraHPC( _computeCanceled, _progress );
+
+ cout << GHS3DPRL_In.ToCString() << endl;
+ exportGMFHPC( &mgTetraHPC, GHS3DPRL_In.ToCString(), meshDS );
+ cout << GHS3DPRL_In.ToCString() << endl;
+ // if ( true /*useLib*/ )
+ // {
+ TCollection_AsciiString cmd = TCollection_AsciiString();
+ std::string _AdvOptions;
+
+ if (_Multithread)
+ cmd += "mg-tetra_hpc.exe";
+ else
+ cmd = cmd + "mpirun --n " + NbPart + " mg-tetra_hpc_mpi.exe";
+
+ cmd = cmd + " --in=" + GHS3DPRL_In;
+
+ if (_Multithread)
+ {
+ cmd = cmd + " --max_number_of_threads " + SMESH_Comment( _hyp->GetNumOfThreads() );
+
+ const char* parallelMode[] = { "none", "reproducible_given_max_number_of_threads", "reproducible", "aggressive" };
+ const short myMode = _hyp->GetParallelMode();
+ if ( myMode >= 0 && myMode < 4 ) {
+ cmd += " --parallel_mode ";
+ cmd += parallelMode[ myMode ];
+ }
+ }
+
+ cmd = cmd + " --gradation " + SMESH_Comment( _hyp->GetGradation() );
+
+ const char* optimizationLevel[] = { "none" , "light" , "standard" , "standard+" , "strong" };
+ const short myOpt = _hyp->GetOptimizationLevel();
+ if ( myOpt >= 0 && myOpt < 5 && myOpt != 3 /*not standard+ for HPC*/) {
+ cmd += " --optimisation_level ";
+ cmd += optimizationLevel[ myOpt ];
+ }
+
+ if ( minSize > 0 ) cmd = cmd + " --min_size " + SMESH_Comment( minSize );
+ if ( maxSize > 0 ) cmd = cmd + " --max_size " + SMESH_Comment( maxSize );
+ if ( verbose ) cmd = cmd + " --verbose " + SMESH_Comment( _hyp->GetVerboseLevel() );
+ if ( proximity ) cmd = cmd + " --volume_proximity_layers " + SMESH_Comment( _hyp->GetNbVolumeProximityLayers() );
+
+ _hyp->SetAdvancedOptionsInCommandLine( _AdvOptions, false );
+ cmd = cmd + " " + _AdvOptions.c_str();
+ cmd = cmd + " --out=" + GHS3DPRL_Out_Mesh;
+ cmd = cmd + " 1>" + logFileName;
+
+ 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() );
+
+ std::string log;
+ Ok = mgTetraHPC.Compute( cmd.ToCString(), log );
+
+ if (!Ok)
+ {
+ std::cout << "Error: " << std::endl;
+ std::cout << log << std::endl;
+ // try to guess an error from the output log
+ std::string log2 = mgTetraHPC.GetLog();
+ if ( log2.find("Dlim" ) != std::string::npos ||
+ log2.find("License") != std::string::npos )
+ return error("License problem");
+ std::cout << log2 << std::endl;
+ if ( log2.find("You are using an empty MPI stubs library") != std::string::npos )
+ {
+ std:string msg = "You are using an empty MPI stubs library. Please build it first to be able to use mg-tetra_hpc_mpi.exe.\n";
+ msg += "./salome context\n";
+ msg += "cd $MESHGEMSHOME/stubs\n";
+ msg += "mpicc meshgems_mpi.c -DMESHGEMS_LINUX_BUILD -I../include -shared -fPIC -o $MESHGEMSHOME/lib/Linux_64/libmeshgems_mpi.so";
+ return error(msg);
+ }
+ return error(log);
+ }
+
+ if (!_Multithread)
+ {
+ fileskinmed=path + casenamemed + "_skin.med";
+ cout<<" Write file "<<fileskinmed<<"...";
+ theMesh.ExportMED(fileskinmed.ToCString(),"SKIN_INITIAL",true);
+ cout<<" ...done\n\n";
+ }
+
+ // Call to tetrahpc2med program is not defined here!
+ // Check the real need for calling this program in production!!!
+
+ // ... continue the original code!
+ if (_Multithread)
+ {
+ // check the med file has been created (only one med file, since multithread)
+ TCollection_AsciiString resuMedFile = TCollection_AsciiString(path) + casenamemed + "_1.med";
+ SMESH_File file( resuMedFile.ToCString() );
+ if (file.exists() && file.size() > 0)
+ {
+ Ok = true;
+ pluginerror = pluginerror + "MG-tetra_hpc mesh not loaded in memory, is stored in file "+ resuMedFile;
+ cout<<pluginerror<<endl;
+ error(COMPERR_WARNING, pluginerror.ToCString() );
+ if (!_keepFiles) system( run_nokeep_files.ToCString() );
+ }
+ }
+ else
+ {
+ // read a result, GHS3DPRL_Outxml is the name of master file (previous xml format)
+ FILE * aResultFile = fopen( GHS3DPRL_Outxml.ToCString(), "r" );
+ if (aResultFile){
+ Ok = true;
+ fclose(aResultFile);
+ cout<<"MG-TETRA_HPC OK output master file "<<casenamemed<<".xml exist !\n\n";
+ pluginerror = pluginerror + "MG-tetra_hpc meshes not loaded in memory, are stored in files "+ path + casenamemed + "_*.med";
+ cout<<pluginerror<<endl;
+ error(COMPERR_WARNING, pluginerror.ToCString() );
+ if (!_keepFiles) system( run_nokeep_files.ToCString() );
+ }
+ else{
+ Ok = false; //it is a problem AND my message is NOT overwritten
+ pluginerror = pluginerror + "output master file " + casenamemed + ".xml do not exist";
+ cout<<pluginerror<<endl;
+ error(COMPERR_ALGO_FAILED, pluginerror.ToCString() );
+ cout<<"MG-TETRA_HPC KO output files "<<GHS3DPRL_Out<<" do not exist ! see intermediate files kept:\n";
+ TCollection_AsciiString run_list_files("ls -alt ");
+ run_list_files += GHS3DPRL_Out + "* " + GHS3DPRL_In + "* " + logFileName;
+ system( run_list_files.ToCString() );
+ cout<<endl;
+ }
+ }
+ return Ok;
+}
+
void GHS3DPlugin_GHS3D::CancelCompute()
{
_computeCanceled = true;