]> SALOME platform Git repositories - plugins/gmshplugin.git/commitdiff
Salome HOME
[bos #38046] [EDF] (2023-T3) Stand alone and Remote versions for GMSH meshers.
authorcconopoima <cesar.conopoima@gmail.com>
Tue, 7 Nov 2023 20:16:03 +0000 (20:16 +0000)
committercesarconopoima <cesar.conopoima@opencascade.com>
Thu, 18 Jan 2024 10:37:48 +0000 (10:37 +0000)
Get created elements and nodes to write to binary file.

Remote version. Fill premeshed faces considering element orientation. Dumping created volumetric elements considering new nodes and old nodes from faces.

Intermermedial commit.

Code clean up.

Final tested version of GMSH_3D_Remote mesher.

15 files changed:
idl/GMSHPlugin_Algorithm.idl
src/GMSHPlugin/CMakeLists.txt
src/GMSHPlugin/GMSHPluginBuilder.py
src/GMSHPlugin/GMSHPlugin_GMSH_3D.cxx
src/GMSHPlugin/GMSHPlugin_GMSH_3D.hxx
src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote.cxx [new file with mode: 0644]
src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote.hxx [new file with mode: 0644]
src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote_i.cxx [new file with mode: 0644]
src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote_i.hxx [new file with mode: 0644]
src/GMSHPlugin/GMSHPlugin_GMSH_3D_SA.cxx [new file with mode: 0644]
src/GMSHPlugin/GMSHPlugin_GMSH_3D_SA.hxx [new file with mode: 0644]
src/GMSHPlugin/GMSHPlugin_Mesher.cxx
src/GMSHPlugin/GMSHPlugin_Mesher.hxx
src/GMSHPlugin/GMSHPlugin_Runner_main.cxx [new file with mode: 0644]
src/GMSHPlugin/GMSHPlugin_i.cxx

index cf0b5c37ebaef8192019c9ac30c85f706551ed19..be7e14e8ce815a576d54af7f56b1ec12478d9165 100644 (file)
@@ -46,6 +46,13 @@ module GMSHPlugin
   {
   };
 
+  /*!
+   * GMSHPlugin_GMSH: interface of "Gmsh" algorithm
+   */
+  interface GMSHPlugin_GMSH_3D_Remote : GMSHPlugin::GMSHPlugin_GMSH_3D
+  {
+  };
+
   /*!
    * GMSHPlugin_GMSH_2D: interface of "Gmsh_2D" algorithm
    */
index 92097da0eda7c15b94966e292162a9583eac71ce..4c6cabb23a9a5aba9f829d9c75912797d90b9db6 100644 (file)
@@ -29,10 +29,12 @@ INCLUDE_DIRECTORIES(
   ${MEDCOUPLING_INCLUDE_DIRS}
   ${Boost_INCLUDE_DIRS}
   ${OMNIORB_INCLUDE_DIR}
-  ${GMSH_INCLUDE_DIRS}
   ${PROJECT_BINARY_DIR}/idl
 )
 
+#Avoid compilation warnings from gmsh headers
+INCLUDE_DIRECTORIES( SYSTEM  ${GMSH_INCLUDE_DIRS} )
+
 # additional preprocessor / compiler flags
 ADD_DEFINITIONS(  
   ${OMNIORB_DEFINITIONS}
@@ -68,6 +70,9 @@ SET(GMSHEngine_HEADERS
   GMSHPlugin_GMSH_2D.hxx
   GMSHPlugin_GMSH_2D_i.hxx
   GMSHPlugin_GMSH_3D.hxx
+  GMSHPlugin_GMSH_3D_SA.hxx
+  GMSHPlugin_GMSH_3D_Remote.hxx
+  GMSHPlugin_GMSH_3D_Remote_i.hxx
   GMSHPlugin_GMSH_3D_i.cxx
   GMSHPlugin_GMSH.hxx
   GMSHPlugin_GMSH_i.hxx
@@ -88,6 +93,9 @@ SET(GMSHEngine_SOURCES
   GMSHPlugin_GMSH_2D.cxx
   GMSHPlugin_GMSH_2D_i.cxx
   GMSHPlugin_GMSH_3D.cxx
+  GMSHPlugin_GMSH_3D_SA.cxx
+  GMSHPlugin_GMSH_3D_Remote.cxx
+  GMSHPlugin_GMSH_3D_Remote_i.cxx
   GMSHPlugin_GMSH_3D_i.cxx
   GMSHPlugin_GMSH.cxx
   GMSHPlugin_GMSH_i.cxx
@@ -101,6 +109,10 @@ SET(GMSHEngine_SOURCES
   GMSHPlugin_i.cxx
 )
 
+SET(GmshRunner_SOURCES
+  GMSHPlugin_Runner_main.cxx
+)
+
 # --- scripts ---
 
 # scripts / static
@@ -115,6 +127,10 @@ ADD_LIBRARY(GMSHEngine ${GMSHEngine_SOURCES})
 TARGET_LINK_LIBRARIES(GMSHEngine ${_link_LIBRARIES} )
 INSTALL(TARGETS GMSHEngine EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
 
+ADD_EXECUTABLE(GMSHPlugin_Runner ${GmshRunner_SOURCES})
+TARGET_LINK_LIBRARIES(GMSHPlugin_Runner ${_link_LIBRARIES} GMSHEngine )
+INSTALL(TARGETS GMSHPlugin_Runner EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_BINS})
+
 INSTALL(FILES ${GMSHEngine_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
 
 SALOME_INSTALL_SCRIPTS("${_bin_SCRIPTS}" ${SALOME_INSTALL_PYTHON}/salome/GMSHPlugin)
index 80dfbad9a92bde905cb5f795d89ce541273c9a48..4717d38f19b40c6b1064139a7cc9c332d6c44d24 100644 (file)
@@ -37,6 +37,7 @@ except ImportError:
 GMSH = "GMSH"
 GMSH_3D       = "GMSH_3D"
 GMSH_2D       = "GMSH_2D"
+GMSH_3D_Remote = "GMSH_3D_Remote"
 
 ## Base of all GMSH algorithms.
 #
@@ -60,6 +61,8 @@ class GMSH_Algorithm(Mesh_Algorithm):
             hypType = "GMSH_Parameters"
         elif self.algoType == GMSH_3D:
             hypType = "GMSH_Parameters_3D"
+        elif self.algoType == GMSH_3D_Remote:
+            hypType = "GMSH_Parameters_3D"
 
         if self.params and self.params.GetName() != hypType:
             self.mesh.RemoveHypothesis( self.params, self.geom )
@@ -79,9 +82,18 @@ class GMSH_2D_Algorithm(GMSH_Algorithm):
 
 class GMSH_3D_Algorithm(GMSH_Algorithm):
     
-     meshMethod = "Tetrahedron"
-     algoType   = GMSH_3D
+    meshMethod = "Tetrahedron"
+    algoType   = GMSH_3D
+
+    ## Private constructor.
+    def __init__(self, mesh, geom=0):
+        GMSH_Algorithm.__init__(self, mesh, geom)
 
-     ## Private constructor.
-     def __init__(self, mesh, geom=0):
-         GMSH_Algorithm.__init__(self, mesh, geom)
+
+class GMSH_3D_Remote_Algorithm(GMSH_Algorithm):
+    meshMethod = "Tetrahedron"
+    algoType   = GMSH_3D_Remote
+
+    ## Private constructor.
+    def __init__(self, mesh, geom=0):
+        GMSH_Algorithm.__init__(self, mesh, geom)
\ No newline at end of file
index b132c540911c1af7c2d67975993b1caaa553c284..35a4406223787ad7a18354bf1e7643b74eaad3a0 100644 (file)
@@ -20,7 +20,6 @@
 //
 #include "GMSHPlugin_GMSH_3D.hxx"
 #include "GMSHPlugin_Hypothesis_2D.hxx"
-#include "GMSHPlugin_Mesher.hxx"
 
 #include <SMESH_Gen.hxx>
 #include <SMESH_ControlsDef.hxx>
@@ -74,7 +73,6 @@ bool GMSHPlugin_GMSH_3D::CheckHypothesis
                           SMESH_Hypothesis::Hypothesis_Status& aStatus)
 {
   MESSAGE("GMSHPlugin_GMSH::CheckHypothesis");
-  
   _hypothesis = NULL;
   
   const list<const SMESHDS_Hypothesis*>& hyps = GetUsedHypothesis(aMesh, aShape);
index c659ae9bcd2b9507e21623872a8b804058f762ea..f41d5460b7888a8a990e2b9ad1db0a1c55df8494 100644 (file)
@@ -22,6 +22,7 @@
 #define _GMSHPlugin_GMSH_3D_HXX_
 
 #include "GMSHPlugin_Defs.hxx"
+#include "GMSHPlugin_Mesher.hxx"
 
 #include "SMESH_Algo.hxx"
 #include "SMESH_subMesh.hxx"
diff --git a/src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote.cxx b/src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote.cxx
new file mode 100644 (file)
index 0000000..7635a9d
--- /dev/null
@@ -0,0 +1,379 @@
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//=============================================================================
+// File      : GMSHPlugin_GMSH_3D_Remote.hxx
+// Created   : 09 Septembre 2023
+// Author    : Cesar Conopoima (OCC)
+// Project   : SALOME
+//=============================================================================
+//
+//
+
+#include "GMSHPlugin_GMSH_3D_Remote.hxx"
+#include "GMSHPlugin_Hypothesis.hxx"
+#include "Utils_SALOME_Exception.hxx"
+
+#include <SMESH_Gen.hxx>
+#include <SMESH_Mesh.hxx>
+#include <SMESH_ParallelMesh.hxx>
+#include <SMESH_MesherHelper.hxx>
+#include <SMESH_DriverShape.hxx>
+#include <SMESH_DriverMesh.hxx>
+#include <SMESHDS_Mesh.hxx>
+#include <SMESH_MeshLocker.hxx>
+#include <SMESH_ProxyMesh.hxx>
+
+#include <TopoDS.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+
+#include <QString>
+#include <QProcess>
+
+#ifdef WIN32
+#include <filesystem>
+namespace fs = std::filesystem;
+#else
+#include <boost/filesystem.hpp>
+namespace fs = boost::filesystem;
+#endif
+
+//=============================================================================
+/*!
+ * Constructor
+ */
+//=============================================================================
+
+GMSHPlugin_GMSH_3D_Remote::GMSHPlugin_GMSH_3D_Remote(int hypId, SMESH_Gen * gen)
+  : GMSHPlugin_GMSH_3D(hypId, gen)
+{
+  _name = "GMSH_3D_Remote";
+}
+
+//=============================================================================
+/*!
+ * Destructor
+ */
+//=============================================================================
+
+GMSHPlugin_GMSH_3D_Remote::~GMSHPlugin_GMSH_3D_Remote()
+{
+}
+
+/**
+ * @brief Fill the structure netgen_param with the information from the hypothesis
+ *
+ * @param param_file name of the file to saven the gmsh parameter
+ * @param hyp the hypothesis
+ */
+void GMSHPlugin_GMSH_3D_Remote::exportGmshParams( const std::string param_file, const SMESHDS_Hypothesis* hyp )
+{
+  std::ofstream myfile(param_file);
+  if ( const GMSHPlugin_Hypothesis* gmshHypo = dynamic_cast<const GMSHPlugin_Hypothesis*>(hyp) )
+  {
+    myfile << 1 << std::endl; // Mark existence of correct hypothesis
+    myfile << (int) gmshHypo->Get2DAlgo()       << std::endl;
+    myfile << (int) gmshHypo->Get3DAlgo()       << std::endl;
+    myfile << (int) gmshHypo->GetRecomb2DAlgo() << std::endl;
+    myfile << (int) gmshHypo->GetRecombineAll() << std::endl;
+    myfile << (int) gmshHypo->GetSubdivAlgo()   << std::endl;
+    myfile << (int) gmshHypo->GetRemeshAlgo()   << std::endl;
+    myfile << (double) gmshHypo->GetSmouthSteps()  << std::endl;
+    myfile << (double) gmshHypo->GetSizeFactor()   << std::endl;
+#if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
+    myfile << (double) gmshHypo->GetMeshCurvatureSize()   << std::endl;
+#elif
+    myfile << -1.0   << std::endl; // dummy value writte for conformity
+#endif
+    myfile << (double) gmshHypo->GetMaxSize()     << std::endl;
+    myfile << (double) gmshHypo->GetMinSize()     << std::endl;
+    myfile << (int) gmshHypo->GetSecondOrder()    << std::endl;
+    myfile << (int) gmshHypo->GetUseIncomplElem() << std::endl;
+    if ( gmshHypo->GetCompoundOnEntries().size() > 0 )
+    {
+      TCompound defCompounds =  gmshHypo->GetCompoundOnEntries();
+      for (TCompound::const_iterator it = defCompounds.begin();  it != defCompounds.end(); ++it )
+      {
+        std::string token = (it !=--defCompounds.end()) ? "," : "";
+        myfile << *it << token;
+      }
+      myfile << std::endl;
+    }
+    else
+    {
+      myfile << 0 << std::endl; // mark the absence of compounds
+    }
+  }
+  else
+  {
+    //Mark tha absence of parameters in the file
+    myfile << 0 << std::endl;
+  }
+  myfile.close();
+}
+
+//
+
+/**
+ * @brief write in a binary file the orientation for each surface element of the mesh
+ *
+ * @param aMesh The mesh
+ * @param aShape the shape associated to the mesh
+ * @param output_file name of the binary file
+ */
+void GMSHPlugin_GMSH_3D_Remote::exportElementOrientation(SMESH_Mesh& aMesh,
+                                                          const TopoDS_Shape& aShape,
+                                                          const std::string output_file)
+{
+  SMESH_MesherHelper helper(aMesh);
+  SMESH_ProxyMesh::Ptr proxyMesh( new SMESH_ProxyMesh( aMesh ));
+  std::map<vtkIdType, bool> elemOrientation;
+
+  for ( TopExp_Explorer exFa( aShape, TopAbs_FACE ); exFa.More(); exFa.Next())
+  {
+    const TopoDS_Shape& aShapeFace = exFa.Current();
+    int faceID = aMesh.GetMeshDS()->ShapeToIndex( aShapeFace );
+    bool isRev = false;
+    if ( helper.NbAncestors(aShapeFace, aMesh, aShape.ShapeType()) > 1 )
+      // IsReversedSubMesh() can work wrong on strongly curved faces,
+      // so we use it as less as possible
+      isRev = helper.IsReversedSubMesh( TopoDS::Face( aShapeFace ));
+
+    const SMESHDS_SubMesh * aSubMeshDSFace = proxyMesh->GetSubMesh( aShapeFace );
+    if ( !aSubMeshDSFace ) continue;
+
+    SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
+
+    while ( iteratorElem->more() ) // loop on elements on a geom face
+    {
+      // check mesh face
+      const SMDS_MeshElement* elem = iteratorElem->next();
+      if ( !elem )
+        error( COMPERR_BAD_INPUT_MESH, "Null element encounters");
+      if ( elem->NbCornerNodes() != 3 )
+        error( COMPERR_BAD_INPUT_MESH, "Not triangle element encounters");
+      elemOrientation[elem->GetID()] = isRev;
+    } // loop on elements on a face
+  } // loop on faces of a SOLID or SHELL
+
+  {
+    std::ofstream df(output_file, ios::out|ios::binary);
+    int size = elemOrientation.size();
+    df.write((char*)&size, sizeof(int));
+    for(auto const& [id, orient]:elemOrientation)
+    {
+      df.write((char*)&id, sizeof(vtkIdType));
+      df.write((char*)&orient, sizeof(bool));
+    }
+    df.close();
+  }
+}
+
+/**
+ * @brief Compute mesh associate to shape
+ *
+ * @param aMesh The mesh
+ * @param aShape The shape
+ * @return true fi there are some error
+ */
+bool GMSHPlugin_GMSH_3D_Remote::Compute(SMESH_Mesh&         aMesh,
+                                           const TopoDS_Shape& aShape)
+{
+  {
+    SMESH_MeshLocker myLocker(&aMesh);
+    SMESH_Hypothesis::Hypothesis_Status hypStatus;
+    GMSHPlugin_GMSH_3D::CheckHypothesis(aMesh, aShape, hypStatus); //in this call the _hypothesis is defined!
+  }
+
+  SMESH_ParallelMesh& aParMesh = dynamic_cast<SMESH_ParallelMesh&>(aMesh);
+  // Temporary folder for run
+#ifdef WIN32
+  // On windows mesh does not have GetTmpFolder
+  fs::path tmp_folder = aParMesh.GetTmpFolder() / fs::path("Volume-%%%%-%%%%");
+#else
+  fs::path tmp_folder = aParMesh.GetTmpFolder() / fs::unique_path(fs::path("Volume-%%%%-%%%%"));
+#endif
+  fs::create_directories(tmp_folder);
+  // Using MESH2D generated after all triangles where created.
+  fs::path mesh_file= aParMesh.GetTmpFolder() / fs::path("Mesh2D.med");
+  fs::path element_orientation_file=tmp_folder / fs::path("element_orientation.dat");
+  fs::path new_element_file=tmp_folder / fs::path("new_elements.dat");
+  //fs::path tmp_mesh_file=tmp_folder / fs::path("tmp_mesh.med");
+  // Not used kept for debug
+  // fs::path output_mesh_file=tmp_folder / fs::path("output_mesh.med");
+  fs::path shape_file=tmp_folder / fs::path("shape.brep");
+  fs::path param_file=tmp_folder / fs::path("gmsh_param.txt");
+  fs::path log_file=tmp_folder / fs::path("run.log");
+  fs::path cmd_file=tmp_folder / fs::path("cmd.txt");  
+  
+  std::string mesh_name = "MESH";
+
+  {
+    SMESH_MeshLocker myLocker(&aMesh);
+    //Writing Shape
+    SMESH_DriverShape::exportShape(shape_file.string(), aShape);
+
+    //Writing hypothesis to file
+    exportGmshParams(param_file.string(), _hypothesis);
+
+    // Exporting element orientation
+    exportElementOrientation(aMesh, aShape, element_orientation_file.string());
+  }
+
+  // Calling run_mesher
+  // Path to mesher script
+  fs::path mesher_launcher = fs::path(std::getenv("SMESH_ROOT_DIR"))/
+       fs::path("bin")/
+       fs::path("salome")/
+       fs::path("mesher_launcher.py");
+
+  std::string s_program="python3";
+  std::list<std::string> params;
+  params.push_back(mesher_launcher.string());
+  params.push_back("GMSH3D");
+  params.push_back(mesh_file.string());
+  params.push_back(shape_file.string());
+  params.push_back(param_file.string());
+  params.push_back("--elem-orient-file=" + element_orientation_file.string());
+  params.push_back("--new-element-file=" + new_element_file.string());
+  // params.push_back("--output-mesh-file=" + output_mesh_file.string());
+
+   // Parallelism method parameters
+  int method = aParMesh.GetParallelismMethod();
+  if(method == ParallelismMethod::MultiThread){
+    params.push_back("--method=local");
+  } else if (method == ParallelismMethod::MultiNode){
+    params.push_back("--method=cluster");
+    params.push_back("--resource="+aParMesh.GetResource());
+    params.push_back("--wc-key="+aParMesh.GetWcKey());
+    params.push_back("--nb-proc=1");
+    params.push_back("--nb-proc-per-node="+std::to_string(aParMesh.GetNbProcPerNode()));
+    params.push_back("--nb-node="+std::to_string(aParMesh.GetNbNode()));
+    params.push_back("--walltime="+aParMesh.GetWalltime());
+  } else {
+    throw SALOME_Exception("Unknown parallelism method "+method);
+  }
+  
+  std::string cmd = "";
+  cmd += s_program;
+  for(auto arg: params){
+    cmd += " " + arg;
+  }
+  MESSAGE("Running command: ");
+  MESSAGE(cmd);
+  // Writing command in cmd.log
+  {
+    std::ofstream flog(cmd_file.string());
+    flog << cmd << endl;
+  }
+
+   // Building arguments for QProcess
+  QString program = QString::fromStdString(s_program);
+  QStringList arguments;
+  for(auto arg : params){
+    arguments << arg.c_str();
+  }
+
+  QString out_file = log_file.string().c_str();
+  QProcess myProcess;
+  // myProcess.setProcessChannelMode(QProcess::MergedChannels);
+  myProcess.setProcessChannelMode(QProcess::ForwardedChannels);
+  myProcess.setStandardOutputFile(out_file);
+
+  myProcess.start(program, arguments);
+  // Waiting for process to finish (argument -1 make it wait until the end of
+  // the process otherwise it just waits 30 seconds)
+  bool finished = myProcess.waitForFinished(-1);
+  int ret = myProcess.exitCode();
+  if(ret != 0 || !finished){
+    // Run crahed
+    std::string msg = "Issue with mesh_launcher: \n";
+    msg += "See log for more details: " + log_file.string() + "\n";
+    msg += cmd + "\n";
+    throw SALOME_Exception(msg);
+  }                 
+  {
+    SMESH_MeshLocker myLocker(&aMesh);
+    // Binary file written from SA version of the mesher
+    std::ifstream df(new_element_file.string(), ios::binary);
+
+    int numberOfNodes;
+    int totalNumberOfNodes;
+    int numberOfVolumes;
+    double meshNodes[3];
+    int    volNodes[4];
+    int nodeID;
+
+    SMESH_MesherHelper helper(aMesh);
+    // This function is mandatory for setElementsOnShape to work
+    helper.IsQuadraticSubMesh(aShape);
+    helper.SetElementsOnShape( true );
+
+    // Number of nodes in intial mesh
+    df.read((char*) &numberOfNodes, sizeof(int));
+    // Number of nodes added by netgen
+    df.read((char*) &totalNumberOfNodes, sizeof(int));
+    // Filling nodevec (correspondence netgen numbering mesh numbering)
+    std::vector< const SMDS_MeshNode* > nodeVec ( totalNumberOfNodes + 1 );
+    SMESHDS_Mesh * meshDS = helper.GetMeshDS();
+    for (int nodeIndex = 1 ; nodeIndex <= numberOfNodes; ++nodeIndex )
+    {
+      //Id of the point
+      df.read((char*) &nodeID, sizeof(int));
+      nodeVec.at(nodeIndex) = meshDS->FindNode(nodeID);
+    }
+
+    // Add new points and update nodeVec
+    for (int nodeIndex = numberOfNodes +1; nodeIndex <= totalNumberOfNodes; ++nodeIndex )
+    {
+      df.read((char *) &meshNodes, sizeof(double)*3);
+      nodeVec.at(nodeIndex) = helper.AddNode(meshNodes[0], meshNodes[1], meshNodes[2]);
+    }
+
+    // Add tetrahedrons
+    df.read((char*) &numberOfVolumes, sizeof(int));
+    for ( int elemIndex = 1; elemIndex <= numberOfVolumes; ++elemIndex )
+    {
+      df.read((char*) &volNodes, sizeof(int)*4);
+      auto n0 = meshDS->FindNode(nodeVec[volNodes[0]]->GetID());
+      auto n1 = meshDS->FindNode(nodeVec[volNodes[1]]->GetID());
+      auto n2 = meshDS->FindNode(nodeVec[volNodes[2]]->GetID());
+      auto n3 = meshDS->FindNode(nodeVec[volNodes[3]]->GetID());
+      if ( n0 && n1 && n2 && n3 )
+        helper.AddVolume( n0, n2, n1, n3 );      
+    }
+  }
+
+  return true;
+}
+
+/**
+ * @brief Assign submeshes to compute
+ *
+ * @param aSubMesh submesh to add
+ */
+void GMSHPlugin_GMSH_3D_Remote::setSubMeshesToCompute(SMESH_subMesh * aSubMesh)
+{
+  SMESH_MeshLocker myLocker(aSubMesh->GetFather());
+  SMESH_Algo::setSubMeshesToCompute(aSubMesh);
+}
diff --git a/src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote.hxx b/src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote.hxx
new file mode 100644 (file)
index 0000000..73265af
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//=============================================================================
+// File      : GMSHPlugin_GMSH_3D_Remote.hxx
+// Created   : 09 Septembre 2023
+// Author    : Cesar Conopoima (OCC)
+// Project   : SALOME
+//=============================================================================
+//
+#ifndef _GMSHPlugin_GMSH_3D_REMOTE_HXX_
+#define _GMSHPlugin_GMSH_3D_REMOTE_HXX_
+
+#include "GMSHPlugin_GMSH_3D.hxx"
+
+#include <vector>
+#include <map>
+
+class SMDS_MeshNode;
+
+class GMSHPLUGIN_EXPORT GMSHPlugin_GMSH_3D_Remote: public GMSHPlugin_GMSH_3D
+{
+ public:
+  GMSHPlugin_GMSH_3D_Remote(int hypId, SMESH_Gen* gen);
+  virtual ~GMSHPlugin_GMSH_3D_Remote();
+
+  // Function whould not be used with remote Computing
+  bool CheckHypothesis (SMESH_Mesh&         aMesh,
+                        const TopoDS_Shape& aShape,
+                        Hypothesis_Status&  aStatus) override {(void)aMesh;(void)aShape;aStatus = HYP_OK;return true;};
+
+  bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape) override;
+
+  void setSubMeshesToCompute(SMESH_subMesh * aSubMesh) override;
+
+
+ protected:
+  void exportElementOrientation(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, const std::string output_file);
+  void exportGmshParams( const std::string param_file,  const SMESHDS_Hypothesis* hyp );
+  typedef std::set<std::string> TCompound;
+};
+
+#endif
diff --git a/src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote_i.cxx b/src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote_i.cxx
new file mode 100644 (file)
index 0000000..0af0b86
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's classes
+//  File   : GMSHPlugin_GMSH_3D_Remote_i.cxx
+//  Author : Cesar Conopoima (OCC)
+//  Module : GMSHPlugin
+//  $Header$
+//
+#include "GMSHPlugin_GMSH_3D_Remote_i.hxx"
+#include "SMESH_Gen.hxx"
+
+#include "Utils_CorbaException.hxx"
+#include "utilities.h"
+
+//=============================================================================
+/*!
+ *  GMSHPlugin_GMSH_3D_Remote_i::GMSHPlugin_GMSH_3D_Remote_i
+ *
+ *  Constructor
+ */
+//=============================================================================
+
+GMSHPlugin_GMSH_3D_Remote_i::GMSHPlugin_GMSH_3D_Remote_i( PortableServer::POA_ptr thePOA,
+                                                    ::SMESH_Gen*            theGenImpl )
+     : SALOME::GenericObj_i( thePOA ),
+       SMESH_Hypothesis_i( thePOA ),
+       SMESH_Algo_i( thePOA ),
+       SMESH_3D_Algo_i( thePOA )
+{
+  myBaseImpl = new ::GMSHPlugin_GMSH_3D_Remote( theGenImpl->GetANewId(),
+                                                  theGenImpl );
+}
+
+//=============================================================================
+/*!
+ *  GMSHPlugin_GMSH_3D_Remote_i::~GMSHPlugin_GMSH_3D_Remote_i
+ *
+ *  Destructor
+ */
+//=============================================================================
+
+GMSHPlugin_GMSH_3D_Remote_i::~GMSHPlugin_GMSH_3D_Remote_i()
+{
+}
+
+//=============================================================================
+/*!
+ *  GMSHPlugin_GMSH_3D_Remote_i::GetImpl
+ *
+ *  Get implementation
+ */
+//=============================================================================
+
+::GMSHPlugin_GMSH_3D_Remote* GMSHPlugin_GMSH_3D_Remote_i::GetImpl()
+{
+  return ( ::GMSHPlugin_GMSH_3D_Remote* )myBaseImpl;
+}
+
diff --git a/src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote_i.hxx b/src/GMSHPlugin/GMSHPlugin_GMSH_3D_Remote_i.hxx
new file mode 100644 (file)
index 0000000..5d21549
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  SMESH SMESH_I : idl implementation based on 'SMESH' unit's classes
+//  File   : GMSHPlugin_GMSH_3D_Remote_i.hxx
+//  Author : Cesar Conopoima (OCC)
+//  Module : GMSHPlugin
+//  $Header$
+//
+#ifndef _GMSHPlugin_GMSH_3D_REMOTE_I_HXX_
+#define _GMSHPlugin_GMSH_3D_REMOTE_I_HXX_
+
+#include "GMSHPlugin_Defs.hxx"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(GMSHPlugin_Algorithm)
+
+#include "SMESH_3D_Algo_i.hxx"
+#include "GMSHPlugin_GMSH_3D_Remote.hxx"
+
+// ======================================================
+// GMSH 3d algorithm
+// ======================================================
+class GMSHPLUGIN_EXPORT GMSHPlugin_GMSH_3D_Remote_i:
+  public virtual POA_GMSHPlugin::GMSHPlugin_GMSH_3D_Remote,
+  public virtual SMESH_3D_Algo_i
+{
+public:
+  // Constructor
+  GMSHPlugin_GMSH_3D_Remote_i( PortableServer::POA_ptr thePOA,
+                            ::SMESH_Gen*            theGenImpl );
+  // Destructor
+  virtual ~GMSHPlugin_GMSH_3D_Remote_i();
+
+  // Get implementation
+  ::GMSHPlugin_GMSH_3D_Remote* GetImpl();
+};
+
+#endif
diff --git a/src/GMSHPlugin/GMSHPlugin_GMSH_3D_SA.cxx b/src/GMSHPlugin/GMSHPlugin_GMSH_3D_SA.cxx
new file mode 100644 (file)
index 0000000..e284ba0
--- /dev/null
@@ -0,0 +1,331 @@
+// Copyright (C) 2012-2015  ALNEOS
+// Copyright (C) 2016-2023  EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.alneos.com/ or email : contact@alneos.fr
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+#include "GMSHPlugin_GMSH_3D.hxx"
+#include "GMSHPlugin_GMSH_3D_SA.hxx"
+#include "GMSHPlugin_Hypothesis_2D.hxx"
+#include "GMSHPlugin_Mesher.hxx"
+
+#include <SMESH_Gen.hxx>
+#include <SMESH_ControlsDef.hxx>
+#include <SMESHDS_Mesh.hxx>
+#include <utilities.h>
+
+#include <list>
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+GMSHPlugin_GMSH_3D_SA::GMSHPlugin_GMSH_3D_SA()
+  : GMSHPlugin_GMSH_3D(0, new SMESH_Gen() )
+{
+  MESSAGE("GMSHPlugin_GMSH_3D_SA::GMSHPlugin_GMSH_3D_SA");
+  _name = "GMSH_3D_SA";
+}
+
+//=============================================================================
+/*!
+ *  
+ */
+//=============================================================================
+
+GMSHPlugin_GMSH_3D_SA::~GMSHPlugin_GMSH_3D_SA()
+{
+  MESSAGE("GMSHPlugin_GMSH_3D_SA::~GMSHPlugin_GMSH_3D_SA");
+}
+
+void GMSHPlugin_GMSH_3D_SA::importGMSHParameters( const std::string hypo_file )
+{
+  GMSHPlugin_Hypothesis * hypParameters = new GMSHPlugin_Hypothesis(0, GetGen());
+  std::ifstream myfile(hypo_file);
+  std::string line;
+
+  std::getline(myfile, line);
+  int hasParams = std::stoi(line);
+  if ( hasParams )
+  {
+    std::getline(myfile, line);
+    hypParameters->Set2DAlgo( (GMSHPlugin_Hypothesis::Algo2D)(std::stoi(line)) );
+    std::getline(myfile, line);
+    hypParameters->Set3DAlgo( (GMSHPlugin_Hypothesis::Algo3D)(std::stoi(line)) );
+    std::getline(myfile, line);
+    hypParameters->SetRecomb2DAlgo( (GMSHPlugin_Hypothesis::Recomb2DAlgo)(std::stoi(line)) );
+    std::getline(myfile, line);
+    hypParameters->SetRecombineAll( std::stoi(line) );  
+    std::getline(myfile, line);
+    hypParameters->SetSubdivAlgo( (GMSHPlugin_Hypothesis::SubdivAlgo)(std::stoi(line)) );  
+    std::getline(myfile, line);
+    hypParameters->SetRemeshAlgo( (GMSHPlugin_Hypothesis::RemeshAlgo)(std::stoi(line)) );
+    std::getline(myfile, line);
+    hypParameters->SetSmouthSteps( std::stod(line) );
+    std::getline(myfile, line);
+    hypParameters->SetSizeFactor( std::stod(line) );
+    std::getline(myfile, line);
+#if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=10
+    hypParameters->SetMeshCurvatureSize( std::stod(line) );
+#endif
+    std::getline(myfile, line);
+    hypParameters->SetMaxSize( std::stod(line) );
+    std::getline(myfile, line);
+    hypParameters->SetMinSize( std::stod(line) );
+    std::getline(myfile, line);
+    hypParameters->SetSecondOrder( std::stoi(line) );
+    std::getline(myfile, line);
+    hypParameters->SetUseIncomplElem( std::stoi(line) );
+    std::getline(myfile, line); // Get Compound names comma separated
+    if ( line != "0" ) // Mark no presence of groups
+    {
+      std::stringstream compoundLine (line);
+      std::string compound;
+      while ( std::getline (compoundLine, compound, ',') ) 
+        hypParameters->SetCompoundOnEntry( compound );
+    }
+    _hypothesis = dynamic_cast< const GMSHPlugin_Hypothesis *> (hypParameters);
+  } 
+  else
+  {
+    // in case the parameters are not defined the _hypothesis should remain undefined
+    // so default parameters are used to mesh!
+    // _hypothesis = NULL; 
+  }   
+}
+
+/**
+ * @brief Write a binary file containing information on the elements/nodes
+ *        created by the mesher
+ *
+ * @param nodeVec mapping between the mesh id and the netgen structure id
+ * @param mesher gmhsplugin mesher
+ * @param new_element_file Name of the output file
+ * @return true if there are some error
+ */
+void GMSHPlugin_GMSH_3D_SA::fillNewElementFile( std::vector< const SMDS_MeshNode* > &nodeVec, GMSHPlugin_Mesher &mesher, std::string new_element_file )
+{
+  GModel* gModel = mesher.GetGModel();
+  const int numberOfNodes = nodeVec.size() - 1;
+  const int numOfVolumens = gModel->getNumMeshElements( 3 );
+  int numberOfTotalNodes  = numberOfNodes;
+  std::map< MVertex *,int> nodeMap;
+  bool isOK = ( numOfVolumens > 0 );
+  if ( isOK && !new_element_file.empty() )
+  {
+    MESSAGE("Writting new elements");
+    
+    std::ofstream df(new_element_file, ios::out|ios::binary);
+    double points[3];
+    int    volumens[4];
+
+    df.write((char*) &numberOfNodes, sizeof(int));
+
+    // To get 3D elements we need to iterate in regions
+    std::map<int,MVertex*> vertexIdToCoordinate;
+    // Index nodes of new volumetric elements in order from the vol region
+    for ( GModel::riter it = gModel->firstRegion(); it != gModel->lastRegion(); ++it)
+    {
+      GRegion *gRegion = *it;
+      for( size_t i = 0; i < gRegion->mesh_vertices.size(); i++)
+      {
+        MVertex *v = gRegion->mesh_vertices[i];
+        const SMDS_MeshNode * preMeshedNode =  mesher.PremeshedNode( v );
+        if ( !preMeshedNode )
+        {
+          numberOfTotalNodes++;
+          vertexIdToCoordinate[ numberOfTotalNodes ] = v;
+          nodeMap.insert({ v, numberOfTotalNodes });
+        }           
+      }
+    }
+
+    df.write((char*) &numberOfTotalNodes, sizeof(int));
+
+    for (int nodeIndex = 1 ; nodeIndex <= numberOfNodes; ++nodeIndex )
+    {
+      //Id of the point
+      int id = nodeVec.at(nodeIndex)->GetID();
+      df.write((char*) &id, sizeof(int));
+    }
+        
+    // Writing info on new points
+    for (int nodeIndex = numberOfNodes+1; nodeIndex <= numberOfTotalNodes; ++nodeIndex )
+    {
+      if ( vertexIdToCoordinate[nodeIndex] )
+      {
+        df.write((char *) &vertexIdToCoordinate[nodeIndex]->x(), sizeof(double) );
+        df.write((char *) &vertexIdToCoordinate[nodeIndex]->y(), sizeof(double) );
+        df.write((char *) &vertexIdToCoordinate[nodeIndex]->z(), sizeof(double) );
+      }      
+    }
+
+    df.write((char*) &numOfVolumens, sizeof(int));
+    for ( GModel::riter it = gModel->firstRegion(); it != gModel->lastRegion(); ++it)
+    {
+      GRegion *gRegion = *it;
+      std::vector<MVertex*> verts;
+
+      for( size_t i = 0; i < gRegion->getNumMeshElements(); i++)
+      {
+        MElement *element = gRegion->getMeshElement(i);
+        verts.clear();
+        element->getVertices(verts);
+        for( MVertex* v : verts )
+        {
+          const SMDS_MeshNode * node = mesher.PremeshedNode( v );
+          auto it = find(nodeVec.begin(), nodeVec.end(), node ); 
+          int nodeId = node ? (it - nodeVec.begin()) : nodeMap[ v ];
+          df.write((char*) &nodeId, sizeof(int) );      
+        }
+      }               
+    }
+    df.close();
+  }
+}
+
+/**
+ * @brief Fill the list of elements in order and associate the read orientation (if any) to then. 
+ *        Index the elements and orientation to the ordered map so we are sure the write orientation 
+ *        match the element from the load mesh. IF no orientation file was written, then all the faces
+ *        of the read mesh match the face orientation of his original associated face
+ * @param aMesh the loaded mesh
+ * @param element_orientation_file name of the file where to read the orientation
+ * @param listElements the ordered map of elements with his orientation associated
+ * @return the listElements filled.
+ */
+void GMSHPlugin_GMSH_3D_SA::fillListOfElementsOriented( SMESH_Mesh& aMesh, std::string element_orientation_file, 
+                                                        std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements )
+{
+   
+  // fill the elements found in the surface to the listOfElements so it can be used by the mesher!
+  SMESHDS_Mesh* meshDS = aMesh.GetMeshDS();
+  std::map<vtkIdType, bool> elemOrientation;
+  {
+    // Setting all element orientation to false if there no element orientation file
+    if(element_orientation_file.empty())
+    {
+      SMDS_ElemIteratorPtr iteratorElem = meshDS->elementsIterator(SMDSAbs_Face);
+      while ( iteratorElem->more() ) // loop on elements on a geom face
+      {
+        // check mesh face
+        const SMDS_MeshElement* elem = iteratorElem->next();
+        listElements[elem] = false;
+      }
+    } 
+    else 
+    {
+      std::ifstream df(element_orientation_file, ios::binary|ios::in);
+      int nbElement;
+      bool orient;
+
+      vtkIdType id;
+      df.read((char*)&nbElement, sizeof(int));
+
+      for(int ielem=0;ielem<nbElement;++ielem){
+        df.read((char*) &id, sizeof(vtkIdType));
+        df.read((char*) &orient, sizeof(bool));
+        elemOrientation[id] = orient;
+      }
+      df.close();
+      //
+      SMDS_ElemIteratorPtr iteratorElem = meshDS->elementsIterator(SMDSAbs_Face);
+      while ( iteratorElem->more() ) // loop on elements on a geom face
+      {
+        // check mesh face
+        const SMDS_MeshElement* elem = iteratorElem->next();
+        // only index registered elements
+        bool isIn = elemOrientation.count(elem->GetID())==1;
+        if(!isIn) continue;
+        listElements[elem] = elemOrientation[elem->GetID()];
+      }
+    }
+  }  
+}
+
+
+/**
+ * @brief Compute the mesh by first filling premeshed faces to gmsh and then calling the mesher for the upper dimension
+ * @param aShape the loaded shape 
+ * @param aMesh the read Mesh (contain 2D elements covering the entire geometry)
+ * @param new_element_file output file containing info the elements created by the mesher
+ * @param element_orientation_file Binary file containing the orientation of surface elemnts
+ * @param output_mesh whether or not write the created elements into the mesh
+ * @return negation of mesh fail: true, false
+ * */
+bool GMSHPlugin_GMSH_3D_SA::Compute( TopoDS_Shape &aShape, SMESH_Mesh& aMesh, std::string new_element_file,
+                                      std::string element_orientation_file, bool output_mesh )
+{
+  GMSHPlugin_Mesher mesher(&aMesh, aShape,/*2d=*/false, true);
+  std::vector< const SMDS_MeshNode* > nodeVec; // to save premeshed elements
+  mesher.SetParameters(dynamic_cast<const GMSHPlugin_Hypothesis*>(_hypothesis));
+
+  std::map<const SMDS_MeshElement*, bool, TIDCompare> listElements;
+  fillListOfElementsOriented( aMesh, element_orientation_file, listElements );
+  bool Compute = mesher.Compute3D( nodeVec, listElements, output_mesh );
+  
+  fillNewElementFile( nodeVec, mesher, new_element_file );
+  mesher.finalizeGModel();
+  return Compute;
+}
+
+/**
+ * @brief Running the mesher on the given files
+ *
+ * @param input_mesh_file Mesh file (containing 2D elements)
+ * @param shape_file Shape file (BREP or STEP format)
+ * @param hypo_file Ascii file containing the gmsh parameters
+ * @param element_orientation_file Binary file containing the orientation of surface elements
+ * @param new_element_file output file containing info the elements created by the mesher
+ * @param output_mesh_file output mesh file (if empty it will not be created)
+ * @return int
+ */
+int GMSHPlugin_GMSH_3D_SA::run(const std::string input_mesh_file,
+                                const std::string shape_file,
+                                const std::string hypo_file,
+                                const std::string element_orientation_file,
+                                const std::string new_element_file,
+                                const std::string output_mesh_file)
+{
+  std::unique_ptr<SMESH_Mesh> myMesh(_gen->CreateMesh(false));
+
+  SMESH_DriverMesh::importMesh(input_mesh_file, *myMesh);
+
+  // Importing shape
+  TopoDS_Shape myShape;
+  SMESH_DriverShape::importShape(shape_file, myShape);
+
+  // Define _hypothesis to then be able to call SetParameters( hypothesis )
+  importGMSHParameters(hypo_file);
+
+  MESSAGE("Meshing with gmsh3d");
+  int ret = Compute(myShape, *myMesh, new_element_file, element_orientation_file, !output_mesh_file.empty());
+
+  if(ret){
+    std::cerr << "Meshing failed" << std::endl;
+    return ret;
+  }
+
+  if(!output_mesh_file.empty()){
+    std::string meshName = "MESH";
+    SMESH_DriverMesh::exportMesh(output_mesh_file, *myMesh, meshName);
+  }
+
+  return ret;
+}
\ No newline at end of file
diff --git a/src/GMSHPlugin/GMSHPlugin_GMSH_3D_SA.hxx b/src/GMSHPlugin/GMSHPlugin_GMSH_3D_SA.hxx
new file mode 100644 (file)
index 0000000..5d72a38
--- /dev/null
@@ -0,0 +1,57 @@
+// Copyright (C) 2012-2015  ALNEOS
+// Copyright (C) 2016-2023  EDF
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.alneos.com/ or email : contact@alneos.fr
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+#ifndef _GMSHPlugin_GMSH_3D_SA_HXX_
+#define _GMSHPlugin_GMSH_3D_SA_HXX_
+
+#include "GMSHPlugin_Defs.hxx"
+#include "GMSHPlugin_GMSH_3D.hxx"
+
+#include <SMESH_DriverShape.hxx>
+#include <SMESH_DriverMesh.hxx>
+
+#include "SMESH_Algo.hxx"
+#include "SMESH_subMesh.hxx"
+#include "SMESH_Mesh.hxx"
+
+class GMSHPLUGIN_EXPORT GMSHPlugin_GMSH_3D_SA: public GMSHPlugin_GMSH_3D
+{
+public:
+  GMSHPlugin_GMSH_3D_SA();
+  virtual ~GMSHPlugin_GMSH_3D_SA();
+
+  int run(const std::string input_mesh_file,
+          const std::string shape_file,
+          const std::string hypo_file,
+          const std::string element_orientation_file,
+          const std::string new_element_file,
+          const std::string output_mesh_file);
+
+  bool Compute( TopoDS_Shape &aShape, SMESH_Mesh& aMesh, std::string new_element_file, std::string element_orientation_file, bool output_mesh );
+
+private:
+  
+  void fillNewElementFile( std::vector< const SMDS_MeshNode* > &nodeVec, GMSHPlugin_Mesher &mesher, std::string new_element_file );
+  void importGMSHParameters( const std::string hypo_file );
+  void fillListOfElementsOriented(SMESH_Mesh& aMesh, std::string element_orientation_file, 
+                                  std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements );
+};
+
+#endif
index b51ed7761b8e55dfa1ad91e155cf61bda91ea1d1..8753e41ae8865064641575c19519df20e3a79f33 100644 (file)
@@ -43,6 +43,7 @@
 #include <vector>
 #include <limits>
 
+#include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopoDS.hxx>
 
@@ -241,6 +242,236 @@ void GMSHPlugin_Mesher::SetMaxThreadsGmsh()
 }
 #endif
 
+
+//================================================================================
+/*!
+ * \brief Check that the passed nodes are all IN the face
+ * \param element the element
+ * \param F the geom Face
+ * \param uvValues a vector of size elem->NbCornerNodes() to save the uv coordinate points on the face
+ * \return true if all the nodes are IN the face
+ */
+ //================================================================================
+bool GMSHPlugin_Mesher::IsAllNodesInSameFace( const SMDS_MeshElement* element, const TopoDS_Face& F, 
+                                                std::vector<gp_XY>& uvValues )
+{
+  Handle(ShapeAnalysis_Surface) sprojector = new ShapeAnalysis_Surface( BRep_Tool::Surface( F ));
+  double tol = BRep_Tool::MaxTolerance( F, TopAbs_FACE );
+  int nbN = element->NbCornerNodes();
+  gp_Pnt surfPnt(0,0,0);
+  for ( int i = 0; i < nbN; ++i )
+  {
+    SMESH_NodeXYZ nXYZ( element->GetNode( i ) );
+    gp_XY uv = sprojector->ValueOfUV( nXYZ, tol ).XY();
+    surfPnt = sprojector->Value( uv );
+    double dist = surfPnt.Distance( nXYZ );
+    if ( dist > tol )
+      return false;
+    else
+      uvValues[ i ] = uv;
+  }
+  return true;
+}
+
+//================================================================================
+/*!
+ * \brief Associate mesh elements to geometrical faces.
+ * \param the list of elements
+ * \return a map between faces (incremental order) and mesh elements found to be placed on the face
+ */
+ //================================================================================
+std::map<int,std::vector<std::tuple<smIdType,bool,std::vector<gp_XY>>>> GMSHPlugin_Mesher::AssociateElementsToFaces( std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements )
+{
+  // Map faces to elementId and uv of nodes.
+  // Index by face id
+  // Index vector with element smIdType, [ gp_XY_0, gp_XY_1, gp_XY_2 ]
+  std::map<int,std::vector<std::tuple<smIdType,bool,std::vector<gp_XY>>>> elementToFaceMap;
+  SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
+  SMDS_ElemIteratorPtr iteratorElem = meshDS->elementsIterator(SMDSAbs_Face);
+  for ( auto const& [elem, IsReverse] : listElements ) // loop on elements on a geom face
+  {  
+    int nbN = elem->NbCornerNodes();
+    std::vector<gp_XY> uvValues(nbN);
+    if ( nbN > 4 /*this restriction might be eliminated. Have to adapt FillGeomMapMeshUsing2DMeshIterator function too */)
+      throw std::string("Polygon sub-meshes not supported");
+
+    int faceId = 1;
+    for( GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it )
+    {
+      GFace *gFace = *it;
+      TopoDS_Face topoFace = *((TopoDS_Face*)gFace->getNativePtr());
+      if ( IsAllNodesInSameFace( elem, topoFace, uvValues ) )
+      {
+        elementToFaceMap[ faceId ].push_back( std::make_tuple( elem->GetID(), IsReverse, uvValues ) );     
+        break;
+      }
+      faceId++;
+    }
+  }
+  return elementToFaceMap;
+}
+
+//================================================================================
+/*!
+ * \brief Add the elements found associated to the face as gmsh elements
+ */
+ //================================================================================
+void GMSHPlugin_Mesher::Set2DMeshes( std::vector< const SMDS_MeshNode* >& nodeVec, std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements )
+{
+  std::map< const SMDS_MeshNode* , const MVertex * > nodes2mvertMap;
+  SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
+  auto elementToFaceMap = AssociateElementsToFaces( listElements );
+  int faceId = 1;
+  std::vector<MVertex *> mVertices;
+
+  for(GModel::fiter it = _gModel->firstFace(); it != _gModel->lastFace(); ++it)
+  {
+    GFace *gFace = *it;
+    gFace->deleteMesh();
+
+    auto element2uv = elementToFaceMap.find( faceId )->second;
+
+    const int numberOfEntries = element2uv.size();
+    
+    for (int el = 0; el < numberOfEntries; el++)
+    {
+      const smIdType elementId      = std::get<0>( element2uv[ el ] ); // smesh element id
+      bool isReverse                = std::get<1>( element2uv[ el ] );
+      const SMDS_MeshElement* elem = meshDS->FindElement( elementId );
+
+      int nbN = elem->NbCornerNodes();
+      mVertices.resize( nbN );
+
+      for ( int i = 0; i < nbN; ++i )
+      {
+        const SMDS_MeshNode* n = elem->GetNode( i );
+        MVertex *           mv = nullptr;
+        auto n2v = nodes2mvertMap.find( n );
+        if ( n2v != nodes2mvertMap.end() )
+        {
+          mv = const_cast< MVertex*>( n2v->second );
+        }
+        else
+        {
+          if ( n->GetPosition()->GetDim() < 2 )
+            throw std::string("Wrong mapping of edge nodes to GMSH nodes");
+          SMESH_NodeXYZ xyz = n;
+          gp_XY uv = std::get<2>(element2uv[ el ])[ i ];
+          mv = new MFaceVertex( xyz.X(), xyz.Y(), xyz.Z(), gFace, uv.X(), uv.Y() );
+          gFace->mesh_vertices.push_back( mv );
+          nodes2mvertMap.insert({ n, mv });
+          _nodeMap.insert      ({ mv, n });
+          _premeshednodeMap.insert({ mv, n });
+        }
+        mVertices[ i ] = mv;
+      }
+       // create GMSH mesh faces
+      switch ( nbN ) {
+      case 3:
+        if ( isReverse )
+          gFace->triangles.push_back (new MTriangle(mVertices[0], mVertices[2], mVertices[1]));
+        else
+          gFace->triangles.push_back (new MTriangle(mVertices[0], mVertices[1], mVertices[2]));
+        break;
+      case 4:
+        if ( isReverse )
+          gFace->quadrangles.push_back (new MQuadrangle(mVertices[0], mVertices[3],
+                                                        mVertices[2], mVertices[1]));
+        else
+          gFace->quadrangles.push_back (new MQuadrangle(mVertices[0], mVertices[1],
+                                                        mVertices[2], mVertices[3]));
+        break;
+      default:;
+      }
+    }        
+    faceId++; // face counter
+  } // iterator in the face
+
+  // Fill the node 
+  nodeVec.resize( nodes2mvertMap.size() + 1, 0 );
+  int count = 1;
+  for (auto k : nodes2mvertMap )
+  {
+    nodeVec[ count ] = k.first; // Index the node id to the smesh node itself        
+    count++;
+  }
+}
+
+
+//================================================================================
+/*!
+ * \brief Initialize GMSH model with mesh elements as geometry objects. 
+ *          Nodes are vertexes and element connections are geom lines
+ */
+ //================================================================================
+void GMSHPlugin_Mesher::FillGeomMapMeshUsing2DMeshIterator( std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements )
+{
+  gmsh::initialize();
+  gmsh::model::add("mesh");
+    // typedef for maps
+  typedef map< const SMDS_MeshNode*, int, TIDCompare > TNodeToIDMap;
+  typedef TNodeToIDMap::value_type                     TN2ID;
+  typedef map<std::pair<int, int>, int> TLineToIDMap;
+  TNodeToIDMap aNodeToID;
+  TLineToIDMap aLineToID;
+  
+  int aNbOfNodes = 0;
+  int aNbOfLines = 0;
+
+  const int invalid_ID = -1;
+  std::vector<int> aTrinagle( 3, 0 );
+  
+  // Playing around with SMESHDS_Mesh structure
+  SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
+
+  for ( auto const& [elem, IsReverse] : listElements ) // loop on elements on a geom face
+  {
+    if ( elem->NbCornerNodes() != 3 )
+      return;
+
+    for (int iN = 0; iN < 3; ++iN)
+    {
+      const SMDS_MeshNode* aNode = elem->GetNode(iN);
+      
+      int& ngID = aNodeToID.insert(TN2ID(aNode, invalid_ID)).first->second;
+      if (ngID == invalid_ID)
+      {
+        ngID = ++aNbOfNodes;
+        gmsh::model::occ::addPoint(aNode->X(), aNode->Y(), aNode->Z(), 1.e-2, ngID);
+      }
+
+      aTrinagle[ IsReverse ? 2 - iN : iN ] = ngID;
+    }
+    // add triangle
+    if ((aTrinagle[0] == aTrinagle[1] ||
+        aTrinagle[0] == aTrinagle[2] ||
+        aTrinagle[2] == aTrinagle[1]))
+      continue;
+    
+    std::vector<int> LinesID(3, 0);
+    for (int anIndex = 0; anIndex < 3; ++anIndex)
+    {
+      int aNextIndex = (anIndex + 1) % 3;
+      if (aLineToID.find({ aTrinagle[anIndex], aTrinagle[aNextIndex] }) == aLineToID.end()
+        && aLineToID.find({ aTrinagle[aNextIndex], aTrinagle[anIndex] }) == aLineToID.end())
+      {
+        LinesID[anIndex] = aLineToID.insert({ { aTrinagle[aNextIndex], aTrinagle[anIndex] }, ++aNbOfLines }).first->second;
+        gmsh::model::occ::addLine(aTrinagle[anIndex], aTrinagle[aNextIndex], LinesID[anIndex]);
+      }
+      else
+      {
+        LinesID[anIndex] = aLineToID.find({ aTrinagle[anIndex], aTrinagle[aNextIndex] })->second;
+        if (LinesID[anIndex] == 0)
+          LinesID[anIndex] = aLineToID.find({ aTrinagle[aNextIndex], aTrinagle[anIndex] })->second;
+
+      }
+    }
+    // if (!aProxyMesh->IsTemporary(ls.first))
+    //   swap(aTrinagle[1], aTrinagle[2]);
+    gmsh::model::occ::addCurveLoop(LinesID);
+  }
+}
+
 //================================================================================
 /*!
  * \brief Initialize GMSH model
@@ -254,7 +485,6 @@ void GMSHPlugin_Mesher::FillGMSHMesh()
   SMESHDS_Mesh* meshDS = _mesh->GetMeshDS();
 
   int aNbOfNodes = 0;
-  int aNbOfCurves = 0;
   int aNbOfLines = 0;
   std::vector<int> aTrinagle(3, 0);
 
@@ -284,7 +514,6 @@ void GMSHPlugin_Mesher::FillGMSHMesh()
   {
     const TopoDS_Shape& aShapeFace = exFa.Current();
     int faceID = meshDS->ShapeToIndex(aShapeFace);
-
     bool isRev = false;
     if (aCheckReverse && aHelper.NbAncestors(aShapeFace, *_mesh, _shape.ShapeType()) > 1)
       // IsReversedSubMesh() can work wrong on strongly curved faces,
@@ -292,8 +521,8 @@ void GMSHPlugin_Mesher::FillGMSHMesh()
       isRev = aHelper.IsReversedSubMesh(TopoDS::Face(aShapeFace));
 
     const SMESHDS_SubMesh* aSubMeshDSFace = aProxyMesh->GetSubMesh(aShapeFace);
-    if (!aSubMeshDSFace) continue;
-
+    if (!aSubMeshDSFace) 
+      continue;
     SMDS_ElemIteratorPtr iteratorElem = aSubMeshDSFace->GetElements();
     if (aHelper.IsQuadraticSubMesh(_shape) &&
       dynamic_cast<const SMESH_ProxyMesh::SubMesh*>(aSubMeshDSFace))
@@ -344,8 +573,8 @@ void GMSHPlugin_Mesher::FillGMSHMesh()
     // add triangle
     if (hasDegen && (aTrinagle[0] == aTrinagle[1] ||
       aTrinagle[0] == aTrinagle[2] ||
-      aTrinagle[2] == aTrinagle[1]))
-        continue;
+      aTrinagle[2] == aTrinagle[1]))      
+        continue;    
 
 
     std::vector<int> LinesID(3, 0);
@@ -369,7 +598,7 @@ void GMSHPlugin_Mesher::FillGMSHMesh()
     if (!aProxyMesh->IsTemporary(ls.first))
       swap(aTrinagle[1], aTrinagle[2]);
 
-    int aTag = gmsh::model::occ::addCurveLoop(LinesID);
+    gmsh::model::occ::addCurveLoop(LinesID);
   }
 
   // Generate 1D and 2D mesh
@@ -634,6 +863,22 @@ const SMDS_MeshNode* GMSHPlugin_Mesher::Node( const MVertex* v )
   return nullptr;
 }
 
+//================================================================================
+/*!
+ * \brief Get a node by a GMSH mesh vertex
+ */
+//================================================================================
+
+const SMDS_MeshNode* GMSHPlugin_Mesher::PremeshedNode( const MVertex* v )
+{
+  std::map< const MVertex *, const SMDS_MeshNode* >::iterator v2n = _premeshednodeMap.find( v );
+  if ( v2n != _premeshednodeMap.end() )
+    return v2n->second;
+
+  return nullptr;
+}
+
+
 //================================================================================
 /*!
  * \brief Return a corresponding sub-mesh if a shape is meshed
@@ -1308,6 +1553,66 @@ void  GMSHPlugin_Mesher::mymsg::operator()(std::string level, std::string msg)
   }
 }
 
+bool GMSHPlugin_Mesher::Compute3D( std::vector< const SMDS_MeshNode* >& nodeVec, std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements, bool addElements )
+{
+  MESSAGE("GMSHPlugin_Mesher::Compute3D");
+  int err = 0;
+  _maxThreads = 1;
+#if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=3
+  _maxThreads = 1;
+#endif
+
+  char* argv[] = {"-noenv"};
+  GmshInitialize(1,argv);
+  SetGmshOptions();
+  _gModel = new GModel();
+  mymsg msg(_gModel);
+  GmshSetMessageHandler(&msg);
+
+  _gModel->importOCCShape((void*)&_shape);
+  try
+  {
+    HideComputedEntities( _gModel, true );   
+    // fill geometry with elements as geom objects
+    FillGeomMapMeshUsing2DMeshIterator( listElements );
+    Set2DMeshes( nodeVec, listElements );
+    _gModel->mesh( /*dim=*/ 3);
+  }
+  catch (std::string& str)
+  {
+    err = 1;
+    MESSAGE(str);
+  }
+  catch (...)
+  {
+    err = 1;
+    MESSAGE("Unrecoverable error during Generation of Gmsh Mesh");
+  }
+
+  if (!err)
+  {
+#if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=8
+    if (_compounds.size() > 0)
+      SetCompoundMeshVisibility();
+#endif
+  }
+  
+  if ( addElements )
+    FillSMesh();
+  MESSAGE("GMSHPlugin_Mesher::Compute3D:End");
+  return err;
+}
+
+void GMSHPlugin_Mesher::finalizeGModel()
+{
+  if ( _gModel )
+  {
+    GmshSetMessageHandler(nullptr);
+    delete _gModel;
+    GmshFinalize();
+  }
+}
+
 //=============================================================================
 /*!
  * Here we are going to use the GMSH mesher
@@ -1339,15 +1644,12 @@ bool GMSHPlugin_Mesher::Compute()
     if (_is3d)
     {
       FillGMSHMesh();
-
       Set2DSubMeshes(_gModel);
-
       _gModel->mesh( /*dim=*/ 3);
     }
     else
     {
       //CTX::instance()->mesh.maxNumThreads1D=1;
-
       _gModel->mesh( /*dim=*/ 1);
 
       Set1DSubMeshes(_gModel);
@@ -1601,7 +1903,7 @@ void GMSHPlugin_Mesher::Set2DSubMeshes( GModel* gModel )
  */
 //================================================================================
 
-void GMSHPlugin_Mesher::HideComputedEntities( GModel* gModel )
+void GMSHPlugin_Mesher::HideComputedEntities( GModel* gModel, bool hideAnyway )
 {
   CTX::instance()->mesh.meshOnlyVisible = true;
 
@@ -1617,7 +1919,7 @@ void GMSHPlugin_Mesher::HideComputedEntities( GModel* gModel )
         continue;
 
     TopoDS_Edge topoEdge = *((TopoDS_Edge*)gEdge->getNativePtr());
-    if ( HasSubMesh( topoEdge ))
+    if ( HasSubMesh( topoEdge ) || hideAnyway )
       gEdge->setVisibility(0);
   }
 
@@ -1634,7 +1936,7 @@ void GMSHPlugin_Mesher::HideComputedEntities( GModel* gModel )
         continue;
 
     TopoDS_Face topoFace = *((TopoDS_Face*)gFace->getNativePtr());
-    if ( HasSubMesh( topoFace ))
+    if ( HasSubMesh( topoFace ) || hideAnyway )
       gFace->setVisibility(0);
   }
 }
index 062b31879de48627ca3d1af3ca341e4102108956..49b1bb26143984425b41037c806402469b754c29 100644 (file)
@@ -42,6 +42,7 @@
 #endif
 #include "MElement.h"
 
+#include <SMDS_MeshElement.hxx>
 #include "GMSHPlugin_Defs.hxx"
 #include "SMESH_Algo.hxx"
 
@@ -72,6 +73,9 @@ class GMSHPLUGIN_EXPORT GMSHPlugin_Mesher
 
   void SetParameters(const GMSHPlugin_Hypothesis*          hyp);
 
+  bool Compute3D( std::vector< const SMDS_MeshNode* >& nodeVec, 
+                  std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements, 
+                  bool addElements );
   bool Compute();
 
   bool Evaluate(MapShapeNbElems& aResMap);
@@ -79,6 +83,11 @@ class GMSHPLUGIN_EXPORT GMSHPlugin_Mesher
   static float DistBoundingBox(const SBoundingBox3d& bounds, const SPoint3& point);
 
   void FillGMSHMesh();
+  void FillGeomMapMeshUsing2DMeshIterator( std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements );
+  GModel* GetGModel(){ return _gModel;};
+  void finalizeGModel();
+  const SMDS_MeshNode* Node( const MVertex* v );
+  const SMDS_MeshNode* PremeshedNode( const MVertex* v );
 
  private:
   SMESH_Mesh*          _mesh;
@@ -108,18 +117,21 @@ class GMSHPLUGIN_EXPORT GMSHPlugin_Mesher
   std::set<std::string> _compounds;
 
   std::map< const MVertex *, const SMDS_MeshNode* > _nodeMap;
-
-  const SMDS_MeshNode* Node( const MVertex* v );
+  std::map< const MVertex *, const SMDS_MeshNode* > _premeshednodeMap; // used for the SA version
   SMESHDS_SubMesh* HasSubMesh( const TopoDS_Shape& s );
 
   void SetGmshOptions();
   void CreateGmshCompounds();
   void FillSMesh();
-  void HideComputedEntities( GModel* gModel );
+  void HideComputedEntities( GModel* gModel, bool hideAnyway = false );
   void RestoreVisibility( GModel* gModel );
   void Set1DSubMeshes( GModel* );
   void Set2DSubMeshes( GModel* );
   void toPython( GModel* );
+  bool IsAllNodesInSameFace( const SMDS_MeshElement* triangle, const TopoDS_Face& F, std::vector<gp_XY>& uvValues );
+  std::map<int,std::vector<std::tuple<smIdType,bool,std::vector<gp_XY>>>> AssociateElementsToFaces( std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements );
+  void Set2DMeshes( std::vector< const SMDS_MeshNode* >& nodeVec, std::map<const SMDS_MeshElement*, bool, TIDCompare>& listElements );
+
 #if GMSH_MAJOR_VERSION >=4 && GMSH_MINOR_VERSION >=3
   void SetMaxThreadsGmsh();
   void SetCompoundMeshVisibility();
diff --git a/src/GMSHPlugin/GMSHPlugin_Runner_main.cxx b/src/GMSHPlugin/GMSHPlugin_Runner_main.cxx
new file mode 100644 (file)
index 0000000..03046c4
--- /dev/null
@@ -0,0 +1,109 @@
+// Copyright (C) 2007-2023  CEA, EDF, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+//  File   : GMSHPlugin_Runner_main.cxx
+//  Author : Cesar Conopoima, Open Cascade
+//  Module : GMSH
+//
+
+#include "GMSHPlugin_GMSH_3D_SA.hxx"
+
+#include <stdio.h>
+#include <string.h>
+#include <iostream>
+#include <chrono>
+
+/**
+ * @brief Main function
+ *
+ * @param argc Number of arguments
+ * @param argv Arguments
+ *
+ * @return error code
+ */
+int main(int argc, char *argv[]){
+
+  if(argc!=8||(argc==2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help")==0))){
+    std::cout << "Error in number of arguments "<< argc-1<<" given expected 7" <<std::endl;
+    std::cout << "Syntax:"<<std::endl;
+    std::cout << "run_mesher MESHER INPUT_MESH_FILE SHAPE_FILE HYPO_FILE" << std::endl;
+    std::cout << "           ELEM_ORIENT_FILE " << std::endl;
+    std::cout << "           NEW_ELEMENT_FILE OUTPUT_MESH_FILE" << std::endl;
+    std::cout << std::endl;
+    std::cout << " Set argument to NONE to ignore them " << std::endl;
+    std::cout << std::endl;
+    std::cout << "Args:" << std::endl;
+    std::cout << "  MESHER: mesher to use from (NETGEN3D, NETGEN2D)" << std::endl;
+    std::cout << "  INPUT_MESH_FILE: MED File containing lower-dimension-elements already meshed" << std::endl;
+    std::cout << "  SHAPE_FILE: STEP file containing the shape to mesh" << std::endl;
+    std::cout << "  HYPO_FILE: Ascii file containint the list of parameters" << std::endl;
+    std::cout << "  (optional) ELEM_ORIENT_FILE: binary file containing the list of element from INPUT_MESH_FILE associated to the shape and their orientation" << std::endl;
+    std::cout << "  (optional) NEW_ELEMENT_FILE: (out) contains elements and nodes added by the meshing" << std::endl;
+    std::cout << "  (optional) OUTPUT_MESH_FILE: (out) MED File containing the mesh after the run of the mesher" << std::endl;
+    return 1;
+  }
+  std::string mesher=argv[1];
+  std::string input_mesh_file=argv[2];
+  std::string shape_file=argv[3];
+  std::string hypo_file=argv[4];
+  std::string element_orientation_file=argv[5];
+  std::string new_element_file=argv[6];
+  std::string output_mesh_file=argv[7];
+
+  //std::string thing;
+  //std::cin >> thing;
+
+  if (output_mesh_file == "NONE")
+    output_mesh_file = "";
+  if (element_orientation_file == "NONE")
+    element_orientation_file = "";
+  if (new_element_file == "NONE")
+    new_element_file = "";
+
+  std::cout << mesher << "\n";
+  std::cout << input_mesh_file << "\n";
+  std::cout << shape_file << "\n";
+  std::cout << hypo_file << "\n";
+  std::cout << element_orientation_file << "\n";
+  std::cout << new_element_file << "\n";
+  std::cout << output_mesh_file << "\n";
+  
+  if (mesher=="GMSH3D"){
+    GMSHPlugin_GMSH_3D_SA myplugin;
+    std::cout << input_mesh_file << "\n";
+    std::cout << shape_file << "\n";
+    std::cout << hypo_file << "\n";
+    std::cout << new_element_file << "\n";
+    std::cout << output_mesh_file << "\n";
+    int run = myplugin.run(input_mesh_file,
+                            shape_file,
+                            hypo_file,
+                            element_orientation_file,
+                            new_element_file,
+                            output_mesh_file );
+  }  
+  else {
+    std::cerr << "Unknown mesher:" << mesher << std::endl;
+    return 1;
+  }
+  return 0;
+}
index c49edcc3e8cb3bc5bc343b2ae972e8c83fc10fdd..2682e5518858c5183346e45f350bc862ef7e3735 100644 (file)
@@ -26,6 +26,7 @@
 #include "GMSHPlugin_GMSH_i.hxx"
 #include "GMSHPlugin_GMSH_2D_i.hxx"
 #include "GMSHPlugin_GMSH_3D_i.hxx"
+#include "GMSHPlugin_GMSH_3D_Remote_i.hxx"
 
 template <class T> class GMSHPlugin_Creator_i:public HypothesisCreator_i<T>
 {
@@ -57,6 +58,8 @@ extern "C"
       aCreator = new GMSHPlugin_Creator_i<GMSHPlugin_GMSH_2D_i>;
     else if (strcmp(aHypName, "GMSH_3D") == 0)
       aCreator = new GMSHPlugin_Creator_i<GMSHPlugin_GMSH_3D_i>;
+    else if (strcmp(aHypName, "GMSH_3D_Remote") == 0)
+      aCreator = new GMSHPlugin_Creator_i<GMSHPlugin_GMSH_3D_Remote_i>;
     // Hypotheses
     else if (strcmp(aHypName, "GMSH_Parameters") == 0)
       aCreator = new GMSHPlugin_Creator_i<GMSHPlugin_Hypothesis_i>;