version 3.11-dev
Loading...
Searching...
No Matches
partialreassembler.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_PARTIAL_REASSEMBLER_HH
13#define DUMUX_PARTIAL_REASSEMBLER_HH
14
15#include <algorithm>
16#include <vector>
17
18#include <dune/grid/common/gridenums.hh>
19#include <dune/istl/multitypeblockvector.hh>
20
21#include <dumux/io/format.hh>
26
27#include "entitycolor.hh"
28
29namespace Dumux {
30
32{
33public:
34 template<typename... Args>
36 { DUNE_THROW(Dune::InvalidStateException, "DefaultPartialReassembler should be never constructed!"); }
37
38 template<typename... Args>
39 void report(Args&&... args) {}
40
41 template<typename... Args>
42 void resetJacobian(Args&&... args) const {}
43
44 template<typename... Args>
45 void computeColors(Args&&... args) {}
46
47 template<typename... Args>
48 void resetColors(Args&&... args) {}
49
50 EntityColor dofColor(size_t idx) const
51 { return EntityColor::red; }
52
53 EntityColor elementColor(size_t idx) const
54 { return EntityColor::red; }
55
56 EntityColor vertexColor(size_t idx) const
57 { return EntityColor::red; }
58};
59
61template<class Assembler, class DiscretizationMethod>
63{
64public:
65 PartialReassemblerEngine(const Assembler&)
66 { DUNE_THROW(Dune::NotImplemented, "PartialReassembler for this discretization method!"); }
67
68 EntityColor elementColor(size_t idx) const
69 { return EntityColor::red; }
70
71 EntityColor dofColor(size_t idx) const
72 { return EntityColor::red; }
73
74 template<typename... Args>
75 std::size_t computeColors(Args&&... args) { return 0; }
76
77 template<typename... Args>
78 void resetJacobian(Args&&... args) const {}
79
80 template<typename... Args>
81 void resetColors(Args&&... args) {}
82};
83
88template<class Assembler>
90{
91 using Scalar = typename Assembler::Scalar;
92 using GridGeometry = typename Assembler::GridGeometry;
93 using JacobianMatrix = typename Assembler::JacobianMatrix;
94 using VertexMapper = typename GridGeometry::VertexMapper;
95 static constexpr int dim = GridGeometry::GridView::dimension;
96
97public:
98 PartialReassemblerEngine(const Assembler& assembler)
99 : elementColor_(assembler.gridGeometry().elementMapper().size(), EntityColor::red)
100 , vertexColor_(assembler.gridGeometry().vertexMapper().size(), EntityColor::red)
101 {}
102
103 // returns number of green elements
104 std::size_t computeColors(const Assembler& assembler,
105 const std::vector<Scalar>& distanceFromLastLinearization,
106 Scalar threshold)
107 {
108 const auto& gridGeometry = assembler.gridGeometry();
109 const auto& gridView = gridGeometry.gridView();
110 const auto& elementMapper = gridGeometry.elementMapper();
111 const auto& vertexMapper = gridGeometry.vertexMapper();
112
113 // set all vertices to green
114 vertexColor_.assign(vertexColor_.size(), EntityColor::green);
115
116 // mark the red vertices
117 for (unsigned int i = 0; i < vertexColor_.size(); ++i)
118 {
119 using std::max;
120 if (distanceFromLastLinearization[i] > threshold)
121 // mark vertex as red if discrepancy is larger than
122 // the relative tolerance
123 vertexColor_[i] = EntityColor::red;
124 }
125
126 // Mark all red elements
127 for (const auto& element : elements(gridView))
128 {
129 // find out whether the current element features a red vertex
130 bool isRed = false;
131
132 int numVertices = element.subEntities(dim);
133
134 for (int i = 0; i < numVertices; ++i) {
135 int globalI = vertexMapper.subIndex(element, i, dim);
136
137 if (vertexColor_[globalI] == EntityColor::red) {
138 isRed = true;
139 break;
140 }
141 }
142
143 int eIdx = elementMapper.index(element);
144 // if a vertex is red, the element color is also red, otherwise green
145 if (isRed)
146 elementColor_[eIdx] = EntityColor::red;
147 else
148 elementColor_[eIdx] = EntityColor::green;
149 }
150
151 // mark orange vertices
152 for (const auto& element : elements(gridView))
153 {
154 int eIdx = elementMapper.index(element);
155
156 // only red elements tint vertices yellow
157 if (elementColor_[eIdx] == EntityColor::red)
158 {
159 int numVertices = element.subEntities(dim);
160
161 for (int i = 0; i < numVertices; ++i) {
162 int globalI = vertexMapper.subIndex(element, i, dim);
163
164 // red vertices don't become orange
165 if (vertexColor_[globalI] != EntityColor::red)
166 vertexColor_[globalI] = EntityColor::orange;
167 }
168 }
169 }
170
171 // at this point we communicate the yellow vertices to the
172 // neighboring processes because a neighbor process may not see
173 // the red vertex for yellow border vertices
175 minHandle(vertexMapper, vertexColor_);
176 if constexpr (Dune::Capabilities::canCommunicate<typename GridGeometry::GridView::Traits::Grid, dim>::v)
177 gridView.communicate(minHandle,
178 Dune::InteriorBorder_InteriorBorder_Interface,
179 Dune::ForwardCommunication);
180 else
181 DUNE_THROW(Dune::InvalidStateException, "Cannot call computeColors on multiple processes for a grid that cannot communicate codim-" << dim << "-entities.");
182
183 // mark yellow elements
184 for (const auto& element : elements(gridView))
185 {
186 int eIdx = elementMapper.index(element);
187
188 // only treat non-red elements
189 if (elementColor_[eIdx] != EntityColor::red)
190 {
191 // check whether the element features a orange vertex
192 bool isOrange = false;
193 int numVertices = element.subEntities(dim);
194
195 for (int i = 0; i < numVertices; ++i) {
196 int globalI = vertexMapper.subIndex(element, i, dim);
197
198 if (vertexColor_[globalI] == EntityColor::orange) {
199 isOrange = true;
200 break;
201 }
202 }
203
204 if (isOrange)
205 elementColor_[eIdx] = EntityColor::yellow;
206 }
207 }
208
209 // change orange vertices to yellow ones if it has at least
210 // one green element as a neighbor
211 for (const auto& element : elements(gridView))
212 {
213 int eIdx = elementMapper.index(element);
214
215 // only green elements are considered
216 if (elementColor_[eIdx] == EntityColor::green)
217 {
218 int numVertices = element.subEntities(dim);
219
220 for (int i = 0; i < numVertices; ++i) {
221 int globalI = vertexMapper.subIndex(element, i, dim);
222
223 // if a vertex is orange, recolor it to yellow
224 if (vertexColor_[globalI] == EntityColor::orange)
225 vertexColor_[globalI] = EntityColor::yellow;
226 }
227 }
228 }
229
230 // demote the border orange vertices
232 maxHandle(vertexMapper, vertexColor_);
233 if constexpr (Dune::Capabilities::canCommunicate<typename GridGeometry::GridView::Traits::Grid, dim>::v)
234 gridView.communicate(maxHandle,
235 Dune::InteriorBorder_InteriorBorder_Interface,
236 Dune::ForwardCommunication);
237 else
238 DUNE_THROW(Dune::InvalidStateException, "Cannot call computeColors on multiple processes for a grid that cannot communicate codim-" << dim << "-entities.");
239
240 // promote the remaining orange vertices to red
241 for (unsigned int i=0; i < vertexColor_.size(); ++i) {
242 // if a vertex is green or yellow don't do anything
243 if (vertexColor_[i] == EntityColor::green || vertexColor_[i] == EntityColor::yellow)
244 continue;
245
246 // set the vertex to red
247 vertexColor_[i] = EntityColor::red;
248 }
249
250 // count green elements
251 return std::count_if(elementColor_.begin(), elementColor_.end(),
252 [](EntityColor c){ return c == EntityColor::green; });
253 }
254
255 void resetJacobian(Assembler& assembler) const
256 {
257 auto& jacobian = assembler.jacobian();
258
259 // loop over all dofs
260 for (unsigned int rowIdx = 0; rowIdx < jacobian.N(); ++rowIdx)
261 {
262 // reset all entries corresponding to a non-green vertex
263 if (vertexColor_[rowIdx] != EntityColor::green)
264 {
265 // set all matrix entries in the row to 0
266 auto colIt = jacobian[rowIdx].begin();
267 const auto& colEndIt = jacobian[rowIdx].end();
268 for (; colIt != colEndIt; ++colIt) {
269 *colIt = 0.0;
270 }
271 }
272 }
273 }
274
276 {
277 elementColor_.assign(elementColor_.size(), EntityColor::red);
278 vertexColor_.assign(vertexColor_.size(), EntityColor::red);
279 }
280
281 EntityColor elementColor(size_t idx) const
282 { return elementColor_[idx]; }
283
284 EntityColor vertexColor(size_t idx) const
285 { return vertexColor_[idx]; }
286
287 EntityColor dofColor(size_t idx) const
288 { return vertexColor_[idx]; }
289
290private:
292 std::vector<EntityColor> elementColor_;
293 std::vector<EntityColor> vertexColor_;
294};
295
300template<class Assembler>
302{
303 using Scalar = typename Assembler::Scalar;
304 using GridGeometry = typename Assembler::GridGeometry;
305 using JacobianMatrix = typename Assembler::JacobianMatrix;
306
307public:
308 PartialReassemblerEngine(const Assembler& assembler)
309 : elementColor_(assembler.gridGeometry().elementMapper().size(), EntityColor::red)
310 {}
311
312 // returns number of green elements
313 std::size_t computeColors(const Assembler& assembler,
314 const std::vector<Scalar>& distanceFromLastLinearization,
315 Scalar threshold)
316 {
317 const auto& gridGeometry = assembler.gridGeometry();
318 const auto& gridView = gridGeometry.gridView();
319 const auto& elementMapper = gridGeometry.elementMapper();
320
321 // mark the red elements
322 for (const auto& element : elements(gridView))
323 {
324 int eIdx = elementMapper.index(element);
325
326 if (distanceFromLastLinearization[eIdx] > threshold)
327 {
328 // mark element as red if discrepancy is larger than
329 // the relative tolerance
330 elementColor_[eIdx] = EntityColor::red;
331 }
332 else
333 {
334 elementColor_[eIdx] = EntityColor::green;
335 }
336 }
337
338 // mark the neighbors also red
339 // (tested on the distance instead of the color, so the marking does not propagate further)
340 const auto& connectivityMap = gridGeometry.connectivityMap();
341 for (unsigned eIdx = 0; eIdx < elementColor_.size(); ++eIdx)
342 {
343 if (distanceFromLastLinearization[eIdx] > threshold)
344 {
345 for (const auto& connectedDof : connectivityMap[eIdx])
346 elementColor_[connectedDof.globalJ] = EntityColor::red;
347 }
348 }
349
350 // count green elements
351 return std::count_if(elementColor_.begin(), elementColor_.end(),
352 [](EntityColor c){return c == EntityColor::green;});
353
354 }
355
356 void resetJacobian(Assembler& assembler) const
357 {
358 auto& jacobian = assembler.jacobian();
359 const auto& connectivityMap = assembler.gridGeometry().connectivityMap();
360
361 // loop over all dofs
362 for (unsigned int colIdx = 0; colIdx < jacobian.M(); ++colIdx)
363 {
364 // reset all entries corresponding to a non-green element
365 if (elementColor_[colIdx] != EntityColor::green)
366 {
367 // set all matrix entries in the column to 0
368 jacobian[colIdx][colIdx] = 0;
369 for (const auto& dataJ : connectivityMap[colIdx])
370 jacobian[dataJ.globalJ][colIdx] = 0;
371 }
372 }
373 }
374
376 {
377 elementColor_.assign(elementColor_.size(), EntityColor::red);
378 }
379
380 EntityColor elementColor(size_t idx) const
381 { return elementColor_[idx]; }
382
383 EntityColor dofColor(size_t idx) const
384 { return elementColor_[idx]; }
385
386private:
388 std::vector<EntityColor> elementColor_;
389};
390
395template<class Assembler>
397: public PartialReassemblerEngine<Assembler, DiscretizationMethods::CCTpfa>
398{
400public:
401 using ParentType::ParentType;
402};
403
406{
407 template<class Engine>
408 auto operator()(Engine&& e) -> decltype(e.vertexColor(0)) {}
409};
410
416template<class Assembler>
418{
419 using Scalar = typename Assembler::Scalar;
420 using GridGeometry = typename Assembler::GridGeometry;
421 using JacobianMatrix = typename Assembler::JacobianMatrix;
422 using VertexMapper = typename GridGeometry::VertexMapper;
423
424 using DiscretizationMethod = typename GridGeometry::DiscretizationMethod;
426
427public:
428
433 PartialReassembler(const Assembler& assembler)
434 : engine_(assembler)
435 , greenElems_(0)
436 {
437 const auto& gridGeometry = assembler.gridGeometry();
438 totalElems_ = gridGeometry.elementMapper().size();
439 totalElems_ = gridGeometry.gridView().comm().sum(totalElems_);
440 }
441
457 void computeColors(const Assembler& assembler,
458 const std::vector<Scalar>& distanceFromLastLinearization,
459 Scalar threshold)
460 {
461 greenElems_ = engine_.computeColors(assembler, distanceFromLastLinearization, threshold);
462 }
463
465 {
466 engine_.resetColors();
467 }
468
469 void resetJacobian(Assembler& assembler) const
470 {
471 engine_.resetJacobian(assembler);
472 }
473
477 template <class Communication>
478 void report(const Communication& comm, std::ostream& outStream)
479 {
480 if (comm.size() > 1)
481 greenElems_ = comm.sum(greenElems_);
482
483 const auto reassembledElems = totalElems_ - greenElems_;
484 const auto width = Fmt::formatted_size("{}", totalElems_);
485 outStream << Fmt::format(", reassembled {:{}} ({:3}%) elements",
486 reassembledElems, width, 100*reassembledElems/totalElems_);
487 }
488
489 EntityColor elementColor(size_t idx) const
490 { return engine_.elementColor(idx); }
491
492 EntityColor dofColor(size_t idx) const
493 { return engine_.dofColor(idx); }
494
495 template<bool enable = decltype(isValid(hasVertexColor()).template check<Engine>())::value,
496 typename std::enable_if_t<enable, int> = 0>
497 EntityColor vertexColor(size_t idx) const
498 { return engine_.vertexColor(idx); }
499
500private:
501 Engine engine_;
502 size_t totalElems_;
503 size_t greenElems_;
504};
505
506} // namespace Dumux
507
508#endif
EntityColor dofColor(size_t idx) const
Definition partialreassembler.hh:50
void resetJacobian(Args &&... args) const
Definition partialreassembler.hh:42
void computeColors(Args &&... args)
Definition partialreassembler.hh:45
EntityColor vertexColor(size_t idx) const
Definition partialreassembler.hh:56
void report(Args &&... args)
Definition partialreassembler.hh:39
DefaultPartialReassembler(Args &&... args)
Definition partialreassembler.hh:35
void resetColors(Args &&... args)
Definition partialreassembler.hh:48
EntityColor elementColor(size_t idx) const
Definition partialreassembler.hh:53
EntityColor dofColor(size_t idx) const
Definition partialreassembler.hh:287
std::size_t computeColors(const Assembler &assembler, const std::vector< Scalar > &distanceFromLastLinearization, Scalar threshold)
Definition partialreassembler.hh:104
PartialReassemblerEngine(const Assembler &assembler)
Definition partialreassembler.hh:98
void resetJacobian(Assembler &assembler) const
Definition partialreassembler.hh:255
EntityColor vertexColor(size_t idx) const
Definition partialreassembler.hh:284
EntityColor elementColor(size_t idx) const
Definition partialreassembler.hh:281
void resetJacobian(Assembler &assembler) const
Definition partialreassembler.hh:356
std::size_t computeColors(const Assembler &assembler, const std::vector< Scalar > &distanceFromLastLinearization, Scalar threshold)
Definition partialreassembler.hh:313
EntityColor dofColor(size_t idx) const
Definition partialreassembler.hh:383
PartialReassemblerEngine(const Assembler &assembler)
Definition partialreassembler.hh:308
EntityColor elementColor(size_t idx) const
Definition partialreassembler.hh:380
the partial reassembler engine specialized for discretization methods
Definition partialreassembler.hh:63
void resetJacobian(Args &&... args) const
Definition partialreassembler.hh:78
EntityColor elementColor(size_t idx) const
Definition partialreassembler.hh:68
PartialReassemblerEngine(const Assembler &)
Definition partialreassembler.hh:65
EntityColor dofColor(size_t idx) const
Definition partialreassembler.hh:71
void resetColors(Args &&... args)
Definition partialreassembler.hh:81
std::size_t computeColors(Args &&... args)
Definition partialreassembler.hh:75
PartialReassembler(const Assembler &assembler)
constructor
Definition partialreassembler.hh:433
EntityColor vertexColor(size_t idx) const
Definition partialreassembler.hh:497
void resetJacobian(Assembler &assembler) const
Definition partialreassembler.hh:469
void resetColors()
Definition partialreassembler.hh:464
void computeColors(const Assembler &assembler, const std::vector< Scalar > &distanceFromLastLinearization, Scalar threshold)
Determine the colors of entities for partial reassembly.
Definition partialreassembler.hh:457
void report(const Communication &comm, std::ostream &outStream)
called by the assembler after successful assembly
Definition partialreassembler.hh:478
EntityColor dofColor(size_t idx) const
Definition partialreassembler.hh:492
EntityColor elementColor(size_t idx) const
Definition partialreassembler.hh:489
An enum class to define the colors of elements and vertices required for partial Jacobian reassembly.
Formatting based on the fmt-library which implements std::format of C++20.
dune-grid capabilities compatibility layer
EntityColor
The colors of elements and vertices required for partial Jacobian reassembly.
Definition entitycolor.hh:23
@ green
does not need to be reassembled
Definition entitycolor.hh:40
@ red
distance from last linearization is above the tolerance
Definition entitycolor.hh:25
@ yellow
neighboring entity is red
Definition entitycolor.hh:28
@ orange
Definition entitycolor.hh:37
constexpr auto isValid(const Expression &t)
A function that creates a test functor to do class member introspection at compile time.
Definition isvalid.hh:81
A helper function for class member function introspection.
The available discretization methods in Dumux.
Definition cellcentered/mpfa/elementvolumevariables.hh:24
Definition method.hh:20
Definition adapt.hh:17
VectorCommDataHandle< Mapper, Vector, codim, Detail::Min, DataType > VectorCommDataHandleMin
Definition vectorcommdatahandle.hh:217
VectorCommDataHandle< Mapper, Vector, codim, Detail::Max, DataType > VectorCommDataHandleMax
Definition vectorcommdatahandle.hh:220
helper struct to determine whether the an engine class has vertex colors
Definition partialreassembler.hh:406
auto operator()(Engine &&e) -> decltype(e.vertexColor(0))
Definition partialreassembler.hh:408
Contains a class to exchange entries of a vector.