// -*- 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 namespace Opm { namespace MatrixBlockHelp { template static inline void invertMatrix(Dune::FieldMatrix& matrix) { matrix.invert(); } template static inline void invertMatrix(Dune::FieldMatrix& matrix) { matrix[0][0] = 1.0/matrix[0][0]; } 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); matrix[0][0] = tmp[1][1]*tmp[2][2]*tmp[3][3] - tmp[1][1]*tmp[2][3]*tmp[3][2] - tmp[2][1]*tmp[1][2]*tmp[3][3] + tmp[2][1]*tmp[1][3]*tmp[3][2] + tmp[3][1]*tmp[1][2]*tmp[2][3] - tmp[3][1]*tmp[1][3]*tmp[2][2]; matrix[1][0] = -tmp[1][0]*tmp[2][2]*tmp[3][3] + tmp[1][0]*tmp[2][3]*tmp[3][2] + tmp[2][0]*tmp[1][2]*tmp[3][3] - tmp[2][0]*tmp[1][3]*tmp[3][2] - tmp[3][0]*tmp[1][2]*tmp[2][3] + tmp[3][0]*tmp[1][3]*tmp[2][2]; matrix[2][0] = tmp[1][0]*tmp[2][1]*tmp[3][3] - tmp[1][0]*tmp[2][3]*tmp[3][1] - tmp[2][0]*tmp[1][1]*tmp[3][3] + tmp[2][0]*tmp[1][3]*tmp[3][1] + tmp[3][0]*tmp[1][1]*tmp[2][3] - tmp[3][0]*tmp[1][3]*tmp[2][1]; matrix[3][0] = -tmp[1][0]*tmp[2][1]*tmp[3][2] + tmp[1][0]*tmp[2][2]*tmp[3][1] + tmp[2][0]*tmp[1][1]*tmp[3][2] - tmp[2][0]*tmp[1][2]*tmp[3][1] - tmp[3][0]*tmp[1][1]*tmp[2][2] + tmp[3][0]*tmp[1][2]*tmp[2][1]; matrix[0][1] = -tmp[0][1]*tmp[2][2]*tmp[3][3] + tmp[0][1]*tmp[2][3]*tmp[3][2] + tmp[2][1]*tmp[0][2]*tmp[3][3] - tmp[2][1]*tmp[0][3]*tmp[3][2] - tmp[3][1]*tmp[0][2]*tmp[2][3] + tmp[3][1]*tmp[0][3]*tmp[2][2]; matrix[1][1] = tmp[0][0]*tmp[2][2]*tmp[3][3] - tmp[0][0]*tmp[2][3]*tmp[3][2] - tmp[2][0]*tmp[0][2]*tmp[3][3] + tmp[2][0]*tmp[0][3]*tmp[3][2] + tmp[3][0]*tmp[0][2]*tmp[2][3] - tmp[3][0]*tmp[0][3]*tmp[2][2]; matrix[2][1] = -tmp[0][0]*tmp[2][1]*tmp[3][3] + tmp[0][0]*tmp[2][3]*tmp[3][1] + tmp[2][0]*tmp[0][1]*tmp[3][3] - tmp[2][0]*tmp[0][3]*tmp[3][1] - tmp[3][0]*tmp[0][1]*tmp[2][3] + tmp[3][0]*tmp[0][3]*tmp[2][1]; matrix[3][1] = tmp[0][0]*tmp[2][1]*tmp[3][2] - tmp[0][0]*tmp[2][2]*tmp[3][1] - tmp[2][0]*tmp[0][1]*tmp[3][2] + tmp[2][0]*tmp[0][2]*tmp[3][1] + tmp[3][0]*tmp[0][1]*tmp[2][2] - tmp[3][0]*tmp[0][2]*tmp[2][1]; matrix[0][2] = tmp[0][1]*tmp[1][2]*tmp[3][3] - tmp[0][1]*tmp[1][3]*tmp[3][2] - tmp[1][1]*tmp[0][2]*tmp[3][3] + tmp[1][1]*tmp[0][3]*tmp[3][2] + tmp[3][1]*tmp[0][2]*tmp[1][3] - tmp[3][1]*tmp[0][3]*tmp[1][2]; matrix[1][2] = -tmp[0][0] *tmp[1][2]*tmp[3][3] + tmp[0][0]*tmp[1][3]*tmp[3][2] + tmp[1][0]*tmp[0][2]*tmp[3][3] - tmp[1][0]*tmp[0][3]*tmp[3][2] - tmp[3][0]*tmp[0][2]*tmp[1][3] + tmp[3][0]*tmp[0][3]*tmp[1][2]; matrix[2][2] = tmp[0][0]*tmp[1][1]*tmp[3][3] - tmp[0][0]*tmp[1][3]*tmp[3][1] - tmp[1][0]*tmp[0][1]*tmp[3][3] + tmp[1][0]*tmp[0][3]*tmp[3][1] + tmp[3][0]*tmp[0][1]*tmp[1][3] - tmp[3][0]*tmp[0][3]*tmp[1][1]; matrix[3][2] = -tmp[0][0]*tmp[1][1]*tmp[3][2] + tmp[0][0]*tmp[1][2]*tmp[3][1] + tmp[1][0]*tmp[0][1]*tmp[3][2] - tmp[1][0]*tmp[0][2]*tmp[3][1] - tmp[3][0]*tmp[0][1]*tmp[1][2] + tmp[3][0]*tmp[0][2]*tmp[1][1]; matrix[0][3] = -tmp[0][1]*tmp[1][2]*tmp[2][3] + tmp[0][1]*tmp[1][3]*tmp[2][2] + tmp[1][1]*tmp[0][2]*tmp[2][3] - tmp[1][1]*tmp[0][3]*tmp[2][2] - tmp[2][1]*tmp[0][2]*tmp[1][3] + tmp[2][1]*tmp[0][3]*tmp[1][2]; matrix[1][3] = tmp[0][0]*tmp[1][2]*tmp[2][3] - tmp[0][0]*tmp[1][3]*tmp[2][2] - tmp[1][0]*tmp[0][2]*tmp[2][3] + tmp[1][0]*tmp[0][3]*tmp[2][2] + tmp[2][0]*tmp[0][2]*tmp[1][3] - tmp[2][0]*tmp[0][3]*tmp[1][2]; matrix[2][3] = -tmp[0][0]*tmp[1][1]*tmp[2][3] + tmp[0][0]*tmp[1][3]*tmp[2][1] + tmp[1][0]*tmp[0][1]*tmp[2][3] - tmp[1][0]*tmp[0][3]*tmp[2][1] - tmp[2][0]*tmp[0][1]*tmp[1][3] + tmp[2][0]*tmp[0][3]*tmp[1][1]; matrix[3][3] = tmp[0][0]*tmp[1][1]*tmp[2][2] - tmp[0][0]*tmp[1][2]*tmp[2][1] - tmp[1][0]*tmp[0][1]*tmp[2][2] + tmp[1][0]*tmp[0][2]*tmp[2][1] + tmp[2][0]*tmp[0][1]*tmp[1][2] - tmp[2][0]*tmp[0][2]*tmp[1][1]; K det = tmp[0][0]*matrix[0][0] + tmp[0][1]*matrix[1][0] + tmp[0][2]*matrix[2][0] + tmp[0][3]*matrix[3][0]; // return identity for singular or nearly singular matrices. if (std::abs(det) < 1e-40) matrix = std::numeric_limits::quiet_NaN(); else matrix *= 1.0/det; } } // namespace MatrixBlockHelp 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() { Opm::MatrixBlockHelp::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 K& firstmatrixelement(Opm::MatrixBlock& A) { return firstmatrixelement(A.asBase()); } 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 } // end namespace Dune #endif