21#ifndef OPM_FLEXIBLE_SOLVER_IMPL_HEADER_INCLUDED
22#define OPM_FLEXIBLE_SOLVER_IMPL_HEADER_INCLUDED
24#include <opm/common/ErrorMacros.hpp>
25#include <opm/common/TimingMacros.hpp>
36#if HAVE_AVX2_EXTENSION
41#include <dune/common/fmatrix.hh>
42#include <dune/istl/bcrsmatrix.hh>
43#include <dune/istl/multitypeblockvector.hh>
44#include <dune/istl/solvers.hh>
45#include <dune/istl/umfpack.hh>
46#include <dune/istl/owneroverlapcopy.hh>
47#include <dune/istl/paamg/pinfo.hh>
53template <
typename... Args>
61#include <opm/simulators/linalg/gpuistl_hip/SolverAdapter.hpp>
70 template <
class Operator>
74 const std::function<
VectorType()>& weightsCalculator,
75 std::size_t pressureIndex)
77 init(op, Dune::Amg::SequentialInformation(), prm, weightsCalculator,
82 template <
class Operator>
88 const std::function<
VectorType()>& weightsCalculator,
89 std::size_t pressureIndex)
91 init(op, comm, prm, weightsCalculator, pressureIndex);
94 template <
class Operator>
101 if (direct_precond && direct_precond->needsRebuild()) {
102 recreateDirectSolver();
103 direct_precond->resetNeedsRebuild();
106 linsolver_->apply(x, rhs, res);
109 template <
class Operator>
114 if (direct_solver_) {
116 if (direct_precond && direct_precond->needsRebuild()) {
117 recreateDirectSolver();
118 direct_precond->resetNeedsRebuild();
121 linsolver_->apply(x, rhs, reduction, res);
125 template <
class Operator>
130 return *preconditioner_;
133 template <
class Operator>
134 Dune::SolverCategory::Category
138 return linearoperator_for_solver_->category();
142 template <
class Operator>
143 template <
class Comm>
148 const std::function<VectorType()> weightsCalculator,
150 std::size_t pressureIndex)
153 linearoperator_for_solver_ = &op;
154 const std::string solver_type = prm.
get<std::string>(
"solver",
"bicgstab");
156 if (solver_type ==
"umfpack") {
157 if (comm.communicator().size() > 1) {
158 OPM_THROW(std::invalid_argument,
159 "UMFPACK is only supported for sequential linear solves. "
160 "Please use an iterative solver for distributed matrices.");
162 preconditioner_ = std::make_shared<Dune::DirectSolverUpdatePreconditioner<VectorType, VectorType>>(
163 linearoperator_for_solver_->category());
171 scalarproduct_ = Dune::createScalarProduct<VectorType, Comm>(comm, op.category());
174 template <
class Operator>
176 FlexibleSolver<Operator>::
177 initOpPrecSp(Operator& op,
179 const std::function<VectorType()> weightsCalculator,
180 const Dune::Amg::SequentialInformation&,
181 std::size_t pressureIndex)
184 linearoperator_for_solver_ = &op;
185 const std::string solver_type = prm.
get<std::string>(
"solver",
"bicgstab");
187 if (solver_type ==
"umfpack") {
188 preconditioner_ = std::make_shared<Dune::DirectSolverUpdatePreconditioner<VectorType, VectorType>>(
189 linearoperator_for_solver_->category());
196 scalarproduct_ = std::make_shared<Dune::SeqScalarProduct<VectorType>>();
200 template <
class Operator>
201 template <
class Comm>
203 FlexibleSolver<Operator>::
206 const bool is_iorank = comm.communicator().rank() == 0;
207 const double tol = prm.
get<
double>(
"tol", 1e-2);
208 const int maxiter = prm.
get<
int>(
"maxiter", 200);
209 const int verbosity = is_iorank ? prm.
get<
int>(
"verbosity", 0) : 0;
210 const std::string solver_type = prm.
get<std::string>(
"solver",
"bicgstab");
218 direct_solver_ =
false;
219 if (solver_type ==
"bicgstab") {
220 linsolver_ = std::make_shared<Dune::BiCGSTABSolver<VectorType>>(*linearoperator_for_solver_,
226#if HAVE_AVX2_EXTENSION
227 }
else if (solver_type ==
"mixed-legacy") {
228 if constexpr (Opm::is_gpu_operator_v<Operator>) {
229 OPM_THROW(std::invalid_argument,
"legacy mixed-bicgstab solver not supported for GPU operators");
230 }
else if constexpr (Opm::detail::is_multi_type_block_vector_v<VectorType>) {
231 OPM_THROW(std::invalid_argument,
"legacy mixed-bicgstab solver not supported for multi-type block vectors.");
232 }
else if constexpr (std::is_same_v<typename VectorType::field_type, float>){
233 OPM_THROW(std::invalid_argument,
"legacy mixed-bicgstab solver not supported for single precision.");
235 const std::string prec_type = prm.
get<std::string>(
"preconditioner.type",
"error");
236 bool use_mixed_dilu= (prec_type==
"legacy-mixed-dilu");
237 using MatrixType =
decltype(linearoperator_for_solver_->getmat());
238 linsolver_ = std::make_shared<Dune::MixedSolver<VectorType,MatrixType>>(
239 linearoperator_for_solver_->getmat(),
246 }
else if (solver_type ==
"mixed-bicgstab") {
247 if constexpr (Opm::is_gpu_operator_v<Operator>) {
248 OPM_THROW(std::invalid_argument,
"mixed-bicgstab solver not supported for GPU operators");
249 }
else if constexpr (Opm::detail::is_multi_type_block_vector_v<VectorType>) {
250 OPM_THROW(std::invalid_argument,
"mixed-bicgstab solver not supported for multi-type block vectors.");
251 }
else if constexpr (std::is_same_v<typename VectorType::field_type, float>){
252 OPM_THROW(std::invalid_argument,
"mixed-bicgstab solver not supported for single precision.");
254 linsolver_ = std::make_shared<Dune::MixedBiCGSTABSolver<Comm,Operator,VectorType>>(linearoperator_for_solver_,
263 }
else if (solver_type ==
"cg") {
264 linsolver_ = std::make_shared<Dune::CGSolver<VectorType>>(*linearoperator_for_solver_,
270 }
else if (solver_type ==
"loopsolver") {
271 linsolver_ = std::make_shared<Dune::LoopSolver<VectorType>>(*linearoperator_for_solver_,
277 }
else if (solver_type ==
"gmres") {
278 int restart = prm.
get<
int>(
"restart", 15);
279 linsolver_ = std::make_shared<Dune::RestartedGMResSolver<VectorType>>(*linearoperator_for_solver_,
286 }
else if (solver_type ==
"flexgmres") {
287 if constexpr (Opm::is_gpu_operator_v<Operator>) {
288 OPM_THROW(std::invalid_argument,
"flexgmres solver not supported for GPU operators.");
290 int restart = prm.
get<
int>(
"restart", 15);
291 linsolver_ = std::make_shared<Dune::RestartedFlexibleGMResSolver<VectorType>>(*linearoperator_for_solver_,
299 }
else if (solver_type ==
"preconditioner2inverseoperator") {
300 if (!preconditioner_) {
301 OPM_THROW(std::invalid_argument,
302 "Properties: Solver preconditioner2inverseoperator requires a preconditioner.");
304 linsolver_ = std::make_shared<Dune::Preconditioner2InverseOperator<VectorType>>(preconditioner_);
306 if constexpr (!Opm::is_gpu_operator_v<Operator> && !Opm::detail::is_multi_type_block_vector_v<VectorType>) {
307#if HAVE_SUITESPARSE_UMFPACK
308 if (solver_type ==
"umfpack") {
309 if constexpr (std::is_same_v<typename VectorType::field_type,float>) {
310 OPM_THROW(std::invalid_argument,
"UMFPack cannot be used with floats");
312 using MatrixType = std::remove_const_t<std::remove_reference_t<
decltype(linearoperator_for_solver_->getmat())>>;
313 linsolver_ = std::make_shared<Dune::UMFPack<MatrixType>>(linearoperator_for_solver_->getmat(), verbosity,
false);
314 direct_solver_ =
true;
318 }
else if (solver_type ==
"gpubicgstab") {
319 if constexpr (VectorType::block_type::dimension
322 Dune::BiCGSTABSolver,
324 *linearoperator_for_solver_,
337 OPM_THROW(std::invalid_argument,
338 "Properties: Solver " + solver_type +
" not known.");
348 template <
class Operator>
350 FlexibleSolver<Operator>::
351 recreateDirectSolver()
353#if HAVE_SUITESPARSE_UMFPACK
354 if constexpr (!Opm::is_gpu_operator_v<Operator> && !Opm::detail::is_multi_type_block_vector_v<VectorType>) {
355 if constexpr (std::is_same_v<typename VectorType::field_type, float>) {
356 OPM_THROW(std::invalid_argument,
"UMFPack cannot be used with floats");
358 using MatrixType = std::remove_const_t<std::remove_reference_t<
decltype(linearoperator_for_solver_->getmat())>>;
359 linsolver_ = std::make_shared<Dune::UMFPack<MatrixType>>(linearoperator_for_solver_->getmat(), 0,
false);
363 OPM_THROW(std::logic_error,
"Direct solver specified, but the FlexibleSolver class was not compiled with SuiteSparse support.");
370 template <
class Operator>
371 template <
class Comm>
377 const std::function<
VectorType()> weightsCalculator,
378 std::size_t pressureIndex)
380 initOpPrecSp(op, prm, weightsCalculator, comm, pressureIndex);
381 initSolver(prm, comm);
390template<
class Scalar,
int N>
391using BV = Dune::BlockVector<Dune::FieldVector<Scalar, N>>;
392template<
class Scalar,
int N>
393using OBM = Dune::BCRSMatrix<Opm::MatrixBlock<Scalar, N, N>>;
396template<
class Scalar,
int N>
398template<
class Scalar,
int N>
404using Comm = Dune::OwnerOverlapCopyCommunication<int, int>;
405template<
class Scalar,
int N>
407template<
class Scalar,
int N>
409template<
class Scalar,
int N>
416#define INSTANTIATE_FLEXIBLESOLVER_OP(...) \
417 template class Dune::FlexibleSolver<__VA_ARGS__>; \
418 template Dune::FlexibleSolver<__VA_ARGS__>:: \
419 FlexibleSolver(__VA_ARGS__& op, \
421 const Opm::PropertyTree& prm, \
422 const std::function<typename __VA_ARGS__::domain_type()>& weightsCalculator, \
423 std::size_t pressureIndex);
425#define INSTANTIATE_FLEXIBLESOLVER(T,N) \
426 INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpM<T,N>); \
427 INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpW<T,N>); \
428 INSTANTIATE_FLEXIBLESOLVER_OP(ParOpM<T,N>); \
429 INSTANTIATE_FLEXIBLESOLVER_OP(ParOpW<T,N>); \
430 INSTANTIATE_FLEXIBLESOLVER_OP(ParOpD<T,N>);
434#define INSTANTIATE_FLEXIBLESOLVER_OP(...) \
435 template class Dune::FlexibleSolver<__VA_ARGS__>;
437#define INSTANTIATE_FLEXIBLESOLVER(T,N) \
438 INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpM<T,N>); \
439 INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpW<T,N>);
Dune::OverlappingSchwarzOperator< OBM< Scalar, N >, BV< Scalar, N >, BV< Scalar, N >, Comm > ParOpD
Definition: FlexibleSolver_impl.hpp:410
Dune::BCRSMatrix< Opm::MatrixBlock< Scalar, N, N > > OBM
Definition: FlexibleSolver_impl.hpp:393
Dune::BlockVector< Dune::FieldVector< Scalar, N > > BV
Definition: FlexibleSolver_impl.hpp:391
Dune::OwnerOverlapCopyCommunication< int, int > Comm
Definition: FlexibleSolver_impl.hpp:404
Dune::MatrixAdapter< OBM< Scalar, N >, BV< Scalar, N >, BV< Scalar, N > > SeqOpM
Definition: FlexibleSolver_impl.hpp:397
Definition: PreconditionerWithUpdate.hpp:98
Definition: FlexibleSolver.hpp:45
Dune::SolverCategory::Category category() const override
Definition: FlexibleSolver_impl.hpp:136
void apply(VectorType &x, VectorType &rhs, Dune::InverseOperatorResult &res) override
Definition: FlexibleSolver_impl.hpp:97
typename Operator::domain_type VectorType
Definition: FlexibleSolver.hpp:47
FlexibleSolver(Operator &op, const Opm::PropertyTree &prm, const std::function< VectorType()> &weightsCalculator, std::size_t pressureIndex)
Create a sequential solver.
Definition: FlexibleSolver_impl.hpp:72
AbstractPrecondType & preconditioner()
Access the contained preconditioner.
Definition: FlexibleSolver_impl.hpp:128
Dune linear operator that assumes ghost rows are ordered after interior rows. Avoids some computation...
Definition: WellOperators.hpp:412
static PrecPtr create(const Operator &op, const PropertyTree &prm, const std::function< Vector()> &weightsCalculator={}, std::size_t pressureIndex=std::numeric_limits< std::size_t >::max())
Definition: PreconditionerFactory_impl.hpp:154
Hierarchical collection of key/value pairs.
Definition: PropertyTree.hpp:39
T get(const std::string &key) const
std::optional< PropertyTree > get_child_optional(const std::string &key) const
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:306
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:229
Wraps a CUDA solver to work with CPU data.
Definition: gpuistl/SolverAdapter.hpp:52
Definition: fvbaseprimaryvariables.hh:161
Definition: flashcompositionstep.hh:36
constexpr bool is_multi_type_block_vector_v
Definition: FlexibleSolver_impl.hpp:56
Dune::InverseOperatorResult InverseOperatorResult
Definition: GpuBridge.hpp:32
constexpr int max_gpu_instantiated_block_size
Definition: is_gpu_operator.hpp:87
Definition: FlexibleSolver_impl.hpp:52