version 3.11-dev
Loading...
Searching...
No Matches
matrixconverter.hh
Go to the documentation of this file.
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//
12#ifndef DUMUX_MATRIX_CONVERTER
13#define DUMUX_MATRIX_CONVERTER
14
15#include <cmath>
16#include <utility>
17#include <dune/common/ftraits.hh>
18#include <dune/common/indices.hh>
19#include <dune/common/hybridutilities.hh>
20#include <dune/istl/bvector.hh>
21#include <dune/istl/bcrsmatrix.hh>
22#include <dune/istl/matrixindexset.hh>
23
25
26namespace Dumux {
27
34template <class MultiTypeBlockMatrix, class Scalar = typename MultiTypeBlockMatrix::field_type>
36{
37 using MatrixBlock = typename Dune::FieldMatrix<Scalar, 1, 1>;
38 using BCRSMatrix = typename Dune::BCRSMatrix<MatrixBlock>;
39
40public:
41
47 static auto multiTypeToBCRSMatrix(const MultiTypeBlockMatrix &A)
48 {
49 // get the size for the converted matrix
50 const auto numRows = getNumRows_(A);
51
52 // create an empty BCRS matrix with 1x1 blocks
53 auto M = BCRSMatrix(numRows, numRows, BCRSMatrix::random);
54
55 // set the occupation pattern and copy the values
56 setOccupationPattern_(M, A);
57 copyValues_(M, A);
58
59 return M;
60 }
61
62private:
63
70 static void setOccupationPattern_(BCRSMatrix& M, const MultiTypeBlockMatrix& A)
71 {
72 // prepare the occupation pattern
73 const auto numRows = M.N();
74 Dune::MatrixIndexSet occupationPattern;
75 occupationPattern.resize(numRows, numRows);
76
77 // lambda function to fill the occupation pattern
78 auto addIndices = [&](const auto& subMatrix, const std::size_t startRow, const std::size_t startCol)
79 {
80 using std::abs;
81 using Magnitude = typename Dune::FieldTraits<Scalar>::real_type;
82 static const Magnitude eps = getParam<Magnitude>("MatrixConverter.DeletePatternEntriesBelowAbsThreshold", -1.0);
83
84 using BlockType = typename std::decay_t<decltype(subMatrix)>::block_type;
85 const auto blockSizeI = BlockType::rows;
86 const auto blockSizeJ = BlockType::cols;
87 for(auto row = subMatrix.begin(); row != subMatrix.end(); ++row)
88 for(auto col = row->begin(); col != row->end(); ++col)
89 for(std::size_t i = 0; i < blockSizeI; ++i)
90 for(std::size_t j = 0; j < blockSizeJ; ++j)
91 if(abs(subMatrix[row.index()][col.index()][i][j]) > eps)
92 occupationPattern.add(startRow + row.index()*blockSizeI + i, startCol + col.index()*blockSizeJ + j);
93 };
94
95 // fill the pattern
96 using namespace Dune::Hybrid;
97 std::size_t rowIndex = 0;
98 forEach(std::make_index_sequence<MultiTypeBlockMatrix::N()>(), [&A, &addIndices, &rowIndex, numRows](const auto i)
99 {
100 std::size_t colIndex = 0;
101 forEach(A[i], [&](const auto& subMatrix)
102 {
103 addIndices(subMatrix, rowIndex, colIndex);
104
105 using SubBlockType = typename std::decay_t<decltype(subMatrix)>::block_type;
106
107 colIndex += SubBlockType::cols * subMatrix.M();
108
109 // if we have arrived at the right side of the matrix, increase the row index
110 if(colIndex == numRows)
111 rowIndex += SubBlockType::rows * subMatrix.N();
112 });
113 });
114
115 occupationPattern.exportIdx(M);
116 }
117
124 static void copyValues_(BCRSMatrix& M, const MultiTypeBlockMatrix& A)
125 {
126 // get number of rows
127 const auto numRows = M.N();
128
129 // lambda function to copy the values
130 auto copyValues = [&](const auto& subMatrix, const std::size_t startRow, const std::size_t startCol)
131 {
132 using std::abs;
133 using Magnitude = typename Dune::FieldTraits<Scalar>::real_type;
134 static const Magnitude eps = getParam<Magnitude>("MatrixConverter.DeletePatternEntriesBelowAbsThreshold", -1.0);
135
136 using BlockType = typename std::decay_t<decltype(subMatrix)>::block_type;
137 const auto blockSizeI = BlockType::rows;
138 const auto blockSizeJ = BlockType::cols;
139 for (auto row = subMatrix.begin(); row != subMatrix.end(); ++row)
140 for (auto col = row->begin(); col != row->end(); ++col)
141 for (std::size_t i = 0; i < blockSizeI; ++i)
142 for (std::size_t j = 0; j < blockSizeJ; ++j)
143 if(abs(subMatrix[row.index()][col.index()][i][j]) > eps)
144 M[startRow + row.index()*blockSizeI + i][startCol + col.index()*blockSizeJ + j] = subMatrix[row.index()][col.index()][i][j];
145
146 };
147
148 using namespace Dune::Hybrid;
149 std::size_t rowIndex = 0;
150 forEach(std::make_index_sequence<MultiTypeBlockMatrix::N()>(), [&A, &copyValues, &rowIndex, numRows](const auto i)
151 {
152 std::size_t colIndex = 0;
153 forEach(A[i], [&](const auto& subMatrix)
154 {
155 copyValues(subMatrix, rowIndex, colIndex);
156
157 using SubBlockType = typename std::decay_t<decltype(subMatrix)>::block_type;
158
159 colIndex += SubBlockType::cols * subMatrix.M();
160
161 // if we have arrived at the right side of the matrix, increase the row index
162 if(colIndex == numRows)
163 rowIndex += SubBlockType::rows * subMatrix.N();
164 });
165 });
166 }
167
173 static std::size_t getNumRows_(const MultiTypeBlockMatrix& A)
174 {
175 // iterate over the first row of the multitype blockmatrix
176 std::size_t numRows = 0;
177 Dune::Hybrid::forEach(Dune::Hybrid::elementAt(A, Dune::Indices::_0), [&numRows](const auto& subMatrixInFirstRow)
178 {
179 // the number of cols of the individual submatrice's block equals the respective number of equations.
180 const auto numEq = std::decay_t<decltype(subMatrixInFirstRow)>::block_type::cols;
181 numRows += numEq * subMatrixInFirstRow.M();
182 });
183
184 return numRows;
185 }
186
187};
188
193template<class MultiTypeBlockVector, class Scalar = typename MultiTypeBlockVector::field_type>
195{
196 using VectorBlock = typename Dune::FieldVector<Scalar, 1>;
197 using BlockVector = typename Dune::BlockVector<VectorBlock>;
198
199public:
200
206 static auto multiTypeToBlockVector(const MultiTypeBlockVector& b)
207 {
208 BlockVector bTmp;
209 bTmp.resize(b.dim());
210
211 std::size_t startIndex = 0;
212 Dune::Hybrid::forEach(b, [&](const auto& subVector)
213 {
214 const auto numEq = std::decay_t<decltype(subVector)>::block_type::size();
215
216 for(std::size_t i = 0; i < subVector.size(); ++i)
217 for(std::size_t j = 0; j < numEq; ++j)
218 bTmp[startIndex + i*numEq + j] = subVector[i][j];
219
220 startIndex += numEq*subVector.size();
221 });
222
223 return bTmp;
224 }
225
232 static void retrieveValues(MultiTypeBlockVector& x, const BlockVector& y)
233 {
234 std::size_t startIndex = 0;
235 Dune::Hybrid::forEach(x, [&](auto& subVector)
236 {
237 const auto numEq = std::decay_t<decltype(subVector)>::block_type::size();
238
239 for(std::size_t i = 0; i < subVector.size(); ++i)
240 for(std::size_t j = 0; j < numEq; ++j)
241 subVector[i][j] = y[startIndex + i*numEq + j];
242
243 startIndex += numEq*subVector.size();
244 });
245 }
246};
247
248} // end namespace Dumux
249
250#endif
A helper class that converts a Dune::MultiTypeBlockMatrix into a plain Dune::BCRSMatrix TODO: allow b...
Definition matrixconverter.hh:36
static auto multiTypeToBCRSMatrix(const MultiTypeBlockMatrix &A)
Converts the matrix to a type the IterativeSolverBackend can handle.
Definition matrixconverter.hh:47
A helper class that converts a Dune::MultiTypeBlockVector into a plain Dune::BlockVector and transfer...
Definition matrixconverter.hh:195
static void retrieveValues(MultiTypeBlockVector &x, const BlockVector &y)
Copies the entries of a Dune::BlockVector to a Dune::MultiTypeBlockVector.
Definition matrixconverter.hh:232
static auto multiTypeToBlockVector(const MultiTypeBlockVector &b)
Converts a Dune::MultiTypeBlockVector to a plain 1x1 Dune::BlockVector.
Definition matrixconverter.hh:206
Definition matrix.hh:20
T getParam(Args &&... args)
A free function to get a parameter from the parameter tree singleton.
Definition parameters.hh:155
Definition adapt.hh:17
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.