dune-istl 2.12-git
Loading...
Searching...
No Matches
foreach.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file LICENSE.md in module root
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
3#pragma once
4
5#include<type_traits>
6#include<utility>
7#include<cassert>
8
13
17
18namespace Dune{
19
20 namespace Impl {
21
22 // stolen from dune-functions: we call a type "scalar" if it does not support index accessing
23 template<class C>
24 using StaticIndexAccessConcept = decltype(std::declval<C>()[Dune::Indices::_0]);
25
26 template<class C>
28
29 // Type trait for matrix types that supports
30 // - iteration done row-wise
31 // - sparse iteration over nonzero entries
32 template <class T>
33 struct IsRowMajorSparse : std::false_type {};
34
35 // This is supported by the following matrix types:
36 template <class B, class A>
37 struct IsRowMajorSparse<BCRSMatrix<B,A>> : std::true_type {};
38
39 template <class B, class P, class A>
40 struct IsRowMajorSparse<Dune::Experimental::BCRSMatrix<B,P,A>> : std::true_type {};
41
42 template <class B, class P, class A>
43 struct IsRowMajorSparse<Dune::Experimental::Matrix<B,P,A>> : std::true_type {};
44
45 template <class K, int n>
46 struct IsRowMajorSparse<DiagonalMatrix<K,n>> : std::true_type {};
47
48 template <class K, int n>
49 struct IsRowMajorSparse<ScaledIdentityMatrix<K,n>> : std::true_type {};
50
51
52 template <class Matrix>
53 auto rows(Matrix const& /*matrix*/, PriorityTag<2>) -> std::integral_constant<std::size_t, Matrix::N()> { return {}; }
54
55 template <class Matrix>
56 auto cols(Matrix const& /*matrix*/, PriorityTag<2>) -> std::integral_constant<std::size_t, Matrix::M()> { return {}; }
57
58 template <class Matrix>
59 auto rows(Matrix const& matrix, PriorityTag<1>) -> decltype(matrix.N()) { return matrix.N(); }
60
61 template <class Matrix>
62 auto cols(Matrix const& matrix, PriorityTag<1>) -> decltype(matrix.M()) { return matrix.M(); }
63
64 template <class Vector>
65 auto size(Vector const& /*vector*/, PriorityTag<2>) -> std::integral_constant<std::size_t, Vector::size()> { return {}; }
66
67 template <class Vector>
68 auto size(Vector const& vector, PriorityTag<1>) -> decltype(vector.size()) { return vector.size(); }
69
70
71 } // end namespace Impl
72
73namespace ForEach{
74
75 template <class Matrix>
76 auto rows(Matrix const& matrix) { return Impl::rows(matrix, PriorityTag<5>{}); }
77
78 template <class Matrix>
79 auto cols(Matrix const& matrix) { return Impl::cols(matrix, PriorityTag<5>{}); }
80
81 template <class Vector>
82 auto size(Vector const& vector) { return Impl::size(vector, PriorityTag<5>{}); }
83
84} // namespace ForEach
85
86
87
88
101template <class Vector, class F>
102std::size_t flatVectorForEach(Vector&& vector, F&& f, std::size_t offset = 0)
103{
104 using V = std::decay_t<Vector>;
105 if constexpr( Impl::IsScalar<V>::value )
106 {
107 f(vector, offset);
108 return 1;
109 }
110 else
111 {
112 std::size_t idx = 0;
113 Hybrid::forEach(Dune::range(ForEach::size(vector)), [&](auto i) {
114 idx += flatVectorForEach(vector[i], f, offset + idx);
115 });
116 return idx;
117 }
118}
119
120
138template <class Matrix, class F>
140{
141 using M = std::decay_t<Matrix>;
142 if constexpr ( Impl::IsScalar<M>::value )
143 {
144 f(matrix,rowOffset,colOffset);
145 return {1,1};
146 }
147 else
148 {
149 // if M supports the IsRowMajorSparse type trait: iterate just over the nonzero entries and
150 // and compute the flat row/col size directly
151 if constexpr ( Impl::IsRowMajorSparse<M>::value )
152 {
153 using Block = std::decay_t<decltype(matrix[0][0])>;
154
155 // find an existing block or at least try to create one
156 auto block = [&]{
157 for (auto const& row : matrix)
158 for (auto const& entry : row)
159 return entry;
160 return Block{};
161 }();
162
163 // compute the scalar size of the block
164 auto [blockRows, blockCols] = flatMatrixForEach(block, [](...){});
165
166 // check whether we have valid sized blocks
167 assert( ( blockRows!=0 or blockCols!=0 ) and "the block size can't be zero");
168
169 for (auto rowIt = matrix.begin(); rowIt != matrix.end(); ++rowIt)
170 {
171 auto&& row = *rowIt;
172 auto rowIdx = rowIt.index();
173 for (auto colIt = row.begin(); colIt != row.end(); colIt++)
174 {
175 auto&& entry = *colIt;
176 auto colIdx = colIt.index();
177#ifndef NDEBUG
178 // only instantiate return value in debug mode (for the assert)
179 auto [ numRows, numCols ] =
180#endif
181 flatMatrixForEach(entry, f, rowOffset + rowIdx*blockRows, colOffset + colIdx*blockCols);
182 assert( numRows == blockRows and numCols == blockCols and "we need the same size of each block in this matrix type");
183 }
184 }
185
186 return { matrix.N()*blockRows, matrix.M()*blockCols };
187 }
188 // all other matrix types are accessed index-wise with dynamic flat row/col counting
189 else
190 {
191 std::size_t r = 0, c = 0;
192 std::size_t nRows, nCols;
193
194 Hybrid::forEach(Dune::range(ForEach::rows(matrix)), [&](auto i) {
195 c = 0;
196 Hybrid::forEach(Dune::range(ForEach::cols(matrix)), [&](auto j) {
197 std::tie(nRows,nCols) = flatMatrixForEach(matrix[i][j], f, rowOffset + r, colOffset + c);
198 c += nCols;
199 });
200 r += nRows;
201 });
202 return {r,c};
203 }
204 }
205}
206
207} // namespace Dune
Some handy generic functions for ISTL matrices.
Implementation of the BCRSMatrix class.
This file implements a quadratic matrix of fixed size which is a multiple of the identity.
auto rows(Matrix const &matrix)
Definition foreach.hh:76
auto cols(Matrix const &matrix)
Definition foreach.hh:79
auto size(Vector const &vector)
Definition foreach.hh:82
int size() const
static constexpr IntegralRange< T > range(T from, T to) noexcept
constexpr void forEach(Range &&range, F &&f)
static constexpr size_type M()
constexpr DiagonalMatrix()=default
std::pair< std::size_t, std::size_t > flatMatrixForEach(Matrix &&matrix, F &&f, std::size_t rowOffset=0, std::size_t colOffset=0)
Traverse a blocked matrix and call a functor at each scalar entry.
Definition foreach.hh:139
std::size_t flatVectorForEach(Vector &&vector, F &&f, std::size_t offset=0)
Traverse a blocked vector and call a functor at each scalar entry.
Definition foreach.hh:102
constexpr index_constant< 0 > _0
A generic dynamic dense matrix.
Definition matrix.hh:561
size_type M() const
Return the number of columns.
Definition matrix.hh:696
size_type N() const
Return the number of rows.
Definition matrix.hh:691
T tie(T... args)