Salome HOME
proposal for plugin merge
[plugins/ghs3dplugin.git] / src / GHS3DPlugin / GHS3DPlugin_GHS3D.cxx
index b7b3109306d3b3b7c098e2dac32da08c8fd93335..b4e93a839684366538252b01abcfb0e963d92a91 100644 (file)
@@ -27,6 +27,7 @@
 #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>
@@ -1580,14 +1581,25 @@ static bool writeGMFFile(MG_Tetra_API*                                   MGInput
   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 );
@@ -1867,13 +1879,33 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   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() );
 
@@ -2083,6 +2115,274 @@ bool GHS3DPlugin_GHS3D::Compute(SMESH_Mesh&         theMesh,
   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;