Line | Branch | Exec | Source |
---|---|---|---|
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 | // | ||
7 | /*! | ||
8 | * \file | ||
9 | * \ingroup Linear | ||
10 | * \brief A helper class that converts a Dune::MultiTypeBlockMatrix into a plain Dune::BCRSMatrix | ||
11 | */ | ||
12 | #ifndef DUMUX_MATRIX_CONVERTER | ||
13 | #define DUMUX_MATRIX_CONVERTER | ||
14 | |||
15 | #include <cmath> | ||
16 | #include <utility> | ||
17 | #include <dune/common/indices.hh> | ||
18 | #include <dune/common/hybridutilities.hh> | ||
19 | #include <dune/istl/bvector.hh> | ||
20 | #include <dune/istl/bcrsmatrix.hh> | ||
21 | #include <dune/istl/matrixindexset.hh> | ||
22 | |||
23 | #include <dumux/common/parameters.hh> | ||
24 | |||
25 | namespace Dumux { | ||
26 | |||
27 | /*! | ||
28 | * \ingroup Linear | ||
29 | * \brief A helper class that converts a Dune::MultiTypeBlockMatrix into a plain Dune::BCRSMatrix | ||
30 | * TODO: allow block sizes for BCRSMatrix other than 1x1 ? | ||
31 | * | ||
32 | */ | ||
33 | template <class MultiTypeBlockMatrix, class Scalar=double> | ||
34 | class MatrixConverter | ||
35 | { | ||
36 | using MatrixBlock = typename Dune::FieldMatrix<Scalar, 1, 1>; | ||
37 | using BCRSMatrix = typename Dune::BCRSMatrix<MatrixBlock>; | ||
38 | |||
39 | public: | ||
40 | |||
41 | /*! | ||
42 | * \brief Converts the matrix to a type the IterativeSolverBackend can handle | ||
43 | * | ||
44 | * \param A The original multitype blockmatrix | ||
45 | */ | ||
46 | 855 | static auto multiTypeToBCRSMatrix(const MultiTypeBlockMatrix &A) | |
47 | { | ||
48 | // get the size for the converted matrix | ||
49 | 855 | const auto numRows = getNumRows_(A); | |
50 | |||
51 | // create an empty BCRS matrix with 1x1 blocks | ||
52 | 855 | auto M = BCRSMatrix(numRows, numRows, BCRSMatrix::random); | |
53 | |||
54 | // set the occupation pattern and copy the values | ||
55 |
1/2✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
|
855 | setOccupationPattern_(M, A); |
56 |
1/2✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
|
855 | copyValues_(M, A); |
57 | |||
58 | 855 | return M; | |
59 | ✗ | } | |
60 | |||
61 | private: | ||
62 | |||
63 | /*! | ||
64 | * \brief Sets the occupation pattern and indices for the converted matrix | ||
65 | * | ||
66 | * \param M The converted matrix | ||
67 | * \param A The original multitype blockmatrix | ||
68 | */ | ||
69 |
1/2✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
|
855 | static void setOccupationPattern_(BCRSMatrix& M, const MultiTypeBlockMatrix& A) |
70 | { | ||
71 | // prepare the occupation pattern | ||
72 |
1/2✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
|
855 | const auto numRows = M.N(); |
73 | 855 | Dune::MatrixIndexSet occupationPattern; | |
74 |
1/2✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
|
855 | occupationPattern.resize(numRows, numRows); |
75 | |||
76 | // lambda function to fill the occupation pattern | ||
77 | 3880 | auto addIndices = [&](const auto& subMatrix, const std::size_t startRow, const std::size_t startCol) | |
78 | { | ||
79 | using std::abs; | ||
80 |
16/24✓ Branch 0 taken 37 times.
✓ Branch 1 taken 3163 times.
✓ Branch 3 taken 37 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 37 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 83 times.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 20 taken 2 times.
✓ Branch 21 taken 83 times.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 30 taken 2 times.
✓ Branch 31 taken 83 times.
✓ Branch 33 taken 2 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 2 times.
✗ Branch 37 not taken.
|
3455 | static const Scalar eps = getParam<Scalar>("MatrixConverter.DeletePatternEntriesBelowAbsThreshold", -1.0); |
81 | |||
82 | using BlockType = typename std::decay_t<decltype(subMatrix)>::block_type; | ||
83 | 3455 | const auto blockSizeI = BlockType::rows; | |
84 | 3455 | const auto blockSizeJ = BlockType::cols; | |
85 |
12/16✗ Branch 0 not taken.
✓ Branch 1 taken 1415420 times.
✓ Branch 2 taken 1412220 times.
✓ Branch 3 taken 3200 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 40136 times.
✓ Branch 6 taken 40051 times.
✓ Branch 7 taken 85 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 122729 times.
✓ Branch 10 taken 122644 times.
✓ Branch 11 taken 85 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 122729 times.
✓ Branch 14 taken 122644 times.
✓ Branch 15 taken 85 times.
|
1701014 | for(auto row = subMatrix.begin(); row != subMatrix.end(); ++row) |
86 |
12/16✗ Branch 0 not taken.
✓ Branch 1 taken 6623943 times.
✓ Branch 2 taken 5211723 times.
✓ Branch 3 taken 1412220 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 49123 times.
✓ Branch 6 taken 9072 times.
✓ Branch 7 taken 40051 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 133876 times.
✓ Branch 10 taken 11232 times.
✓ Branch 11 taken 122644 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 711472 times.
✓ Branch 14 taken 588828 times.
✓ Branch 15 taken 122644 times.
|
7518414 | for(auto col = row->begin(); col != row->end(); ++col) |
87 |
8/8✓ Branch 0 taken 11927481 times.
✓ Branch 1 taken 5211723 times.
✓ Branch 2 taken 18144 times.
✓ Branch 3 taken 9072 times.
✓ Branch 4 taken 11232 times.
✓ Branch 5 taken 11232 times.
✓ Branch 6 taken 588828 times.
✓ Branch 7 taken 588828 times.
|
18366540 | for(std::size_t i = 0; i < blockSizeI; ++i) |
88 |
8/8✓ Branch 0 taken 30319949 times.
✓ Branch 1 taken 11927481 times.
✓ Branch 2 taken 18144 times.
✓ Branch 3 taken 18144 times.
✓ Branch 4 taken 22464 times.
✓ Branch 5 taken 11232 times.
✓ Branch 6 taken 588828 times.
✓ Branch 7 taken 588828 times.
|
43495070 | for(std::size_t j = 0; j < blockSizeJ; ++j) |
89 |
9/16✓ Branch 1 taken 30319949 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29343508 times.
✓ Branch 4 taken 976441 times.
✓ Branch 6 taken 18144 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 18144 times.
✓ Branch 11 taken 22464 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 22464 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 588828 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 588828 times.
|
30949385 | if(abs(subMatrix[row.index()][col.index()][i][j]) > eps) |
90 |
4/8✓ Branch 1 taken 30319949 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18144 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 22464 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 588828 times.
✗ Branch 11 not taken.
|
30949385 | occupationPattern.add(startRow + row.index()*blockSizeI + i, startCol + col.index()*blockSizeJ + j); |
91 | }; | ||
92 | |||
93 | // fill the pattern | ||
94 | using namespace Dune::Hybrid; | ||
95 | 855 | std::size_t rowIndex = 0; | |
96 |
1/2✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
|
7723 | forEach(std::make_index_sequence<MultiTypeBlockMatrix::N()>(), [&A, &addIndices, &rowIndex, numRows](const auto i) |
97 | { | ||
98 | 1717 | std::size_t colIndex = 0; | |
99 | 15537 | forEach(A[i], [&](const auto& subMatrix) | |
100 | { | ||
101 |
7/8✓ Branch 1 taken 855 times.
✓ Branch 2 taken 777 times.
✓ Branch 4 taken 770 times.
✓ Branch 5 taken 862 times.
✓ Branch 7 taken 92 times.
✓ Branch 8 taken 14 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 85 times.
|
3455 | addIndices(subMatrix, rowIndex, colIndex); |
102 | |||
103 | using SubBlockType = typename std::decay_t<decltype(subMatrix)>::block_type; | ||
104 | |||
105 | 3455 | colIndex += SubBlockType::cols * subMatrix.M(); | |
106 | |||
107 | // if we have arrived at the right side of the matrix, increase the row index | ||
108 |
7/8✓ Branch 0 taken 855 times.
✓ Branch 1 taken 777 times.
✓ Branch 2 taken 770 times.
✓ Branch 3 taken 862 times.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 85 times.
|
3455 | if(colIndex == numRows) |
109 | 1717 | rowIndex += SubBlockType::rows * subMatrix.N(); | |
110 | }); | ||
111 | }); | ||
112 | |||
113 |
1/2✓ Branch 1 taken 855 times.
✗ Branch 2 not taken.
|
855 | occupationPattern.exportIdx(M); |
114 | 855 | } | |
115 | |||
116 | /*! | ||
117 | * \brief Sets the occupation pattern (i.e. indices) for the converted matrix | ||
118 | * | ||
119 | * \param M The converted matrix | ||
120 | * \param A The original subMatrix of the multitype blockmatrix | ||
121 | */ | ||
122 | 855 | static void copyValues_(BCRSMatrix& M, const MultiTypeBlockMatrix& A) | |
123 | { | ||
124 | // get number of rows | ||
125 | 855 | const auto numRows = M.N(); | |
126 | |||
127 | // lambda function to copy the values | ||
128 | 3880 | auto copyValues = [&](const auto& subMatrix, const std::size_t startRow, const std::size_t startCol) | |
129 | { | ||
130 | using std::abs; | ||
131 |
16/24✓ Branch 0 taken 37 times.
✓ Branch 1 taken 3163 times.
✓ Branch 3 taken 37 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 37 times.
✗ Branch 7 not taken.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 83 times.
✓ Branch 13 taken 2 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 2 times.
✗ Branch 17 not taken.
✓ Branch 20 taken 2 times.
✓ Branch 21 taken 83 times.
✓ Branch 23 taken 2 times.
✗ Branch 24 not taken.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
✓ Branch 30 taken 2 times.
✓ Branch 31 taken 83 times.
✓ Branch 33 taken 2 times.
✗ Branch 34 not taken.
✓ Branch 36 taken 2 times.
✗ Branch 37 not taken.
|
3455 | static const Scalar eps = getParam<Scalar>("MatrixConverter.DeletePatternEntriesBelowAbsThreshold", -1.0); |
132 | |||
133 | using BlockType = typename std::decay_t<decltype(subMatrix)>::block_type; | ||
134 | 3455 | const auto blockSizeI = BlockType::rows; | |
135 | 3455 | const auto blockSizeJ = BlockType::cols; | |
136 |
12/16✗ Branch 0 not taken.
✓ Branch 1 taken 1415420 times.
✓ Branch 2 taken 1412220 times.
✓ Branch 3 taken 3200 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 40136 times.
✓ Branch 6 taken 40051 times.
✓ Branch 7 taken 85 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 122729 times.
✓ Branch 10 taken 122644 times.
✓ Branch 11 taken 85 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 122729 times.
✓ Branch 14 taken 122644 times.
✓ Branch 15 taken 85 times.
|
1701014 | for (auto row = subMatrix.begin(); row != subMatrix.end(); ++row) |
137 |
12/16✗ Branch 0 not taken.
✓ Branch 1 taken 6623943 times.
✓ Branch 2 taken 5211723 times.
✓ Branch 3 taken 1412220 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 49123 times.
✓ Branch 6 taken 9072 times.
✓ Branch 7 taken 40051 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 133876 times.
✓ Branch 10 taken 11232 times.
✓ Branch 11 taken 122644 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 711472 times.
✓ Branch 14 taken 588828 times.
✓ Branch 15 taken 122644 times.
|
7518414 | for (auto col = row->begin(); col != row->end(); ++col) |
138 |
8/8✓ Branch 0 taken 11927481 times.
✓ Branch 1 taken 5211723 times.
✓ Branch 2 taken 18144 times.
✓ Branch 3 taken 9072 times.
✓ Branch 4 taken 11232 times.
✓ Branch 5 taken 11232 times.
✓ Branch 6 taken 588828 times.
✓ Branch 7 taken 588828 times.
|
18366540 | for (std::size_t i = 0; i < blockSizeI; ++i) |
139 |
8/8✓ Branch 0 taken 30319949 times.
✓ Branch 1 taken 11927481 times.
✓ Branch 2 taken 18144 times.
✓ Branch 3 taken 18144 times.
✓ Branch 4 taken 22464 times.
✓ Branch 5 taken 11232 times.
✓ Branch 6 taken 588828 times.
✓ Branch 7 taken 588828 times.
|
43495070 | for (std::size_t j = 0; j < blockSizeJ; ++j) |
140 |
9/16✓ Branch 1 taken 30319949 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 29343508 times.
✓ Branch 4 taken 976441 times.
✓ Branch 6 taken 18144 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 18144 times.
✓ Branch 11 taken 22464 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 22464 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 588828 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 588828 times.
|
30949385 | if(abs(subMatrix[row.index()][col.index()][i][j]) > eps) |
141 |
8/16✓ Branch 1 taken 30319949 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 30319949 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18144 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 18144 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 22464 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 22464 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 588828 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 588828 times.
✗ Branch 23 not taken.
|
30949385 | M[startRow + row.index()*blockSizeI + i][startCol + col.index()*blockSizeJ + j] = subMatrix[row.index()][col.index()][i][j]; |
142 | |||
143 | }; | ||
144 | |||
145 | using namespace Dune::Hybrid; | ||
146 | 855 | std::size_t rowIndex = 0; | |
147 | 7723 | forEach(std::make_index_sequence<MultiTypeBlockMatrix::N()>(), [&A, ©Values, &rowIndex, numRows](const auto i) | |
148 | { | ||
149 | 1717 | std::size_t colIndex = 0; | |
150 | 15537 | forEach(A[i], [&](const auto& subMatrix) | |
151 | { | ||
152 |
7/8✓ Branch 1 taken 855 times.
✓ Branch 2 taken 777 times.
✓ Branch 4 taken 770 times.
✓ Branch 5 taken 862 times.
✓ Branch 7 taken 92 times.
✓ Branch 8 taken 14 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 85 times.
|
3455 | copyValues(subMatrix, rowIndex, colIndex); |
153 | |||
154 | using SubBlockType = typename std::decay_t<decltype(subMatrix)>::block_type; | ||
155 | |||
156 | 3455 | colIndex += SubBlockType::cols * subMatrix.M(); | |
157 | |||
158 | // if we have arrived at the right side of the matrix, increase the row index | ||
159 |
7/8✓ Branch 0 taken 855 times.
✓ Branch 1 taken 777 times.
✓ Branch 2 taken 770 times.
✓ Branch 3 taken 862 times.
✓ Branch 4 taken 92 times.
✓ Branch 5 taken 14 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 85 times.
|
3455 | if(colIndex == numRows) |
160 | 1717 | rowIndex += SubBlockType::rows * subMatrix.N(); | |
161 | }); | ||
162 | }); | ||
163 | 855 | } | |
164 | |||
165 | /*! | ||
166 | * \brief Calculates the total number of rows (== number of cols) for the converted matrix, assuming a block size of 1x1 | ||
167 | * | ||
168 | * \param A The original multitype blockmatrix | ||
169 | */ | ||
170 | 855 | static std::size_t getNumRows_(const MultiTypeBlockMatrix& A) | |
171 | { | ||
172 | // iterate over the first row of the multitype blockmatrix | ||
173 | std::size_t numRows = 0; | ||
174 | 855 | Dune::Hybrid::forEach(Dune::Hybrid::elementAt(A, Dune::Indices::_0), [&numRows](const auto& subMatrixInFirstRow) | |
175 | { | ||
176 | // the number of cols of the individual submatrice's block equals the respective number of equations. | ||
177 | 855 | const auto numEq = std::decay_t<decltype(subMatrixInFirstRow)>::block_type::cols; | |
178 | 855 | numRows += numEq * subMatrixInFirstRow.M(); | |
179 | }); | ||
180 | |||
181 | return numRows; | ||
182 | } | ||
183 | |||
184 | }; | ||
185 | |||
186 | /*! | ||
187 | * \ingroup Linear | ||
188 | * \brief A helper class that converts a Dune::MultiTypeBlockVector into a plain Dune::BlockVector and transfers back values | ||
189 | */ | ||
190 | template<class MultiTypeBlockVector, class Scalar=double> | ||
191 | class VectorConverter | ||
192 | { | ||
193 | using VectorBlock = typename Dune::FieldVector<Scalar, 1>; | ||
194 | using BlockVector = typename Dune::BlockVector<VectorBlock>; | ||
195 | |||
196 | public: | ||
197 | |||
198 | /*! | ||
199 | * \brief Converts a Dune::MultiTypeBlockVector to a plain 1x1 Dune::BlockVector | ||
200 | * | ||
201 | * \param b The original multitype blockvector | ||
202 | */ | ||
203 | 1166 | static auto multiTypeToBlockVector(const MultiTypeBlockVector& b) | |
204 | { | ||
205 | 1166 | BlockVector bTmp; | |
206 |
1/2✓ Branch 1 taken 1166 times.
✗ Branch 2 not taken.
|
1166 | bTmp.resize(b.dim()); |
207 | |||
208 | 1166 | std::size_t startIndex = 0; | |
209 | 1990 | Dune::Hybrid::forEach(b, [&](const auto& subVector) | |
210 | { | ||
211 | 2341 | const auto numEq = std::decay_t<decltype(subVector)>::block_type::size(); | |
212 | |||
213 |
4/4✓ Branch 0 taken 989360 times.
✓ Branch 1 taken 2238 times.
✓ Branch 2 taken 148108 times.
✓ Branch 3 taken 103 times.
|
1139809 | for(std::size_t i = 0; i < subVector.size(); ++i) |
214 |
4/4✓ Branch 0 taken 2235803 times.
✓ Branch 1 taken 989360 times.
✓ Branch 2 taken 148108 times.
✓ Branch 3 taken 148108 times.
|
3521379 | for(std::size_t j = 0; j < numEq; ++j) |
215 | 2383911 | bTmp[startIndex + i*numEq + j] = subVector[i][j]; | |
216 | |||
217 | 2341 | startIndex += numEq*subVector.size(); | |
218 | }); | ||
219 | |||
220 | 1166 | return bTmp; | |
221 | ✗ | } | |
222 | |||
223 | /*! | ||
224 | * \brief Copies the entries of a Dune::BlockVector to a Dune::MultiTypeBlockVector | ||
225 | * | ||
226 | * \param x The multitype blockvector where the values are copied to | ||
227 | * \param y The regular blockvector where the values are copied from | ||
228 | */ | ||
229 | 855 | static void retrieveValues(MultiTypeBlockVector& x, const BlockVector& y) | |
230 | { | ||
231 | 855 | std::size_t startIndex = 0; | |
232 | 1535 | Dune::Hybrid::forEach(x, [&](auto& subVector) | |
233 | { | ||
234 | 1717 | const auto numEq = std::decay_t<decltype(subVector)>::block_type::size(); | |
235 | |||
236 |
4/4✓ Branch 0 taken 721835 times.
✓ Branch 1 taken 1632 times.
✓ Branch 2 taken 122644 times.
✓ Branch 3 taken 85 times.
|
846196 | for(std::size_t i = 0; i < subVector.size(); ++i) |
237 |
4/4✓ Branch 0 taken 1642149 times.
✓ Branch 1 taken 721835 times.
✓ Branch 2 taken 122644 times.
✓ Branch 3 taken 122644 times.
|
2609272 | for(std::size_t j = 0; j < numEq; ++j) |
238 | 1764793 | subVector[i][j] = y[startIndex + i*numEq + j]; | |
239 | |||
240 | 1717 | startIndex += numEq*subVector.size(); | |
241 | }); | ||
242 | 855 | } | |
243 | }; | ||
244 | |||
245 | } // end namespace Dumux | ||
246 | |||
247 | #endif | ||
248 |