dune-assembler 2.12
Loading...
Searching...
No Matches
istlmatrixbackend.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_BACKENDS_ISTLMATRIXBACKEND_HH
5#define DUNE_ASSEMBLER_BACKENDS_ISTLMATRIXBACKEND_HH
6
7#include <array>
8#include <vector>
9
12
14
21
22
23
24namespace Dune::Assembler::Impl {
25
26
27
28// Mix-in class for MatrixPatternBackend implementations.
29// This CRTP base class implements scatter() by adding individual
30// index pairs to the global pattern using the
31// add(rowIndex, colIndex) provided by the derived
32// implementation class.
33// The used LocalPattern class can be switched using a
34// template parameter, using LocalPatternMatrix as default.
35template <class Impl, class LP=Dune::Assembler::LocalPatternMatrix>
36class MatrixPatternBackendMixIn
37{
38public:
39 using LocalPattern = LP;
40
41 // use a given pattern
42 template <class RowLocalView, class ColLocalView>
43 void scatter (const RowLocalView& rowLocalView, const ColLocalView& colLocalView,
44 const LocalPattern& localPattern)
45 {
46 auto rowIndices = Dune::Assembler::Impl::localIndices(rowLocalView.tree());
47 auto colIndices = Dune::Assembler::Impl::localIndices(colLocalView.tree());
48 localPattern.visitEntries(rowIndices, colIndices, [&](const auto& i, const auto&j) {
49 static_cast<Impl*>(this)->add(rowLocalView.index(i), colLocalView.index(j));
50 });
51 }
52
53};
54
55
56
57// Number of matrix rows provided as Dune::index_constant
58// if matrix does not support dynamic access.
59template <class Matrix>
60auto numRows (const Matrix& m)
61{
62 if constexpr (requires { m[0]; })
63 return m.N();
64 else
66}
67
68// Number of matrix columns provided as Dune::index_constant
69// if matrix does not support dynamic access.
70template <class Matrix>
71auto numCols (const Matrix& m)
72{
73 if constexpr (requires { m[Dune::Indices::_0][0]; })
74 return m.M();
75 else
77}
78
79// Invoke callback with index corresponding to i in given range
80template <class T, T to, T from, class I, class F>
81static decltype(auto) indexInRange(const Dune::StaticIntegralRange<T, to, from>& range, const I& i, F&& f)
82{
83 if constexpr (to==from+1)
85 else
86 {
87 if (i==from)
89 else
90 return indexInRange(Dune::StaticIntegralRange<T, to, from+1>(), i, f);
91 }
92}
93
94// Invoke callback with index corresponding to i in given range
95template <class T, class I, class F>
96static decltype(auto) indexInRange(const Dune::IntegralRange<T>& range, const I& i, F&& f)
97{
98 return f(i);
99}
100
101// This calls f(matrix[i][j]) and returns the result.
102// This works with dynamic indices i,j, even for a multi-type matrix.
103// However, it requires that f() has a unique return type.
104template <class Matrix, class RowIndex, class ColIndex, class F>
105decltype(auto) hybridFlatMatrixEntryAccess(Matrix&& matrix, const RowIndex& i, const ColIndex& j, F&& f)
106{
107 return indexInRange(range(numRows(matrix)), i, [&](auto ii) -> decltype(auto) {
108 return indexInRange(range(numCols(matrix)), j, [&](auto jj) -> decltype(auto) {
109 return f(matrix[ii][jj]);
110 });
111 });
112}
113
114
115
116// Call f(matrix[i0][j0]...[in][jm]), by recursively resolving row- and column-multi-indices.
117// Whenenver a SingleRowMatrix or SingleColumnMatrix is encountered, a zero row- or column-index
118// is inserted, respectively. The recursion ends, whenever f(matrixEntry) can be called.
119// This works with dynamic indices i,j, even for a multi-type matrix.
120// However, it requires that f() has a unique return type.
121template <class Matrix, class RowIndex, class ColIndex, class F>
122static decltype(auto) hybridRecursiveMatrixEntryAccess(Matrix& matrix, const RowIndex& iii, const ColIndex& jjj, F&& f)
123{
124 using Dune::Functions::Imp::shiftedDynamicMultiIndex;
125 auto splitIndex = [] (auto&& multiIndex, auto insertZero) {
126 if constexpr (decltype(insertZero)::value)
127 return std::make_tuple(Dune::Indices::_0, shiftedDynamicMultiIndex<0>(multiIndex));
128 else
129 {
130 assert(multiIndex.size()>0);
131 return std::make_tuple(multiIndex[Dune::Indices::_0], shiftedDynamicMultiIndex<1>(multiIndex)) ;
132 }
133 };
134 if constexpr (std::is_invocable_v<F, Matrix&>)
135 return f(matrix);
136 else if constexpr (std::is_invocable_v<F, Matrix&, const RowIndex&, const ColIndex&>)
137 return f(matrix, iii, jjj);
138 else
139 {
140 auto [i, ii] = splitIndex(iii, IsSingleRowMatrix<Matrix>());
141 auto [j, jj] = splitIndex(jjj, IsSingleColumnMatrix<Matrix>());
142 return hybridFlatMatrixEntryAccess(matrix, i, j, [&,ii=ii,jj=jj](auto&& matrix_ij) -> decltype(auto) {
143 return hybridRecursiveMatrixEntryAccess(matrix_ij, ii, jj, f);
144 });
145 }
146}
147
148
149
150} // end namespace Dune::Assembler::Impl
151
152
153
154
155namespace Dune::Assembler {
156
157// forward declaration
158template <class Matrix>
160
161template <class Matrix>
163{
164
165public:
168
170 using LocalPattern = typename PatternBuilder::LocalPattern;
171
172private:
173
174 template <class R>
175 struct ConvertToRef
176 {
177
178 template <class M>
179 R& operator() (M& matrix) const
180 requires(std::is_convertible_v<M&, R&>)
181 {
182 return matrix;
183 }
184
185 // This is needed for treating `Dune::FieldMatrix<R,1,1>` like
186 // a scalar, because there's no cast to `R&`. We don't need
187 // an overload for the const case, because there is a cast
188 // to `const R&`.
190 requires(not std::is_const_v<R>)
191 {
192 return matrix[0][0];
193 }
194 };
195
196 class AccumulateValue
197 {
198 const value_type& value_;
199
200 public:
201
202 AccumulateValue (const value_type& value)
203 : value_(value)
204 {}
205
206 template <class M>
207 void operator() (M& matrix) const
208 requires(std::is_convertible_v<M&, value_type&>)
209 {
210 matrix += value_;
211 }
212
213 template <class T, class A, class RowIndex, class ColIndex>
214 void operator() (Dune::BCRSMatrix<T, A>& matrix, const RowIndex& ii, const ColIndex& jj) const
215 requires(std::is_convertible_v<T&, value_type&>)
216 {
217 using namespace Dune::Indices;
218 matrix[ii[_0]][jj[_0]] += value_;
219 }
220
221 template <class T, int n, int m, class A, class RowIndex, class ColIndex>
222 void operator() (Dune::BCRSMatrix<Dune::FieldMatrix<T, n, m>, A>& matrix, const RowIndex& ii, const ColIndex& jj) const
223 requires(std::is_convertible_v<T&, value_type&>)
224 {
225 using namespace Dune::Indices;
226 matrix[ii[_0]][jj[_0]][ii[_1]][jj[_1]] += value_;
227 }
228
229 template <class T, int n, class A, class RowIndex, class ColIndex>
230 void operator() (Dune::BCRSMatrix<Dune::DiagonalMatrix<T, n>, A>& matrix, const RowIndex& ii, const ColIndex& jj) const
231 requires(std::is_convertible_v<T&, value_type&>)
232 {
233 using namespace Dune::Indices;
234 if (ii[_1] == jj[_1])
235 matrix[ii[_0]][jj[_0]].diagonal(ii[_1]) += value_;
236 }
237
238 template <class T, int n, class A, class RowIndex, class ColIndex>
240 requires(std::is_convertible_v<T&, value_type&>)
241 {
242 using namespace Dune::Indices;
243 if ((ii[_1] == 0) and (jj[_1] == 0))
244 matrix[ii[_0]][jj[_0]].scalar() += value_;
245 }
246
247 template <class F, int n, class RowIndex, class ColIndex>
248 void operator() (Dune::DiagonalMatrix<F, n>& matrix, const RowIndex& ii, const ColIndex& jj) const
249 {
250 using namespace Dune::Indices;
251 if (ii[_0] == jj[_0])
252 matrix.diagonal(ii[_0]) += value_;
253 }
254
255 template <class F, int n, class RowIndex, class ColIndex>
256 void operator() (Dune::ScaledIdentityMatrix<F, n>& matrix, const RowIndex& ii, const ColIndex& jj) const
257 {
258 using namespace Dune::Indices;
259 if ((ii[_0] == 0) and (jj[_0] == 0))
260 matrix.scalar() += value_;
261 }
262
263 };
264
265public:
267 : matrix_(matrix)
268 {}
269
271 {
272 return PatternBuilder{matrix_};
273 }
274
275 template <class RowMultiIndex, class ColMultiIndex>
276 const value_type& operator() (const RowMultiIndex& row, const ColMultiIndex& col) const
277 {
278 return Impl::hybridRecursiveMatrixEntryAccess(matrix_, row, col, ConvertToRef<const value_type>());
279 }
280
281 template <class RowMultiIndex, class ColMultiIndex>
283 {
284 return Impl::hybridRecursiveMatrixEntryAccess(matrix_, row, col, ConvertToRef<value_type>());
285 }
286
287 template <class RowLocalView, class ColLocalView>
288 void scatter (const RowLocalView& rowLocalView, const ColLocalView& colLocalView,
290 {
291 auto rowIndices = Dune::Assembler::Impl::localIndices(rowLocalView.tree());
292 auto colIndices = Dune::Assembler::Impl::localIndices(colLocalView.tree());
293 localPattern.visitEntries(rowIndices, colIndices, [&](const auto& i, const auto&j) {
294 Impl::hybridRecursiveMatrixEntryAccess(matrix_, rowLocalView.index(i), colLocalView.index(j), AccumulateValue(localMatrix[i][j]));
295 });
296 }
297
298 void setZero ()
299 {
300 matrix_ = 0;
301 }
302
303private:
304 Matrix& matrix_;
305};
306
307
308
309// Specialization for flat BCRSMatrix
310template <class T, class A>
312 : public Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Dune::BCRSMatrix<T, A>>>
313{
315 using Base = Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Matrix>>;
316
317public:
318
320
322 : matrix_(matrix)
323 {}
324
325 template <class RowBasis, class ColBasis>
326 void resize (const RowBasis& rowBasis, const ColBasis& colBasis)
327 {
328 indexSet_.resize(rowBasis.size(), colBasis.size());
329 }
330
331 template <class RowIndex, class ColIndex>
332 void add (const RowIndex& rowIndex, const ColIndex& colIndex)
333 {
334 indexSet_.add(rowIndex[0], colIndex[0]);
335 }
336
338 {
339 indexSet_.exportIdx(matrix_);
340 matrix_ = 0;
341 }
342
351 template <class F>
352 void forEachEntry (F&& f) const
353 {
354 for (auto row : Dune::range(indexSet_.rows()))
355 {
356 std::visit([&](const auto& columnIndices) {
357 for (auto col : columnIndices)
359 }, indexSet_.columnIndices(row));
360 }
361 }
362
363private:
364 Matrix& matrix_;
365 Dune::MatrixIndexSet indexSet_;
366};
367
368
369
370// Specialization for flat MultiTypeBlockMatrix of flat matrix
371template <class Row0, class ... Rows>
373 : public Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<MultiTypeBlockMatrix<Row0,Rows...>>>
374{
375 using Matrix = MultiTypeBlockMatrix<Row0,Rows...>;
376 using Base = Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Matrix>>;
377
378 static constexpr auto outerRows_ = Dune::index_constant<Matrix::N()>();
379 static constexpr auto outerCols_ = Dune::index_constant<Matrix::M()>();
380
381public:
382
384
386 : matrix_(matrix)
387 {}
388
389 template <class RowBasis, class ColBasis>
390 void resize (const RowBasis& rowBasis, const ColBasis& colBasis)
391 {
392 for (auto i : Dune::range(outerRows_))
393 for (auto j : Dune::range(outerCols_))
394 indices_[i][j].resize(rowBasis.size({i}), colBasis.size({j}));
395 }
396
397 template <class RowIndex, class ColIndex>
398 void add (const RowIndex& rowIndex, const ColIndex& colIndex)
399 {
400 indices_[rowIndex[0]][colIndex[0]].add(rowIndex[1], colIndex[1]);
401 }
402
404 {
405 Hybrid::forEach(Dune::range(outerRows_), [&](auto&& i) {
406 Hybrid::forEach(Dune::range(outerCols_), [&](auto&& j) {
407 indices_[i][j].exportIdx(matrix_[i][j]);
408 matrix_[i][j] = 0;
409 });
410 });
411 }
412
421 template <class F>
422 void forEachEntry (F&& f) const
423 {
425 Hybrid::forEach(Dune::range(std::size_t(outerRows_)), [&](auto&& i) {
426 Hybrid::forEach(Dune::range(std::size_t(outerCols_)), [&](auto&& j) {
427 for (auto ii : Dune::range(std::size_t(indices_[i][j].rows())))
428 {
429 std::visit([&](const auto& columnIndices) {
430 for (auto jj : columnIndices)
432 }, indices_[i][j].columnIndices(ii));
433 }
434 });
435 });
436 }
437
438private:
439 Matrix& matrix_;
441};
442
443
444
445// Specialization for Dune::Matrix of flat BCRSMatrix
446template <class T, class OuterA, class InnerA>
447class ISTLMatrixPatternBackend<Dune::Matrix<Dune::BCRSMatrix<T, InnerA>, OuterA>>
448 : public Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Dune::Matrix<Dune::BCRSMatrix<T, InnerA>, OuterA>>>
449{
451 using Base = Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Matrix>>;
452
453public:
454
456
458 : matrix_(matrix)
459 {}
460
461 template <class RowBasis, class ColBasis>
462 void resize (const RowBasis& rowBasis, const ColBasis& colBasis)
463 {
464 auto outerRows = rowBasis.size();
465 auto outerCols = colBasis.size();
466 indices_.resize(outerRows);
467 for (auto i : Dune::range(outerRows))
468 indices_[i].resize(outerCols);
469 for (auto i : Dune::range(outerRows))
470 for (auto j : Dune::range(outerCols))
471 indices_[i][j].resize(rowBasis.size({i}), colBasis.size({j}));
472 }
473
474 template <class RowIndex, class ColIndex>
475 void add (const RowIndex& rowIndex, const ColIndex& colIndex)
476 {
477 indices_[rowIndex[0]][colIndex[0]].add(rowIndex[1], colIndex[1]);
478 }
479
481 {
482 auto outerRows = indices_.size();
483 auto outerCols = indices_[0].size();
484 matrix_.setSize(outerRows, outerCols);
485 for (auto i : Dune::range(outerRows))
486 for (auto j : Dune::range(outerCols))
487 indices_[i][j].exportIdx(matrix_[i][j]);
488 for (auto i : Dune::range(outerRows))
489 for (auto j : Dune::range(outerCols))
490 matrix_[i][j] = 0;
491 }
492
501 template <class F>
502 void forEachEntry (F&& f) const
503 {
505 Hybrid::forEach(Dune::range(std::size_t(indices_.size())), [&](auto&& i) {
506 Hybrid::forEach(Dune::range(std::size_t(indices_[i].size())), [&](auto&& j) {
507 for (auto ii : Dune::range(std::size_t(indices_[i][j].rows())))
508 {
509 std::visit([&](const auto& columnIndices) {
510 for (auto jj : columnIndices)
511 f(MultiIndex{{i, ii}}, MultiIndex{{j, std::size_t(jj)}});
512 }, indices_[i][j].columnIndices(ii));
513 }
514 });
515 });
516 }
517
518private:
519 Matrix& matrix_;
521};
522
523
524
525} // end namespace Dune::Assembler
526
527#endif // DUNE_ASSEMBLER_BACKENDS_ISTLMATRIXBACKEND_HH
Definition localboundaryintersectionmatrixassembler.hh:9
Col col
OperatorHierarchy::ParallelMatrixHierarchy::ConstIterator matrix
void add(const Vertex &vertex)
static constexpr IntegralRange< T > range(T from, T to) noexcept
constexpr void forEach(Range &&range, F &&f)
static constexpr size_type M()
size_type rowIndex() const
virtual void operator()()=0
constexpr index_constant< 0 > _0
constexpr index_constant< 1 > _1
void setSize(size_type rows, size_type cols)
typename Imp::BlockTraits< T >::field_type field_type
size_type M() const
size_type N() const
Definition istlmatrixbackend.hh:159
Definition istlmatrixbackend.hh:163
PatternBuilder patternBuilder()
Definition istlmatrixbackend.hh:270
ISTLMatrixBackend(Matrix &matrix)
Definition istlmatrixbackend.hh:266
typename PatternBuilder::LocalPattern LocalPattern
Definition istlmatrixbackend.hh:170
typename Matrix::field_type value_type
Definition istlmatrixbackend.hh:166
void scatter(const RowLocalView &rowLocalView, const ColLocalView &colLocalView, const LocalMatrix &localMatrix, const LocalPattern &localPattern)
Definition istlmatrixbackend.hh:288
void setZero()
Definition istlmatrixbackend.hh:298
void resize(const RowBasis &rowBasis, const ColBasis &colBasis)
Definition istlmatrixbackend.hh:326
void forEachEntry(F &&f) const
Traverse entries in the pattern.
Definition istlmatrixbackend.hh:352
ISTLMatrixPatternBackend(Matrix &matrix)
Definition istlmatrixbackend.hh:321
typename Base::LocalPattern LocalPattern
Definition istlmatrixbackend.hh:319
void add(const RowIndex &rowIndex, const ColIndex &colIndex)
Definition istlmatrixbackend.hh:332
void forEachEntry(F &&f) const
Traverse entries in the pattern.
Definition istlmatrixbackend.hh:422
ISTLMatrixPatternBackend(Matrix &matrix)
Definition istlmatrixbackend.hh:385
void add(const RowIndex &rowIndex, const ColIndex &colIndex)
Definition istlmatrixbackend.hh:398
typename Base::LocalPattern LocalPattern
Definition istlmatrixbackend.hh:383
void resize(const RowBasis &rowBasis, const ColBasis &colBasis)
Definition istlmatrixbackend.hh:390
void resize(const RowBasis &rowBasis, const ColBasis &colBasis)
Definition istlmatrixbackend.hh:462
typename Base::LocalPattern LocalPattern
Definition istlmatrixbackend.hh:455
void add(const RowIndex &rowIndex, const ColIndex &colIndex)
Definition istlmatrixbackend.hh:475
void forEachEntry(F &&f) const
Traverse entries in the pattern.
Definition istlmatrixbackend.hh:502
T make_tuple(T... args)
T visit(T... args)