// -*- 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