version 3.8
scotchbackend.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
7
14#ifndef DUMUX_SCOTCH_BACKEND_HH
15#define DUMUX_SCOTCH_BACKEND_HH
16
17#include <string>
18#include <vector>
19#include <iostream>
20
21#include <dune/common/exceptions.hh>
22
23#if HAVE_PTSCOTCH
24#if HAVE_MPI
25#include <mpi.h>
26#endif
27extern "C"
28{
29#include <stdint.h>
30#include <ptscotch.h>
31}
32#else
33#warning "PTSCOTCH was not found on your system. Dumux::ScotchBackend won't do anything."
34#endif
35
36namespace Dumux {
37
38#if HAVE_PTSCOTCH
39
44template<class IndexType = int>
45class ScotchGraph
46{
47public:
49 using Graph = std::vector<std::vector<IndexType>>;
50
51 ScotchGraph(const Graph& graph)
52 {
53 // Number of local graph vertices
54 const SCOTCH_Num numNodes = graph.size();
55
56 // Data structures for graph input to SCOTCH
57 // add 1 for case that graph size is zero
58 vertTab_.reserve(numNodes + 1);
59 edgeTab_.reserve(20*numNodes);
60
61 // Build local graph input for SCOTCH
62 // (number of graph vertices (cells),
63 // number of edges connecting two vertices)
64 SCOTCH_Num numEdges = 0;
65 vertTab_.push_back(0);
66 for (auto vertex = graph.begin(); vertex != graph.end(); ++vertex)
67 {
68 numEdges += vertex->size();
69 vertTab_.push_back(vertTab_.back() + vertex->size());
70 edgeTab_.insert(edgeTab_.end(), vertex->begin(), vertex->end());
71 }
72
73 // Shrink vectors to hopefully recover any unused memory
74 vertTab_.shrink_to_fit();
75 edgeTab_.shrink_to_fit();
76
77 if (SCOTCH_graphInit(&scotchGraph_) != 0)
78 DUNE_THROW(Dune::Exception, "Error initializing SCOTCH graph!");
79
80 // check graph's consistency (recommended before building)
81 if (SCOTCH_graphCheck(&scotchGraph_) != 0)
82 DUNE_THROW(Dune::Exception, "Error within SCOTCH graph's consistency!");
83
84 // build graph
85 const SCOTCH_Num baseValue = 0; // C-style array indexing
86 if (SCOTCH_graphBuild(&scotchGraph_, baseValue, numNodes, vertTab_.data(), vertTab_.data()+1, NULL, NULL, numEdges, edgeTab_.data(), NULL))
87 DUNE_THROW(Dune::Exception, "Error building SCOTCH graph!");
88 }
89
91 ~ScotchGraph()
92 {
93 SCOTCH_graphExit(&scotchGraph_);
94 }
95
97 SCOTCH_Graph* data()
98 { return &scotchGraph_; }
99
100private:
101 SCOTCH_Graph scotchGraph_;
102 // we have to maintain these ourselves to keep the Scotch graph valid
103 std::vector<SCOTCH_Num> vertTab_;
104 std::vector<SCOTCH_Num> edgeTab_;
105};
106
111class ScotchGraphOrderStrategy
112{
113public:
114 ScotchGraphOrderStrategy(const std::string& strategy = "")
115 {
116 if (SCOTCH_stratInit(&strategy_) != 0)
117 DUNE_THROW(Dune::Exception, "Error initializing SCOTCH strategy!");
118
119 // Set SCOTCH strategy (if provided)
120 if (!strategy.empty())
121 SCOTCH_stratGraphOrder(&strategy_, strategy.c_str());
122 }
123
125 ~ScotchGraphOrderStrategy()
126 {
127 SCOTCH_stratExit(&strategy_);
128 }
129
131 SCOTCH_Strat* data()
132 { return &strategy_; }
133
134private:
135 SCOTCH_Strat strategy_;
136};
137
138#endif // HAVE_PTSCOTCH
139
145template<class IndexType>
147{
148public:
150 using Graph = std::vector<std::vector<IndexType>>;
151
154 static std::vector<int> computeGPSReordering(const Graph& graph,
155 std::size_t numPasses = 5)
156 {
157 // Create strategy string for Gibbs-Poole-Stockmeyer ordering
158 std::string strategy = "g{pass= " + std::to_string(numPasses) + "}";
159 return computeReordering(graph, strategy);
160 }
161
163 static std::vector<int> computeReordering(const Graph& graph,
164 std::string scotchStrategy = "")
165 {
166 std::vector<int> permutation, inversePermutation;
167 computeReordering(graph, permutation, inversePermutation, scotchStrategy);
168 return permutation;
169 }
170
172 static void computeReordering(const Graph& graph,
173 std::vector<int>& permutation,
174 std::vector<int>& inversePermutation,
175 std::string scotchStrategy = "")
176 {
177#if HAVE_PTSCOTCH
178 ScotchGraph<IndexType> scotchGraph(graph);
179 ScotchGraphOrderStrategy strategy(scotchStrategy);
180
181 // Vector to hold permutation vectors
182 const auto graphSize = graph.size();
183 std::vector<SCOTCH_Num> permutationIndices(graphSize);
184 std::vector<SCOTCH_Num> inversePermutationIndices(graphSize);
185
186 // Reset SCOTCH random number generator to produce deterministic partitions
187 SCOTCH_randomReset();
188
189 // Compute re-ordering
190 if (SCOTCH_graphOrder(
191 scotchGraph.data(), strategy.data(), permutationIndices.data(),
192 inversePermutationIndices.data(), NULL, NULL, NULL
193 ))
194 DUNE_THROW(Dune::Exception, "Error reordering SCOTCH graph!");
195
196 // Copy permutation vectors
197 permutation.resize(graphSize);
198 inversePermutation.resize(graphSize);
199 std::copy(permutationIndices.begin(), permutationIndices.end(),
200 permutation.begin());
201 std::copy(inversePermutationIndices.begin(), inversePermutationIndices.end(),
202 inversePermutation.begin());
203#endif // HAVE_PTSCOTCH
204 }
205};
206
207} // end namespace Dumux
208
209#endif
A reordering backend using the scotch library.
Definition: scotchbackend.hh:147
static std::vector< int > computeReordering(const Graph &graph, std::string scotchStrategy="")
Compute graph re-ordering.
Definition: scotchbackend.hh:163
std::vector< std::vector< IndexType > > Graph
the graph type
Definition: scotchbackend.hh:150
static std::vector< int > computeGPSReordering(const Graph &graph, std::size_t numPasses=5)
Definition: scotchbackend.hh:154
static void computeReordering(const Graph &graph, std::vector< int > &permutation, std::vector< int > &inversePermutation, std::string scotchStrategy="")
Compute graph re-ordering.
Definition: scotchbackend.hh:172
Definition: adapt.hh:17