Salome HOME
Convert .mesh to .med in multithread as before. But don't create joints and xml files...
[plugins/ghs3dprlplugin.git] / src / GHS3DPRLPlugin / GHS3DPRLPlugin_GHS3DPRL.cxx
index 2705370cfcdcacc041c5a020f17d22428e7f61ea..8c0f78d90e7bdc68d7260a902dd61a14b7b4dade 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2020  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
@@ -31,6 +31,7 @@
 #include <SMESH_TypeDefs.hxx>
 #include <SMESH_subMesh.hxx>
 #include <SMESH_MesherHelper.hxx>
+#include <SMESH_File.hxx>
 
 #include "utilities.h"
 
@@ -57,7 +58,7 @@ 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");
   }
 }
@@ -207,7 +208,7 @@ static void exportGMF(MG_TetraHPC_API*    theTetraInput,
 //=============================================================================
 // 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)
+                                      const TopoDS_Shape& /*theShape*/)
 {
   SMESH_MesherHelper helper( theMesh );
   bool ok = Compute( theMesh, &helper );
@@ -217,16 +218,16 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
 //=============================================================================
 // 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)
+                                      SMESH_MesherHelper* /*theHelper*/)
 {
   bool Ok=false;
-  TCollection_AsciiString pluginerror("ghs3dprl: ");
+  TCollection_AsciiString pluginerror("MG-TETRA_HPC: ");
   SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
   if ( theMesh.NbTriangles() == 0 )
     return error( COMPERR_BAD_INPUT_MESH, "No triangles in the mesh" );
 
   if (_hypothesis==NULL){
-    pluginerror += "No existing parameters/hypothesis for GHS3DPRL";
+    pluginerror += "No existing parameters/hypothesis for MG-TETRA_HPC";
     cout <<"\n"<<pluginerror<<"\n\n";
     error(COMPERR_ALGO_FAILED, pluginerror.ToCString() );
     return false;
@@ -279,11 +280,13 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
 
   map <int,int> aSmdsToGHS3DPRLIdMap;
   map <int,const SMDS_MeshNode*> aGHS3DPRLIdToNodeMap;
-  GHS3DPRL_In = path + "GHS3DPRL";
+  _genericName = GHS3DPRLPlugin_Hypothesis::GetFileName(_hypothesis);
+  TCollection_AsciiString aGenericName((char*) _genericName.c_str() );
+  GHS3DPRL_In = aGenericName + ".mesh";
   GHS3DPRL_Out = path + casenamemed;
-  GHS3DPRL_Out_Mesh = path + casenamemed + "_out.mesh";
+  GHS3DPRL_Out_Mesh = aGenericName + "_out.mesh";
   GHS3DPRL_Outxml = path + casenamemed + ".xml"; //master file
-  logFileName = path + casenamemed + ".log"; // MG library output
+  logFileName = aGenericName + ".log"; // MG library output
   NbPart=_NbPart;
   Gradation=_Gradation;
   MinSize=_MinSize;
@@ -295,7 +298,7 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
   //             --verbose=0 --menu=no --launchtetra=yes;
 
   run_GHS3DPRL = run_GHS3DPRL +
-    " --casename=" + GHS3DPRL_In +
+    " --casename=" + aGenericName +
     " --number=" + NbPart +
     " --medname=" + GHS3DPRL_Out +
     " --launchtetra=yes" +
@@ -310,8 +313,6 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
   system( run_nokeep_files.ToCString() ); //clean files
   run_nokeep_files = rm + GHS3DPRL_In + "* ";
 
-  fileskinmesh=path + "GHS3DPRL.mesh";
-  GHS3DPRL_Out = path + casenamemed;
   removeFile( GHS3DPRL_Outxml ); //only the master xml file
 
   MG_TetraHPC_API mgTetraHPC( _computeCanceled, _progress );
@@ -319,30 +320,54 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
   if ( !useLib )
     mgTetraHPC.SetUseExecutable();
 
-  exportGMF( &mgTetraHPC, fileskinmesh.ToCString(), meshDS );
+  exportGMF( &mgTetraHPC, GHS3DPRL_In.ToCString(), meshDS );
 
-  if ( useLib )
+  if ( true /*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();
+    TCollection_AsciiString cmd = TCollection_AsciiString();
+    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=" + NbPart;
+    cmd = cmd + " --gradation=" + Gradation;
+    cmd = cmd + " --min_size=" + MinSize;
+    cmd = cmd + " --max_size=" + MaxSize;
+    cmd = cmd + " --verbose=3";
+    cmd = cmd + " --out=" + GHS3DPRL_Out_Mesh;
+    cmd = cmd + " " + _AdvOptions.c_str();
+    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() );
 
-    mgTetraHPC.Compute( cmd.ToCString() );
+    std::string log;
+    Ok = mgTetraHPC.Compute( cmd.ToCString(), log );
 
-    std::string log = mgTetraHPC.GetLog();
-    if ( log.find(" Dlim "   ) != std::string::npos ||
-         log.find(" license ") != std::string::npos )
-      return error("License problem");
+    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("icense") != 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);
+    }
 
     // set --launchtetra=no
     int yesPos = run_GHS3DPRL.Search("launchtetra") + sizeof("launchtetra");
@@ -355,56 +380,79 @@ bool GHS3DPRLPlugin_GHS3DPRL::Compute(SMESH_Mesh&         theMesh,
     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);
-  cout<<" ...done\n\n";
 
-  cout<<"GHS3DPRL command :\n  "<<run_GHS3DPRL.ToCString()<<endl;
+  if (!_Multithread)
+  {
+    fileskinmed=path + casenamemed + "_skin.med";
+    cout<<"  Write file "<<fileskinmed<<"...";
+    theMesh.ExportMED(fileskinmed.ToCString(),"SKIN_INITIAL",true);
+    cout<<" ...done\n\n";
+  }
+
+  // convert .mesh (one or several) to med file(s) with xml master file if mpi
+  cout<<"Mesh conversion command :\n  "<<run_GHS3DPRL.ToCString()<<endl;
   //sometimes it is better to wait flushing files on slow filesystem...
-  system( "sleep 3" );
+  //   system( "sleep 3" );
   //launch tetrahpc2med which launch mg-tetra_hpc.py which launch mg-tetra_hpc(_mpi?).exe
   res = system( run_GHS3DPRL.ToCString() );
-  if (res > 0) 
+  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" );
+  //system( "sleep 3" );
 
   if (_Background) {
-    pluginerror = pluginerror + "backgrounding... plugin is not waiting for output files "+ casenamemed + "_*.med";
+    pluginerror = pluginerror + "backgrounding... plugin is not waiting for output files "+ path +casenamemed + "_*.med";
     cout<<pluginerror<<endl;
     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 = true;
-    fclose(aResultFile);
-    cout<<"GHS3DPRL OK output master file "<<casenamemed<<".xml exist !\n\n";
-    pluginerror = pluginerror + "MG-tetra_hpc mesh(es) not loaded in memory, are stored in files "+ casenamemed + "_*.med";
-    cout<<pluginerror<<endl;
-    error(COMPERR_WARNING, pluginerror.ToCString() );
-    if (!_KeepFiles) system( run_nokeep_files.ToCString() );
+  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{
-    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<<"GHS3DPRL KO output files "<<GHS3DPRL_Out<<" do not exist ! see intermediates files keeped:\n";
-    TCollection_AsciiString run_list_files("ls -alt ");
-    run_list_files +=  GHS3DPRL_Out + "* " + GHS3DPRL_In + "* " + path + "tetrahpc.log";
-    system( run_list_files.ToCString() );
-    cout<<endl;
+  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;
 }
 
@@ -419,7 +467,7 @@ bool GHS3DPRLPlugin_GHS3DPRL::Evaluate(SMESH_Mesh& aMesh,
                                        const TopoDS_Shape& aShape,
                                        MapShapeNbElems& aResMap)
 {
-  int nbtri = 0, nbqua = 0;
+  smIdType nbtri = 0, nbqua = 0;
   double fullArea = 0.0;
   for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) {
     TopoDS_Face F = TopoDS::Face( exp.Current() );
@@ -431,9 +479,9 @@ bool GHS3DPRLPlugin_GHS3DPRL::Evaluate(SMESH_Mesh& aMesh,
                                             "Submesh can not be evaluated",this));
       return false;
     }
-    std::vector<int> aVec = (*anIt).second;
-    nbtri += Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
-    nbqua += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
+    std::vector<smIdType> aVec = (*anIt).second;
+    nbtri += std::max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]);
+    nbqua += std::max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]);
     GProp_GProps G;
     BRepGProp::SurfaceProperties(F,G);
     double anArea = G.Mass();
@@ -441,7 +489,7 @@ bool GHS3DPRLPlugin_GHS3DPRL::Evaluate(SMESH_Mesh& aMesh,
   }
 
   // collect info from edges
-  int nb0d_e = 0, nb1d_e = 0;
+  smIdType nb0d_e = 0, nb1d_e = 0;
   bool IsQuadratic = false;
   bool IsFirst = true;
   TopTools_MapOfShape tmpMap;
@@ -452,9 +500,9 @@ bool GHS3DPRLPlugin_GHS3DPRL::Evaluate(SMESH_Mesh& aMesh,
     tmpMap.Add(E);
     SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current());
     MapShapeNbElemsItr anIt = aResMap.find(aSubMesh);
-    std::vector<int> aVec = (*anIt).second;
+    std::vector<smIdType> aVec = (*anIt).second;
     nb0d_e += aVec[SMDSEntity_Node];
-    nb1d_e += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
+    nb1d_e += std::max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]);
     if(IsFirst) {
       IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]);
       IsFirst = false;
@@ -469,11 +517,11 @@ bool GHS3DPRLPlugin_GHS3DPRL::Evaluate(SMESH_Mesh& aMesh,
   double aVolume = G.Mass();
   double tetrVol = 0.1179*ELen*ELen*ELen;
   double CoeffQuality = 0.9;
-  int nbVols = (int)aVolume/tetrVol/CoeffQuality;
-  int nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
-  int nb1d_in = (int) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
-  std::vector<int> aVec(SMDSEntity_Last);
-  for(int i=0; i<SMDSEntity_Last; i++) aVec[i]=0;
+  smIdType nbVols = (smIdType)aVolume/tetrVol/CoeffQuality;
+  smIdType nb1d_f = (nbtri*3 + nbqua*4 - nb1d_e) / 2;
+  smIdType nb1d_in = (smIdType) ( nbVols*6 - nb1d_e - nb1d_f ) / 5;
+  std::vector<smIdType> aVec(SMDSEntity_Last);
+  for(smIdType i=0; i<SMDSEntity_Last; i++) aVec[i]=0;
   if( IsQuadratic ) {
     aVec[SMDSEntity_Node] = nb1d_in/6 + 1 + nb1d_in;
     aVec[SMDSEntity_Quad_Tetra] = nbVols - nbqua*2;