3.5-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_ASSEMBLY_COLORING_HH
25#define DUMUX_ASSEMBLY_COLORING_HH
26
27#include <vector>
28#include <deque>
29#include <iostream>
30#include <tuple>
31
32#include <dune/common/timer.hh>
33#include <dune/common/exceptions.hh>
34
35#include <dumux/io/format.hh>
37
38#ifndef DOXYGEN // hide from doxygen
39namespace Dumux::Detail {
40
42template <class GridGeometry>
43std::vector<std::vector<std::size_t>>
44computeDofToElementMap(const GridGeometry& gg)
45{
46 std::vector<std::vector<std::size_t>> dofToElements;
47
48 if constexpr (GridGeometry::discMethod == DiscretizationMethods::cctpfa)
49 {
50 dofToElements.resize(gg.gridView().size(0));
51 const auto& eMapper = gg.elementMapper();
52 for (const auto& element : elements(gg.gridView()))
53 {
54 const auto eIdx = eMapper.index(element);
55 for (const auto& intersection : intersections(gg.gridView(), element))
56 if (intersection.neighbor())
57 dofToElements[eMapper.index(intersection.outside())].push_back(eIdx);
58 }
59 }
60
61 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::box)
62 {
63 static constexpr int dim = GridGeometry::GridView::dimension;
64 dofToElements.resize(gg.gridView().size(dim));
65 const auto& vMapper = gg.vertexMapper();
66 for (const auto& element : elements(gg.gridView()))
67 {
68 const auto eIdx = gg.elementMapper().index(element);
69 for (int i = 0; i < element.subEntities(dim); i++)
70 dofToElements[vMapper.subIndex(element, i, dim)].push_back(eIdx);
71 }
72 }
73
74 else
75 DUNE_THROW(Dune::NotImplemented,
76 "Missing coloring scheme implementation for this discretization method"
77 );
78
79 return dofToElements;
80}
81
94template<class GridGeometry, class DofToElementMap>
95void addNeighborColors(const GridGeometry& gg,
96 const typename GridGeometry::LocalView::Element& element,
97 const std::vector<int>& colors,
98 const DofToElementMap& dofToElement,
99 std::vector<int>& neighborColors)
100{
101 if constexpr (GridGeometry::discMethod == DiscretizationMethods::cctpfa)
102 {
103 // we modify neighbor elements during the assembly
104 // check who else modifies these neighbor elements
105 const auto& eMapper = gg.elementMapper();
106 for (const auto& intersection : intersections(gg.gridView(), element))
107 {
108 if (intersection.neighbor())
109 {
110 // direct face neighbors
111 const auto nIdx = eMapper.index(intersection.outside());
112 neighborColors.push_back(colors[nIdx]);
113
114 // neighbor-neighbors
115 for (const auto nnIdx : dofToElement[eMapper.index(intersection.outside())])
116 neighborColors.push_back(colors[nnIdx]);
117 }
118 }
119 }
120
121 else if constexpr (GridGeometry::discMethod == DiscretizationMethods::box)
122 {
123 // we modify the vertex dofs of our element during the assembly
124 // check who else modifies these vertex dofs
125 const auto& vMapper = gg.vertexMapper();
126 static constexpr int dim = GridGeometry::GridView::dimension;
127 // direct vertex neighbors
128 for (int i = 0; i < element.subEntities(dim); i++)
129 for (auto eIdx : dofToElement[vMapper.subIndex(element, i, dim)])
130 neighborColors.push_back(colors[eIdx]);
131 }
132
133 else
134 DUNE_THROW(Dune::NotImplemented,
135 "Missing coloring scheme implementation for this discretization method"
136 );
137}
138
144int smallestAvailableColor(const std::vector<int>& colors,
145 std::vector<bool>& colorUsed)
146{
147 const int numColors = colors.size();
148 colorUsed.assign(numColors, false);
149
150 // The worst case for e.g. numColors=3 is colors={0, 1, 2}
151 // in which case we return 3 as smallest available color
152 // That means, we only track candidates in the (half-open) interval [0, numColors)
153 // Mark candidate colors which are present in colors
154 for (int i = 0; i < numColors; i++)
155 if (colors[i] >= 0 && colors[i] < numColors)
156 colorUsed[colors[i]] = true;
157
158 // return smallest color not in colors
159 for (int i = 0; i < numColors; i++)
160 if (!colorUsed[i])
161 return i;
162
163 return numColors;
164}
165
166} // end namespace Dumux::Detail
167#endif // DOXYGEN
168
169namespace Dumux {
170
191template<class GridGeometry>
192auto computeColoring(const GridGeometry& gg, int verbosity = 1)
193{
194 Dune::Timer timer;
195
196 using ElementSeed = typename GridGeometry::GridView::Grid::template Codim<0>::EntitySeed;
197 struct Coloring
198 {
199 using Sets = std::deque<std::vector<ElementSeed>>;
200 using Colors = std::vector<int>;
201
202 Coloring(std::size_t size) : sets{}, colors(size, -1) {}
203
204 Sets sets;
205 Colors colors;
206 };
207
208 Coloring coloring(gg.gridView().size(0));
209
210 // pre-reserve some memory for helper arrays to avoid reallocation
211 std::vector<int> neighborColors; neighborColors.reserve(30);
212 std::vector<bool> colorUsed; colorUsed.reserve(30);
213
214 // dof to element map to speed up neighbor search
215 const auto dofToElement = Detail::computeDofToElementMap(gg);
216
217 for (const auto& element : elements(gg.gridView()))
218 {
219 // compute neighbor colors based on discretization-dependent stencil
220 neighborColors.clear();
221 Detail::addNeighborColors(gg, element, coloring.colors, dofToElement, neighborColors);
222
223 // find smallest color (positive integer) not in neighborColors
224 const auto color = Detail::smallestAvailableColor(neighborColors, colorUsed);
225
226 // assign color to element
227 coloring.colors[gg.elementMapper().index(element)] = color;
228
229 // add element to the set of elements with the same color
230 if (color < coloring.sets.size())
231 coloring.sets[color].push_back(element.seed());
232 else
233 coloring.sets.push_back(std::vector<ElementSeed>{ element.seed() });
234 }
235
236 if (verbosity > 0)
237 std::cout << Fmt::format("Colored {} elements with {} colors in {} seconds.\n",
238 gg.gridView().size(0), coloring.sets.size(), timer.elapsed());
239
240 return coloring;
241}
242
244template<class DiscretizationMethod>
245struct SupportsColoring : public std::false_type {};
246
247template<> struct SupportsColoring<DiscretizationMethods::CCTpfa> : public std::true_type {};
248template<> struct SupportsColoring<DiscretizationMethods::Box> : public std::true_type {};
249
250} // end namespace Dumux
251
252#endif
The available discretization methods in Dumux.
Formatting based on the fmt-library which implements std::format of C++20.
Definition: adapt.hh:29
auto computeColoring(const GridGeometry &gg, int verbosity=1)
Compute iterable lists of element seeds partitioned by color.
Definition: coloring.hh:192
Distance implementation details.
Definition: fclocalassembler.hh:42
constexpr CCTpfa cctpfa
Definition: method.hh:137
constexpr Box box
Definition: method.hh:139
Traits specifying if a given discretization tag supports coloring.
Definition: coloring.hh:245