From b7d9fb5b13780cceb64ba5f8e1bf660751ab69ce Mon Sep 17 00:00:00 2001
From: Wenqing Wang <wenqing.wang@ufz.de>
Date: Wed, 22 Jun 2016 10:38:19 +0200
Subject: [PATCH] [PMesh] Let mpmetis be called via system() and changed METIS
 repository.

---
 .gitmodules                                   |  2 +-
 .../PartitionMesh/CMakeLists.txt              | 40 ++++++++++--------
 .../PartitionMesh/MeshPartitioning.cpp        | 18 ++++----
 .../PartitionMesh/MetisSetup.cmake            |  2 +
 .../PartitionMesh/PartitionMesh.cpp           | 41 ++++++++-----------
 CMakeLists.txt                                |  4 ++
 ThirdParty/metis                              |  1 +
 scripts/cmake/SubmoduleSetup.cmake            |  6 +++
 8 files changed, 63 insertions(+), 51 deletions(-)
 create mode 160000 ThirdParty/metis

diff --git a/.gitmodules b/.gitmodules
index d5696e4418f..c6296f99e94 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -24,4 +24,4 @@
 	url = https://github.com/ufz/vtkGUISupportQt.git
 [submodule "ThirdParty/metis"]
 	path = ThirdParty/metis
-	url = https://github.com/envinf/metis.git
+	url = https://github.com/scibuilder/metis.git
diff --git a/Applications/Utils/ModelPreparation/PartitionMesh/CMakeLists.txt b/Applications/Utils/ModelPreparation/PartitionMesh/CMakeLists.txt
index 097b8707b57..f1c3a152bd7 100644
--- a/Applications/Utils/ModelPreparation/PartitionMesh/CMakeLists.txt
+++ b/Applications/Utils/ModelPreparation/PartitionMesh/CMakeLists.txt
@@ -1,23 +1,7 @@
 ###
 add_executable(partmesh PartitionMesh.cpp MeshPartitioning.h MeshPartitioning.cpp)
 set_target_properties(partmesh PROPERTIES FOLDER Utilities)
-target_link_libraries(partmesh FileIO)
-
-if(UTILS_PARTMESH_BUILD_WITH_METIS)
-	include_directories(${METIS_PATH}/libmetis)
-	include_directories(${METIS_PATH}/programs)
-
-	set(METIS_SOURCES
-	  ${METIS_PATH}/programs/mpmetis.c
-	  ${METIS_PATH}/programs/cmdline_mpmetis.c
-	  ${METIS_PATH}/programs/io.c
-	  ${METIS_PATH}/programs/stat.c
-	  metis_main.h
-	)
-	ADD_LIBRARY(METIS_Lib STATIC ${METIS_SOURCES} )
-
-	target_link_libraries(partmesh METIS_Lib metis)
-endif()
+target_link_libraries(partmesh MeshLib)
 
 ADD_VTK_DEPENDENCY(partmesh)
 
@@ -31,3 +15,25 @@ cpack_add_component(ogs_partmesh
 	DESCRIPTION "Mesh partitioning tool."
 	GROUP Utilities
 )
+
+## Compile mpmetis
+add_definitions(-DSVNINFO="${SVNREV}")
+include_directories(${METIS_PATH}/libmetis)
+include_directories(${METIS_PATH}/programs)
+set(METIS_SOURCES
+   ${METIS_PATH}/programs/mpmetis.c
+   ${METIS_PATH}/programs/cmdline_mpmetis.c
+   ${METIS_PATH}/programs/io.c
+   ${METIS_PATH}/programs/stat.c
+	)
+add_executable(mpmetis ${METIS_SOURCES})
+
+target_link_libraries(mpmetis metis)
+
+install(TARGETS mpmetis RUNTIME DESTINATION bin COMPONENT ogs_metis)
+
+cpack_add_component(ogs_metis
+	DISPLAY_NAME "mpmetis"
+	DESCRIPTION "METIS."
+	GROUP Utilities
+)
diff --git a/Applications/Utils/ModelPreparation/PartitionMesh/MeshPartitioning.cpp b/Applications/Utils/ModelPreparation/PartitionMesh/MeshPartitioning.cpp
index 7494757d141..f3719c3b4d2 100644
--- a/Applications/Utils/ModelPreparation/PartitionMesh/MeshPartitioning.cpp
+++ b/Applications/Utils/ModelPreparation/PartitionMesh/MeshPartitioning.cpp
@@ -30,7 +30,7 @@ void MeshPartitioning :: write2METIS(const std::string& file_name)
     os << _elements.size() <<" \n";
     for (const auto elem : _elements)
     {
-        for (unsigned j=0; j<elem->getNNodes(); j++)
+        for (unsigned j=0; j<elem->getNumberOfNodes(); j++)
         {
             os << elem->getNodeIndex(j) + 1 <<" ";
         }
@@ -192,7 +192,7 @@ void MeshPartitioning :: partitionByNodeMETIS(const std::string& file_name_base,
 
                 std::vector<unsigned> nonghost_nodes_local_ids;
                 unsigned ghost_counter = 0;
-                for (unsigned kk=0; kk<elem->getNNodes(); kk++)
+                for (unsigned kk=0; kk<elem->getNumberOfNodes(); kk++)
                 {
                     if (nodes_reseved[elem->getNodeIndex(kk)])
                     {
@@ -225,7 +225,7 @@ void MeshPartitioning :: partitionByNodeMETIS(const std::string& file_name_base,
         // Mark the non-ghost nodes for each ghost element
         for (const auto ghost_elem : partition_ghost_elements)
         {
-            for (unsigned k=0; k<ghost_elem->getNNodes(); k++)
+            for (unsigned k=0; k<ghost_elem->getNumberOfNodes(); k++)
                 nodes_reseved[ghost_elem->getNodeIndex(k)] = false;
 
             // Mark non-ghost nodes
@@ -236,7 +236,7 @@ void MeshPartitioning :: partitionByNodeMETIS(const std::string& file_name_base,
         // Add the ghost nodes to the node vector of this partition
         for (const auto ghost_elem : partition_ghost_elements)
         {
-            for (unsigned k=0; k<ghost_elem->getNNodes(); k++)
+            for (unsigned k=0; k<ghost_elem->getNumberOfNodes(); k++)
             {
                 const unsigned node_id = ghost_elem->getNodeIndex(k);
                 if (nodes_reseved[node_id])
@@ -279,13 +279,13 @@ void MeshPartitioning :: partitionByNodeMETIS(const std::string& file_name_base,
         PetscInt nmb_element_idxs = 3 * num_non_ghost_elems;
         for (PetscInt j=0; j<num_non_ghost_elems; j++)
         {
-            nmb_element_idxs += partition_regular_elements[j]->getNNodes();
+            nmb_element_idxs += partition_regular_elements[j]->getNumberOfNodes();
         }
         const PetscInt num_ghost_elems = partition_ghost_elements.size();
         PetscInt nmb_element_idxs_g = 3 * num_ghost_elems;
         for (PetscInt j=0; j<num_ghost_elems; j++)
         {
-            nmb_element_idxs_g += partition_ghost_elements[j]->getNNodes();
+            nmb_element_idxs_g += partition_ghost_elements[j]->getNumberOfNodes();
         }
 
         std::string ipart_str = std::to_string(ipart);
@@ -465,7 +465,7 @@ void MeshPartitioning::getElementIntegerVariables(const Element& elem,
         PetscInt& counter)
 {
     unsigned mat_id = 0; // Materical ID to be set from the mesh data
-    const PetscInt nn = elem.getNNodes();;
+    const PetscInt nn = elem.getNumberOfNodes();;
     elem_info[counter++] = mat_id;
     elem_info[counter++] = static_cast<unsigned>(getElementType(elem)) + 1;
     elem_info[counter++] = nn;
@@ -481,8 +481,8 @@ void MeshPartitioning::writeLocalElementNodeIndicies(std::ostream& os, const Ele
 {
     unsigned mat_id = 0; // Materical ID to be set from the mesh data
     os << mat_id << " " << static_cast<unsigned>(getElementType(elem)) + 1 << " "
-       << elem.getNNodes() <<" ";
-    for(unsigned i=0; i<elem.getNNodes(); i++)
+       << elem.getNumberOfNodes() <<" ";
+    for(unsigned i=0; i<elem.getNumberOfNodes(); i++)
     {
         os << local_node_ids[elem.getNodeIndex(i)] << " ";
     }
diff --git a/Applications/Utils/ModelPreparation/PartitionMesh/MetisSetup.cmake b/Applications/Utils/ModelPreparation/PartitionMesh/MetisSetup.cmake
index 9a0e5910b8f..e2a1aefa871 100644
--- a/Applications/Utils/ModelPreparation/PartitionMesh/MetisSetup.cmake
+++ b/Applications/Utils/ModelPreparation/PartitionMesh/MetisSetup.cmake
@@ -1,6 +1,8 @@
 MESSAGE( STATUS "The METIS package is copyrighted by the Regents of the University of Minnesota." )
 MESSAGE( STATUS "Please read the license of the METIS package carefully before you use the METIS." )
 
+set(METIS_PATH "${CMAKE_SOURCE_DIR}/ThirdParty/metis")
+
 add_definitions(-DUSE_GKREGEX)
 
 set(GKLIB_PATH "${METIS_PATH}/GKlib" CACHE PATH "path to GKlib")
diff --git a/Applications/Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp b/Applications/Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp
index 999ce5c412a..622e51f18d1 100644
--- a/Applications/Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp
+++ b/Applications/Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp
@@ -12,13 +12,8 @@
 
 */
 
-#include "tclap/CmdLine.h"
-
-#ifdef BUILD_WITH_METIS
-extern "C" {
-#include "metis_main.h"
-}
-#endif
+#include <sstream>
+#include <tclap/CmdLine.h>
 
 #include "Applications/ApplicationsLib/LogogSetup.h"
 #include "BaseLib/FileTools.h"
@@ -54,6 +49,8 @@ int main (int argc, char* argv[])
     TCLAP::SwitchArg ogs2metis_flag("1", "ogs2metis",
                                     "Indicator to convert the ogs mesh file to METIS input file", cmd, false);
 
+    TCLAP::SwitchArg exe_metis_flag("m","exe_metis","Call mpmetis inside the programme via system().", false);
+    cmd.add(exe_metis_flag);
     TCLAP::SwitchArg asci_flag("a","asci","Enable ASCII output.", false);
     cmd.add(asci_flag);
     TCLAP::SwitchArg elem_part_flag("e","element_wise","Enable element wise partitioing.", false);
@@ -70,7 +67,7 @@ int main (int argc, char* argv[])
     const std::string file_name_base = BaseLib::dropFileExtension(ifile_name);
     MeshLib::MeshPartitioning* mesh = static_cast<MeshLib::MeshPartitioning*>
                                       (MeshLib::IO::readMeshFromFile(file_name_base + ".vtu"));
-    INFO("Mesh read: %d nodes, %d elements.", mesh->getNNodes(), mesh->getNElements());
+    INFO("Mesh read: %d nodes, %d elements.", mesh->getNumberOfNodes(), mesh->getNumberOfElements());
 
     if (ogs2metis_flag.getValue())
     {
@@ -89,23 +86,17 @@ int main (int argc, char* argv[])
             const int num_partitions = nparts.getValue();
             std::string str_nparts = std::to_string(num_partitions);
 
-            // With the metis source code being compiled
-            if (num_partitions > 1)
+            // Execute mpmetis via system(...)
+            if (num_partitions > 1 && exe_metis_flag.getValue())
             {
-#ifdef BUILD_WITH_METIS
                 INFO("METIS is running ...");
-                const int argc_m = 4;
-                char *argv_m[argc_m];
-                std::string unsc = "-";	 // Avoid compilation warning by argv_m[0] = "-";
-                argv_m[0] = &unsc[0];
-                std::string option = "-gtype=nodal";
-                argv_m[1] = &option[0];
-                std::string part_mesh_file = file_name_base + ".mesh";
-                argv_m[2] = &part_mesh_file[0];
-                argv_m[3] = &str_nparts[0];
-
-                metis_main(argc_m, argv_m);
-#endif
+                std::stringstream ss;
+                ss << "mpmetis " << " -gtype=nodal "
+                   << file_name_base + ".mesh "
+                   << nparts.getValue();
+
+                int status = system(ss.str().c_str());
+                INFO("Return value of system calling %d ", status);
             }
 
             INFO("Partitioning the mesh in the node wise way ...");
@@ -123,5 +114,7 @@ int main (int argc, char* argv[])
     INFO( "Total runtime: %g s.\n", run_timer.elapsed() );
     INFO( "Total CPU time: %g s.\n", CPU_timer.elapsed() );
 
-    return 0;
+    delete mesh;
+
+    return EXIT_SUCCESS;
 }
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1396b488687..3faf588d928 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -150,6 +150,10 @@ if(OGS_BUILD_TESTS)
     set(Data_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/Tests/Data CACHE INTERNAL "")
 endif()
 
+if(OGS_BUILD_UTILS)
+    include(${CMAKE_SOURCE_DIR}/Applications/Utils/ModelPreparation/PartitionMesh/MetisSetup.cmake)
+endif()
+
 ######################
 ### Subdirectories ###
 ######################
diff --git a/ThirdParty/metis b/ThirdParty/metis
new file mode 160000
index 00000000000..0f44bee3cab
--- /dev/null
+++ b/ThirdParty/metis
@@ -0,0 +1 @@
+Subproject commit 0f44bee3cab5d5453d4fff7cd877c0d4b858f72b
diff --git a/scripts/cmake/SubmoduleSetup.cmake b/scripts/cmake/SubmoduleSetup.cmake
index 6a0c9d20625..5331d4cfcbf 100644
--- a/scripts/cmake/SubmoduleSetup.cmake
+++ b/scripts/cmake/SubmoduleSetup.cmake
@@ -12,12 +12,18 @@ set(REQUIRED_SUBMODULES
     ThirdParty/tetgen
     ${OGS_ADDITIONAL_SUBMODULES_TO_CHECKOUT}
 )
+
+
+
 if(OGS_BUILD_TESTS)
     list(APPEND REQUIRED_SUBMODULES Tests/Data)
 endif()
 if(OGS_BUILD_GUI)
     list(APPEND REQUIRED_SUBMODULES ThirdParty/vtkGUISupportQt)
 endif()
+if(OGS_BUILD_UTILS)
+    list(APPEND REQUIRED_SUBMODULES ThirdParty/metis)
+endif()
 
 foreach(SUBMODULE ${REQUIRED_SUBMODULES})
     execute_process(
-- 
GitLab