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> 26 #include <opm/simulators/linalg/matrixblock.hh> 27 #include <opm/simulators/linalg/ilufirstelement.hh> 28 #include <opm/simulators/linalg/FlexibleSolver.hpp> 29 #include <opm/simulators/linalg/PreconditionerFactory.hpp> 30 #include <opm/simulators/linalg/PropertyTree.hpp> 31 #include <opm/simulators/linalg/Preconditioner2InverseOperator.hpp> 32 #include <opm/simulators/linalg/WellOperators.hpp> 33 #include <opm/simulators/linalg/PreconditionerFactoryGPUIncludeWrapper.hpp> 34 #include <opm/simulators/linalg/is_gpu_operator.hpp> 36 #if HAVE_AVX2_EXTENSION 37 #include <opm/simulators/linalg/mixed/wrapper.hpp> 40 #include <dune/common/fmatrix.hh> 41 #include <dune/istl/bcrsmatrix.hh> 42 #include <dune/istl/multitypeblockvector.hh> 43 #include <dune/istl/solvers.hh> 44 #include <dune/istl/umfpack.hh> 45 #include <dune/istl/owneroverlapcopy.hh> 46 #include <dune/istl/paamg/pinfo.hh> 47 #include <type_traits> 52 template <
typename... Args>
60 #include <opm/simulators/linalg/gpuistl_hip/SolverAdapter.hpp> 62 #include <opm/simulators/linalg/gpuistl/SolverAdapter.hpp> 69 template <
class Operator>
73 const std::function<VectorType()>& weightsCalculator,
74 std::size_t pressureIndex)
76 init(op, Dune::Amg::SequentialInformation(), prm, weightsCalculator,
81 template <
class Operator>
87 const std::function<VectorType()>& weightsCalculator,
88 std::size_t pressureIndex)
90 init(op, comm, prm, weightsCalculator, pressureIndex);
93 template <
class Operator>
96 apply(VectorType& x, VectorType& rhs, Dune::InverseOperatorResult& res)
100 if (direct_precond && direct_precond->needsRebuild()) {
101 recreateDirectSolver();
102 direct_precond->resetNeedsRebuild();
105 linsolver_->apply(x, rhs, res);
108 template <
class Operator>
110 FlexibleSolver<Operator>::
111 apply(VectorType& x, VectorType& rhs,
double reduction, Dune::InverseOperatorResult& res)
113 if (direct_solver_) {
115 if (direct_precond && direct_precond->needsRebuild()) {
116 recreateDirectSolver();
117 direct_precond->resetNeedsRebuild();
120 linsolver_->apply(x, rhs, reduction, res);
124 template <
class Operator>
129 return *preconditioner_;
132 template <
class Operator>
133 Dune::SolverCategory::Category
137 return linearoperator_for_solver_->category();
141 template <
class Operator>
142 template <
class Comm>
144 FlexibleSolver<Operator>::
145 initOpPrecSp(Operator& op,
147 const std::function<VectorType()> weightsCalculator,
149 std::size_t pressureIndex)
152 linearoperator_for_solver_ = &op;
153 const std::string solver_type = prm.
get<std::string>(
"solver",
"bicgstab");
155 if (solver_type ==
"umfpack") {
156 preconditioner_ = std::make_shared<Dune::DirectSolverUpdatePreconditioner<VectorType, VectorType>>(
157 linearoperator_for_solver_->category());
165 scalarproduct_ = Dune::createScalarProduct<VectorType, Comm>(comm, op.category());
168 template <
class Operator>
170 FlexibleSolver<Operator>::
171 initOpPrecSp(Operator& op,
173 const std::function<VectorType()> weightsCalculator,
174 const Dune::Amg::SequentialInformation&,
175 std::size_t pressureIndex)
178 linearoperator_for_solver_ = &op;
179 const std::string solver_type = prm.
get<std::string>(
"solver",
"bicgstab");
181 if (solver_type ==
"umfpack") {
182 preconditioner_ = std::make_shared<Dune::DirectSolverUpdatePreconditioner<VectorType, VectorType>>(
183 linearoperator_for_solver_->category());
190 scalarproduct_ = std::make_shared<Dune::SeqScalarProduct<VectorType>>();
194 template <
class Operator>
195 template <
class Comm>
197 FlexibleSolver<Operator>::
200 const bool is_iorank = comm.communicator().rank() == 0;
201 const double tol = prm.
get<
double>(
"tol", 1e-2);
202 const int maxiter = prm.
get<
int>(
"maxiter", 200);
203 const int verbosity = is_iorank ? prm.
get<
int>(
"verbosity", 0) : 0;
204 const std::string solver_type = prm.
get<std::string>(
"solver",
"bicgstab");
212 direct_solver_ =
false;
213 if (solver_type ==
"bicgstab") {
214 linsolver_ = std::make_shared<Dune::BiCGSTABSolver<VectorType>>(*linearoperator_for_solver_,
220 #if HAVE_AVX2_EXTENSION 221 }
else if (solver_type ==
"mixed-bicgstab") {
222 if constexpr (Opm::is_gpu_operator_v<Operator>) {
223 OPM_THROW(std::invalid_argument,
"mixed-bicgstab solver not supported for GPU operatorsg");
224 }
else if constexpr (Opm::detail::is_multi_type_block_vector_v<VectorType>) {
225 OPM_THROW(std::invalid_argument,
"mixed-bicgstab solver not supported for multi-type block vectors.");
226 }
else if constexpr (std::is_same_v<typename VectorType::field_type, float>){
227 OPM_THROW(std::invalid_argument,
"mixed-bicgstab solver not supported for single precision.");
229 const std::string prec_type = prm.
get<std::string>(
"preconditioner.type",
"error");
230 bool use_mixed_dilu= (prec_type==
"mixed-dilu");
231 using MatrixType = decltype(linearoperator_for_solver_->getmat());
232 linsolver_ = std::make_shared<Dune::MixedSolver<VectorType,MatrixType>>(
233 linearoperator_for_solver_->getmat(),
240 }
else if (solver_type ==
"loopsolver") {
241 linsolver_ = std::make_shared<Dune::LoopSolver<VectorType>>(*linearoperator_for_solver_,
247 }
else if (solver_type ==
"gmres") {
248 int restart = prm.
get<
int>(
"restart", 15);
249 linsolver_ = std::make_shared<Dune::RestartedGMResSolver<VectorType>>(*linearoperator_for_solver_,
256 }
else if (solver_type ==
"flexgmres") {
257 if constexpr (Opm::is_gpu_operator_v<Operator>) {
258 OPM_THROW(std::invalid_argument,
"flexgmres solver not supported for GPU operators.");
260 int restart = prm.
get<
int>(
"restart", 15);
261 linsolver_ = std::make_shared<Dune::RestartedFlexibleGMResSolver<VectorType>>(*linearoperator_for_solver_,
269 }
else if (solver_type ==
"preconditioner2inverseoperator") {
270 if (!preconditioner_) {
271 OPM_THROW(std::invalid_argument,
272 "Properties: Solver preconditioner2inverseoperator requires a preconditioner.");
274 linsolver_ = std::make_shared<Dune::Preconditioner2InverseOperator<VectorType>>(preconditioner_);
276 if constexpr (!Opm::is_gpu_operator_v<Operator> && !Opm::detail::is_multi_type_block_vector_v<VectorType>) {
277 #if HAVE_SUITESPARSE_UMFPACK 278 if (solver_type ==
"umfpack") {
279 if constexpr (std::is_same_v<typename VectorType::field_type,float>) {
280 OPM_THROW(std::invalid_argument,
"UMFPack cannot be used with floats");
282 using MatrixType = std::remove_const_t<std::remove_reference_t<decltype(linearoperator_for_solver_->getmat())>>;
283 linsolver_ = std::make_shared<Dune::UMFPack<MatrixType>>(linearoperator_for_solver_->getmat(), verbosity,
false);
284 direct_solver_ =
true;
288 }
else if (solver_type ==
"gpubicgstab") {
290 *linearoperator_for_solver_,
302 OPM_THROW(std::invalid_argument,
303 "Properties: Solver " + solver_type +
" not known.");
313 template <
class Operator>
315 FlexibleSolver<Operator>::
316 recreateDirectSolver()
318 #if HAVE_SUITESPARSE_UMFPACK 319 if constexpr (!Opm::is_gpu_operator_v<Operator> && !Opm::detail::is_multi_type_block_vector_v<VectorType>) {
320 if constexpr (std::is_same_v<typename VectorType::field_type, float>) {
321 OPM_THROW(std::invalid_argument,
"UMFPack cannot be used with floats");
323 using MatrixType = std::remove_const_t<std::remove_reference_t<decltype(linearoperator_for_solver_->getmat())>>;
324 linsolver_ = std::make_shared<Dune::UMFPack<MatrixType>>(linearoperator_for_solver_->getmat(), 0,
false);
328 OPM_THROW(std::logic_error,
"Direct solver specified, but the FlexibleSolver class was not compiled with SuiteSparse support.");
335 template <
class Operator>
336 template <
class Comm>
338 FlexibleSolver<Operator>::
342 const std::function<VectorType()> weightsCalculator,
343 std::size_t pressureIndex)
345 initOpPrecSp(op, prm, weightsCalculator, comm, pressureIndex);
346 initSolver(prm, comm);
355 template<
class Scalar,
int N>
356 using BV = Dune::BlockVector<Dune::FieldVector<Scalar, N>>;
357 template<
class Scalar,
int N>
358 using OBM = Dune::BCRSMatrix<Opm::MatrixBlock<Scalar, N, N>>;
361 template<
class Scalar,
int N>
362 using SeqOpM = Dune::MatrixAdapter<OBM<Scalar,N>, BV<Scalar,N>, BV<Scalar,N>>;
363 template<
class Scalar,
int N>
369 using Comm = Dune::OwnerOverlapCopyCommunication<int, int>;
370 template<
class Scalar,
int N>
372 template<
class Scalar,
int N>
374 template<
class Scalar,
int N>
375 using ParOpD = Dune::OverlappingSchwarzOperator<OBM<Scalar,N>, BV<Scalar,N>, BV<Scalar,N>, Comm>;
381 #define INSTANTIATE_FLEXIBLESOLVER_OP(...) \ 382 template class Dune::FlexibleSolver<__VA_ARGS__>; \ 383 template Dune::FlexibleSolver<__VA_ARGS__>:: \ 384 FlexibleSolver(__VA_ARGS__& op, \ 386 const Opm::PropertyTree& prm, \ 387 const std::function<typename __VA_ARGS__::domain_type()>& weightsCalculator, \ 388 std::size_t pressureIndex); 390 #define INSTANTIATE_FLEXIBLESOLVER(T,N) \ 391 INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpM<T,N>); \ 392 INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpW<T,N>); \ 393 INSTANTIATE_FLEXIBLESOLVER_OP(ParOpM<T,N>); \ 394 INSTANTIATE_FLEXIBLESOLVER_OP(ParOpW<T,N>); \ 395 INSTANTIATE_FLEXIBLESOLVER_OP(ParOpD<T,N>); 399 #define INSTANTIATE_FLEXIBLESOLVER_OP(...) \ 400 template class Dune::FlexibleSolver<__VA_ARGS__>; 402 #define INSTANTIATE_FLEXIBLESOLVER(T,N) \ 403 INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpM<T,N>); \ 404 INSTANTIATE_FLEXIBLESOLVER_OP(SeqOpW<T,N>); 408 #endif // OPM_FLEXIBLE_SOLVER_IMPL_HEADER_INCLUDED Definition: alignedallocator.hh:32
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:298
T get(const std::string &key) const
Retrieve property value given hierarchical property key.
Definition: PropertyTree.cpp:59
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:224
Wraps a CUDA solver to work with CPU data.
Definition: SolverAdapter.hpp:51
Definition: fvbaseprimaryvariables.hh:161
FlexibleSolver(Operator &op, const Opm::PropertyTree &prm, const std::function< VectorType()> &weightsCalculator, std::size_t pressureIndex)
Create a sequential solver.
Definition: FlexibleSolver_impl.hpp:71
A solver class that encapsulates all needed objects for a linear solver (operator, scalar product, iterative solver and preconditioner) and sets them up based on runtime parameters, using the PreconditionerFactory for setting up preconditioners.
Definition: FlexibleSolver.hpp:43
std::optional< PropertyTree > get_child_optional(const std::string &key) const
Retrieve copy of sub tree rooted at node.
Definition: PropertyTree.cpp:90
AbstractPrecondType & preconditioner()
Access the contained preconditioner.
Definition: FlexibleSolver_impl.hpp:127
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())
Create a new serial preconditioner and return a pointer to it.
Definition: PreconditionerFactory_impl.hpp:154
Definition: PreconditionerWithUpdate.hpp:97
Dune linear operator that assumes ghost rows are ordered after interior rows.
Definition: WellOperators.hpp:401
Definition: FlexibleSolver_impl.hpp:51
Hierarchical collection of key/value pairs.
Definition: PropertyTree.hpp:38