dune-assembler 2.11
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
137 {
138 auto [i, ii] = splitIndex(iii, IsSingleRowMatrix<Matrix>());
139 auto [j, jj] = splitIndex(jjj, IsSingleColumnMatrix<Matrix>());
140 return hybridFlatMatrixEntryAccess(matrix, i, j, [&,ii=ii,jj=jj](auto&& matrix_ij) -> decltype(auto) {
141 return hybridRecursiveMatrixEntryAccess(matrix_ij, ii, jj, f);
142 });
143 }
144}
145
146
147
148} // end namespace Dune::Assembler::Impl
149
150
151
152
153namespace Dune::Assembler {
154
155// forward declaration
156template <class Matrix>
158
159template <class Matrix>
161{
162
163public:
166
168 using LocalPattern = typename PatternBuilder::LocalPattern;
169
170private:
171
172 template <class R>
173 struct ConvertToRef
174 {
175
176 template <class M>
177 R& operator() (M& matrix) const
178 requires(std::is_convertible_v<M&, R&>)
179 {
180 return matrix;
181 }
182
183 // This is needed for treating `Dune::FieldMatrix<R,1,1>` like
184 // a scalar, because there's no cast to `R&`. We don't need
185 // an overload for the const case, because there is a cast
186 // to `const R&`.
188 requires(not std::is_const_v<R>)
189 {
190 return matrix[0][0];
191 }
192 };
193
194public:
196 : matrix_(matrix)
197 {}
198
200 {
201 return PatternBuilder{matrix_};
202 }
203
204 template <class RowMultiIndex, class ColMultiIndex>
205 const value_type& operator() (const RowMultiIndex& row, const ColMultiIndex& col) const
206 {
207 return Impl::hybridRecursiveMatrixEntryAccess(matrix_, row, col, ConvertToRef<const value_type>());
208 }
209
210 template <class RowMultiIndex, class ColMultiIndex>
212 {
213 return Impl::hybridRecursiveMatrixEntryAccess(matrix_, row, col, ConvertToRef<value_type>());
214 }
215
216 template <class RowLocalView, class ColLocalView>
217 void scatter (const RowLocalView& rowLocalView, const ColLocalView& colLocalView,
219 {
220 auto rowIndices = Dune::Assembler::Impl::localIndices(rowLocalView.tree());
221 auto colIndices = Dune::Assembler::Impl::localIndices(colLocalView.tree());
222 localPattern.visitEntries(rowIndices, colIndices, [&](const auto& i, const auto&j) {
223 (*this)(rowLocalView.index(i), colLocalView.index(j)) += localMatrix[i][j];
224 });
225 }
226
227 void setZero ()
228 {
229 matrix_ = 0;
230 }
231
232private:
233 Matrix& matrix_;
234};
235
236
237
238// Specialization for flat BCRSMatrix
239template <class T, class A>
241 : public Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Dune::BCRSMatrix<T, A>>>
242{
244 using Base = Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Matrix>>;
245
246public:
247
249
251 : matrix_(matrix)
252 {}
253
254 template <class RowBasis, class ColBasis>
255 void resize (const RowBasis& rowBasis, const ColBasis& colBasis)
256 {
257 indexSet_.resize(rowBasis.size(), colBasis.size());
258 }
259
260 template <class RowIndex, class ColIndex>
261 void add (const RowIndex& rowIndex, const ColIndex& colIndex)
262 {
263 indexSet_.add(rowIndex[0], colIndex[0]);
264 }
265
267 {
268 indexSet_.exportIdx(matrix_);
269 matrix_ = 0;
270 }
271
280 template <class F>
281 void forEachEntry (F&& f) const
282 {
283 for (auto row : Dune::range(indexSet_.rows()))
284 {
285 std::visit([&](const auto& columnIndices) {
286 for (auto col : columnIndices)
288 }, indexSet_.columnIndices(row));
289 }
290 }
291
292private:
293 Matrix& matrix_;
294 Dune::MatrixIndexSet indexSet_;
295};
296
297
298
299// Specialization for flat MultiTypeBlockMatrix of flat matrix
300template <class Row0, class ... Rows>
302 : public Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<MultiTypeBlockMatrix<Row0,Rows...>>>
303{
304 using Matrix = MultiTypeBlockMatrix<Row0,Rows...>;
305 using Base = Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Matrix>>;
306
307 static constexpr auto outerRows_ = Dune::index_constant<Matrix::N()>();
308 static constexpr auto outerCols_ = Dune::index_constant<Matrix::M()>();
309
310public:
311
313
315 : matrix_(matrix)
316 {}
317
318 template <class RowBasis, class ColBasis>
319 void resize (const RowBasis& rowBasis, const ColBasis& colBasis)
320 {
321 for (auto i : Dune::range(outerRows_))
322 for (auto j : Dune::range(outerCols_))
323 indices_[i][j].resize(rowBasis.size({i}), colBasis.size({j}));
324 }
325
326 template <class RowIndex, class ColIndex>
327 void add (const RowIndex& rowIndex, const ColIndex& colIndex)
328 {
329 indices_[rowIndex[0]][colIndex[0]].add(rowIndex[1], colIndex[1]);
330 }
331
333 {
334 Hybrid::forEach(Dune::range(outerRows_), [&](auto&& i) {
335 Hybrid::forEach(Dune::range(outerCols_), [&](auto&& j) {
336 indices_[i][j].exportIdx(matrix_[i][j]);
337 matrix_[i][j] = 0;
338 });
339 });
340 }
341
350 template <class F>
351 void forEachEntry (F&& f) const
352 {
354 Hybrid::forEach(Dune::range(std::size_t(outerRows_)), [&](auto&& i) {
355 Hybrid::forEach(Dune::range(std::size_t(outerCols_)), [&](auto&& j) {
356 for (auto ii : Dune::range(std::size_t(indices_[i][j].rows())))
357 {
358 std::visit([&](const auto& columnIndices) {
359 for (auto jj : columnIndices)
361 }, indices_[i][j].columnIndices(ii));
362 }
363 });
364 });
365 }
366
367private:
368 Matrix& matrix_;
370};
371
372
373
374// Specialization for Dune::Matrix of flat BCRSMatrix
375template <class T, class OuterA, class InnerA>
376class ISTLMatrixPatternBackend<Dune::Matrix<Dune::BCRSMatrix<T, InnerA>, OuterA>>
377 : public Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Dune::Matrix<Dune::BCRSMatrix<T, InnerA>, OuterA>>>
378{
380 using Base = Impl::MatrixPatternBackendMixIn<ISTLMatrixPatternBackend<Matrix>>;
381
382public:
383
385
387 : matrix_(matrix)
388 {}
389
390 template <class RowBasis, class ColBasis>
391 void resize (const RowBasis& rowBasis, const ColBasis& colBasis)
392 {
393 auto outerRows = rowBasis.size();
394 auto outerCols = colBasis.size();
395 indices_.resize(outerRows);
396 for (auto i : Dune::range(outerRows))
397 indices_[i].resize(outerCols);
398 for (auto i : Dune::range(outerRows))
399 for (auto j : Dune::range(outerCols))
400 indices_[i][j].resize(rowBasis.size({i}), colBasis.size({j}));
401 }
402
403 template <class RowIndex, class ColIndex>
404 void add (const RowIndex& rowIndex, const ColIndex& colIndex)
405 {
406 indices_[rowIndex[0]][colIndex[0]].add(rowIndex[1], colIndex[1]);
407 }
408
410 {
411 auto outerRows = indices_.size();
412 auto outerCols = indices_[0].size();
413 matrix_.setSize(outerRows, outerCols);
414 for (auto i : Dune::range(outerRows))
415 for (auto j : Dune::range(outerCols))
416 indices_[i][j].exportIdx(matrix_[i][j]);
417 for (auto i : Dune::range(outerRows))
418 for (auto j : Dune::range(outerCols))
419 matrix_[i][j] = 0;
420 }
421
430 template <class F>
431 void forEachEntry (F&& f) const
432 {
434 Hybrid::forEach(Dune::range(std::size_t(indices_.size())), [&](auto&& i) {
435 Hybrid::forEach(Dune::range(std::size_t(indices_[i].size())), [&](auto&& j) {
436 for (auto ii : Dune::range(std::size_t(indices_[i][j].rows())))
437 {
438 std::visit([&](const auto& columnIndices) {
439 for (auto jj : columnIndices)
440 f(MultiIndex{{i, ii}}, MultiIndex{{j, std::size_t(jj)}});
441 }, indices_[i][j].columnIndices(ii));
442 }
443 });
444 });
445 }
446
447private:
448 Matrix& matrix_;
450};
451
452
453
454} // end namespace Dune::Assembler
455
456#endif // DUNE_ASSEMBLER_BACKENDS_ISTLMATRIXBACKEND_HH
Definition localboundaryintersectionmatrixassembler.hh:9
Col col
void add(const Vertex &vertex)
constexpr index_constant< 0 > _0
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
constexpr void forEach(Range &&range, F &&f)
static constexpr size_type M()
size_type rowIndex() const
virtual void operator()()=0
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:157
Definition istlmatrixbackend.hh:161
PatternBuilder patternBuilder()
Definition istlmatrixbackend.hh:199
ISTLMatrixBackend(Matrix &matrix)
Definition istlmatrixbackend.hh:195
typename PatternBuilder::LocalPattern LocalPattern
Definition istlmatrixbackend.hh:168
typename Matrix::field_type value_type
Definition istlmatrixbackend.hh:164
void scatter(const RowLocalView &rowLocalView, const ColLocalView &colLocalView, const LocalMatrix &localMatrix, const LocalPattern &localPattern)
Definition istlmatrixbackend.hh:217
void setZero()
Definition istlmatrixbackend.hh:227
void resize(const RowBasis &rowBasis, const ColBasis &colBasis)
Definition istlmatrixbackend.hh:255
void forEachEntry(F &&f) const
Traverse entries in the pattern.
Definition istlmatrixbackend.hh:281
ISTLMatrixPatternBackend(Matrix &matrix)
Definition istlmatrixbackend.hh:250
typename Base::LocalPattern LocalPattern
Definition istlmatrixbackend.hh:248
void add(const RowIndex &rowIndex, const ColIndex &colIndex)
Definition istlmatrixbackend.hh:261
void forEachEntry(F &&f) const
Traverse entries in the pattern.
Definition istlmatrixbackend.hh:351
ISTLMatrixPatternBackend(Matrix &matrix)
Definition istlmatrixbackend.hh:314
void add(const RowIndex &rowIndex, const ColIndex &colIndex)
Definition istlmatrixbackend.hh:327
typename Base::LocalPattern LocalPattern
Definition istlmatrixbackend.hh:312
void resize(const RowBasis &rowBasis, const ColBasis &colBasis)
Definition istlmatrixbackend.hh:319
void resize(const RowBasis &rowBasis, const ColBasis &colBasis)
Definition istlmatrixbackend.hh:391
typename Base::LocalPattern LocalPattern
Definition istlmatrixbackend.hh:384
void add(const RowIndex &rowIndex, const ColIndex &colIndex)
Definition istlmatrixbackend.hh:404
void forEachEntry(F &&f) const
Traverse entries in the pattern.
Definition istlmatrixbackend.hh:431
T make_tuple(T... args)
T visit(T... args)