mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-10-13 09:22:05 -05:00
Adding functions for pressure system manipulation to well models.
Also add well-aware operator and transfer policy. This will be used for CPR with custom operators.
This commit is contained in:
1 parent
0bb293aeb0
commit
f3acfcde0b
15 files changed
+821
-103
No files matched your search
@@ -42,12 +42,12 @@ list (APPEND MAIN_SOURCE_FILES
|
|||||||
opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.cpp
|
opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.cpp
|
||||||
opm/simulators/flow/ValidationFunctions.cpp
|
opm/simulators/flow/ValidationFunctions.cpp
|
||||||
opm/simulators/linalg/ExtractParallelGridInformationToISTL.cpp
|
opm/simulators/linalg/ExtractParallelGridInformationToISTL.cpp
|
||||||
opm/simulators/linalg/FlexibleSolver1.cpp
|
# opm/simulators/linalg/FlexibleSolver1.cpp
|
||||||
opm/simulators/linalg/FlexibleSolver2.cpp
|
# opm/simulators/linalg/FlexibleSolver2.cpp
|
||||||
opm/simulators/linalg/FlexibleSolver3.cpp
|
# opm/simulators/linalg/FlexibleSolver3.cpp
|
||||||
opm/simulators/linalg/FlexibleSolver4.cpp
|
# opm/simulators/linalg/FlexibleSolver4.cpp
|
||||||
opm/simulators/linalg/FlexibleSolver5.cpp
|
# opm/simulators/linalg/FlexibleSolver5.cpp
|
||||||
opm/simulators/linalg/FlexibleSolver6.cpp
|
# opm/simulators/linalg/FlexibleSolver6.cpp
|
||||||
opm/simulators/linalg/PropertyTree.cpp
|
opm/simulators/linalg/PropertyTree.cpp
|
||||||
opm/simulators/linalg/setupPropertyTree.cpp
|
opm/simulators/linalg/setupPropertyTree.cpp
|
||||||
opm/simulators/utils/PartiallySupportedFlowKeywords.cpp
|
opm/simulators/utils/PartiallySupportedFlowKeywords.cpp
|
||||||
|
|||||||
@@ -35,27 +35,25 @@ namespace Dune
|
|||||||
/// (operator, scalar product, iterative solver and preconditioner) and sets
|
/// (operator, scalar product, iterative solver and preconditioner) and sets
|
||||||
/// them up based on runtime parameters, using the PreconditionerFactory for
|
/// them up based on runtime parameters, using the PreconditionerFactory for
|
||||||
/// setting up preconditioners.
|
/// setting up preconditioners.
|
||||||
template <class MatrixTypeT, class VectorTypeT>
|
template <class Operator>
|
||||||
class FlexibleSolver : public Dune::InverseOperator<VectorTypeT, VectorTypeT>
|
class FlexibleSolver : public Dune::InverseOperator<typename Operator::domain_type,
|
||||||
|
typename Operator::range_type>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using MatrixType = MatrixTypeT;
|
using VectorType = typename Operator::domain_type; // Assuming symmetry: domain == range
|
||||||
using VectorType = VectorTypeT;
|
|
||||||
|
|
||||||
/// Base class type of the operator passed to the solver.
|
|
||||||
using AbstractOperatorType = Dune::AssembledLinearOperator<MatrixType, VectorType, VectorType>;
|
|
||||||
/// Base class type of the contained preconditioner.
|
/// Base class type of the contained preconditioner.
|
||||||
using AbstractPrecondType = Dune::PreconditionerWithUpdate<VectorType, VectorType>;
|
using AbstractPrecondType = Dune::PreconditionerWithUpdate<VectorType, VectorType>;
|
||||||
|
|
||||||
/// Create a sequential solver.
|
/// Create a sequential solver.
|
||||||
FlexibleSolver(AbstractOperatorType& op,
|
FlexibleSolver(Operator& op,
|
||||||
const Opm::PropertyTree& prm,
|
const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()>& weightsCalculator,
|
const std::function<VectorType()>& weightsCalculator,
|
||||||
std::size_t pressureIndex);
|
std::size_t pressureIndex);
|
||||||
|
|
||||||
/// Create a parallel solver (if Comm is e.g. OwnerOverlapCommunication).
|
/// Create a parallel solver (if Comm is e.g. OwnerOverlapCommunication).
|
||||||
template <class Comm>
|
template <class Comm>
|
||||||
FlexibleSolver(AbstractOperatorType& op,
|
FlexibleSolver(Operator& op,
|
||||||
const Comm& comm,
|
const Comm& comm,
|
||||||
const Opm::PropertyTree& prm,
|
const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()>& weightsCalculator,
|
const std::function<VectorType()>& weightsCalculator,
|
||||||
@@ -76,11 +74,11 @@ private:
|
|||||||
|
|
||||||
// Machinery for making sequential or parallel operators/preconditioners/scalar products.
|
// Machinery for making sequential or parallel operators/preconditioners/scalar products.
|
||||||
template <class Comm>
|
template <class Comm>
|
||||||
void initOpPrecSp(AbstractOperatorType& op, const Opm::PropertyTree& prm,
|
void initOpPrecSp(Operator& op, const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()> weightsCalculator, const Comm& comm,
|
const std::function<VectorType()> weightsCalculator, const Comm& comm,
|
||||||
std::size_t pressureIndex);
|
std::size_t pressureIndex);
|
||||||
|
|
||||||
void initOpPrecSp(AbstractOperatorType& op, const Opm::PropertyTree& prm,
|
void initOpPrecSp(Operator& op, const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()> weightsCalculator, const Dune::Amg::SequentialInformation&,
|
const std::function<VectorType()> weightsCalculator, const Dune::Amg::SequentialInformation&,
|
||||||
std::size_t pressureIndex);
|
std::size_t pressureIndex);
|
||||||
|
|
||||||
@@ -89,14 +87,13 @@ private:
|
|||||||
// Main initialization routine.
|
// Main initialization routine.
|
||||||
// Call with Comm == Dune::Amg::SequentialInformation to get a serial solver.
|
// Call with Comm == Dune::Amg::SequentialInformation to get a serial solver.
|
||||||
template <class Comm>
|
template <class Comm>
|
||||||
void init(AbstractOperatorType& op,
|
void init(Operator& op,
|
||||||
const Comm& comm,
|
const Comm& comm,
|
||||||
const Opm::PropertyTree& prm,
|
const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()> weightsCalculator,
|
const std::function<VectorType()> weightsCalculator,
|
||||||
std::size_t pressureIndex);
|
std::size_t pressureIndex);
|
||||||
|
|
||||||
AbstractOperatorType* linearoperator_for_solver_;
|
Operator* linearoperator_for_solver_;
|
||||||
std::shared_ptr<AbstractOperatorType> linearoperator_for_precond_;
|
|
||||||
std::shared_ptr<AbstractPrecondType> preconditioner_;
|
std::shared_ptr<AbstractPrecondType> preconditioner_;
|
||||||
std::shared_ptr<AbstractScalarProductType> scalarproduct_;
|
std::shared_ptr<AbstractScalarProductType> scalarproduct_;
|
||||||
std::shared_ptr<AbstractSolverType> linsolver_;
|
std::shared_ptr<AbstractSolverType> linsolver_;
|
||||||
@@ -104,6 +101,7 @@ private:
|
|||||||
|
|
||||||
} // namespace Dune
|
} // namespace Dune
|
||||||
|
|
||||||
|
#include <opm/simulators/linalg/FlexibleSolver_impl.hpp>
|
||||||
|
|
||||||
|
|
||||||
#endif // OPM_FLEXIBLE_SOLVER_HEADER_INCLUDED
|
#endif // OPM_FLEXIBLE_SOLVER_HEADER_INCLUDED
|
||||||
@@ -36,9 +36,9 @@
|
|||||||
namespace Dune
|
namespace Dune
|
||||||
{
|
{
|
||||||
/// Create a sequential solver.
|
/// Create a sequential solver.
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
FlexibleSolver(AbstractOperatorType& op,
|
FlexibleSolver(Operator& op,
|
||||||
const Opm::PropertyTree& prm,
|
const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()>& weightsCalculator,
|
const std::function<VectorType()>& weightsCalculator,
|
||||||
std::size_t pressureIndex)
|
std::size_t pressureIndex)
|
||||||
@@ -48,10 +48,10 @@ namespace Dune
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a parallel solver (if Comm is e.g. OwnerOverlapCommunication).
|
/// Create a parallel solver (if Comm is e.g. OwnerOverlapCommunication).
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
template <class Comm>
|
template <class Comm>
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
FlexibleSolver(AbstractOperatorType& op,
|
FlexibleSolver(Operator& op,
|
||||||
const Comm& comm,
|
const Comm& comm,
|
||||||
const Opm::PropertyTree& prm,
|
const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()>& weightsCalculator,
|
const std::function<VectorType()>& weightsCalculator,
|
||||||
@@ -60,89 +60,83 @@ namespace Dune
|
|||||||
init(op, comm, prm, weightsCalculator, pressureIndex);
|
init(op, comm, prm, weightsCalculator, pressureIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
void
|
void
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
apply(VectorType& x, VectorType& rhs, Dune::InverseOperatorResult& res)
|
apply(VectorType& x, VectorType& rhs, Dune::InverseOperatorResult& res)
|
||||||
{
|
{
|
||||||
linsolver_->apply(x, rhs, res);
|
linsolver_->apply(x, rhs, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
void
|
void
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
apply(VectorType& x, VectorType& rhs, double reduction, Dune::InverseOperatorResult& res)
|
apply(VectorType& x, VectorType& rhs, double reduction, Dune::InverseOperatorResult& res)
|
||||||
{
|
{
|
||||||
linsolver_->apply(x, rhs, reduction, res);
|
linsolver_->apply(x, rhs, reduction, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Access the contained preconditioner.
|
/// Access the contained preconditioner.
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
auto
|
auto
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
preconditioner() -> AbstractPrecondType&
|
preconditioner() -> AbstractPrecondType&
|
||||||
{
|
{
|
||||||
return *preconditioner_;
|
return *preconditioner_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
Dune::SolverCategory::Category
|
Dune::SolverCategory::Category
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
category() const
|
category() const
|
||||||
{
|
{
|
||||||
return linearoperator_for_solver_->category();
|
return linearoperator_for_solver_->category();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Machinery for making sequential or parallel operators/preconditioners/scalar products.
|
// Machinery for making sequential or parallel operators/preconditioners/scalar products.
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
template <class Comm>
|
template <class Comm>
|
||||||
void
|
void
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
initOpPrecSp(AbstractOperatorType& op,
|
initOpPrecSp(Operator& op,
|
||||||
const Opm::PropertyTree& prm,
|
const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()> weightsCalculator,
|
const std::function<VectorType()> weightsCalculator,
|
||||||
const Comm& comm,
|
const Comm& comm,
|
||||||
std::size_t pressureIndex)
|
std::size_t pressureIndex)
|
||||||
{
|
{
|
||||||
// Parallel case.
|
// Parallel case.
|
||||||
using ParOperatorType = Dune::OverlappingSchwarzOperator<MatrixType, VectorType, VectorType, Comm>;
|
|
||||||
linearoperator_for_solver_ = &op;
|
linearoperator_for_solver_ = &op;
|
||||||
auto op_prec = std::make_shared<ParOperatorType>(op.getmat(), comm);
|
|
||||||
auto child = prm.get_child_optional("preconditioner");
|
auto child = prm.get_child_optional("preconditioner");
|
||||||
preconditioner_ = Opm::PreconditionerFactory<ParOperatorType, Comm>::create(*op_prec,
|
preconditioner_ = Opm::PreconditionerFactory<Operator, Comm>::create(op,
|
||||||
child ? *child : Opm::PropertyTree(),
|
child ? *child : Opm::PropertyTree(),
|
||||||
weightsCalculator,
|
weightsCalculator,
|
||||||
comm,
|
comm,
|
||||||
pressureIndex);
|
pressureIndex);
|
||||||
scalarproduct_ = Dune::createScalarProduct<VectorType, Comm>(comm, op.category());
|
scalarproduct_ = Dune::createScalarProduct<VectorType, Comm>(comm, op.category());
|
||||||
linearoperator_for_precond_ = op_prec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
void
|
void
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
initOpPrecSp(AbstractOperatorType& op,
|
initOpPrecSp(Operator& op,
|
||||||
const Opm::PropertyTree& prm,
|
const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()> weightsCalculator,
|
const std::function<VectorType()> weightsCalculator,
|
||||||
const Dune::Amg::SequentialInformation&,
|
const Dune::Amg::SequentialInformation&,
|
||||||
std::size_t pressureIndex)
|
std::size_t pressureIndex)
|
||||||
{
|
{
|
||||||
// Sequential case.
|
// Sequential case.
|
||||||
using SeqOperatorType = Dune::MatrixAdapter<MatrixType, VectorType, VectorType>;
|
|
||||||
linearoperator_for_solver_ = &op;
|
linearoperator_for_solver_ = &op;
|
||||||
auto op_prec = std::make_shared<SeqOperatorType>(op.getmat());
|
|
||||||
auto child = prm.get_child_optional("preconditioner");
|
auto child = prm.get_child_optional("preconditioner");
|
||||||
preconditioner_ = Opm::PreconditionerFactory<SeqOperatorType>::create(*op_prec,
|
preconditioner_ = Opm::PreconditionerFactory<Operator>::create(op,
|
||||||
child ? *child : Opm::PropertyTree(),
|
child ? *child : Opm::PropertyTree(),
|
||||||
weightsCalculator,
|
weightsCalculator,
|
||||||
pressureIndex);
|
pressureIndex);
|
||||||
scalarproduct_ = std::make_shared<Dune::SeqScalarProduct<VectorType>>();
|
scalarproduct_ = std::make_shared<Dune::SeqScalarProduct<VectorType>>();
|
||||||
linearoperator_for_precond_ = op_prec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
void
|
void
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
initSolver(const Opm::PropertyTree& prm, const bool is_iorank)
|
initSolver(const Opm::PropertyTree& prm, const bool is_iorank)
|
||||||
{
|
{
|
||||||
const double tol = prm.get<double>("tol", 1e-2);
|
const double tol = prm.get<double>("tol", 1e-2);
|
||||||
@@ -175,6 +169,7 @@ namespace Dune
|
|||||||
#if HAVE_SUITESPARSE_UMFPACK
|
#if HAVE_SUITESPARSE_UMFPACK
|
||||||
} else if (solver_type == "umfpack") {
|
} else if (solver_type == "umfpack") {
|
||||||
bool dummy = false;
|
bool dummy = false;
|
||||||
|
using MatrixType = std::remove_const_t<std::remove_reference_t<decltype(linearoperator_for_solver_->getmat())>>;
|
||||||
linsolver_.reset(new Dune::UMFPack<MatrixType>(linearoperator_for_solver_->getmat(), verbosity, dummy));
|
linsolver_.reset(new Dune::UMFPack<MatrixType>(linearoperator_for_solver_->getmat(), verbosity, dummy));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@@ -185,11 +180,11 @@ namespace Dune
|
|||||||
|
|
||||||
// Main initialization routine.
|
// Main initialization routine.
|
||||||
// Call with Comm == Dune::Amg::SequentialInformation to get a serial solver.
|
// Call with Comm == Dune::Amg::SequentialInformation to get a serial solver.
|
||||||
template <class MatrixType, class VectorType>
|
template <class Operator>
|
||||||
template <class Comm>
|
template <class Comm>
|
||||||
void
|
void
|
||||||
FlexibleSolver<MatrixType, VectorType>::
|
FlexibleSolver<Operator>::
|
||||||
init(AbstractOperatorType& op,
|
init(Operator& op,
|
||||||
const Comm& comm,
|
const Comm& comm,
|
||||||
const Opm::PropertyTree& prm,
|
const Opm::PropertyTree& prm,
|
||||||
const std::function<VectorType()> weightsCalculator,
|
const std::function<VectorType()> weightsCalculator,
|
||||||
@@ -203,7 +198,7 @@ namespace Dune
|
|||||||
|
|
||||||
|
|
||||||
// Macros to simplify explicit instantiation of FlexibleSolver for various block sizes.
|
// Macros to simplify explicit instantiation of FlexibleSolver for various block sizes.
|
||||||
|
/*
|
||||||
template <int N>
|
template <int N>
|
||||||
using BV = Dune::BlockVector<Dune::FieldVector<double, N>>;
|
using BV = Dune::BlockVector<Dune::FieldVector<double, N>>;
|
||||||
template <int N>
|
template <int N>
|
||||||
@@ -240,6 +235,8 @@ template class Dune::FlexibleSolver<BM<N>, BV<N>>; \
|
|||||||
template class Dune::FlexibleSolver<OBM<N>, BV<N>>;
|
template class Dune::FlexibleSolver<OBM<N>, BV<N>>;
|
||||||
|
|
||||||
#endif // HAVE_MPI
|
#endif // HAVE_MPI
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define INSTANTIATE_FLEXIBLESOLVER(N) do(){}
|
||||||
|
|
||||||
#endif // OPM_FLEXIBLE_SOLVER_IMPL_HEADER_INCLUDED
|
#endif // OPM_FLEXIBLE_SOLVER_IMPL_HEADER_INCLUDED
|
||||||
@@ -87,9 +87,11 @@ namespace Opm
|
|||||||
using Matrix = typename SparseMatrixAdapter::IstlMatrix;
|
using Matrix = typename SparseMatrixAdapter::IstlMatrix;
|
||||||
using ThreadManager = GetPropType<TypeTag, Properties::ThreadManager>;
|
using ThreadManager = GetPropType<TypeTag, Properties::ThreadManager>;
|
||||||
using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
|
using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
|
||||||
using FlexibleSolverType = Dune::FlexibleSolver<Matrix, Vector>;
|
using AbstractSolverType = Dune::InverseOperator<Vector, Vector>;
|
||||||
using AbstractOperatorType = Dune::AssembledLinearOperator<Matrix, Vector, Vector>;
|
using AbstractOperatorType = Dune::AssembledLinearOperator<Matrix, Vector, Vector>;
|
||||||
|
using AbstractPreconditionerType = Dune::PreconditionerWithUpdate<Vector, Vector>;
|
||||||
using WellModelOperator = WellModelAsLinearOperator<WellModel, Vector, Vector>;
|
using WellModelOperator = WellModelAsLinearOperator<WellModel, Vector, Vector>;
|
||||||
|
using ParOperatorType = WellModelGhostLastMatrixAdapter<Matrix, Vector, Vector, true>;
|
||||||
using ElementMapper = GetPropType<TypeTag, Properties::ElementMapper>;
|
using ElementMapper = GetPropType<TypeTag, Properties::ElementMapper>;
|
||||||
constexpr static std::size_t pressureIndex = GetPropType<TypeTag, Properties::Indices>::pressureSwitchIdx;
|
constexpr static std::size_t pressureIndex = GetPropType<TypeTag, Properties::Indices>::pressureSwitchIdx;
|
||||||
|
|
||||||
@@ -381,35 +383,47 @@ namespace Opm
|
|||||||
#if HAVE_MPI
|
#if HAVE_MPI
|
||||||
if (useWellConn_) {
|
if (useWellConn_) {
|
||||||
using ParOperatorType = Dune::OverlappingSchwarzOperator<Matrix, Vector, Vector, Comm>;
|
using ParOperatorType = Dune::OverlappingSchwarzOperator<Matrix, Vector, Vector, Comm>;
|
||||||
linearOperatorForFlexibleSolver_ = std::make_unique<ParOperatorType>(getMatrix(), *comm_);
|
auto op = std::make_unique<ParOperatorType>(getMatrix(), *comm_);
|
||||||
flexibleSolver_ = std::make_unique<FlexibleSolverType>(*linearOperatorForFlexibleSolver_, *comm_, prm_, weightsCalculator,
|
using FlexibleSolverType = Dune::FlexibleSolver<ParOperatorType>;
|
||||||
pressureIndex);
|
auto sol = std::make_unique<FlexibleSolverType>(*op, *comm_, prm_, weightsCalculator, pressureIndex);
|
||||||
|
preconditionerForFlexibleSolver_ = &(sol->preconditioner());
|
||||||
|
linearOperatorForFlexibleSolver_ = std::move(op);
|
||||||
|
flexibleSolver_ = std::move(sol);
|
||||||
} else {
|
} else {
|
||||||
using ParOperatorType = WellModelGhostLastMatrixAdapter<Matrix, Vector, Vector, true>;
|
using ParOperatorType = WellModelGhostLastMatrixAdapter<Matrix, Vector, Vector, true>;
|
||||||
wellOperator_ = std::make_unique<WellModelOperator>(simulator_.problem().wellModel());
|
wellOperator_ = std::make_unique<WellModelOperator>(simulator_.problem().wellModel());
|
||||||
linearOperatorForFlexibleSolver_ = std::make_unique<ParOperatorType>(getMatrix(), *wellOperator_, interiorCellNum_);
|
auto op = std::make_unique<ParOperatorType>(getMatrix(), *wellOperator_, interiorCellNum_);
|
||||||
flexibleSolver_ = std::make_unique<FlexibleSolverType>(*linearOperatorForFlexibleSolver_, *comm_, prm_, weightsCalculator,
|
using FlexibleSolverType = Dune::FlexibleSolver<ParOperatorType>;
|
||||||
pressureIndex);
|
auto sol = std::make_unique<FlexibleSolverType>(*op, *comm_, prm_, weightsCalculator, pressureIndex);
|
||||||
|
preconditionerForFlexibleSolver_ = &(sol->preconditioner());
|
||||||
|
linearOperatorForFlexibleSolver_ = std::move(op);
|
||||||
|
flexibleSolver_ = std::move(sol);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
if (useWellConn_) {
|
if (useWellConn_) {
|
||||||
using SeqOperatorType = Dune::MatrixAdapter<Matrix, Vector, Vector>;
|
using SeqOperatorType = Dune::MatrixAdapter<Matrix, Vector, Vector>;
|
||||||
linearOperatorForFlexibleSolver_ = std::make_unique<SeqOperatorType>(getMatrix());
|
auto op = std::make_unique<SeqOperatorType>(getMatrix());
|
||||||
flexibleSolver_ = std::make_unique<FlexibleSolverType>(*linearOperatorForFlexibleSolver_, prm_, weightsCalculator,
|
using FlexibleSolverType = Dune::FlexibleSolver<SeqOperatorType>;
|
||||||
pressureIndex);
|
auto sol = std::make_unique<FlexibleSolverType>(*op, prm_, weightsCalculator, pressureIndex);
|
||||||
|
preconditionerForFlexibleSolver_ = &(sol->preconditioner());
|
||||||
|
linearOperatorForFlexibleSolver_ = std::move(op);
|
||||||
|
flexibleSolver_ = std::move(sol);
|
||||||
} else {
|
} else {
|
||||||
using SeqOperatorType = WellModelMatrixAdapter<Matrix, Vector, Vector, false>;
|
using SeqOperatorType = WellModelMatrixAdapter<Matrix, Vector, Vector, false>;
|
||||||
wellOperator_ = std::make_unique<WellModelOperator>(simulator_.problem().wellModel());
|
wellOperator_ = std::make_unique<WellModelOperator>(simulator_.problem().wellModel());
|
||||||
linearOperatorForFlexibleSolver_ = std::make_unique<SeqOperatorType>(getMatrix(), *wellOperator_);
|
auto op = std::make_unique<SeqOperatorType>(getMatrix(), *wellOperator_);
|
||||||
flexibleSolver_ = std::make_unique<FlexibleSolverType>(*linearOperatorForFlexibleSolver_, prm_, weightsCalculator,
|
using FlexibleSolverType = Dune::FlexibleSolver<SeqOperatorType>;
|
||||||
pressureIndex);
|
auto sol = std::make_unique<FlexibleSolverType>(*op, prm_, weightsCalculator, pressureIndex);
|
||||||
|
preconditionerForFlexibleSolver_ = &(sol->preconditioner());
|
||||||
|
linearOperatorForFlexibleSolver_ = std::move(op);
|
||||||
|
flexibleSolver_ = std::move(sol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
flexibleSolver_->preconditioner().update();
|
preconditionerForFlexibleSolver_->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,9 +466,11 @@ namespace Opm
|
|||||||
using namespace std::string_literals;
|
using namespace std::string_literals;
|
||||||
|
|
||||||
auto preconditionerType = prm_.get("preconditioner.type"s, "cpr"s);
|
auto preconditionerType = prm_.get("preconditioner.type"s, "cpr"s);
|
||||||
if (preconditionerType == "cpr" || preconditionerType == "cprt") {
|
if (preconditionerType == "cpr" || preconditionerType == "cprt"
|
||||||
const bool transpose = preconditionerType == "cprt";
|
|| preconditionerType == "cprw" || preconditionerType == "cprwt") {
|
||||||
|
const bool transpose = preconditionerType == "cprt" || preconditionerType == "cprwt";
|
||||||
const auto weightsType = prm_.get("preconditioner.weight_type"s, "quasiimpes"s);
|
const auto weightsType = prm_.get("preconditioner.weight_type"s, "quasiimpes"s);
|
||||||
|
const auto pressureIndex = this->prm_.get("preconditioner.pressure_var_index", 1);
|
||||||
if (weightsType == "quasiimpes") {
|
if (weightsType == "quasiimpes") {
|
||||||
// weights will be created as default in the solver
|
// weights will be created as default in the solver
|
||||||
// assignment p = pressureIndex prevent compiler warning about
|
// assignment p = pressureIndex prevent compiler warning about
|
||||||
@@ -598,8 +614,9 @@ namespace Opm
|
|||||||
|
|
||||||
std::unique_ptr<Matrix> blockJacobiForGPUILU0_;
|
std::unique_ptr<Matrix> blockJacobiForGPUILU0_;
|
||||||
|
|
||||||
std::unique_ptr<FlexibleSolverType> flexibleSolver_;
|
std::unique_ptr<AbstractSolverType> flexibleSolver_;
|
||||||
std::unique_ptr<AbstractOperatorType> linearOperatorForFlexibleSolver_;
|
std::unique_ptr<AbstractOperatorType> linearOperatorForFlexibleSolver_;
|
||||||
|
AbstractPreconditionerType* preconditionerForFlexibleSolver_;
|
||||||
std::unique_ptr<WellModelAsLinearOperator<WellModel, Vector, Vector>> wellOperator_;
|
std::unique_ptr<WellModelAsLinearOperator<WellModel, Vector, Vector>> wellOperator_;
|
||||||
std::vector<int> overlapRows_;
|
std::vector<int> overlapRows_;
|
||||||
std::vector<int> interiorRows_;
|
std::vector<int> interiorRows_;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace Dune
|
|||||||
|
|
||||||
|
|
||||||
// Must forward-declare FlexibleSolver as we want to use it as solver for the pressure system.
|
// Must forward-declare FlexibleSolver as we want to use it as solver for the pressure system.
|
||||||
template <class MatrixTypeT, class VectorTypeT>
|
template <class Operator>
|
||||||
class FlexibleSolver;
|
class FlexibleSolver;
|
||||||
|
|
||||||
template <typename T, typename A, int i>
|
template <typename T, typename A, int i>
|
||||||
@@ -183,7 +183,7 @@ private:
|
|||||||
ParCoarseOperatorType>;
|
ParCoarseOperatorType>;
|
||||||
using LevelTransferPolicy = Opm::PressureTransferPolicy<OperatorType, CoarseOperatorType, Communication, transpose>;
|
using LevelTransferPolicy = Opm::PressureTransferPolicy<OperatorType, CoarseOperatorType, Communication, transpose>;
|
||||||
using CoarseSolverPolicy = Dune::Amg::PressureSolverPolicy<CoarseOperatorType,
|
using CoarseSolverPolicy = Dune::Amg::PressureSolverPolicy<CoarseOperatorType,
|
||||||
FlexibleSolver<PressureMatrixType, PressureVectorType>,
|
FlexibleSolver<CoarseOperatorType>,
|
||||||
LevelTransferPolicy>;
|
LevelTransferPolicy>;
|
||||||
using TwoLevelMethod
|
using TwoLevelMethod
|
||||||
= Dune::Amg::TwoLevelMethodCpr<OperatorType, CoarseSolverPolicy, Dune::Preconditioner<VectorType, VectorType>>;
|
= Dune::Amg::TwoLevelMethodCpr<OperatorType, CoarseSolverPolicy, Dune::Preconditioner<VectorType, VectorType>>;
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
|
||||||
|
|
||||||
|
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 3 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <opm/simulators/linalg/PreconditionerWithUpdate.hpp>
|
||||||
|
#include <opm/simulators/linalg/PressureSolverPolicy.hpp>
|
||||||
|
#include <opm/simulators/linalg/PressureBhpTransferPolicy.hpp>
|
||||||
|
#include <opm/simulators/linalg/getQuasiImpesWeights.hpp>
|
||||||
|
#include <opm/simulators/linalg/twolevelmethodcpr.hh>
|
||||||
|
|
||||||
|
#include <opm/common/ErrorMacros.hpp>
|
||||||
|
|
||||||
|
#include <dune/common/fmatrix.hh>
|
||||||
|
#include <dune/istl/bcrsmatrix.hh>
|
||||||
|
#include <dune/istl/paamg/amg.hh>
|
||||||
|
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Opm
|
||||||
|
{
|
||||||
|
// Circular dependency between PreconditionerFactory [which can make an OwningTwoLevelPreconditioner]
|
||||||
|
// and OwningTwoLevelPreconditioner [which uses PreconditionerFactory to choose the fine-level smoother]
|
||||||
|
// must be broken, accomplished by forward-declaration here.
|
||||||
|
//template <class Operator, class Comm = Dune::Amg::SequentialInformation>
|
||||||
|
//class PreconditionerFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Dune
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// Must forward-declare FlexibleSolver as we want to use it as solver for the pressure system.
|
||||||
|
template <class Operator>
|
||||||
|
class FlexibleSolver;
|
||||||
|
|
||||||
|
// template <typename T, typename A, int i>
|
||||||
|
// std::ostream& operator<<(std::ostream& out,
|
||||||
|
// const BlockVector< FieldVector< T, i >, A >& vector)
|
||||||
|
// {
|
||||||
|
// Dune::writeMatrixMarket(vector, out);
|
||||||
|
// return out;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template <typename T, typename A, int i>
|
||||||
|
// std::istream& operator>>(std::istream& input,
|
||||||
|
// BlockVector< FieldVector< T, i >, A >& vector)
|
||||||
|
// {
|
||||||
|
// Dune::readMatrixMarket(vector, input);
|
||||||
|
// return input;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// A version of the two-level preconditioner that is:
|
||||||
|
/// - Self-contained, because it owns its policy components.
|
||||||
|
/// - Flexible, because it uses the runtime-flexible solver
|
||||||
|
/// and preconditioner factory.
|
||||||
|
template <class OperatorType,
|
||||||
|
class VectorType,
|
||||||
|
bool transpose = false,
|
||||||
|
class Communication = Dune::Amg::SequentialInformation>
|
||||||
|
class OwningTwoLevelPreconditionerWell : public Dune::PreconditionerWithUpdate<VectorType, VectorType>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using pt = boost::property_tree::ptree;
|
||||||
|
using MatrixType = typename OperatorType::matrix_type;
|
||||||
|
using PrecFactory = Opm::PreconditionerFactory<OperatorType, Communication>;
|
||||||
|
using AbstractOperatorType = Dune::AssembledLinearOperator<MatrixType, VectorType, VectorType>;
|
||||||
|
|
||||||
|
OwningTwoLevelPreconditionerWell(const OperatorType& linearoperator, const pt& prm,
|
||||||
|
const std::function<VectorType()> weightsCalculator)
|
||||||
|
: linear_operator_(linearoperator)
|
||||||
|
, finesmoother_(PrecFactory::create(linearoperator,
|
||||||
|
prm.get_child_optional("finesmoother")?
|
||||||
|
prm.get_child("finesmoother"): pt()))
|
||||||
|
, comm_(nullptr)
|
||||||
|
, weightsCalculator_(weightsCalculator)
|
||||||
|
, weights_(weightsCalculator())
|
||||||
|
, levelTransferPolicy_(dummy_comm_, weights_, prm)//.get<int>("pressure_var_index"))
|
||||||
|
, coarseSolverPolicy_(prm.get_child_optional("coarsesolver")? prm.get_child("coarsesolver") : pt())
|
||||||
|
, twolevel_method_(linearoperator,
|
||||||
|
finesmoother_,
|
||||||
|
levelTransferPolicy_,
|
||||||
|
coarseSolverPolicy_,
|
||||||
|
prm.get<int>("pre_smooth", transpose? 1 : 0),
|
||||||
|
prm.get<int>("post_smooth", transpose? 0 : 1))
|
||||||
|
, prm_(prm)
|
||||||
|
{
|
||||||
|
if (prm.get<int>("verbosity", 0) > 10) {
|
||||||
|
std::string filename = prm.get<std::string>("weights_filename", "impes_weights.txt");
|
||||||
|
std::ofstream outfile(filename);
|
||||||
|
if (!outfile) {
|
||||||
|
OPM_THROW(std::ofstream::failure, "Could not write weights to file " << filename << ".");
|
||||||
|
}
|
||||||
|
Dune::writeMatrixMarket(weights_, outfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OwningTwoLevelPreconditionerWell(const OperatorType& linearoperator,
|
||||||
|
const pt& prm,
|
||||||
|
const std::function<VectorType()> weightsCalculator, const Communication& comm)
|
||||||
|
: linear_operator_(linearoperator)
|
||||||
|
, finesmoother_(PrecFactory::create(linearoperator,
|
||||||
|
prm.get_child_optional("finesmoother")?
|
||||||
|
prm.get_child("finesmoother"): pt(), comm))
|
||||||
|
, comm_(&comm)
|
||||||
|
, weightsCalculator_(weightsCalculator)
|
||||||
|
, weights_(weightsCalculator())
|
||||||
|
, levelTransferPolicy_(*comm_, weights_, prm)//.get<int>("pressure_var_index", 1))
|
||||||
|
, coarseSolverPolicy_(prm.get_child_optional("coarsesolver")? prm.get_child("coarsesolver") : pt())
|
||||||
|
, twolevel_method_(linearoperator,
|
||||||
|
finesmoother_,
|
||||||
|
levelTransferPolicy_,
|
||||||
|
coarseSolverPolicy_,
|
||||||
|
prm.get<int>("pre_smooth", transpose? 1 : 0),
|
||||||
|
prm.get<int>("post_smooth", transpose? 0 : 1))
|
||||||
|
, prm_(prm)
|
||||||
|
{
|
||||||
|
if (prm.get<int>("verbosity", 0) > 10 && comm.communicator().rank() == 0) {
|
||||||
|
auto filename = prm.get<std::string>("weights_filename", "impes_weights.txt");
|
||||||
|
std::ofstream outfile(filename);
|
||||||
|
if (!outfile) {
|
||||||
|
OPM_THROW(std::ofstream::failure, "Could not write weights to file " << filename << ".");
|
||||||
|
}
|
||||||
|
Dune::writeMatrixMarket(weights_, outfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void pre(VectorType& x, VectorType& b) override
|
||||||
|
{
|
||||||
|
twolevel_method_.pre(x, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(VectorType& v, const VectorType& d) override
|
||||||
|
{
|
||||||
|
twolevel_method_.apply(v, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void post(VectorType& x) override
|
||||||
|
{
|
||||||
|
twolevel_method_.post(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void update() override
|
||||||
|
{
|
||||||
|
weights_ = weightsCalculator_();
|
||||||
|
updateImpl(comm_);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Dune::SolverCategory::Category category() const override
|
||||||
|
{
|
||||||
|
return linear_operator_.category();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
using PressureMatrixType = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||||
|
using PressureVectorType = Dune::BlockVector<Dune::FieldVector<double, 1>>;
|
||||||
|
using SeqCoarseOperatorType = Dune::MatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType>;
|
||||||
|
using ParCoarseOperatorType
|
||||||
|
= Dune::OverlappingSchwarzOperator<PressureMatrixType, PressureVectorType, PressureVectorType, Communication>;
|
||||||
|
using CoarseOperatorType = std::conditional_t<std::is_same<Communication, Dune::Amg::SequentialInformation>::value,
|
||||||
|
SeqCoarseOperatorType,
|
||||||
|
ParCoarseOperatorType>;
|
||||||
|
using LevelTransferPolicy = Opm::PressureBhpTransferPolicy<OperatorType, CoarseOperatorType, Communication, transpose>;
|
||||||
|
using CoarseSolverPolicy = Dune::Amg::PressureSolverPolicy<CoarseOperatorType,
|
||||||
|
FlexibleSolver<CoarseOperatorType>,
|
||||||
|
LevelTransferPolicy>;
|
||||||
|
using TwoLevelMethod
|
||||||
|
= Dune::Amg::TwoLevelMethodCpr<OperatorType, CoarseSolverPolicy, Dune::Preconditioner<VectorType, VectorType>>;
|
||||||
|
|
||||||
|
// Handling parallel vs serial instantiation of preconditioner factory.
|
||||||
|
template <class Comm>
|
||||||
|
void updateImpl(const Comm*)
|
||||||
|
{
|
||||||
|
// Parallel case.
|
||||||
|
// using ParOperatorType = Dune::OverlappingSchwarzOperator<MatrixType, VectorType, VectorType, Comm>;
|
||||||
|
// auto op_prec = std::make_shared<ParOperatorType>(linear_operator_.getmat(), *comm_);
|
||||||
|
auto child = prm_.get_child_optional("finesmoother");
|
||||||
|
finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : pt(), *comm_);
|
||||||
|
twolevel_method_.updatePreconditioner(finesmoother_, coarseSolverPolicy_);
|
||||||
|
// linearoperator_for_precond_ = op_prec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateImpl(const Dune::Amg::SequentialInformation*)
|
||||||
|
{
|
||||||
|
// Serial case.
|
||||||
|
// using SeqOperatorType = Dune::MatrixAdapter<MatrixType, VectorType, VectorType>;
|
||||||
|
// auto op_prec = std::make_shared<SeqOperatorType>(linear_operator_.getmat());
|
||||||
|
auto child = prm_.get_child_optional("finesmoother");
|
||||||
|
finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : pt());
|
||||||
|
twolevel_method_.updatePreconditioner(finesmoother_, coarseSolverPolicy_);
|
||||||
|
// linearoperator_for_precond_ = op_prec;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OperatorType& linear_operator_;
|
||||||
|
std::shared_ptr<Dune::Preconditioner<VectorType, VectorType>> finesmoother_;
|
||||||
|
const Communication* comm_;
|
||||||
|
std::function<VectorType()> weightsCalculator_;
|
||||||
|
VectorType weights_;
|
||||||
|
LevelTransferPolicy levelTransferPolicy_;
|
||||||
|
CoarseSolverPolicy coarseSolverPolicy_;
|
||||||
|
TwoLevelMethod twolevel_method_;
|
||||||
|
boost::property_tree::ptree prm_;
|
||||||
|
Communication dummy_comm_;
|
||||||
|
//std::shared_ptr<AbstractOperatorType> linearoperator_for_precond_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Dune
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -24,10 +24,12 @@
|
|||||||
|
|
||||||
#include <opm/simulators/linalg/OwningBlockPreconditioner.hpp>
|
#include <opm/simulators/linalg/OwningBlockPreconditioner.hpp>
|
||||||
#include <opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp>
|
#include <opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp>
|
||||||
|
#include <opm/simulators/linalg/OwningTwoLevelPreconditionerWell.hpp>
|
||||||
#include <opm/simulators/linalg/ParallelOverlappingILU0.hpp>
|
#include <opm/simulators/linalg/ParallelOverlappingILU0.hpp>
|
||||||
#include <opm/simulators/linalg/PreconditionerWithUpdate.hpp>
|
#include <opm/simulators/linalg/PreconditionerWithUpdate.hpp>
|
||||||
#include <opm/simulators/linalg/PropertyTree.hpp>
|
#include <opm/simulators/linalg/PropertyTree.hpp>
|
||||||
#include <opm/simulators/linalg/amgcpr.hh>
|
#include <opm/simulators/linalg/amgcpr.hh>
|
||||||
|
#include <opm/simulators/linalg/WellOperators.hpp>
|
||||||
|
|
||||||
#include <dune/istl/paamg/amg.hh>
|
#include <dune/istl/paamg/amg.hh>
|
||||||
#include <dune/istl/paamg/kamg.hh>
|
#include <dune/istl/paamg/kamg.hh>
|
||||||
@@ -328,6 +330,27 @@ private:
|
|||||||
}
|
}
|
||||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, true, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
|
return std::make_shared<OwningTwoLevelPreconditioner<O, V, true, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<O, WellModelGhostLastMatrixAdapter<M, V, V, true>>) {
|
||||||
|
doAddCreator("cprw",
|
||||||
|
[](const O& op, const P& prm, const std::function<Vector()> weightsCalculator, std::size_t pressureIndex, const C& comm) {
|
||||||
|
assert(weightsCalculator);
|
||||||
|
if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
|
||||||
|
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||||
|
}
|
||||||
|
return std::make_shared<OwningTwoLevelPreconditionerWell<O, V, false, Comm>>(
|
||||||
|
op, prm, weightsCalculator, comm);
|
||||||
|
});
|
||||||
|
doAddCreator("cprwt",
|
||||||
|
[](const O& op, const P& prm, const std::function<Vector()> weightsCalculator, std::size_t pressureIndex, const C& comm) {
|
||||||
|
assert(weightsCalculator);
|
||||||
|
if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
|
||||||
|
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||||
|
}
|
||||||
|
return std::make_shared<OwningTwoLevelPreconditionerWell<O, V, true, Comm>>(
|
||||||
|
op, prm, weightsCalculator, comm);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a useful default set of preconditioners to the factory.
|
// Add a useful default set of preconditioners to the factory.
|
||||||
@@ -449,6 +472,21 @@ private:
|
|||||||
return wrapPreconditioner<Dune::Amg::FastAMG<O, V>>(op, crit, parms);
|
return wrapPreconditioner<Dune::Amg::FastAMG<O, V>>(op, crit, parms);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if constexpr (std::is_same_v<O, WellModelMatrixAdapter<M, V, V, false>>) {
|
||||||
|
doAddCreator("cprw", [](const O& op, const P& prm, const std::function<Vector()>& weightsCalculator) {
|
||||||
|
if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
|
||||||
|
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||||
|
}
|
||||||
|
return std::make_shared<OwningTwoLevelPreconditionerWell<O, V, false>>(op, prm, weightsCalculator);
|
||||||
|
});
|
||||||
|
doAddCreator("cprwt", [](const O& op, const P& prm, const std::function<Vector()>& weightsCalculator) {
|
||||||
|
if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
|
||||||
|
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||||
|
}
|
||||||
|
return std::make_shared<OwningTwoLevelPreconditionerWell<O, V, true>>(op, prm, weightsCalculator);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
doAddCreator("cpr", [](const O& op, const P& prm, const std::function<Vector()>& weightsCalculator, std::size_t pressureIndex) {
|
doAddCreator("cpr", [](const O& op, const P& prm, const std::function<Vector()>& weightsCalculator, std::size_t pressureIndex) {
|
||||||
if (pressureIndex == std::numeric_limits<std::size_t>::max())
|
if (pressureIndex == std::numeric_limits<std::size_t>::max())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,254 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
|
||||||
|
Copyright 2019 Dr. Blatt - HPC-Simulation-Software & Services.
|
||||||
|
|
||||||
|
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 3 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <opm/simulators/linalg/twolevelmethodcpr.hh>
|
||||||
|
#include <dune/istl/paamg/pinfo.hh>
|
||||||
|
|
||||||
|
namespace Opm
|
||||||
|
{
|
||||||
|
template <class Communication>
|
||||||
|
void extendCommunicatorWithWells(const Communication& comm,
|
||||||
|
std::shared_ptr<Communication>& commRW,
|
||||||
|
const int nw)
|
||||||
|
{
|
||||||
|
// used for extending the coarse communicator pattern
|
||||||
|
using IndexSet = typename Communication::ParallelIndexSet;
|
||||||
|
using LocalIndex = typename IndexSet::LocalIndex;
|
||||||
|
const IndexSet& indset = comm.indexSet();
|
||||||
|
IndexSet& indset_rw = commRW->indexSet();
|
||||||
|
const int max_nw = comm.communicator().max(nw);
|
||||||
|
const int num_proc = comm.communicator().size();
|
||||||
|
int glo_max = 0;
|
||||||
|
size_t loc_max = 0;
|
||||||
|
indset_rw.beginResize();
|
||||||
|
for (auto ind = indset.begin(), indend = indset.end(); ind != indend; ++ind) {
|
||||||
|
indset_rw.add(ind->global(), LocalIndex(ind->local(), ind->local().attribute(), true));
|
||||||
|
const int glo = ind->global();
|
||||||
|
const size_t loc = ind->local().local();
|
||||||
|
glo_max = std::max(glo_max, glo);
|
||||||
|
loc_max = std::max(loc_max, loc);
|
||||||
|
}
|
||||||
|
const int global_max = comm.communicator().max(glo_max);
|
||||||
|
// used append the welldofs at the end
|
||||||
|
assert(loc_max + 1 == indset.size());
|
||||||
|
size_t local_ind = loc_max + 1;
|
||||||
|
for (int i = 0; i < nw; ++i) {
|
||||||
|
// need to set unique global number
|
||||||
|
const size_t v = global_max + max_nw * num_proc + i + 1;
|
||||||
|
// set to true to not have problems with higher levels if growing of domains is used
|
||||||
|
indset_rw.add(v, LocalIndex(local_ind, Dune::OwnerOverlapCopyAttributeSet::owner, true));
|
||||||
|
++local_ind;
|
||||||
|
}
|
||||||
|
indset_rw.endResize();
|
||||||
|
assert(indset_rw.size() == indset.size() + nw);
|
||||||
|
// assume same communication pattern
|
||||||
|
commRW->remoteIndices().setNeighbours(comm.remoteIndices().getNeighbours());
|
||||||
|
commRW->remoteIndices().template rebuild<true>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <class FineOperator, class CoarseOperator, class Communication, bool transpose = false>
|
||||||
|
class PressureBhpTransferPolicy : public Dune::Amg::LevelTransferPolicyCpr<FineOperator, CoarseOperator>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef Dune::Amg::LevelTransferPolicyCpr<FineOperator, CoarseOperator> ParentType;
|
||||||
|
typedef Communication ParallelInformation;
|
||||||
|
typedef typename FineOperator::domain_type FineVectorType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PressureBhpTransferPolicy(const Communication& comm,
|
||||||
|
const FineVectorType& weights,
|
||||||
|
const boost::property_tree::ptree& prm)
|
||||||
|
: communication_(&const_cast<Communication&>(comm))
|
||||||
|
, weights_(weights)
|
||||||
|
, prm_(prm)
|
||||||
|
, pressure_var_index_(prm_.get<int>("pressure_var_index"))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void createCoarseLevelSystem(const FineOperator& fineOperator) override
|
||||||
|
{
|
||||||
|
using CoarseMatrix = typename CoarseOperator::matrix_type;
|
||||||
|
const auto& fineLevelMatrix = fineOperator.getmat();
|
||||||
|
const auto& nw = fineOperator.getNumberOfExtraEquations();
|
||||||
|
if (prm_.get<bool>("add_wells")) {
|
||||||
|
const size_t average_elements_per_row
|
||||||
|
= static_cast<size_t>(std::ceil(fineLevelMatrix.nonzeroes() / fineLevelMatrix.N()));
|
||||||
|
const double overflow_fraction = 1.2;
|
||||||
|
coarseLevelMatrix_.reset(new CoarseMatrix(fineLevelMatrix.N() + nw,
|
||||||
|
fineLevelMatrix.M() + nw,
|
||||||
|
average_elements_per_row,
|
||||||
|
overflow_fraction,
|
||||||
|
CoarseMatrix::implicit));
|
||||||
|
int rownum = 0;
|
||||||
|
for (const auto& row : fineLevelMatrix) {
|
||||||
|
for (auto col = row.begin(), cend = row.end(); col != cend; ++col) {
|
||||||
|
coarseLevelMatrix_->entry(rownum, col.index()) = 0.0;
|
||||||
|
}
|
||||||
|
++rownum;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
coarseLevelMatrix_.reset(
|
||||||
|
new CoarseMatrix(fineLevelMatrix.N(), fineLevelMatrix.M(), CoarseMatrix::row_wise));
|
||||||
|
auto createIter = coarseLevelMatrix_->createbegin();
|
||||||
|
for (const auto& row : fineLevelMatrix) {
|
||||||
|
for (auto col = row.begin(), cend = row.end(); col != cend; ++col) {
|
||||||
|
createIter.insert(col.index());
|
||||||
|
}
|
||||||
|
++createIter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
|
||||||
|
if constexpr (std::is_same_v<Communication, Dune::Amg::SequentialInformation>) {
|
||||||
|
coarseLevelCommunication_ = std::make_shared<Communication>();
|
||||||
|
} else {
|
||||||
|
coarseLevelCommunication_ = std::make_shared<Communication>(
|
||||||
|
communication_->communicator(), communication_->category(), false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if constexpr (std::is_same_v<Communication, Dune::Amg::SequentialInformation>) {
|
||||||
|
coarseLevelCommunication_ = std::make_shared<Communication>();
|
||||||
|
} else {
|
||||||
|
coarseLevelCommunication_ = std::make_shared<Communication>(
|
||||||
|
communication_->communicator(), communication_->getSolverCategory(), false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (prm_.get<bool>("add_wells")) {
|
||||||
|
fineOperator.addWellPressureEquationsStruct(*coarseLevelMatrix_);
|
||||||
|
coarseLevelMatrix_->compress(); // all elemenst should be set
|
||||||
|
if constexpr (!std::is_same_v<Communication, Dune::Amg::SequentialInformation>) {
|
||||||
|
extendCommunicatorWithWells(*communication_, coarseLevelCommunication_, nw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calculateCoarseEntries(fineOperator);
|
||||||
|
|
||||||
|
this->lhs_.resize(this->coarseLevelMatrix_->M());
|
||||||
|
this->rhs_.resize(this->coarseLevelMatrix_->N());
|
||||||
|
using OperatorArgs = typename Dune::Amg::ConstructionTraits<CoarseOperator>::Arguments;
|
||||||
|
#if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
|
||||||
|
OperatorArgs oargs(coarseLevelMatrix_, *coarseLevelCommunication_);
|
||||||
|
this->operator_ = Dune::Amg::ConstructionTraits<CoarseOperator>::construct(oargs);
|
||||||
|
#else
|
||||||
|
OperatorArgs oargs(*coarseLevelMatrix_, *coarseLevelCommunication_);
|
||||||
|
this->operator_.reset(Dune::Amg::ConstructionTraits<CoarseOperator>::construct(oargs));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void calculateCoarseEntries(const FineOperator& fineOperator) override
|
||||||
|
{
|
||||||
|
const auto& fineMatrix = fineOperator.getmat();
|
||||||
|
*coarseLevelMatrix_ = 0;
|
||||||
|
auto rowCoarse = coarseLevelMatrix_->begin();
|
||||||
|
for (auto row = fineMatrix.begin(), rowEnd = fineMatrix.end(); row != rowEnd; ++row, ++rowCoarse) {
|
||||||
|
assert(row.index() == rowCoarse.index());
|
||||||
|
auto entryCoarse = rowCoarse->begin();
|
||||||
|
for (auto entry = row->begin(), entryEnd = row->end(); entry != entryEnd; ++entry, ++entryCoarse) {
|
||||||
|
assert(entry.index() == entryCoarse.index());
|
||||||
|
double matrix_el = 0;
|
||||||
|
if (transpose) {
|
||||||
|
const auto& bw = weights_[entry.index()];
|
||||||
|
for (size_t i = 0; i < bw.size(); ++i) {
|
||||||
|
matrix_el += (*entry)[pressure_var_index_][i] * bw[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto& bw = weights_[row.index()];
|
||||||
|
for (size_t i = 0; i < bw.size(); ++i) {
|
||||||
|
matrix_el += (*entry)[i][pressure_var_index_] * bw[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(*entryCoarse) = matrix_el;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (prm_.get<bool>("add_wells")) {
|
||||||
|
assert(transpose == false); // not implemented
|
||||||
|
fineOperator.addWellPressureEquations(*coarseLevelMatrix_, weights_);
|
||||||
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
std::advance(rowCoarse, fineOperator.getNumberOfExtraEquations());
|
||||||
|
assert(rowCoarse == coarseLevelMatrix_->end());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void moveToCoarseLevel(const typename ParentType::FineRangeType& fine) override
|
||||||
|
{
|
||||||
|
//NB we iterate over fine assumming welldofs is at the end
|
||||||
|
// Set coarse vector to zero
|
||||||
|
this->rhs_ = 0;
|
||||||
|
|
||||||
|
auto end = fine.end(), begin = fine.begin();
|
||||||
|
|
||||||
|
for (auto block = begin; block != end; ++block) {
|
||||||
|
const auto& bw = weights_[block.index()];
|
||||||
|
double rhs_el = 0.0;
|
||||||
|
if (transpose) {
|
||||||
|
rhs_el = (*block)[pressure_var_index_];
|
||||||
|
} else {
|
||||||
|
for (size_t i = 0; i < block->size(); ++i) {
|
||||||
|
rhs_el += (*block)[i] * bw[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->rhs_[block - begin] = rhs_el;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->lhs_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void moveToFineLevel(typename ParentType::FineDomainType& fine) override
|
||||||
|
{
|
||||||
|
//NB we iterate over fine assumming welldofs is at the end
|
||||||
|
auto end = fine.end(), begin = fine.begin();
|
||||||
|
|
||||||
|
for (auto block = begin; block != end; ++block) {
|
||||||
|
if (transpose) {
|
||||||
|
const auto& bw = weights_[block.index()];
|
||||||
|
for (size_t i = 0; i < block->size(); ++i) {
|
||||||
|
(*block)[i] = this->lhs_[block - begin] * bw[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(*block)[pressure_var_index_] = this->lhs_[block - begin];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual PressureBhpTransferPolicy* clone() const override
|
||||||
|
{
|
||||||
|
return new PressureBhpTransferPolicy(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Communication& getCoarseLevelCommunication() const
|
||||||
|
{
|
||||||
|
return *coarseLevelCommunication_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Communication* communication_;
|
||||||
|
const FineVectorType& weights_;
|
||||||
|
boost::property_tree::ptree prm_;
|
||||||
|
const int pressure_var_index_;
|
||||||
|
std::shared_ptr<Communication> coarseLevelCommunication_;
|
||||||
|
std::shared_ptr<typename CoarseOperator::matrix_type> coarseLevelMatrix_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Opm
|
||||||
|
|
||||||
@@ -45,30 +45,40 @@ namespace Opm
|
|||||||
/// WellModelMatrixAdapter separately for each TypeTag, as it will only
|
/// WellModelMatrixAdapter separately for each TypeTag, as it will only
|
||||||
/// depend on the matrix and vector types involved, which typically are
|
/// depend on the matrix and vector types involved, which typically are
|
||||||
/// just one for each block size with block sizes 1-4.
|
/// just one for each block size with block sizes 1-4.
|
||||||
template <class WellModel, class X, class Y>
|
template <class X, class Y>
|
||||||
class WellModelAsLinearOperator : public Dune::LinearOperator<X, Y>
|
class LinearOperatorExtra : public Dune::LinearOperator<X, Y>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using Base = Dune::LinearOperator<X, Y>;
|
using PressureMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||||
using field_type = typename Base::field_type;
|
virtual void addWellPressureEquations(PressureMatrix& jacobian, const X& weights) const = 0;
|
||||||
|
virtual void addWellPressureEquationsStruct(PressureMatrix& jacobian) const = 0;
|
||||||
|
virtual int getNumberOfExtraEquations() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class WellModel, class X, class Y>
|
||||||
|
class WellModelAsLinearOperator : public Opm::LinearOperatorExtra<X, Y>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using Base = Opm::LinearOperatorExtra<X, Y>;
|
||||||
|
using field_type = typename Base::field_type;
|
||||||
|
using PressureMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||||
explicit WellModelAsLinearOperator(const WellModel& wm)
|
explicit WellModelAsLinearOperator(const WellModel& wm)
|
||||||
: wellMod_(wm)
|
: wellMod_(wm)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/*! \brief apply operator to x: \f$ y = A(x) \f$
|
/*! \brief apply operator to x: \f$ y = A(x) \f$
|
||||||
The input vector is consistent and the output must also be
|
The input vector is consistent and the output must also be
|
||||||
consistent on the interior+border partition.
|
consistent on the interior+border partition.
|
||||||
*/
|
*/
|
||||||
void apply (const X& x, Y& y) const override
|
void apply(const X& x, Y& y) const override
|
||||||
{
|
{
|
||||||
wellMod_.apply(x, y );
|
wellMod_.apply(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! apply operator to x, scale and add: \f$ y = y + \alpha A(x) \f$
|
//! apply operator to x, scale and add: \f$ y = y + \alpha A(x) \f$
|
||||||
virtual void applyscaleadd (field_type alpha, const X& x, Y& y) const override
|
virtual void applyscaleadd(field_type alpha, const X& x, Y& y) const override
|
||||||
{
|
{
|
||||||
wellMod_.applyScaleAdd( alpha, x, y );
|
wellMod_.applyScaleAdd(alpha, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Category for operator.
|
/// Category for operator.
|
||||||
@@ -80,6 +90,19 @@ public:
|
|||||||
{
|
{
|
||||||
return Dune::SolverCategory::sequential;
|
return Dune::SolverCategory::sequential;
|
||||||
}
|
}
|
||||||
|
void addWellPressureEquations(PressureMatrix& jacobian, const X& weights) const override
|
||||||
|
{
|
||||||
|
wellMod_.addWellPressureEquations(jacobian, weights);
|
||||||
|
}
|
||||||
|
void addWellPressureEquationsStruct(PressureMatrix& jacobian) const override
|
||||||
|
{
|
||||||
|
wellMod_.addWellPressureEquationsStruct(jacobian);
|
||||||
|
}
|
||||||
|
int getNumberOfExtraEquations() const override
|
||||||
|
{
|
||||||
|
return wellMod_.numLocalWells();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const WellModel& wellMod_;
|
const WellModel& wellMod_;
|
||||||
};
|
};
|
||||||
@@ -103,7 +126,7 @@ public:
|
|||||||
typedef X domain_type;
|
typedef X domain_type;
|
||||||
typedef Y range_type;
|
typedef Y range_type;
|
||||||
typedef typename X::field_type field_type;
|
typedef typename X::field_type field_type;
|
||||||
|
using PressureMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||||
#if HAVE_MPI
|
#if HAVE_MPI
|
||||||
typedef Dune::OwnerOverlapCopyCommunication<int,int> communication_type;
|
typedef Dune::OwnerOverlapCopyCommunication<int,int> communication_type;
|
||||||
#else
|
#else
|
||||||
@@ -118,7 +141,7 @@ public:
|
|||||||
|
|
||||||
//! constructor: just store a reference to a matrix
|
//! constructor: just store a reference to a matrix
|
||||||
WellModelMatrixAdapter (const M& A,
|
WellModelMatrixAdapter (const M& A,
|
||||||
const Dune::LinearOperator<X, Y>& wellOper,
|
const Opm::LinearOperatorExtra<X, Y>& wellOper,
|
||||||
const std::shared_ptr< communication_type >& comm = std::shared_ptr< communication_type >())
|
const std::shared_ptr< communication_type >& comm = std::shared_ptr< communication_type >())
|
||||||
: A_( A ), wellOper_( wellOper ), comm_(comm)
|
: A_( A ), wellOper_( wellOper ), comm_(comm)
|
||||||
{}
|
{}
|
||||||
@@ -153,9 +176,22 @@ public:
|
|||||||
|
|
||||||
virtual const matrix_type& getmat() const override { return A_; }
|
virtual const matrix_type& getmat() const override { return A_; }
|
||||||
|
|
||||||
|
void addWellPressureEquations(PressureMatrix& jacobian, const X& weights) const
|
||||||
|
{
|
||||||
|
wellOper_.addWellPressureEquations(jacobian, weights);
|
||||||
|
}
|
||||||
|
void addWellPressureEquationsStruct(PressureMatrix& jacobian) const
|
||||||
|
{
|
||||||
|
wellOper_.addWellPressureEquationsStruct(jacobian);
|
||||||
|
}
|
||||||
|
int getNumberOfExtraEquations() const
|
||||||
|
{
|
||||||
|
return wellOper_.getNumberOfExtraEquations();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const matrix_type& A_ ;
|
const matrix_type& A_ ;
|
||||||
const Dune::LinearOperator<X, Y>& wellOper_;
|
const Opm::LinearOperatorExtra<X, Y>& wellOper_;
|
||||||
std::shared_ptr< communication_type > comm_;
|
std::shared_ptr< communication_type > comm_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -176,7 +212,7 @@ public:
|
|||||||
typedef X domain_type;
|
typedef X domain_type;
|
||||||
typedef Y range_type;
|
typedef Y range_type;
|
||||||
typedef typename X::field_type field_type;
|
typedef typename X::field_type field_type;
|
||||||
|
using PressureMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||||
#if HAVE_MPI
|
#if HAVE_MPI
|
||||||
typedef Dune::OwnerOverlapCopyCommunication<int,int> communication_type;
|
typedef Dune::OwnerOverlapCopyCommunication<int,int> communication_type;
|
||||||
#else
|
#else
|
||||||
@@ -192,7 +228,7 @@ public:
|
|||||||
|
|
||||||
//! constructor: just store a reference to a matrix
|
//! constructor: just store a reference to a matrix
|
||||||
WellModelGhostLastMatrixAdapter (const M& A,
|
WellModelGhostLastMatrixAdapter (const M& A,
|
||||||
const Dune::LinearOperator<X, Y>& wellOper,
|
const Opm::LinearOperatorExtra<X, Y>& wellOper,
|
||||||
const size_t interiorSize )
|
const size_t interiorSize )
|
||||||
: A_( A ), wellOper_( wellOper ), interiorSize_(interiorSize)
|
: A_( A ), wellOper_( wellOper ), interiorSize_(interiorSize)
|
||||||
{}
|
{}
|
||||||
@@ -230,6 +266,19 @@ public:
|
|||||||
|
|
||||||
virtual const matrix_type& getmat() const override { return A_; }
|
virtual const matrix_type& getmat() const override { return A_; }
|
||||||
|
|
||||||
|
void addWellPressureEquations(PressureMatrix& jacobian, const X& weights) const
|
||||||
|
{
|
||||||
|
wellOper_.addWellPressureEquations(jacobian, weights);
|
||||||
|
}
|
||||||
|
void addWellPressureEquationsStruct(PressureMatrix& jacobian) const
|
||||||
|
{
|
||||||
|
wellOper_.addWellPressureEquationsStruct(jacobian);
|
||||||
|
}
|
||||||
|
int getNumberOfExtraEquations() const
|
||||||
|
{
|
||||||
|
return wellOper_.getNumberOfExtraEquations();
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ghostLastProject(Y& y) const
|
void ghostLastProject(Y& y) const
|
||||||
{
|
{
|
||||||
@@ -239,7 +288,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const matrix_type& A_ ;
|
const matrix_type& A_ ;
|
||||||
const Dune::LinearOperator<X, Y>& wellOper_;
|
const Opm::LinearOperatorExtra< X, Y>& wellOper_;
|
||||||
size_t interiorSize_;
|
size_t interiorSize_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -294,6 +294,29 @@ namespace Opm {
|
|||||||
WellInterfacePtr getWell(const std::string& well_name) const;
|
WellInterfacePtr getWell(const std::string& well_name) const;
|
||||||
bool hasWell(const std::string& well_name) const;
|
bool hasWell(const std::string& well_name) const;
|
||||||
|
|
||||||
|
// The number of components in the model.
|
||||||
|
int numComponents() const;
|
||||||
|
|
||||||
|
int numLocalWells() const;
|
||||||
|
|
||||||
|
int numPhases() const;
|
||||||
|
|
||||||
|
using PressureMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||||
|
|
||||||
|
void addWellPressureEquations(PressureMatrix& jacobian, const BVector& weights) const
|
||||||
|
{
|
||||||
|
for (const auto& well : well_container_) {
|
||||||
|
well->addWellPressureEquations(jacobian, weights);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addWellPressureEquationsStruct(PressureMatrix& jacobian) const
|
||||||
|
{
|
||||||
|
for (const auto& well : well_container_) {
|
||||||
|
well->addWellPressureEquationsStruct(jacobian);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void initGliftEclWellMap(GLiftEclWells &ecl_well_map);
|
void initGliftEclWellMap(GLiftEclWells &ecl_well_map);
|
||||||
|
|
||||||
/// \brief Get list of local nonshut wells
|
/// \brief Get list of local nonshut wells
|
||||||
@@ -386,12 +409,7 @@ namespace Opm {
|
|||||||
void calculateProductivityIndexValues(const WellInterface<TypeTag>* wellPtr,
|
void calculateProductivityIndexValues(const WellInterface<TypeTag>* wellPtr,
|
||||||
DeferredLogger& deferred_logger);
|
DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
// The number of components in the model.
|
void assembleWellEq(const std::vector<Scalar>& B_avg, const double dt, Opm::DeferredLogger& deferred_logger);
|
||||||
int numComponents() const;
|
|
||||||
|
|
||||||
int reportStepIndex() const;
|
|
||||||
|
|
||||||
void assembleWellEq(const double dt, DeferredLogger& deferred_logger);
|
|
||||||
|
|
||||||
bool maybeDoGasLiftOptimize(DeferredLogger& deferred_logger);
|
bool maybeDoGasLiftOptimize(DeferredLogger& deferred_logger);
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ namespace Opm
|
|||||||
using PolymerModule = BlackOilPolymerModule<TypeTag>;
|
using PolymerModule = BlackOilPolymerModule<TypeTag>;
|
||||||
using FoamModule = BlackOilFoamModule<TypeTag>;
|
using FoamModule = BlackOilFoamModule<TypeTag>;
|
||||||
using BrineModule = BlackOilBrineModule<TypeTag>;
|
using BrineModule = BlackOilBrineModule<TypeTag>;
|
||||||
|
using PressureMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||||
|
|
||||||
// number of the conservation equations
|
// number of the conservation equations
|
||||||
static constexpr int numWellConservationEq = Indices::numPhases + Indices::numSolvents;
|
static constexpr int numWellConservationEq = Indices::numPhases + Indices::numSolvents;
|
||||||
@@ -178,7 +179,11 @@ namespace Opm
|
|||||||
WellState& well_state,
|
WellState& well_state,
|
||||||
DeferredLogger& deferred_logger) const override;
|
DeferredLogger& deferred_logger) const override;
|
||||||
|
|
||||||
virtual void addWellContributions(SparseMatrixAdapter& mat) const override;
|
virtual void addWellContributions(SparseMatrixAdapter& mat) const override;
|
||||||
|
|
||||||
|
virtual void addWellPressureEquationsStruct(PressureMatrix& mat) const override;
|
||||||
|
|
||||||
|
virtual void addWellPressureEquations(PressureMatrix& mat, const BVector& x) const override;
|
||||||
|
|
||||||
// iterate well equations with the specified control until converged
|
// iterate well equations with the specified control until converged
|
||||||
bool iterateWellEqWithControl(const Simulator& ebosSimulator,
|
bool iterateWellEqWithControl(const Simulator& ebosSimulator,
|
||||||
|
|||||||
@@ -2170,6 +2170,96 @@ namespace Opm
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename TypeTag>
|
||||||
|
void
|
||||||
|
StandardWell<TypeTag>::addWellPressureEquationsStruct(PressureMatrix& jacobian) const
|
||||||
|
{
|
||||||
|
// sustem is the pressur variant of
|
||||||
|
// We need to change matrx A as follows
|
||||||
|
// A CT
|
||||||
|
// B D
|
||||||
|
// we need to add the elemenst of CT
|
||||||
|
// then we need to ad the quasiimpes type well equation for B D if the well is not
|
||||||
|
// BHP contolled
|
||||||
|
const int welldof_ind = duneC_.M() + index_of_well_;
|
||||||
|
for (auto colC = duneC_[0].begin(), endC = duneC_[0].end(); colC != endC; ++colC) {
|
||||||
|
const auto row_index = colC.index();
|
||||||
|
double matel = 0;
|
||||||
|
jacobian.entry(row_index, welldof_ind) = matel;
|
||||||
|
}
|
||||||
|
|
||||||
|
jacobian.entry(welldof_ind, welldof_ind) = 0.0;
|
||||||
|
|
||||||
|
// set the matrix elements for well reservoir coupling
|
||||||
|
for (auto colB = duneB_[0].begin(), endB = duneB_[0].end(); colB != endB; ++colB) {
|
||||||
|
const auto col_index = colB.index();
|
||||||
|
double matel = 0;
|
||||||
|
jacobian.entry(welldof_ind, col_index) = matel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename TypeTag>
|
||||||
|
void
|
||||||
|
StandardWell<TypeTag>::addWellPressureEquations(PressureMatrix& jacobian, const BVector& weights) const
|
||||||
|
{
|
||||||
|
// sustem is the pressur variant of
|
||||||
|
// We need to change matrx A as follows
|
||||||
|
// A CT
|
||||||
|
// B D
|
||||||
|
// we need to add the elemenst of CT
|
||||||
|
// then we need to ad the quasiimpes type well equation for B D if the well is not
|
||||||
|
// BHP contolled
|
||||||
|
int bhp_var_index = Bhp;
|
||||||
|
assert(duneC_.M() == weights.size());
|
||||||
|
const int welldof_ind = duneC_.M() + index_of_well_;
|
||||||
|
for (auto colC = duneC_[0].begin(), endC = duneC_[0].end(); colC != endC; ++colC) {
|
||||||
|
const auto row_ind = colC.index();
|
||||||
|
const auto& bw = weights[row_ind];
|
||||||
|
double matel = 0;
|
||||||
|
assert((*colC).M() == bw.size());
|
||||||
|
for (size_t i = 0; i < bw.size(); ++i) {
|
||||||
|
matel += (*colC)[bhp_var_index][i] * bw[i];
|
||||||
|
}
|
||||||
|
jacobian[row_ind][welldof_ind] = matel;
|
||||||
|
}
|
||||||
|
// make quasipes weights for bhp it should be trival
|
||||||
|
using VectorBlockType = typename BVector::block_type;
|
||||||
|
using MatrixBlockType = DiagMatrixBlockWellType;
|
||||||
|
VectorBlockType bweights(0.0);
|
||||||
|
double diagElem = 0;
|
||||||
|
{
|
||||||
|
// const DiagMatrixBlockWellType& invA = invDuneD_[0][0];
|
||||||
|
VectorBlockType rhs(0.0);
|
||||||
|
rhs[bhp_var_index] = 1.0;
|
||||||
|
MatrixBlockType inv_diag_block = invDuneD_[0][0];
|
||||||
|
auto inv_diag_block_transpose = Opm::wellhelpers::transposeDenseDynMatrix(inv_diag_block);
|
||||||
|
// diag_block_transpose.solve(bweights, rhs);
|
||||||
|
inv_diag_block_transpose.mv(rhs, bweights);
|
||||||
|
// NB how to scale to make it most symmetric
|
||||||
|
// double abs_max = *std::max_element(
|
||||||
|
// bweights.begin(), bweights.end(), [](double a, double b) { return std::fabs(a) < std::fabs(b); });
|
||||||
|
// bweights /= std::fabs(abs_max);
|
||||||
|
}
|
||||||
|
//
|
||||||
|
jacobian[welldof_ind][welldof_ind] = 1.0;
|
||||||
|
// set the matrix elements for well reservoir coupling
|
||||||
|
for (auto colB = duneB_[0].begin(), endB = duneB_[0].end(); colB != endB; ++colB) {
|
||||||
|
const auto col_index = colB.index();
|
||||||
|
const auto& bw = bweights;
|
||||||
|
double matel = 0;
|
||||||
|
for (size_t i = 0; i < bw.size(); ++i) {
|
||||||
|
matel += (*colB)[bhp_var_index][i] * bw[i];
|
||||||
|
}
|
||||||
|
jacobian[welldof_ind][col_index] = matel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename TypeTag>
|
template<typename TypeTag>
|
||||||
typename StandardWell<TypeTag>::EvalWell
|
typename StandardWell<TypeTag>::EvalWell
|
||||||
StandardWell<TypeTag>::
|
StandardWell<TypeTag>::
|
||||||
|
|||||||
@@ -233,8 +233,19 @@ namespace Opm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace wellhelpers
|
template <class DenseMatrix>
|
||||||
|
DenseMatrix transposeDenseDynMatrix(const DenseMatrix& M)
|
||||||
|
{
|
||||||
|
DenseMatrix tmp{M.cols(), M.rows()};
|
||||||
|
for (int i = 0; i < M.rows(); ++i) {
|
||||||
|
for (int j = 0; j < M.cols(); ++j) {
|
||||||
|
tmp[j][i] = M[i][j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace wellhelpers
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -95,6 +95,7 @@ public:
|
|||||||
using MatrixBlockType = Dune::FieldMatrix<Scalar, Indices::numEq, Indices::numEq>;
|
using MatrixBlockType = Dune::FieldMatrix<Scalar, Indices::numEq, Indices::numEq>;
|
||||||
using BVector = Dune::BlockVector<VectorBlockType>;
|
using BVector = Dune::BlockVector<VectorBlockType>;
|
||||||
using Eval = DenseAd::Evaluation<Scalar, /*size=*/Indices::numEq>;
|
using Eval = DenseAd::Evaluation<Scalar, /*size=*/Indices::numEq>;
|
||||||
|
using PressureMatrix = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||||
|
|
||||||
using RateConverterType =
|
using RateConverterType =
|
||||||
typename WellInterfaceFluidSystem<FluidSystem>::RateConverterType;
|
typename WellInterfaceFluidSystem<FluidSystem>::RateConverterType;
|
||||||
@@ -224,6 +225,15 @@ public:
|
|||||||
// Add well contributions to matrix
|
// Add well contributions to matrix
|
||||||
virtual void addWellContributions(SparseMatrixAdapter&) const = 0;
|
virtual void addWellContributions(SparseMatrixAdapter&) const = 0;
|
||||||
|
|
||||||
|
virtual void addWellPressureEquationsStruct(PressureMatrix&) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void addWellPressureEquations(PressureMatrix&,
|
||||||
|
const BVector& x) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void addCellRates(RateVector& rates, int cellIdx) const;
|
void addCellRates(RateVector& rates, int cellIdx) const;
|
||||||
|
|
||||||
Scalar volumetricSurfaceRateForConnection(int cellIdx, int phaseIdx) const;
|
Scalar volumetricSurfaceRateForConnection(int cellIdx, int phaseIdx) const;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ testSolver(const Opm::PropertyTree& prm, const std::string& matrix_filename, con
|
|||||||
|
|
||||||
using SeqOperatorType = Dune::MatrixAdapter<Matrix, Vector, Vector>;
|
using SeqOperatorType = Dune::MatrixAdapter<Matrix, Vector, Vector>;
|
||||||
SeqOperatorType op(matrix);
|
SeqOperatorType op(matrix);
|
||||||
Dune::FlexibleSolver<Matrix, Vector> solver(op, prm, wc, 1);
|
Dune::FlexibleSolver<SeqOperatorType> solver(op, prm, wc, 1);
|
||||||
Vector x(rhs.size());
|
Vector x(rhs.size());
|
||||||
Dune::InverseOperatorResult res;
|
Dune::InverseOperatorResult res;
|
||||||
solver.apply(x, rhs, res);
|
solver.apply(x, rhs, res);
|
||||||
|
|||||||
Reference in new issue
Block a user