From e4ea829c35ade0209197170d846b53e4b717ed9b Mon Sep 17 00:00:00 2001
From: "Praetorius, Simon" <simon.praetorius@tu-dresden.de>
Date: Thu, 22 Aug 2019 08:46:52 +0200
Subject: [PATCH] Feature/petsc cmake

---
 cmake/modules/AmdisMacros.cmake            | 23 ++++--
 cmake/modules/FindPETSc.cmake              | 92 ++++++++++++++++++++++
 cmake/modules/PkgConfigLinkLibraries.cmake | 56 +++++++++++++
 config.h.cmake                             |  7 +-
 src/amdis/Environment.cpp                  | 21 ++++-
 src/amdis/Environment.hpp                  | 12 +++
 6 files changed, 201 insertions(+), 10 deletions(-)
 create mode 100644 cmake/modules/FindPETSc.cmake
 create mode 100644 cmake/modules/PkgConfigLinkLibraries.cmake

diff --git a/cmake/modules/AmdisMacros.cmake b/cmake/modules/AmdisMacros.cmake
index 863d990b..0d080888 100644
--- a/cmake/modules/AmdisMacros.cmake
+++ b/cmake/modules/AmdisMacros.cmake
@@ -1,27 +1,38 @@
 include(AmdisCXXFeatures)
 include(AddAmdisExecutable)
 
-set(BACKEND "ISTL" CACHE STRING "LinearAlgebra backend. One of MTL, EIGEN, ISTL")
-set_property(CACHE BACKEND PROPERTY STRINGS "MTL" "EIGEN" "ISTL")
+if (NOT BACKEND)
+  set(BACKEND "ISTL" CACHE STRING "LinearAlgebra backend. One of MTL, EIGEN, PETSC, ISTL")
+  set_property(CACHE BACKEND PROPERTY STRINGS "MTL" "EIGEN" "ISTL" "PETSC")
+endif (NOT BACKEND)
 
 if (BACKEND STREQUAL "MTL" OR BACKEND STREQUAL "MTL4")
   find_package(MTL REQUIRED)
-  set(HAVE_MTL MTL_FOUND)
+  set(HAVE_MTL TRUE)
   if (MTL_FOUND)
     message(STATUS "  Found MTL, version: ${MTL_VERSION}")
     dune_register_package_flags(LIBRARIES MTL::MTL COMPILE_DEFINITIONS "ENABLE_MTL=1")
   endif (MTL_FOUND)
 elseif (BACKEND STREQUAL "EIGEN" OR BACKEND STREQUAL "EIGEN3")
   find_package(Eigen3 REQUIRED 3.3.5)
-  set(HAVE_EIGEN EIGEN_FOUND)
+  set(HAVE_EIGEN TRUE)
   if (EIGEN3_FOUND)
     message(STATUS "  Found Eigen3, version: ${Eigen3_VERSION}")
     dune_register_package_flags(LIBRARIES Eigen3::Eigen COMPILE_DEFINITIONS "ENABLE_EIGEN=1")
   endif (EIGEN3_FOUND)
+elseif (BACKEND STREQUAL "PETSC")
+  find_package(PETSc REQUIRED)
+  if (PETSc_FOUND)
+    set(HAVE_PETSC TRUE)
+    dune_register_package_flags(LIBRARIES PETSc::PETSc COMPILE_DEFINITIONS "ENABLE_PETSC=1")
+  endif (PETSc_FOUND)
 elseif (BACKEND STREQUAL "ISTL")
   if (NOT dune-istl_FOUND)
-    message(FATAL_ERROR "Need dune-istl, MTL, or Eigen3 as linear algebra backend. Change flag BACKEND!")
+    message(FATAL_ERROR "Need dune-istl, MTL, PETSc, or Eigen3 as linear algebra backend. Change flag BACKEND!")
   endif ()
 else ()
-  message(FATAL_ERROR "BACKEND must be one of MTL, EIGEN, ISTL")
+  message(FATAL_ERROR "BACKEND must be one of MTL, EIGEN, PETSC, ISTL")
 endif ()
+
+
+set(DUNE_CUSTOM_PKG_CONFIG_SECTION "set(BACKEND \"${BACKEND}\")")
\ No newline at end of file
diff --git a/cmake/modules/FindPETSc.cmake b/cmake/modules/FindPETSc.cmake
new file mode 100644
index 00000000..10624fd3
--- /dev/null
+++ b/cmake/modules/FindPETSc.cmake
@@ -0,0 +1,92 @@
+# FindPETSc.cmake
+#
+# Finds the PETSc library
+#
+# This will define the following variables
+#
+#    PETSc_FOUND
+#    PETSc_VERSION
+#
+# and the following imported targets
+#
+#    PETSc::PETSc
+#
+# Author: Simon Praetorius <simon.praetorius@tu-dresden.de>
+
+include(FindPkgConfig)
+
+if (NOT PKG_CONFIG_FOUND)
+  message(FATAL_ERROR "Can not find PkgConfig!")
+endif()
+
+mark_as_advanced(PETSc_FOUND PETSc_VERSION PETSC_PKG_CONFIG)
+
+find_path(PETSC_PKG_CONFIG "PETSc.pc"
+  HINTS
+    ${PETSC_DIR}
+    ${PETSC_ROOT}
+    ENV PETSC_DIR
+    ENV PETSC_ROOT
+    ENV PKG_CONFIG_PATH
+  PATHS
+    /etc/alternatives
+    /usr/lib/petsc
+    /usr/lib/petsc/linux-gnu-cxx-opt
+    /usr/lib/petsc/linux-gnu-c-opt
+  PATH_SUFFIXES lib/pkgconfig/
+)
+
+if (PETSC_PKG_CONFIG)
+  set(ENV{PKG_CONFIG_PATH} "${PETSC_PKG_CONFIG}:$ENV{PKG_CONFIG_PATH}")
+endif (PETSC_PKG_CONFIG)
+
+if (PETSc_FIND_VERSION)
+  pkg_check_modules(PETSC PETSc>=${PETSc_FIND_VERSION})
+else ()
+  pkg_check_modules(PETSC PETSc)
+endif ()
+
+if (PETSC_STATIC_FOUND)
+  set(_prefix PETSC_STATIC)
+elseif (PETSC_FOUND)
+  set(_prefix PETSC)
+endif ()
+
+set(PETSc_VERSION "${${_prefix}_VERSION}")
+if ((PETSC_STATIC_FOUND OR PETSC_FOUND) AND NOT TARGET PETSc::PETSc)
+  add_library(PETSc::PETSc INTERFACE IMPORTED GLOBAL)
+  if (${_prefix}_INCLUDE_DIRS)
+    set_property(TARGET PETSc::PETSc PROPERTY
+                 INTERFACE_INCLUDE_DIRECTORIES "${${_prefix}_INCLUDE_DIRS}")
+  endif ()
+  if (${_prefix}_LINK_LIBRARIES)
+    set_property(TARGET PETSc::PETSc PROPERTY
+                 INTERFACE_LINK_LIBRARIES "${${_prefix}_LINK_LIBRARIES}")
+  else ()
+    # extract the absolute paths of link libraries from the LDFLAGS
+    include(PkgConfigLinkLibraries)
+    pkg_config_link_libraries(${_prefix} _libs)
+    set_property(TARGET PETSc::PETSc PROPERTY
+                 INTERFACE_LINK_LIBRARIES "${_libs}")
+    unset(_libs)
+  endif ()
+  if (${_prefix}_LDFLAGS_OTHER)
+    set_property(TARGET PETSc::PETSc PROPERTY
+                 INTERFACE_LINK_OPTIONS "${${_prefix}_LDFLAGS_OTHER}")
+  endif ()
+  if (${_prefix}_CFLAGS_OTHER)
+    set_property(TARGET PETSc::PETSc PROPERTY
+                 INTERFACE_COMPILE_OPTIONS "${${_prefix}_CFLAGS_OTHER}")
+  endif ()
+endif ()
+unset(_prefix)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PETSc
+  REQUIRED_VARS PETSc_VERSION
+  VERSION_VAR PETSc_VERSION
+)
+
+# text for feature summary
+set_package_properties("PETSc" PROPERTIES
+  DESCRIPTION "Portable, Extensible Toolkit for Scientific Computation")
\ No newline at end of file
diff --git a/cmake/modules/PkgConfigLinkLibraries.cmake b/cmake/modules/PkgConfigLinkLibraries.cmake
new file mode 100644
index 00000000..ee8c2393
--- /dev/null
+++ b/cmake/modules/PkgConfigLinkLibraries.cmake
@@ -0,0 +1,56 @@
+# PkgConfigLinkLibraries.cmake
+#
+# Scan the LDFLAGS returned by pkg-config for library directories and
+# libraries and figure out the absolute paths of that libraries in the
+# given directories.
+#
+# This macro is extracted from FindPkgConfig.cmake
+#
+# This will define the following macro
+#
+#    pkg_config_link_libraries(PREFIX, OUTPUT)
+#
+# .. cmake_macro:: pkg_config_link_libraries
+#
+#    .. cmake_brief::
+#
+#       Creates a list ob absolute path for link libraries
+#
+#    .. cmake_param:: PREFIX
+#       :single:
+#
+#       The module prefix (including _STATIC for static libraries)
+#
+#    .. cmake_param:: OUTPUT
+#       :single:
+#
+#       The name of the output list of absolute paths
+#
+#
+# Author: Simon Praetorius <simon.praetorius@tu-dresden.de>
+
+macro(pkg_config_link_libraries _prefix _output)
+  unset(_search_paths)
+  foreach (flag IN LISTS ${_prefix}_LDFLAGS)
+    if (flag MATCHES "^-L(.*)")
+      list(APPEND _search_paths ${CMAKE_MATCH_1})
+      continue()
+    endif()
+    if (flag MATCHES "^-l(.*)")
+      set(_pkg_search "${CMAKE_MATCH_1}")
+    else()
+      continue()
+    endif()
+
+    if(_search_paths)
+      # Firstly search in -L paths
+      find_library(pkgcfg_lib_${_prefix}_${_pkg_search}
+                    NAMES ${_pkg_search}
+                    HINTS ${_search_paths} NO_DEFAULT_PATH)
+    endif()
+    find_library(pkgcfg_lib_${_prefix}_${_pkg_search}
+                NAMES ${_pkg_search}
+                ${_find_opts})
+    list(APPEND ${_output} "${pkgcfg_lib_${_prefix}_${_pkg_search}}")
+  endforeach()
+endmacro(pkg_config_link_libraries)
\ No newline at end of file
diff --git a/config.h.cmake b/config.h.cmake
index d570e2d3..ec1f0739 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -40,12 +40,15 @@
 /* Define to the revision of amdis */
 #define AMDIS_VERSION_REVISION @AMDIS_VERSION_REVISION@
 
-/* Define to ENABLE_MTL if the MTL library is available */
+/* Define to true if the MTL library is available */
 #cmakedefine HAVE_MTL 1
 
-/* Define to ENABLE_EIGEN if the Eigen3 library is available */
+/* Define to true if the Eigen3 library is available */
 #cmakedefine HAVE_EIGEN 1
 
+/* Define to true if the PETSc library is available */
+#cmakedefine HAVE_PETSC ENABLE_PETSC
+
 /* some detected compiler features may be used in AMDiS */
 #cmakedefine AMDIS_HAS_CXX_FOLD_EXPRESSIONS 1
 #cmakedefine AMDIS_HAS_CXX_CONSTEXPR_IF 1
diff --git a/src/amdis/Environment.cpp b/src/amdis/Environment.cpp
index 08cd067c..c7625130 100644
--- a/src/amdis/Environment.cpp
+++ b/src/amdis/Environment.cpp
@@ -4,6 +4,10 @@
 
 #include "Environment.hpp"
 
+#if HAVE_PETSC
+#include <petscsys.h>
+#endif
+
 // AMDiS includes
 #include <amdis/Initfile.hpp>
 #include <amdis/Output.hpp>
@@ -17,13 +21,17 @@ namespace AMDiS
       Parameters::init(initFileName);
   }
 
+
   Environment::Environment(int& argc, char**& argv, std::string const& initFileName)
     : Environment(initFileName)
   {
-    auto& helper = Dune::MPIHelper::instance(argc, argv);
+#if HAVE_PETSC
+    PetscInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL);
+    petscInitialized_ = true;
+#endif
 
     auto& mpi = Mpi::instance();
-    mpi.registerMpiHelper(helper);
+    mpi.registerMpiHelper(Dune::MPIHelper::instance(argc, argv));
 
     Parameters::clearData();
     if (initFileName.empty()) {
@@ -34,4 +42,13 @@ namespace AMDiS
     }
   }
 
+
+  Environment::~Environment()
+  {
+#if HAVE_PETSC
+    if (petscInitialized_)
+      PetscFinalize();
+#endif
+  }
+
 } // end namespace AMDiS
diff --git a/src/amdis/Environment.hpp b/src/amdis/Environment.hpp
index 67b8b07f..21abf85c 100644
--- a/src/amdis/Environment.hpp
+++ b/src/amdis/Environment.hpp
@@ -56,6 +56,9 @@ namespace AMDiS
     /// or the provided initfile filename.
     Environment(int& argc, char**& argv, std::string const& initFileName = "");
 
+    /// Finishes MPI and PETSc
+    ~Environment();
+
     /// Return the MPI_Rank of the current processor.
     static int mpiRank()
     {
@@ -67,6 +70,15 @@ namespace AMDiS
     {
       return Mpi::instance().size();
     }
+
+    /// Return the MPI_Comm object (or a fake communicator)
+    static typename Dune::MPIHelper::MPICommunicator comm()
+    {
+      return Dune::MPIHelper::getCommunicator();
+    }
+
+  private:
+    bool petscInitialized_ = false;
   };
 
 } // end namespace AMDiS
-- 
GitLab