Make ParallelOverlappingILU0 updateable & use it to construct ILU0/n

This should force the flexible solver approach to recalculate the
decomposition during update.

Closes #2490
This commit is contained in:
Markus Blatt 2020-03-23 09:32:28 +01:00
parent 81b9947e92
commit c14bf078a1
2 changed files with 60 additions and 50 deletions

View File

@ -21,6 +21,7 @@
#define OPM_PARALLELOVERLAPPINGILU0_HEADER_INCLUDED
#include <opm/simulators/linalg/GraphColoring.hpp>
#include <opm/simulators/linalg/PreconditionerWithUpdate.hpp>
#include <opm/common/Exceptions.hpp>
#include <opm/common/ErrorMacros.hpp>
#include <dune/common/version.hh>
@ -506,6 +507,9 @@ namespace Opm
typedef typename M :: size_type size_type;
lower.clear();
upper.clear();
inv.clear();
lower.resize( A.N() );
upper.resize( A.N() );
inv.resize( A.N() );
@ -599,7 +603,7 @@ namespace Opm
/// used, e.g. Dune::OwnerOverlapCommunication
template<class Matrix, class Domain, class Range, class ParallelInfoT>
class ParallelOverlappingILU0
: public Dune::Preconditioner<Domain,Range>
: public Dune::PreconditionerWithUpdate<Domain,Range>
{
typedef ParallelInfoT ParallelInfo;
@ -656,6 +660,14 @@ protected:
cols_.push_back( index );
}
void clear()
{
rows_.clear();
values_.clear();
cols_.clear();
nRows_= 0;
}
std::vector< size_type > rows_;
std::vector< block_type > values_;
std::vector< size_type > cols_;
@ -691,13 +703,14 @@ public:
upper_(),
inv_(),
comm_(nullptr), w_(w),
relaxation_( std::abs( w - 1.0 ) > 1e-15 )
relaxation_( std::abs( w - 1.0 ) > 1e-15 ),
A_(&reinterpret_cast<const Matrix&>(A)), iluIteration_(n),
milu_(milu), redBlack_(redblack), reorderSphere_(reorder_sphere)
{
interiorSize_ = A.N();
// BlockMatrix is a Subclass of FieldMatrix that just adds
// methods. Therefore this cast should be safe.
init( reinterpret_cast<const Matrix&>(A), n, milu, redblack,
reorder_sphere );
update();
}
/*! \brief Constructor gets all parameters to operate the prec.
@ -721,13 +734,14 @@ public:
upper_(),
inv_(),
comm_(&comm), w_(w),
relaxation_( std::abs( w - 1.0 ) > 1e-15 )
relaxation_( std::abs( w - 1.0 ) > 1e-15 ),
A_(&reinterpret_cast<const Matrix&>(A)), iluIteration_(n),
milu_(milu), redBlack_(redblack), reorderSphere_(reorder_sphere)
{
interiorSize_ = A.N();
// BlockMatrix is a Subclass of FieldMatrix that just adds
// methods. Therefore this cast should be safe.
init( reinterpret_cast<const Matrix&>(A), n, milu, redblack,
reorder_sphere );
update();
}
/*! \brief Constructor.
@ -772,13 +786,14 @@ public:
upper_(),
inv_(),
comm_(&comm), w_(w),
relaxation_( std::abs( w - 1.0 ) > 1e-15 )
relaxation_( std::abs( w - 1.0 ) > 1e-15 ),
A_(&reinterpret_cast<const Matrix&>(A)), iluIteration_(0),
milu_(milu), redBlack_(redblack), reorderSphere_(reorder_sphere)
{
interiorSize_ = A.N();
// BlockMatrix is a Subclass of FieldMatrix that just adds
// methods. Therefore this cast should be safe.
init( reinterpret_cast<const Matrix&>(A), 0, milu, redblack,
reorder_sphere );
update();
}
/*! \brief Constructor.
@ -806,12 +821,13 @@ public:
inv_(),
comm_(&comm), w_(w),
relaxation_( std::abs( w - 1.0 ) > 1e-15 ),
interiorSize_(interiorSize)
interiorSize_(interiorSize),
A_(&reinterpret_cast<const Matrix&>(A)), iluIteration_(0),
milu_(milu), redBlack_(redblack), reorderSphere_(reorder_sphere)
{
// BlockMatrix is a Subclass of FieldMatrix that just adds
// methods. Therefore this cast should be safe.
init( reinterpret_cast<const Matrix&>(A), 0, milu, redblack,
reorder_sphere );
update( );
}
/*!
@ -905,15 +921,14 @@ public:
DUNE_UNUSED_PARAMETER(x);
}
protected:
void init( const Matrix& A, const int iluIteration, MILU_VARIANT milu, bool redBlack, bool reorderSpheres )
virtual void update() override
{
// (For older DUNE versions the communicator might be
// invalid if redistribution in AMG happened on the coarset level.
// Therefore we check for nonzero size
if ( comm_ && comm_->communicator().size()<=0 )
{
if ( A.N() > 0 )
if ( A_->N() > 0 )
{
OPM_THROW(std::logic_error, "Expected a matrix with zero rows for an invalid communicator.");
}
@ -930,15 +945,15 @@ protected:
std::unique_ptr< Matrix > ILU;
if ( redBlack )
if ( redBlack_ )
{
using Graph = Dune::Amg::MatrixGraph<const Matrix>;
Graph graph(A);
Graph graph(*A_);
auto colorsTuple = colorVerticesWelshPowell(graph);
const auto& colors = std::get<0>(colorsTuple);
const auto& verticesPerColor = std::get<2>(colorsTuple);
auto noColors = std::get<1>(colorsTuple);
if ( reorderSpheres )
if ( reorderSphere_ )
{
ordering_ = reorderVerticesSpheres(colors, noColors, verticesPerColor,
graph, 0);
@ -959,27 +974,27 @@ protected:
try
{
if( iluIteration == 0 ) {
if( iluIteration_ == 0 ) {
// create ILU-0 decomposition
if ( ordering_.empty() )
{
ILU.reset( new Matrix( A ) );
ILU.reset( new Matrix( *A_ ) );
}
else
{
ILU.reset( new Matrix(A.N(), A.M(), A.nonzeroes(), Matrix::row_wise));
ILU.reset( new Matrix(A_->N(), A_->M(), A_->nonzeroes(), Matrix::row_wise));
auto& newA = *ILU;
// Create sparsity pattern
for(auto iter=newA.createbegin(), iend = newA.createend(); iter != iend; ++iter)
{
const auto& row = A[inverseOrdering[iter.index()]];
const auto& row = (*A_)[inverseOrdering[iter.index()]];
for(auto col = row.begin(), cend = row.end(); col != cend; ++col)
{
iter.insert(ordering_[col.index()]);
}
}
// Copy values
for(auto iter = A.begin(), iend = A.end(); iter != iend; ++iter)
for(auto iter = A_->begin(), iend = A_->end(); iter != iend; ++iter)
{
auto& newRow = newA[ordering_[iter.index()]];
for(auto col = iter->begin(), cend = iter->end(); col != cend; ++col)
@ -989,7 +1004,7 @@ protected:
}
}
switch ( milu )
switch ( milu_ )
{
case MILU_VARIANT::MILU_1:
detail::milu0_decomposition ( *ILU);
@ -1007,7 +1022,7 @@ protected:
detail::IsPositiveFunctor() );
break;
default:
if (interiorSize_ == A.N())
if (interiorSize_ == A_->N())
bilu0_decomposition( *ILU );
else
detail::ghost_last_bilu0_decomposition(*ILU, interiorSize_);
@ -1016,7 +1031,7 @@ protected:
}
else {
// create ILU-n decomposition
ILU.reset( new Matrix( A.N(), A.M(), Matrix::row_wise) );
ILU.reset( new Matrix( A_->N(), A_->M(), Matrix::row_wise) );
std::unique_ptr<detail::Reorderer> reorderer, inverseReorderer;
if ( ordering_.empty() )
{
@ -1029,7 +1044,7 @@ protected:
inverseReorderer.reset(new detail::RealReorderer(inverseOrdering));
}
milun_decomposition( A, iluIteration, milu, *ILU, *reorderer, *inverseReorderer );
milun_decomposition( *A_, iluIteration_, milu_, *ILU, *reorderer, *inverseReorderer );
}
}
catch (const Dune::MatrixBlockError& error)
@ -1053,6 +1068,7 @@ protected:
detail::convertToCRS( *ILU, lower_, upper_, inv_ );
}
protected:
/// \brief Reorder D if needed and return a reference to it.
Range& reorderD(const Range& d)
{
@ -1123,6 +1139,11 @@ protected:
const field_type w_;
const bool relaxation_;
size_type interiorSize_;
const Matrix* A_;
int iluIteration_;
MILU_VARIANT milu_;
bool redBlack_;
bool reorderSphere_;
};
} // end namespace Opm

View File

@ -156,26 +156,20 @@ private:
using C = Comm;
doAddCreator("ILU0", [](const O& op, const P& prm, const C& comm) {
const double w = prm.get<double>("relaxation");
#if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqILU<M, V, V>>>(comm, op.getmat(), w);
#else
return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqILU0<M, V, V>>>(comm, op.getmat(), w);
#endif
return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V, C>>(
op.getmat(), comm, 0, w, Opm::MILU_VARIANT::ILU);
});
doAddCreator("ParOverILU0", [](const O& op, const P& prm, const C& comm) {
const double w = prm.get<double>("relaxation");
// Already a parallel preconditioner. Need to pass comm, but no need to wrap it in a BlockPreconditioner.
return wrapPreconditioner<Opm::ParallelOverlappingILU0<M, V, V, C>>(
return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V, C>>(
op.getmat(), comm, 0, w, Opm::MILU_VARIANT::ILU);
});
doAddCreator("ILUn", [](const O& op, const P& prm, const C& comm) {
const int n = prm.get<int>("ilulevel");
const double w = prm.get<double>("relaxation");
#if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqILU<M, V, V>>>(comm, op.getmat(), n, w);
#else
return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqILUn<M, V, V>>>(comm, op.getmat(), n, w);
#endif
return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V, C>>(
op.getmat(), comm, n, w, Opm::MILU_VARIANT::ILU);
});
doAddCreator("Jac", [](const O& op, const P& prm, const C& comm) {
const int n = prm.get<int>("repeats");
@ -229,24 +223,19 @@ private:
using P = boost::property_tree::ptree;
doAddCreator("ILU0", [](const O& op, const P& prm) {
const double w = prm.get<double>("relaxation");
#if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
return wrapPreconditioner<SeqILU<M, V, V>>(op.getmat(), w);
#else
return wrapPreconditioner<SeqILU0<M, V, V>>(op.getmat(), w);
#endif
return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V>>(
op.getmat(), 0, w, Opm::MILU_VARIANT::ILU);
});
doAddCreator("ParOverILU0", [](const O& op, const P& prm) {
const double w = prm.get<double>("relaxation");
return wrapPreconditioner<Opm::ParallelOverlappingILU0<M, V, V>>(op.getmat(), 0, w, Opm::MILU_VARIANT::ILU);
return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V>>(
op.getmat(), 0, w, Opm::MILU_VARIANT::ILU);
});
doAddCreator("ILUn", [](const O& op, const P& prm) {
const int n = prm.get<int>("ilulevel");
const double w = prm.get<double>("relaxation");
#if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
return wrapPreconditioner<SeqILU<M, V, V>>(op.getmat(), n, w);
#else
return wrapPreconditioner<SeqILUn<M, V, V>>(op.getmat(), n, w);
#endif
return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V>>(
op.getmat(), n, w, Opm::MILU_VARIANT::ILU);
});
doAddCreator("Jac", [](const O& op, const P& prm) {
const int n = prm.get<int>("repeats");