opm-simulators
matrixblock.hh
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  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
23 #ifndef EWOMS_MATRIX_BLOCK_HH
24 #define EWOMS_MATRIX_BLOCK_HH
25 
26 #include <dune/common/dynmatrix.hh>
27 #include <dune/common/fmatrix.hh>
28 #include <dune/common/typetraits.hh>
29 
30 #include <dune/istl/superlu.hh>
31 #include <dune/istl/umfpack.hh>
32 #include <dune/istl/matrixutils.hh>
33 
34 #include <opm/common/Exceptions.hpp>
35 
36 #include <limits>
37 
38 namespace Opm {
39 namespace detail {
40 
41 template <typename K, int m, int n>
42 static inline void invertMatrix(Dune::FieldMatrix<K,m,n>& matrix)
43 {
44  matrix.invert();
45 }
46 
47 template <typename K>
48 static inline void invertMatrix(Dune::FieldMatrix<K,1,1>& matrix)
49 {
50  Dune::FieldMatrix<K,1,1> tmp(matrix);
51  Dune::FMatrixHelp::invertMatrix(tmp,matrix);
52 }
53 
54 template <typename K>
55 static inline void invertMatrix(Dune::FieldMatrix<K,2,2>& matrix)
56 {
57  Dune::FieldMatrix<K,2,2> tmp(matrix);
58  Dune::FMatrixHelp::invertMatrix(tmp,matrix);
59 }
60 
61 template <typename K>
62 static inline void invertMatrix(Dune::FieldMatrix<K,3,3>& matrix)
63 {
64  Dune::FieldMatrix<K,3,3> tmp(matrix);
65  Dune::FMatrixHelp::invertMatrix(tmp,matrix);
66 }
67 
69 template <template<class K> class Matrix, typename K>
70 static inline K invertMatrix4(const Matrix<K>& matrix, Matrix<K>& inverse)
71 {
72  inverse[0][0] = matrix[1][1] * matrix[2][2] * matrix[3][3] -
73  matrix[1][1] * matrix[2][3] * matrix[3][2] -
74  matrix[2][1] * matrix[1][2] * matrix[3][3] +
75  matrix[2][1] * matrix[1][3] * matrix[3][2] +
76  matrix[3][1] * matrix[1][2] * matrix[2][3] -
77  matrix[3][1] * matrix[1][3] * matrix[2][2];
78 
79  inverse[1][0] = -matrix[1][0] * matrix[2][2] * matrix[3][3] +
80  matrix[1][0] * matrix[2][3] * matrix[3][2] +
81  matrix[2][0] * matrix[1][2] * matrix[3][3] -
82  matrix[2][0] * matrix[1][3] * matrix[3][2] -
83  matrix[3][0] * matrix[1][2] * matrix[2][3] +
84  matrix[3][0] * matrix[1][3] * matrix[2][2];
85 
86  inverse[2][0] = matrix[1][0] * matrix[2][1] * matrix[3][3] -
87  matrix[1][0] * matrix[2][3] * matrix[3][1] -
88  matrix[2][0] * matrix[1][1] * matrix[3][3] +
89  matrix[2][0] * matrix[1][3] * matrix[3][1] +
90  matrix[3][0] * matrix[1][1] * matrix[2][3] -
91  matrix[3][0] * matrix[1][3] * matrix[2][1];
92 
93  inverse[3][0] = -matrix[1][0] * matrix[2][1] * matrix[3][2] +
94  matrix[1][0] * matrix[2][2] * matrix[3][1] +
95  matrix[2][0] * matrix[1][1] * matrix[3][2] -
96  matrix[2][0] * matrix[1][2] * matrix[3][1] -
97  matrix[3][0] * matrix[1][1] * matrix[2][2] +
98  matrix[3][0] * matrix[1][2] * matrix[2][1];
99 
100  inverse[0][1]= -matrix[0][1] * matrix[2][2] * matrix[3][3] +
101  matrix[0][1] * matrix[2][3] * matrix[3][2] +
102  matrix[2][1] * matrix[0][2] * matrix[3][3] -
103  matrix[2][1] * matrix[0][3] * matrix[3][2] -
104  matrix[3][1] * matrix[0][2] * matrix[2][3] +
105  matrix[3][1] * matrix[0][3] * matrix[2][2];
106 
107  inverse[1][1] = matrix[0][0] * matrix[2][2] * matrix[3][3] -
108  matrix[0][0] * matrix[2][3] * matrix[3][2] -
109  matrix[2][0] * matrix[0][2] * matrix[3][3] +
110  matrix[2][0] * matrix[0][3] * matrix[3][2] +
111  matrix[3][0] * matrix[0][2] * matrix[2][3] -
112  matrix[3][0] * matrix[0][3] * matrix[2][2];
113 
114  inverse[2][1] = -matrix[0][0] * matrix[2][1] * matrix[3][3] +
115  matrix[0][0] * matrix[2][3] * matrix[3][1] +
116  matrix[2][0] * matrix[0][1] * matrix[3][3] -
117  matrix[2][0] * matrix[0][3] * matrix[3][1] -
118  matrix[3][0] * matrix[0][1] * matrix[2][3] +
119  matrix[3][0] * matrix[0][3] * matrix[2][1];
120 
121  inverse[3][1] = matrix[0][0] * matrix[2][1] * matrix[3][2] -
122  matrix[0][0] * matrix[2][2] * matrix[3][1] -
123  matrix[2][0] * matrix[0][1] * matrix[3][2] +
124  matrix[2][0] * matrix[0][2] * matrix[3][1] +
125  matrix[3][0] * matrix[0][1] * matrix[2][2] -
126  matrix[3][0] * matrix[0][2] * matrix[2][1];
127 
128  inverse[0][2] = matrix[0][1] * matrix[1][2] * matrix[3][3] -
129  matrix[0][1] * matrix[1][3] * matrix[3][2] -
130  matrix[1][1] * matrix[0][2] * matrix[3][3] +
131  matrix[1][1] * matrix[0][3] * matrix[3][2] +
132  matrix[3][1] * matrix[0][2] * matrix[1][3] -
133  matrix[3][1] * matrix[0][3] * matrix[1][2];
134 
135  inverse[1][2] = -matrix[0][0] * matrix[1][2] * matrix[3][3] +
136  matrix[0][0] * matrix[1][3] * matrix[3][2] +
137  matrix[1][0] * matrix[0][2] * matrix[3][3] -
138  matrix[1][0] * matrix[0][3] * matrix[3][2] -
139  matrix[3][0] * matrix[0][2] * matrix[1][3] +
140  matrix[3][0] * matrix[0][3] * matrix[1][2];
141 
142  inverse[2][2] = matrix[0][0] * matrix[1][1] * matrix[3][3] -
143  matrix[0][0] * matrix[1][3] * matrix[3][1] -
144  matrix[1][0] * matrix[0][1] * matrix[3][3] +
145  matrix[1][0] * matrix[0][3] * matrix[3][1] +
146  matrix[3][0] * matrix[0][1] * matrix[1][3] -
147  matrix[3][0] * matrix[0][3] * matrix[1][1];
148 
149  inverse[3][2] = -matrix[0][0] * matrix[1][1] * matrix[3][2] +
150  matrix[0][0] * matrix[1][2] * matrix[3][1] +
151  matrix[1][0] * matrix[0][1] * matrix[3][2] -
152  matrix[1][0] * matrix[0][2] * matrix[3][1] -
153  matrix[3][0] * matrix[0][1] * matrix[1][2] +
154  matrix[3][0] * matrix[0][2] * matrix[1][1];
155 
156  inverse[0][3] = -matrix[0][1] * matrix[1][2] * matrix[2][3] +
157  matrix[0][1] * matrix[1][3] * matrix[2][2] +
158  matrix[1][1] * matrix[0][2] * matrix[2][3] -
159  matrix[1][1] * matrix[0][3] * matrix[2][2] -
160  matrix[2][1] * matrix[0][2] * matrix[1][3] +
161  matrix[2][1] * matrix[0][3] * matrix[1][2];
162 
163  inverse[1][3] = matrix[0][0] * matrix[1][2] * matrix[2][3] -
164  matrix[0][0] * matrix[1][3] * matrix[2][2] -
165  matrix[1][0] * matrix[0][2] * matrix[2][3] +
166  matrix[1][0] * matrix[0][3] * matrix[2][2] +
167  matrix[2][0] * matrix[0][2] * matrix[1][3] -
168  matrix[2][0] * matrix[0][3] * matrix[1][2];
169 
170  inverse[2][3] = -matrix[0][0] * matrix[1][1] * matrix[2][3] +
171  matrix[0][0] * matrix[1][3] * matrix[2][1] +
172  matrix[1][0] * matrix[0][1] * matrix[2][3] -
173  matrix[1][0] * matrix[0][3] * matrix[2][1] -
174  matrix[2][0] * matrix[0][1] * matrix[1][3] +
175  matrix[2][0] * matrix[0][3] * matrix[1][1];
176 
177  inverse[3][3] = matrix[0][0] * matrix[1][1] * matrix[2][2] -
178  matrix[0][0] * matrix[1][2] * matrix[2][1] -
179  matrix[1][0] * matrix[0][1] * matrix[2][2] +
180  matrix[1][0] * matrix[0][2] * matrix[2][1] +
181  matrix[2][0] * matrix[0][1] * matrix[1][2] -
182  matrix[2][0] * matrix[0][2] * matrix[1][1];
183 
184  K det = matrix[0][0] * inverse[0][0] + matrix[0][1] * inverse[1][0] +
185  matrix[0][2] * inverse[2][0] + matrix[0][3] * inverse[3][0];
186 
187  // return identity for singular or nearly singular matrices.
188  // Note for maintainers: If updating this value, also update the value
189  // in gpuistl/detail/deviceBlockOperations.hpp
190  if (std::abs(det) < 1e-40) {
191  inverse = std::numeric_limits<K>::quiet_NaN();
192  throw NumericalProblem("Singular matrix");
193  } else
194  inverse *= 1.0 / det;
195 
196  return det;
197 }
198 
199 template<class K> using FMat4 = Dune::FieldMatrix<K,4,4>;
200 
201 template <typename K>
202 static inline void invertMatrix(Dune::FieldMatrix<K,4,4>& matrix)
203 {
204  FMat4<K> tmp(matrix);
205  invertMatrix4<FMat4>(tmp, matrix);
206 }
207 
208 template <typename K>
209 static inline void invertMatrix(Dune::DynamicMatrix<K>& matrix)
210 {
211  // this function is only for 4 X 4 matrix
212  // for 4 X 4 matrix, using the invertMatrix() function above
213  // it is for temporary usage, mainly to reduce the huge burden of testing
214  // what algorithm should be used to invert 4 X 4 matrix will be handled
215  // as a seperate issue
216  if (matrix.rows() == 4) {
217  Dune::DynamicMatrix<K> A = matrix;
218  invertMatrix4(A, matrix);
219  return;
220  }
221 
222  matrix.invert();
223 }
224 
225 } // namespace detail
226 
227 template <class Scalar, int n, int m>
228 class MatrixBlock : public Dune::FieldMatrix<Scalar, n, m>
229 {
230 public:
231  using BaseType = Dune::FieldMatrix<Scalar, n, m> ;
232 
233  using BaseType::operator= ;
234  using BaseType::rows;
235  using BaseType::cols;
236 
237  MatrixBlock()
238  : BaseType(Scalar(0.0))
239  {}
240 
241  explicit MatrixBlock(const Scalar value)
242  : BaseType(value)
243  {}
244 
245  void invert()
246  { detail::invertMatrix(asBase()); }
247 
248  const BaseType& asBase() const
249  { return static_cast<const BaseType&>(*this); }
250 
251  BaseType& asBase()
252  { return static_cast<BaseType&>(*this); }
253 };
254 
255 } // namespace Opm
256 
257 namespace Dune {
258 
259 template<class K, int n, int m>
260 void print_row(std::ostream& s, const Opm::MatrixBlock<K, n, m>& A,
261  typename FieldMatrix<K, n, m>::size_type I,
262  typename FieldMatrix<K, n, m>::size_type J,
263  typename FieldMatrix<K, n, m>::size_type therow,
264  int width,
265  int precision)
266 { print_row(s, A.asBase(), I, J, therow, width, precision); }
267 
268 template <typename Scalar, int n, int m>
269 struct MatrixDimension<Opm::MatrixBlock<Scalar, n, m> >
270  : public MatrixDimension<typename Opm::MatrixBlock<Scalar, n, m>::BaseType>
271 { };
272 
273 
274 #if HAVE_SUITESPARSE_UMFPACK
275 template <typename T, typename A, int n, int m>
279 class UMFPack<BCRSMatrix<Opm::MatrixBlock<T, n, m>, A> >
280  : public UMFPack<BCRSMatrix<FieldMatrix<T, n, m>, A> >
281 {
282  using Base = UMFPack<BCRSMatrix<FieldMatrix<T, n, m>, A> >;
283  using Matrix = BCRSMatrix<FieldMatrix<T, n, m>, A>;
284 
285 public:
286  using RealMatrix = BCRSMatrix<Opm::MatrixBlock<T, n, m>, A>;
287 
288  UMFPack(const RealMatrix& matrix, int verbose, bool)
289  : Base(reinterpret_cast<const Matrix&>(matrix), verbose)
290  {}
291 };
292 #endif
293 
294 #if HAVE_SUPERLU
295 template <typename T, typename A, int n, int m>
299 class SuperLU<BCRSMatrix<Opm::MatrixBlock<T, n, m>, A> >
300  : public SuperLU<BCRSMatrix<FieldMatrix<T, n, m>, A> >
301 {
302  using Base = SuperLU<BCRSMatrix<FieldMatrix<T, n, m>, A> >;
303  using Matrix = BCRSMatrix<FieldMatrix<T, n, m>, A>;
304 
305 public:
306  using RealMatrix = BCRSMatrix<Opm::MatrixBlock<T, n, m>, A>;
307 
308  SuperLU(const RealMatrix& matrix, int verb, bool reuse=true)
309  : Base(reinterpret_cast<const Matrix&>(matrix), verb, reuse)
310  {}
311 };
312 #endif
313 
314 template<typename T, int n, int m>
315 struct IsNumber<Opm::MatrixBlock<T, n, m>>
316  : public IsNumber<Dune::FieldMatrix<T,n,m>>
317 {};
318 
319 template<typename T, int n, int m>
320 struct FieldTraits<Opm::MatrixBlock<T, n, m>>
321  : public FieldTraits<Dune::FieldMatrix<T,n,m>>
322 {};
323 
324 } // end namespace Dune
325 
326 
327 #endif
Definition: MSWellHelpers.hpp:29
Definition: fvbaseprimaryvariables.hh:161
Definition: matrixblock.hh:228
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45