From c2190b23b40f01fdfdee9fb0eb7484288401deb4 Mon Sep 17 00:00:00 2001 From: Timo Koch <timo.koch@iws.uni-stuttgart.de> Date: Sat, 27 Aug 2016 15:09:05 +0200 Subject: [PATCH] [ptscotch] Implement PTScotch backend for graph reordering --- cmake/modules/DumuxMacros.cmake | 1 + dumux/linear/CMakeLists.txt | 1 + dumux/linear/reordering/CMakeLists.txt | 4 + dumux/linear/reordering/scotchbackend.hh | 169 +++++++++++++++++++++++ 4 files changed, 175 insertions(+) create mode 100644 dumux/linear/reordering/CMakeLists.txt create mode 100644 dumux/linear/reordering/scotchbackend.hh diff --git a/cmake/modules/DumuxMacros.cmake b/cmake/modules/DumuxMacros.cmake index a8d3041bff..b3e7328fe3 100644 --- a/cmake/modules/DumuxMacros.cmake +++ b/cmake/modules/DumuxMacros.cmake @@ -9,3 +9,4 @@ find_package(Gnuplot) set(HAVE_GNUPLOT ${GNUPLOT_FOUND}) find_package(Valgrind) +find_package(PTScotch) diff --git a/dumux/linear/CMakeLists.txt b/dumux/linear/CMakeLists.txt index c8ce338dbc..38a751c16f 100644 --- a/dumux/linear/CMakeLists.txt +++ b/dumux/linear/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(reordering) #install headers install(FILES diff --git a/dumux/linear/reordering/CMakeLists.txt b/dumux/linear/reordering/CMakeLists.txt new file mode 100644 index 0000000000..a08d5315e2 --- /dev/null +++ b/dumux/linear/reordering/CMakeLists.txt @@ -0,0 +1,4 @@ +#install headers +install(FILES +scotchbackend.hh +DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/linear/reordering) diff --git a/dumux/linear/reordering/scotchbackend.hh b/dumux/linear/reordering/scotchbackend.hh new file mode 100644 index 0000000000..d93c0f900d --- /dev/null +++ b/dumux/linear/reordering/scotchbackend.hh @@ -0,0 +1,169 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/***************************************************************************** + * See the file COPYING for full copying permissions. * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + +/*! + * \file An interface to the scotch library for matrix reordering + * \brief An interface to the scotch library for matrix reordering + * \note This is adapted from the FEniCS implementation of the scotch interface + */ +#ifndef DUMUX_SCOTCH_BACKEND_HH +#define DUMUX_SCOTCH_BACKEND_HH + +#include <string> +#include <vector> +#include <iostream> + +#if HAVE_PTSCOTCH +extern "C" +{ +#include <stdint.h> +#include <ptscotch.h> +} +#endif + +namespace Dumux +{ + +template<class IndexType> +class ScotchBackend +{ + using Graph = std::vector<std::vector<IndexType>>; + +public: + //! Compute reordering (map[old] -> new) using + //! Gibbs-Poole-Stockmeyer (GPS) re-ordering + static std::vector<int> computeGPSReordering(const Graph& graph, + std::size_t numPasses = 5) + { + // Create strategy string for Gibbs-Poole-Stockmeyer ordering + std::string strategy = "g{pass= " + std::to_string(numPasses) + "}"; + return computeReordering(graph, strategy); + } + + // Compute graph re-ordering + static std::vector<int> computeReordering(const Graph& graph, + std::string scotchStrategy = "") + { + std::vector<int> permutation, inversePermutation; + computeReordering(graph, permutation, inversePermutation, scotchStrategy); + return permutation; + } + + // Compute graph re-ordering + static void computeReordering(const Graph& graph, + std::vector<int>& permutation, + std::vector<int>& inversePermutation, + std::string scotchStrategy = "") + { + // Number of local graph vertices (cells) + const SCOTCH_Num vertnbr = graph.size(); + + // Data structures for graph input to SCOTCH (add 1 for case that + // graph size is zero) + std::vector<SCOTCH_Num> verttab; + verttab.reserve(vertnbr + 1); + std::vector<SCOTCH_Num> edgetab; + edgetab.reserve(20*vertnbr); + + // Build local graph input for SCOTCH + // (number of graph vertices (cells), + // number of edges connecting two vertices) + SCOTCH_Num edgenbr = 0; + verttab.push_back(0); + typename Graph::const_iterator vertex; + for (vertex = graph.begin(); vertex != graph.end(); ++vertex) + { + edgenbr += vertex->size(); + verttab.push_back(verttab.back() + vertex->size()); + edgetab.insert(edgetab.end(), vertex->begin(), vertex->end()); + } + + // Shrink vectors to hopefully recover an unused memory + verttab.shrink_to_fit(); + edgetab.shrink_to_fit(); + + // Create SCOTCH graph + SCOTCH_Graph scotchGraph; + + // C-style array indexing + const SCOTCH_Num baseval = 0; + + // Create SCOTCH graph and initialise + if (SCOTCH_graphInit(&scotchGraph) != 0) + { + std::cerr << "Error initializing SCOTCH graph!" << std::endl; + exit(1); + } + + // Build SCOTCH graph + if (SCOTCH_graphBuild(&scotchGraph, baseval, + vertnbr, &verttab[0], &verttab[1], NULL, NULL, + edgenbr, &edgetab[0], NULL)) + { + std::cerr << "Error building SCOTCH graph!" << std::endl; + exit(1); + } + + // Check graph data for consistency + // if (SCOTCH_graphCheck(&scotchGraph)) + // { + // std::cerr << "Consistency error in SCOTCH graph!" << std::endl; + // exit(1); + // } + + // Re-ordering strategy + SCOTCH_Strat strat; + SCOTCH_stratInit(&strat); + + // Set SCOTCH strategy (if provided) + if (!scotchStrategy.empty()) + SCOTCH_stratGraphOrder(&strat, scotchStrategy.c_str()); + + // Vector to hold permutation vectors + std::vector<SCOTCH_Num> permutationIndices(vertnbr); + std::vector<SCOTCH_Num> inversePermutationIndices(vertnbr); + + // Reset SCOTCH random number generator to produce deterministic partitions + SCOTCH_randomReset(); + + // Compute re-ordering + if (SCOTCH_graphOrder(&scotchGraph, &strat, permutationIndices.data(), + inversePermutationIndices.data(), NULL, NULL, NULL)) + { + std::cerr << "SCOTCH: Error during reordering graph!" << std::endl; + exit(1); + } + + // Clean up SCOTCH objects + SCOTCH_graphExit(&scotchGraph); + SCOTCH_stratExit(&strat); + + // Copy permutation vectors + permutation.resize(vertnbr); + inversePermutation.resize(vertnbr); + std::copy(permutationIndices.begin(), permutationIndices.end(), + permutation.begin()); + std::copy(inversePermutationIndices.begin(), inversePermutationIndices.end(), + inversePermutation.begin()); + } +}; + +} // end namespace Dumux + +#endif -- GitLab