dune-assembler 2.12
Loading...
Searching...
No Matches
graphutilities.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
3
4#ifndef DUNE_ASSEMBLER_PARALLEL_GRAPHUTILITIES_HH
5#define DUNE_ASSEMBLER_PARALLEL_GRAPHUTILITIES_HH
6
7#include <algorithm>
8#include <cstddef>
9#if __has_include(<execution>)
10#include <execution>
11#else
12#include <version>
13#endif
14#include <iostream>
15#include <type_traits>
16#include <utility>
17#include <vector>
18
20
22
23namespace Impl {
24
25
26
27/* A class for building a container that looks like std::vector<std::vector<T>>
28 * but uses flat storage. The class should be used as follows:
29 *
30 * // Create with given outer size
31 * auto vec = FlatBlockedVector<T>(size);
32 *
33 * // Reserve size for all entries.
34 * // It's allowed to do this in arbitrary order.
35 * vec.capacity(2) = ...;
36 * vec.capacity(1) = ...;
37 * vec.capacity(2) += ...;
38 *
39 * // Initialize blocks
40 * vec.initialize();
41 *
42 * // Fill blocks in arbitrary order
43 * vec[i].push_back(value);
44 * vec[i].push_back(value);
45 *
46 * // Swap or access entries using operator[] or iterators
47 * // or resize within reserved capacity
48 * vec[i][0] = ...;
49 * auto&& vec_i = vec[i];
50 * std::sort(vec_i.begin(), vec_i.end());
51 * vec[i].resize(1);
52 *
53 * // Export a range of ranges. This will steal the internal data.
54 * auto r = std::move(vec).toRange();
55 *
56 * // Use r like a nested range
57 * for (auto&& ri : r)
58 * for (auto&& rij : ri)
59 * foo(rij);
60 */
61template <class T, class st = std::size_t>
62class FlatBlockedVector
63{
64public:
65 using size_type = st;
66
67private:
68
69 struct MutableBlock
70 {
71 void push_back (const T& t)
72 {
73 data_[end_] = t;
74 ++end_;
75 }
76
77 T& operator[] (size_type i)
78 {
79 return data_[begin_+i];
80 }
81
82 auto begin ()
83 {
84 return data_.begin() + begin_;
85 }
86
87 auto end ()
88 {
89 return data_.begin() + end_;
90 }
91
92 void resize (size_type size)
93 {
94 end_ = begin_+size;
95 }
96
97 std::vector<T>& data_;
98 size_type& begin_;
99 size_type& end_;
100 };
101
102public:
103
104 FlatBlockedVector (size_type size)
105 : blockBegin_(size, 0),
106 blockEnd_(size, 0)
107 {
108 blockEnd_.clear();
109 blockEnd_.resize(size, 0);
110 }
111
112 size_type size () const
113 {
114 return blockBegin_.size();
115 }
116
117 size_type& capacity (size_type i)
118 {
119 return blockEnd_[i];
120 }
121
122 void initialize ()
123 {
124 auto size = blockBegin_.size();
125 blockBegin_[0] = 0;
126 for (auto i : Dune::range(std::size_t(1), size))
127 {
128 blockBegin_[i] = blockBegin_[i-1] + capacity(i-1);
129 blockEnd_[i-1] = blockBegin_[i-1];
130 }
131 data_.resize(blockBegin_[size-1] + capacity(size-1));
132 blockEnd_[size-1] = blockBegin_[size-1];
133 }
134
135 auto operator[] (size_type i) const
136 {
137 return Dune::transformedRangeView(Dune::range(blockBegin_[i], blockEnd_[i]), [&](auto j) {
138 return data_[j];
139 });
140 }
141
142 auto operator[] (size_type i)
143 {
144 return MutableBlock{data_, blockBegin_[i], blockEnd_[i]};
145 }
146
147 auto toRange () &&
148 {
149 auto size = blockBegin_.size();
151 [setVector=std::move(*this)](auto i) {
152 return setVector[i];
153 });
154 }
155
156 std::vector<T> data_;
157 std::vector<size_type> blockBegin_;
158 std::vector<size_type> blockEnd_;
159};
160
161
162
163// Sort vector and drop duplicate entries
164template <class V>
165void sortAndUnifyVector (V&& v)
166{
167 std::sort(v.begin(), v.end());
168 auto lastUnique = std::unique(v.begin(), v.end());
169 v.resize(lastUnique-v.begin());
170}
171
172
173
174} // end namespace Impl within Dune::Assembler::Experimental
175
176
177
205template <class CliqueList>
207{
208 using size_type = std::decay_t<decltype(*(cliqueList.begin()->begin()))>;
209
210 // In verbode mode: Compute size of the largest provided clique.
211 // This is a lower bound for the clique number (largest existing clique)
212 // which itself is a lower bound for the chromatic number.
213 // Notice that even for planar 2d grids the element graph is not planar
214 // and thus we may need more than 4 colors.
215 if (verbose)
216 {
217 size_type maxCliqueSize = 0;
218 for (const auto& clique : cliqueList)
219 maxCliqueSize = std::max(size_type(maxCliqueSize), size_type(clique.size()));
220 std::cout << "Largest found element clique (lower bound of required colors) has size " << maxCliqueSize << std::endl;
221 }
222
223 // Theoretically we could use a std::set for each adjacency[k]
224 // and simply insert all entries from the cliques into this set.
225 // However, simply pushing back entries and removing duplicates
226 // afterwards is faster.
227 // Furthermore using windows into a flat std::vector<size_type>
228 // is faster than using a std::vector<std::vector<size_type>>.
229 // The latter is provided by the FlatBlockedVector helper class.
230 auto adjacency = Impl::FlatBlockedVector<size_type, size_type>(size);
231
232 // We first must compute an upper bound for the
233 // degree of each vertex to reserve the appropriate
234 // block in the flat vector.
235 for (const auto& clique : cliqueList)
236 for (auto k : clique)
237 adjacency.capacity(k) += clique.size()-1;
238 adjacency.initialize();
239
240 // Add edges to adjacency list
241 for (const auto& clique : cliqueList)
242 for (auto k : clique)
243 for (auto l : clique)
244 if (k!=l)
245 adjacency[k].push_back(l);
246
247 // Remove duplicate entries in inner container
248 {
249 auto indices = Dune::range(adjacency.size());
250#if __cpp_lib_execution >= 201603L
251 std::for_each(std::execution::par, indices.begin(), indices.end(), [&](auto i) {
252#else
253 std::for_each(indices.begin(), indices.end(), [&](auto i) {
254#endif
255 Impl::sortAndUnifyVector(adjacency[i]);
256 });
257 }
258
259 return std::move(adjacency).toRange();
260}
261
262} // end namespace Dune::Assembler::Experimental
263
264#endif // DUNE_ASSEMBLER_PARALLEL_GRAPHUTILITIES_HH
STL namespace.
Definition barrier.hh:11
auto cliqueListToAdjacency(const CliqueList &cliqueList, std::size_t size, bool verbose=false)
Compute an adjacency list from a clique list.
Definition graphutilities.hh:206
BCRSMatrix< FieldMatrix< T, n, m >, A >::size_type size_type
int size() const
auto transformedRangeView(R &&range, F &&f)
static constexpr IntegralRange< T > range(T from, T to) noexcept
size_t() const
constexpr std::integer_sequence< T, II..., T(IN)> push_back(std::integer_sequence< T, II... >, std::integral_constant< T, IN >={})
RowIterator begin()
T begin(T... args)
T end(T... args)
T endl(T... args)
T for_each(T... args)
T max(T... args)
T sort(T... args)
T unique(T... args)