GCC Code Coverage Report


Directory: ../../../builds/dumux-repositories/
File: dumux/dumux/linear/matrixconverter.hh
Date: 2025-04-12 19:19:20
Exec Total Coverage
Lines: 75 77 97.4%
Functions: 100 100 100.0%
Branches: 194 264 73.5%

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, &copyValues, &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