version 3.11-dev
Loading...
Searching...
No Matches
coloring.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-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_ASSEMBLY_COLORING_HH
13#define DUMUX_ASSEMBLY_COLORING_HH
14
15#include <vector>
16#include <deque>
17#include <iostream>
18#include <tuple>
19#include <algorithm>
20
21#include <dune/common/timer.hh>
22#include <dune/common/exceptions.hh>
23
24#include <dumux/io/format.hh>
26
27#ifndef DOXYGEN // hide from doxygen
28namespace Dumux::Detail {
29
31template <class GridGeometry>
32std::vector<std::vector<std::size_t>>
33computeConnectedElements(const GridGeometry& gg)
34{
35 std::vector<std::vector<std::size_t>> connectedElements;
36
37 if constexpr (GridGeometry::discMethod == DiscretizationMethods::cctpfa)
38 {
39 connectedElements.resize(gg.gridView().size(0));
40 const auto& eMapper = gg.elementMapper();
41 for (const auto& element : elements(gg.gridView()))
42 {
43 const auto eIdx = eMapper.index(element);
44 for (const auto& intersection : intersections(gg.gridView(), element))
45 if (intersection.neighbor())
46 connectedElements[eMapper.index(intersection.outside())].push_back(eIdx);
47 }
48 }
49
50 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::box
51 || GridGeometry::discMethod == DiscretizationMethods::pq1bubble
52 || GridGeometry::discMethod == DiscretizationMethods::pq2
53 || GridGeometry::discMethod == DiscretizationMethods::pq3)
54 {
55 static constexpr int dim = GridGeometry::GridView::dimension;
56 connectedElements.resize(gg.gridView().size(dim));
57 const auto& vMapper = gg.vertexMapper();
58 for (const auto& element : elements(gg.gridView()))
59 {
60 const auto eIdx = gg.elementMapper().index(element);
61 for (int i = 0; i < element.subEntities(dim); i++)
62 connectedElements[vMapper.subIndex(element, i, dim)].push_back(eIdx);
63 }
64 }
65
66 else if constexpr (
67 GridGeometry::discMethod == DiscretizationMethods::fcstaggered
68 || GridGeometry::discMethod == DiscretizationMethods::ccmpfa
69 )
70 {
71 // for MPFA-O schemes the assembly of each element residual touches all vertex neighbors
72 // for face-centered staggered it is all codim-2 neighbors (vertex neighbors in 2D, edge neighbors in 3D)
73 // but we use vertex neighbors also in 3D for simplicity
74 std::vector<std::vector<std::size_t>> vToElements;
75 static constexpr int dim = GridGeometry::GridView::dimension;
76 vToElements.resize(gg.gridView().size(dim));
77 const auto& vMapper = gg.vertexMapper();
78 for (const auto& element : elements(gg.gridView()))
79 {
80 const auto eIdx = gg.elementMapper().index(element);
81 for (int i = 0; i < element.subEntities(dim); i++)
82 vToElements[vMapper.subIndex(element, i, dim)].push_back(eIdx);
83 }
84
85 connectedElements.resize(gg.gridView().size(0));
86 for (const auto& element : elements(gg.gridView()))
87 {
88 const auto eIdx = gg.elementMapper().index(element);
89 for (int i = 0; i < element.subEntities(dim); i++)
90 {
91 const auto& e = vToElements[vMapper.subIndex(element, i, dim)];
92 connectedElements[eIdx].insert(connectedElements[eIdx].end(), e.begin(), e.end());
93 }
94
95 // make unique
96 std::sort(connectedElements[eIdx].begin(), connectedElements[eIdx].end());
97 connectedElements[eIdx].erase(
98 std::unique(connectedElements[eIdx].begin(), connectedElements[eIdx].end()),
99 connectedElements[eIdx].end()
100 );
101 }
102 }
103
104 // nothing has to be precomputed here as only immediate face neighbors are connected
105 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::fcdiamond)
106 return connectedElements;
107
108 else
109 DUNE_THROW(Dune::NotImplemented,
110 "Missing coloring scheme implementation for this discretization method"
111 );
112
113 return connectedElements;
114}
115
128template<class GridGeometry, class ConnectedElements>
129void addNeighborColors(const GridGeometry& gg,
130 const typename GridGeometry::LocalView::Element& element,
131 const std::vector<int>& colors,
132 const ConnectedElements& connectedElements,
133 std::vector<int>& neighborColors)
134{
135 if constexpr (
136 GridGeometry::discMethod == DiscretizationMethods::cctpfa
137 || GridGeometry::discMethod == DiscretizationMethods::ccmpfa
138 || GridGeometry::discMethod == DiscretizationMethods::fcstaggered
139 )
140 {
141 // we modify neighbor elements during the assembly
142 // check who else modifies these neighbor elements
143 const auto& eMapper = gg.elementMapper();
144 for (const auto& intersection : intersections(gg.gridView(), element))
145 {
146 if (intersection.neighbor())
147 {
148 // direct face neighbors
149 const auto nIdx = eMapper.index(intersection.outside());
150 neighborColors.push_back(colors[nIdx]);
151
152 // neighbor-neighbors
153 for (const auto nnIdx : connectedElements[eMapper.index(intersection.outside())])
154 neighborColors.push_back(colors[nnIdx]);
155 }
156 }
157 }
158
159 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::box
160 || GridGeometry::discMethod == DiscretizationMethods::pq1bubble
161 || GridGeometry::discMethod == DiscretizationMethods::pq2
162 || GridGeometry::discMethod == DiscretizationMethods::pq3)
163 {
164 // we modify the vertex dofs of our element during the assembly
165 // check who else modifies these vertex dofs
166 const auto& vMapper = gg.vertexMapper();
167 static constexpr int dim = GridGeometry::GridView::dimension;
168 // direct vertex neighbors
169 for (int i = 0; i < element.subEntities(dim); i++)
170 for (auto eIdx : connectedElements[vMapper.subIndex(element, i, dim)])
171 neighborColors.push_back(colors[eIdx]);
172 }
173
174 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::fcdiamond)
175 {
176 // we modify neighbor faces during the assembly
177 // check who else modifies these neighbor elements
178 const auto& eMapper = gg.elementMapper();
179 for (const auto& intersection : intersections(gg.gridView(), element))
180 if (intersection.neighbor())
181 neighborColors.push_back(colors[eMapper.index(intersection.outside())]);
182 }
183
184 else
185 DUNE_THROW(Dune::NotImplemented,
186 "Missing coloring scheme implementation for this discretization method"
187 );
188}
189
195int smallestAvailableColor(const std::vector<int>& colors,
196 std::vector<bool>& colorUsed)
197{
198 const int numColors = colors.size();
199 colorUsed.assign(numColors, false);
200
201 // The worst case for e.g. numColors=3 is colors={0, 1, 2}
202 // in which case we return 3 as smallest available color
203 // That means, we only track candidates in the (half-open) interval [0, numColors)
204 // Mark candidate colors which are present in colors
205 for (int i = 0; i < numColors; i++)
206 if (colors[i] >= 0 && colors[i] < numColors)
207 colorUsed[colors[i]] = true;
208
209 // return smallest color not in colors
210 for (int i = 0; i < numColors; i++)
211 if (!colorUsed[i])
212 return i;
213
214 return numColors;
215}
216
217} // end namespace Dumux::Detail
218#endif // DOXYGEN
219
220namespace Dumux {
221
242template<class GridGeometry>
243auto computeColoring(const GridGeometry& gg, int verbosity = 1)
244{
245 Dune::Timer timer;
246
247 using ElementSeed = typename GridGeometry::GridView::Grid::template Codim<0>::EntitySeed;
248 struct Coloring
249 {
250 using Sets = std::deque<std::vector<ElementSeed>>;
251 using Colors = std::vector<int>;
252
253 Coloring(std::size_t size) : sets{}, colors(size, -1) {}
254
255 Sets sets;
256 Colors colors;
257 };
258
259 Coloring coloring(gg.gridView().size(0));
260
261 // pre-reserve some memory for helper arrays to avoid reallocation
262 std::vector<int> neighborColors; neighborColors.reserve(30);
263 std::vector<bool> colorUsed; colorUsed.reserve(30);
264
265 // dof to element map to speed up neighbor search
266 const auto connectedElements = Detail::computeConnectedElements(gg);
267
268 for (const auto& element : elements(gg.gridView()))
269 {
270 // compute neighbor colors based on discretization-dependent stencil
271 neighborColors.clear();
272 Detail::addNeighborColors(gg, element, coloring.colors, connectedElements, neighborColors);
273
274 // find smallest color (positive integer) not in neighborColors
275 const auto color = Detail::smallestAvailableColor(neighborColors, colorUsed);
276
277 // assign color to element
278 coloring.colors[gg.elementMapper().index(element)] = color;
279
280 // add element to the set of elements with the same color
281 if (color < coloring.sets.size())
282 coloring.sets[color].push_back(element.seed());
283 else
284 coloring.sets.push_back(std::vector<ElementSeed>{ element.seed() });
285 }
286
287 if (verbosity > 0)
288 std::cout << Fmt::format("Colored {} elements with {} colors in {} seconds.\n",
289 gg.gridView().size(0), coloring.sets.size(), timer.elapsed());
290
291 return coloring;
292}
293
295template<class DiscretizationMethod>
296struct SupportsColoring : public std::false_type {};
297
298template<> struct SupportsColoring<DiscretizationMethods::CCTpfa> : public std::true_type {};
299template<> struct SupportsColoring<DiscretizationMethods::CCMpfa> : public std::true_type {};
300template<> struct SupportsColoring<DiscretizationMethods::Box> : public std::true_type {};
301template<> struct SupportsColoring<DiscretizationMethods::FCStaggered> : public std::true_type {};
302template<> struct SupportsColoring<DiscretizationMethods::FCDiamond> : public std::true_type {};
303template<> struct SupportsColoring<DiscretizationMethods::PQ1Bubble> : public std::true_type {};
304template<> struct SupportsColoring<DiscretizationMethods::PQ2> : public std::true_type {};
305template<> struct SupportsColoring<DiscretizationMethods::PQ3> : public std::true_type {};
306
307} // end namespace Dumux
308
309#endif
Formatting based on the fmt-library which implements std::format of C++20.
@ element
Definition fieldtype.hh:23
The available discretization methods in Dumux.
Definition cellcentered/mpfa/elementvolumevariables.hh:24
Definition cvfelocalresidual.hh:25
Definition method.hh:20
constexpr CCMpfa ccmpfa
Definition method.hh:165
constexpr FCDiamond fcdiamond
Definition method.hh:173
constexpr PQ2 pq2
Definition method.hh:167
constexpr CCTpfa cctpfa
Definition method.hh:164
constexpr Box box
Definition method.hh:166
constexpr PQ3 pq3
Definition method.hh:168
constexpr PQ1Bubble pq1bubble
Definition method.hh:169
constexpr FCStaggered fcstaggered
Definition method.hh:172
Definition adapt.hh:17
auto computeColoring(const GridGeometry &gg, int verbosity=1)
Compute iterable lists of element seeds partitioned by color.
Definition coloring.hh:243
Traits specifying if a given discretization tag supports coloring.
Definition coloring.hh:296