Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ghost entries skipped for ILU apply and SpMV operator in all levels of AMG/CPR hierarchy #5182

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists_files.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,8 @@ if (HAVE_ECL_INPUT)
endif()

if(MPI_FOUND)
list(APPEND TEST_SOURCE_FILES tests/test_parallelistlinformation.cpp
list(APPEND TEST_SOURCE_FILES tests/test_ghostlastmatrixadapter.cpp
tests/test_parallelistlinformation.cpp
tests/test_ParallelSerialization.cpp)
endif()

Expand Down
7 changes: 5 additions & 2 deletions opm/simulators/linalg/FlexibleSolver_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,11 @@ using SeqOpW = Opm::WellModelMatrixAdapter<OBM<N>, BV<N>, BV<N>, false>;
// Parallel communicator and operators.
using Comm = Dune::OwnerOverlapCopyCommunication<int, int>;
template <int N>
using ParOpM = Dune::OverlappingSchwarzOperator<OBM<N>, BV<N>, BV<N>, Comm>;
using ParOpM = Opm::GhostLastMatrixAdapter<OBM<N>, BV<N>, BV<N>, Comm>;
template <int N>
using ParOpW = Opm::WellModelGhostLastMatrixAdapter<OBM<N>, BV<N>, BV<N>, true>;
template <int N>
using ParOpD = Dune::OverlappingSchwarzOperator<OBM<N>, BV<N>, BV<N>, Comm>;

// Note: we must instantiate the constructor that is a template.
// This is only needed in the parallel case, since otherwise the Comm type is
Expand All @@ -288,7 +290,8 @@ template Dune::FlexibleSolver<Operator>::FlexibleSolver(Operator& op,
INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpM<N>); \
INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpW<N>); \
INSTANTIATE_FLEXIBLESOLVER_OP(ParOpM<N>); \
INSTANTIATE_FLEXIBLESOLVER_OP(ParOpW<N>);
INSTANTIATE_FLEXIBLESOLVER_OP(ParOpW<N>); \
INSTANTIATE_FLEXIBLESOLVER_OP(ParOpD<N>);

#else // HAVE_MPI

Expand Down
2 changes: 1 addition & 1 deletion opm/simulators/linalg/ISTLSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ void FlexibleSolverInfo<Matrix,Vector,Comm>::create(const Matrix& matrix,
if (parallel) {
#if HAVE_MPI
if (!wellOperator_) {
using ParOperatorType = Dune::OverlappingSchwarzOperator<Matrix, Vector, Vector, Comm>;
using ParOperatorType = Opm::GhostLastMatrixAdapter<Matrix, Vector, Vector, Comm>;
auto pop = std::make_unique<ParOperatorType>(matrix, comm);
using FlexibleSolverType = Dune::FlexibleSolver<ParOperatorType>;
auto sol = std::make_unique<FlexibleSolverType>(*pop, comm, prm,
Expand Down
34 changes: 34 additions & 0 deletions opm/simulators/linalg/ParallelOverlappingILU0_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,35 @@ void convertToCRS(const M& A, CRS& lower, CRS& upper, InvVector& inv)
assert(colcount == numUpper);
}

template <class PI>
size_t set_interiorSize( [[maybe_unused]] size_t N, size_t interiorSize, [[maybe_unused]] const PI& comm)
{
return interiorSize;
}

#if HAVE_MPI
template<>
size_t set_interiorSize(size_t N, size_t interiorSize, const Dune::OwnerOverlapCopyCommunication<int,int>& comm)
{
if (interiorSize<N)
return interiorSize;
auto indexSet = comm.indexSet();

size_t new_is = 0;
for (auto idx = indexSet.begin(); idx!=indexSet.end(); ++idx)
{
if (idx->local().attribute()==1)
{
auto loc = idx->local().local();
if (loc > new_is) {
new_is = loc;
}
}
}
return new_is + 1;
}
#endif

} // end namespace detail


Expand Down Expand Up @@ -411,6 +440,11 @@ update()
{
OPM_TIMEBLOCK(iluDecomposition);
if (iluIteration_ == 0) {

if (comm_) {
interiorSize_ = detail::set_interiorSize(A_->N(), interiorSize_, *comm_);
}

// create ILU-0 decomposition
if (ordering_.empty())
{
Expand Down
19 changes: 17 additions & 2 deletions opm/simulators/linalg/PreconditionerFactory_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ struct StandardPreconditioners {
// is the overlapping schwarz operator. This could be extended
// later, but at this point no other operators are compatible
// with the AMG hierarchy construction.
if constexpr (std::is_same_v<O, Dune::OverlappingSchwarzOperator<M, V, V, C>>) {
if constexpr (std::is_same_v<O, Dune::OverlappingSchwarzOperator<M, V, V, C>> ||
std::is_same_v<O, Opm::GhostLastMatrixAdapter<M, V, V, C>>) {
F::addCreator("amg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
using PrecPtr = std::shared_ptr<Dune::PreconditionerWithUpdate<V, V>>;
const std::string smoother = prm.get<std::string>("smoother", "ParOverILU0");
Expand Down Expand Up @@ -780,14 +781,28 @@ using OpBPar = Dune::OverlappingSchwarzOperator<Dune::BCRSMatrix<MatrixBlock<dou
Dune::BlockVector<Dune::FieldVector<double, Dim>>,
Dune::BlockVector<Dune::FieldVector<double, Dim>>,
CommPar>;
template<int Dim>
using OpGLFPar = Opm::GhostLastMatrixAdapter<Dune::BCRSMatrix<Dune::FieldMatrix<double,Dim,Dim>>,
Dune::BlockVector<Dune::FieldVector<double,Dim>>,
Dune::BlockVector<Dune::FieldVector<double,Dim>>,
CommPar>;

template<int Dim>
using OpGLBPar = Opm::GhostLastMatrixAdapter<Dune::BCRSMatrix<MatrixBlock<double,Dim,Dim>>,
Dune::BlockVector<Dune::FieldVector<double,Dim>>,
Dune::BlockVector<Dune::FieldVector<double,Dim>>,
CommPar>;

#define INSTANCE_PF_PAR(Dim) \
template class PreconditionerFactory<OpBSeq<Dim>, CommPar>; \
template class PreconditionerFactory<OpFPar<Dim>, CommPar>; \
template class PreconditionerFactory<OpBPar<Dim>, CommPar>; \
template class PreconditionerFactory<OpGLFPar<Dim>,CommPar>; \
template class PreconditionerFactory<OpGLBPar<Dim>,CommPar>; \
template class PreconditionerFactory<OpW<Dim, false>, CommPar>; \
template class PreconditionerFactory<OpWG<Dim, true>, CommPar>; \
template class PreconditionerFactory<OpBPar<Dim>, CommSeq>;
template class PreconditionerFactory<OpBPar<Dim>,CommSeq>; \
template class PreconditionerFactory<OpGLBPar<Dim>,CommSeq>;
#endif

#define INSTANCE_PF_SEQ(Dim) \
Expand Down
3 changes: 2 additions & 1 deletion opm/simulators/linalg/PressureBhpTransferPolicy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <opm/simulators/linalg/twolevelmethodcpr.hh>

#include <dune/istl/paamg/pinfo.hh>
#include <opm/simulators/linalg/WellOperators.hpp>

#include <cstddef>

Expand Down Expand Up @@ -81,7 +82,7 @@ namespace Opm
using SeqCoarseOperatorType = Dune::MatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType>;
template <class Comm>
using ParCoarseOperatorType
= Dune::OverlappingSchwarzOperator<PressureMatrixType, PressureVectorType, PressureVectorType, Comm>;
= Opm::GhostLastMatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType, Comm>;
template <class Comm>
using CoarseOperatorType = std::conditional_t<std::is_same<Comm, Dune::Amg::SequentialInformation>::value,
SeqCoarseOperatorType,
Expand Down
3 changes: 2 additions & 1 deletion opm/simulators/linalg/PressureTransferPolicy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <opm/simulators/linalg/twolevelmethodcpr.hh>
#include <opm/simulators/linalg/PropertyTree.hpp>
#include <opm/simulators/linalg/matrixblock.hh>
#include <opm/simulators/linalg/WellOperators.hpp>

#include <cstddef>

Expand All @@ -38,7 +39,7 @@ namespace Details
using SeqCoarseOperatorType = Dune::MatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType>;
template <class Comm>
using ParCoarseOperatorType
= Dune::OverlappingSchwarzOperator<PressureMatrixType, PressureVectorType, PressureVectorType, Comm>;
= Opm::GhostLastMatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType, Comm>;
template <class Comm>
using CoarseOperatorType = std::conditional_t<std::is_same<Comm, Dune::Amg::SequentialInformation>::value,
SeqCoarseOperatorType,
Expand Down
123 changes: 123 additions & 0 deletions opm/simulators/linalg/WellOperators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include <opm/common/TimingMacros.hpp>

#include <opm/simulators/linalg/matrixblock.hh>
#include <dune/common/shared_ptr.hh>
#include <dune/istl/paamg/smoother.hh>

#include <cstddef>

Expand Down Expand Up @@ -311,7 +313,128 @@ class WellModelGhostLastMatrixAdapter : public Dune::AssembledLinearOperator<M,X
std::size_t interiorSize_;
};

/*!
\brief Dune linear operator that assumes ghost rows are ordered after
interior rows. Avoids some computations because of this.

This is similar to WellModelGhostLastMatrixAdapter, with the difference that
here we do not have a well model, and also do calcilate the interiorSize
using the parallel index set. Created for use in AMG/CPR smoothers.
*/
template<class M, class X, class Y, class C>
class GhostLastMatrixAdapter : public Dune::AssembledLinearOperator<M,X,Y>
{
public:
typedef M matrix_type;
typedef X domain_type;
typedef Y range_type;
typedef typename X::field_type field_type;


typedef C communication_type;

Dune::SolverCategory::Category category() const override
{
return Dune::SolverCategory::overlapping;
}

//! constructor: just store a reference to a matrix
GhostLastMatrixAdapter (const M& A,
const communication_type& comm)
: A_( Dune::stackobject_to_shared_ptr(A) ), comm_(comm)
{
interiorSize_ = setInteriorSize(comm_);
}

GhostLastMatrixAdapter (const std::shared_ptr<M> A,
const communication_type& comm)
: A_( A ), comm_(comm)
{
interiorSize_ = setInteriorSize(comm_);
}

virtual void apply( const X& x, Y& y ) const override
{
for (auto row = A_->begin(); row.index() < interiorSize_; ++row)
{
y[row.index()]=0;
auto endc = (*row).end();
for (auto col = (*row).begin(); col != endc; ++col)
(*col).umv(x[col.index()], y[row.index()]);
}

ghostLastProject( y );
}

// y += \alpha * A * x
virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const override
{
for (auto row = A_->begin(); row.index() < interiorSize_; ++row)
{
auto endc = (*row).end();
for (auto col = (*row).begin(); col != endc; ++col)
(*col).usmv(alpha, x[col.index()], y[row.index()]);
}

ghostLastProject( y );
}

virtual const matrix_type& getmat() const override { return *A_; }

size_t getInteriorSize() const { return interiorSize_;}

private:
void ghostLastProject(Y& y) const
{
size_t end = y.size();
for (size_t i = interiorSize_; i < end; ++i)
y[i] = 0; //project to interiorsize, i.e. ignore ghost
}

size_t setInteriorSize(const communication_type& comm) const
{
auto indexSet = comm.indexSet();

size_t is = 0;
// Loop over index set
for (auto idx = indexSet.begin(); idx!=indexSet.end(); ++idx) {
//Only take "owner" indices
if (idx->local().attribute()==1) {
//get local index
auto loc = idx->local().local();
// if loc is higher than "old interior size", update it
if (loc > is) {
is = loc;
}
}
}
return is + 1; //size is plus 1 since we start at 0
}
const std::shared_ptr<const matrix_type> A_ ;
const communication_type& comm_;
size_t interiorSize_;
};

} // namespace Opm

namespace Dune {
namespace Amg {

template<class M, class X, class Y, class C>
class ConstructionTraits<Opm::GhostLastMatrixAdapter<M,X,Y,C> >
{
public:
typedef ParallelOperatorArgs<M,C> Arguments;

static inline std::shared_ptr<Opm::GhostLastMatrixAdapter<M,X,Y,C>> construct(const Arguments& args)
{
return std::make_shared<Opm::GhostLastMatrixAdapter<M,X,Y,C>>
(args.matrix_, args.comm_);
}
};

} // end namespace Amg
} // end namespace Dune

#endif // OPM_WELLOPERATORS_HEADER_INCLUDED