// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- // vi: set et ts=4 sw=4 sts=4: /* This file is part of the Open Porous Media project (OPM). OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. OPM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OPM. If not, see . Consult the COPYING file in the top-level source directory of this module for the precise wording of the license and the list of copyright holders. */ #ifndef EWOMS_MATRIX_BLOCK_HH #define EWOMS_MATRIX_BLOCK_HH #include #include #include #include #include #include #include #include namespace Opm { namespace detail { template static inline void invertMatrix(Dune::FieldMatrix& matrix) { matrix.invert(); } template static inline void invertMatrix(Dune::FieldMatrix& matrix) { Dune::FieldMatrix tmp(matrix); Dune::FMatrixHelp::invertMatrix(tmp,matrix); } template static inline void invertMatrix(Dune::FieldMatrix& matrix) { Dune::FieldMatrix tmp(matrix); Dune::FMatrixHelp::invertMatrix(tmp,matrix); } template static inline void invertMatrix(Dune::FieldMatrix& matrix) { Dune::FieldMatrix tmp(matrix); Dune::FMatrixHelp::invertMatrix(tmp,matrix); } //! invert 4x4 Matrix without changing the original matrix template class Matrix, typename K> static inline K invertMatrix4(const Matrix& matrix, Matrix& inverse) { inverse[0][0] = matrix[1][1] * matrix[2][2] * matrix[3][3] - matrix[1][1] * matrix[2][3] * matrix[3][2] - matrix[2][1] * matrix[1][2] * matrix[3][3] + matrix[2][1] * matrix[1][3] * matrix[3][2] + matrix[3][1] * matrix[1][2] * matrix[2][3] - matrix[3][1] * matrix[1][3] * matrix[2][2]; inverse[1][0] = -matrix[1][0] * matrix[2][2] * matrix[3][3] + matrix[1][0] * matrix[2][3] * matrix[3][2] + matrix[2][0] * matrix[1][2] * matrix[3][3] - matrix[2][0] * matrix[1][3] * matrix[3][2] - matrix[3][0] * matrix[1][2] * matrix[2][3] + matrix[3][0] * matrix[1][3] * matrix[2][2]; inverse[2][0] = matrix[1][0] * matrix[2][1] * matrix[3][3] - matrix[1][0] * matrix[2][3] * matrix[3][1] - matrix[2][0] * matrix[1][1] * matrix[3][3] + matrix[2][0] * matrix[1][3] * matrix[3][1] + matrix[3][0] * matrix[1][1] * matrix[2][3] - matrix[3][0] * matrix[1][3] * matrix[2][1]; inverse[3][0] = -matrix[1][0] * matrix[2][1] * matrix[3][2] + matrix[1][0] * matrix[2][2] * matrix[3][1] + matrix[2][0] * matrix[1][1] * matrix[3][2] - matrix[2][0] * matrix[1][2] * matrix[3][1] - matrix[3][0] * matrix[1][1] * matrix[2][2] + matrix[3][0] * matrix[1][2] * matrix[2][1]; inverse[0][1]= -matrix[0][1] * matrix[2][2] * matrix[3][3] + matrix[0][1] * matrix[2][3] * matrix[3][2] + matrix[2][1] * matrix[0][2] * matrix[3][3] - matrix[2][1] * matrix[0][3] * matrix[3][2] - matrix[3][1] * matrix[0][2] * matrix[2][3] + matrix[3][1] * matrix[0][3] * matrix[2][2]; inverse[1][1] = matrix[0][0] * matrix[2][2] * matrix[3][3] - matrix[0][0] * matrix[2][3] * matrix[3][2] - matrix[2][0] * matrix[0][2] * matrix[3][3] + matrix[2][0] * matrix[0][3] * matrix[3][2] + matrix[3][0] * matrix[0][2] * matrix[2][3] - matrix[3][0] * matrix[0][3] * matrix[2][2]; inverse[2][1] = -matrix[0][0] * matrix[2][1] * matrix[3][3] + matrix[0][0] * matrix[2][3] * matrix[3][1] + matrix[2][0] * matrix[0][1] * matrix[3][3] - matrix[2][0] * matrix[0][3] * matrix[3][1] - matrix[3][0] * matrix[0][1] * matrix[2][3] + matrix[3][0] * matrix[0][3] * matrix[2][1]; inverse[3][1] = matrix[0][0] * matrix[2][1] * matrix[3][2] - matrix[0][0] * matrix[2][2] * matrix[3][1] - matrix[2][0] * matrix[0][1] * matrix[3][2] + matrix[2][0] * matrix[0][2] * matrix[3][1] + matrix[3][0] * matrix[0][1] * matrix[2][2] - matrix[3][0] * matrix[0][2] * matrix[2][1]; inverse[0][2] = matrix[0][1] * matrix[1][2] * matrix[3][3] - matrix[0][1] * matrix[1][3] * matrix[3][2] - matrix[1][1] * matrix[0][2] * matrix[3][3] + matrix[1][1] * matrix[0][3] * matrix[3][2] + matrix[3][1] * matrix[0][2] * matrix[1][3] - matrix[3][1] * matrix[0][3] * matrix[1][2]; inverse[1][2] = -matrix[0][0] * matrix[1][2] * matrix[3][3] + matrix[0][0] * matrix[1][3] * matrix[3][2] + matrix[1][0] * matrix[0][2] * matrix[3][3] - matrix[1][0] * matrix[0][3] * matrix[3][2] - matrix[3][0] * matrix[0][2] * matrix[1][3] + matrix[3][0] * matrix[0][3] * matrix[1][2]; inverse[2][2] = matrix[0][0] * matrix[1][1] * matrix[3][3] - matrix[0][0] * matrix[1][3] * matrix[3][1] - matrix[1][0] * matrix[0][1] * matrix[3][3] + matrix[1][0] * matrix[0][3] * matrix[3][1] + matrix[3][0] * matrix[0][1] * matrix[1][3] - matrix[3][0] * matrix[0][3] * matrix[1][1]; inverse[3][2] = -matrix[0][0] * matrix[1][1] * matrix[3][2] + matrix[0][0] * matrix[1][2] * matrix[3][1] + matrix[1][0] * matrix[0][1] * matrix[3][2] - matrix[1][0] * matrix[0][2] * matrix[3][1] - matrix[3][0] * matrix[0][1] * matrix[1][2] + matrix[3][0] * matrix[0][2] * matrix[1][1]; inverse[0][3] = -matrix[0][1] * matrix[1][2] * matrix[2][3] + matrix[0][1] * matrix[1][3] * matrix[2][2] + matrix[1][1] * matrix[0][2] * matrix[2][3] - matrix[1][1] * matrix[0][3] * matrix[2][2] - matrix[2][1] * matrix[0][2] * matrix[1][3] + matrix[2][1] * matrix[0][3] * matrix[1][2]; inverse[1][3] = matrix[0][0] * matrix[1][2] * matrix[2][3] - matrix[0][0] * matrix[1][3] * matrix[2][2] - matrix[1][0] * matrix[0][2] * matrix[2][3] + matrix[1][0] * matrix[0][3] * matrix[2][2] + matrix[2][0] * matrix[0][2] * matrix[1][3] - matrix[2][0] * matrix[0][3] * matrix[1][2]; inverse[2][3] = -matrix[0][0] * matrix[1][1] * matrix[2][3] + matrix[0][0] * matrix[1][3] * matrix[2][1] + matrix[1][0] * matrix[0][1] * matrix[2][3] - matrix[1][0] * matrix[0][3] * matrix[2][1] - matrix[2][0] * matrix[0][1] * matrix[1][3] + matrix[2][0] * matrix[0][3] * matrix[1][1]; inverse[3][3] = matrix[0][0] * matrix[1][1] * matrix[2][2] - matrix[0][0] * matrix[1][2] * matrix[2][1] - matrix[1][0] * matrix[0][1] * matrix[2][2] + matrix[1][0] * matrix[0][2] * matrix[2][1] + matrix[2][0] * matrix[0][1] * matrix[1][2] - matrix[2][0] * matrix[0][2] * matrix[1][1]; K det = matrix[0][0] * inverse[0][0] + matrix[0][1] * inverse[1][0] + matrix[0][2] * inverse[2][0] + matrix[0][3] * inverse[3][0]; // return identity for singular or nearly singular matrices. if (std::abs(det) < 1e-40) { inverse = std::numeric_limits::quiet_NaN(); throw NumericalProblem("Singular matrix"); } else inverse *= 1.0 / det; return det; } template using FMat4 = Dune::FieldMatrix; template static inline void invertMatrix(Dune::FieldMatrix& matrix) { FMat4 tmp(matrix); invertMatrix4(tmp, matrix); } template static inline void invertMatrix(Dune::DynamicMatrix& matrix) { // this function is only for 4 X 4 matrix // for 4 X 4 matrix, using the invertMatrix() function above // it is for temporary usage, mainly to reduce the huge burden of testing // what algorithm should be used to invert 4 X 4 matrix will be handled // as a seperate issue if (matrix.rows() == 4) { Dune::DynamicMatrix A = matrix; invertMatrix4(A, matrix); return; } matrix.invert(); } } // namespace detail template class MatrixBlock : public Dune::FieldMatrix { public: using BaseType = Dune::FieldMatrix ; using BaseType::operator= ; using BaseType::rows; using BaseType::cols; MatrixBlock() : BaseType(Scalar(0.0)) {} explicit MatrixBlock(const Scalar value) : BaseType(value) {} void invert() { detail::invertMatrix(asBase()); } const BaseType& asBase() const { return static_cast(*this); } BaseType& asBase() { return static_cast(*this); } }; } // namespace Opm namespace Dune { template void print_row(std::ostream& s, const Opm::MatrixBlock& A, typename FieldMatrix::size_type I, typename FieldMatrix::size_type J, typename FieldMatrix::size_type therow, int width, int precision) { print_row(s, A.asBase(), I, J, therow, width, precision); } template struct MatrixDimension > : public MatrixDimension::BaseType> { }; #if HAVE_UMFPACK /// \brief UMFPack specialization for Opm::MatrixBlock to make AMG happy /// /// Without this the empty default implementation would be used. template class UMFPack, A> > : public UMFPack, A> > { using Base = UMFPack, A> >; using Matrix = BCRSMatrix, A>; public: using RealMatrix = BCRSMatrix, A>; UMFPack(const RealMatrix& matrix, int verbose, bool) : Base(reinterpret_cast(matrix), verbose) {} }; #endif #if HAVE_SUPERLU /// \brief SuperLU specialization for Opm::MatrixBlock to make AMG happy /// /// Without this the empty default implementation would be used. template class SuperLU, A> > : public SuperLU, A> > { using Base = SuperLU, A> >; using Matrix = BCRSMatrix, A>; public: using RealMatrix = BCRSMatrix, A>; SuperLU(const RealMatrix& matrix, int verb, bool reuse=true) : Base(reinterpret_cast(matrix), verb, reuse) {} }; #endif template struct IsNumber> : public IsNumber> {}; } // end namespace Dune #endif