First version of a AMG for the Blackoil equations.

The approach is inspired by Geiger's system-amg but we use dune-istl
aggregation AMG for it. On the fine level all unknowns attached to a cell
form a matrix block and are treated fully coupled. To form the first
coarse level system we use only the pressure component to guide the aggregation
and neglect all other unknowns on the fine level. All other level are formed
in the usual way by scalar aggregation.

Currently,it has to be requested for flow_ebos manually by passing
"linear_solver_use_amg=true amg_blackoil_system=true" to it.
This commit is contained in:
Markus Blatt
2017-09-07 09:15:39 +02:00
parent a2419e285f
commit f5d81513da
6 changed files with 1124 additions and 22 deletions

View File

@@ -21,6 +21,7 @@
#define OPM_ISTLSOLVER_HEADER_INCLUDED
#include <opm/autodiff/AdditionalObjectDeleter.hpp>
#include <opm/autodiff/BlackoilAmg.hpp>
#include <opm/autodiff/CPRPreconditioner.hpp>
#include <opm/autodiff/NewtonIterationBlackoilInterleaved.hpp>
#include <opm/autodiff/NewtonIterationUtilities.hpp>
@@ -407,10 +408,8 @@ namespace Opm
if( parameters_.linear_solver_use_amg_ )
{
typedef ISTLUtility::CPRSelector< Matrix, Vector, Vector, POrComm> CPRSelectorType;
typedef typename CPRSelectorType::AMG AMG;
typedef typename CPRSelectorType::Operator MatrixOperator;
std::unique_ptr< AMG > amg;
std::unique_ptr< MatrixOperator > opA;
if( ! std::is_same< LinearOperator, MatrixOperator > :: value )
@@ -420,12 +419,34 @@ namespace Opm
}
const double relax = 1.0;
if ( ! parameters_.amg_blackoil_system_ )
{
typedef typename CPRSelectorType::AMG AMG;
std::unique_ptr< AMG > amg;
// Construct preconditioner.
constructAMGPrecond( linearOperator, parallelInformation_arg, amg, opA, relax );
// Construct preconditioner.
constructAMGPrecond( linearOperator, parallelInformation_arg, amg, opA, relax );
// Solve.
solve(linearOperator, x, istlb, *sp, *amg, result);
// Solve.
solve(linearOperator, x, istlb, *sp, *amg, result);
}
else
{
using Matrix = typename MatrixOperator::matrix_type;
using CouplingMetric = Dune::Amg::Diagonal<pressureIndex>;
using CritBase = Dune::Amg::SymmetricCriterion<Matrix, CouplingMetric>;
using Criterion = Dune::Amg::CoarsenCriterion<CritBase>;
using AMG = typename ISTLUtility
::BlackoilAmgSelector< Matrix, Vector, Vector,POrComm, Criterion, pressureIndex >::AMG;
std::unique_ptr< AMG > amg;
// Construct preconditioner.
Criterion crit(15, 2000);
constructAMGPrecond<Criterion>( linearOperator, parallelInformation_arg, amg, opA, relax );
// Solve.
solve(linearOperator, x, istlb, *sp, *amg, result);
}
}
else
#endif
@@ -495,6 +516,20 @@ namespace Opm
ISTLUtility::template createAMGPreconditionerPointer<pressureIndex>( opA, relax, comm, amg );
}
template <class C, class LinearOperator, class MatrixOperator, class POrComm, class AMG >
void
constructAMGPrecond(LinearOperator& /* linearOperator */, const POrComm& comm, std::unique_ptr< AMG >& amg, std::unique_ptr< MatrixOperator >& opA, const double relax ) const
{
ISTLUtility::template createAMGPreconditionerPointer<C>( *opA, relax, comm, amg );
}
template <class C, class MatrixOperator, class POrComm, class AMG >
void
constructAMGPrecond(MatrixOperator& opA, const POrComm& comm, std::unique_ptr< AMG >& amg, std::unique_ptr< MatrixOperator >&, const double relax ) const
{
ISTLUtility::template createAMGPreconditionerPointer<C>( opA, relax, comm, amg );
}
/// \brief Solve the system using the given preconditioner and scalar product.
template <class Operator, class ScalarProd, class Precond>
void solve(Operator& opA, Vector& x, Vector& istlb, ScalarProd& sp, Precond& precond, Dune::InverseOperatorResult& result) const