Go to the documentation of this file.
21#ifndef OPM_STANDARDPRECONDITIONERS_MPI_HEADER
22#define OPM_STANDARDPRECONDITIONERS_MPI_HEADER
26#include <opm/simulators/linalg/gpuistl_hip/PreconditionerCPUMatrixToGPUMatrix.hpp>
37#if HAVE_AVX2_EXTENSION
44template < class Smoother>
49 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
50 SmootherArgs smootherArgs;
51 smootherArgs.iterations = prm. get< int>( "iterations", 1);
55 smootherArgs.relaxationFactor = prm. get< double>( "relaxation", 1.0);
60template < class M, class V, class C>
66 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
67 SmootherArgs smootherArgs;
68 smootherArgs.iterations = prm. get< int>( "iterations", 1);
69 const int iluwitdh = prm. get< int>( "iluwidth", 0);
70 smootherArgs.setN(iluwitdh);
72 smootherArgs.setMilu(milu);
76 smootherArgs.relaxationFactor = prm. get< double>( "relaxation", 1.0);
83auto setUseFixedOrder(C& criterion, bool booleanValue) -> decltype(criterion.setUseFixedOrder(booleanValue))
85 return criterion.setUseFixedOrder(booleanValue);
93template < class Amg, class... Args>
96 auto amg = std::make_shared<Amg>(std::forward<Args>(args)...);
97 amg->setDirichletPresolve(prm. get< bool>( "dirichlet_presolve", false));
101template < class Operator, class Comm, class Matrix, class Vector>
105 Criterion criterion(15, prm. get< int>( "coarsenTarget", 1200));
106 criterion.setDefaultValuesIsotropic(2);
107 criterion.setAlpha(prm. get< double>( "alpha", 0.33));
108 criterion.setBeta(prm. get< double>( "beta", 1e-5));
109 criterion.setMaxLevel(prm. get< int>( "maxlevel", 15));
110 criterion.setSkipIsolated(prm. get< bool>( "skip_isolated", false));
111 criterion.setNoPreSmoothSteps(prm. get< int>( "pre_smooth", 1));
112 criterion.setNoPostSmoothSteps(prm. get< int>( "post_smooth", 1));
113 criterion.setDebugLevel(prm. get< int>( "verbosity", 0));
117 criterion.setAccumulate( static_cast<Dune::Amg::AccumulationMode >(prm. get< int>( "accumulate", 1)));
118 criterion.setProlongationDampingFactor(prm. get< double>( "prolongationdamping", 1.6));
119 criterion.setMaxDistance(prm. get< int>( "maxdistance", 2));
120 criterion.setMaxConnectivity(prm. get< int>( "maxconnectivity", 15));
121 criterion.setMaxAggregateSize(prm. get< int>( "maxaggsize", 6));
122 criterion.setMinAggregateSize(prm. get< int>( "minaggsize", 4));
127template < class Operator, class Comm, class Matrix, class Vector>
128template < class Smoother>
134 auto crit = criterion(prm);
138 return std::make_shared<Type>(
139 op, crit, sargs, prm. get<std::size_t>( "max_krylov", 1), prm. get< double>( "min_reduction", 1e-1));
142 return makeAmgCpr<Type>(prm, op, crit, sargs);
146template < class Operator, class Comm, typename = void>
151 using namespace Dune;
155 using M = typename F::Matrix;
156 using V = typename F::Vector;
158 F::addCreator( "ilu0", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
161 F::addCreator( "paroverilu0",
162 []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
163 return createParILU(op, prm, comm, prm.get< int>( "ilulevel", 0));
165 F::addCreator( "ilun", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
166 return createParILU(op, prm, comm, prm.get< int>( "ilulevel", 0));
168 F::addCreator( "duneilu", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
169 const int n = prm.get< int>( "ilulevel", 0);
170 const double w = prm.get< double>( "relaxation", 1.0);
171 const bool resort = prm.get< bool>( "resort", false);
172 return wrapBlockPreconditioner<RebuildOnUpdatePreconditioner<Dune::SeqILU<M, V, V>>>(
173 comm, std::cref(op.getmat()), n, w, resort);
175 F::addCreator( "dilu", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
176 DUNE_UNUSED_PARAMETER(prm);
177 return wrapBlockPreconditioner<MultithreadDILU<M, V, V>>(comm, op.getmat());
179#if HAVE_AVX2_EXTENSION
180 F::addCreator( "mixed-ilu0", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
181 DUNE_UNUSED_PARAMETER(prm);
182 if constexpr (std::is_same_v<typename V::field_type, float>) {
183 OPM_THROW(std::logic_error, "mixed-ilu0 is not available for floats");
186 return wrapBlockPreconditioner<MixedPreconditioner<M,V,V>>(comm, op.getmat());
189 F::addCreator( "mixed-dilu", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
190 DUNE_UNUSED_PARAMETER(prm);
191 if constexpr (std::is_same_v<typename V::field_type, float>) {
192 OPM_THROW(std::logic_error, "mixed-dilu is not available for floats");
195 return wrapBlockPreconditioner<MixedPreconditioner<M,V,V>>(comm, op.getmat(), true);
199 F::addCreator( "jac", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
200 const int n = prm.get< int>( "repeats", 1);
201 const double w = prm.get< double>( "relaxation", 1.0);
202 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqJac<M, V, V>>>(comm, op.getmat(), n, w);
204 F::addCreator( "gs", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
205 const int n = prm.get< int>( "repeats", 1);
206 const double w = prm.get< double>( "relaxation", 1.0);
207 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqGS<M, V, V>>>(comm, op.getmat(), n, w);
209 F::addCreator( "sor", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
210 const int n = prm.get< int>( "repeats", 1);
211 const double w = prm.get< double>( "relaxation", 1.0);
212 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqSOR<M, V, V>>>(comm, op.getmat(), n, w);
214 F::addCreator( "ssor", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
215 const int n = prm.get< int>( "repeats", 1);
216 const double w = prm.get< double>( "relaxation", 1.0);
217 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqSSOR<M, V, V>>>(comm, op.getmat(), n, w);
224 if constexpr (std::is_same_v<O, Dune::OverlappingSchwarzOperator<M, V, V, C>> ||
225 std::is_same_v<O, Opm::GhostLastMatrixAdapter<M, V, V, C>>) {
226 F::addCreator( "amg", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
227 using PrecPtr = std::shared_ptr<Dune::PreconditionerWithUpdate<V, V>>;
228 std::string smoother = prm.get<std::string>( "smoother", "paroverilu0");
230 std::ranges::transform(smoother, smoother.begin(), ::tolower);
232 if (smoother == "ilu0" || smoother == "paroverilu0") {
236 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
238 } else if (smoother == "dilu") {
240 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
241 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
244 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
246 } else if (smoother == "jac") {
247 using SeqSmoother = SeqJac<M, V, V>;
248 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
249 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
252 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
254 } else if (smoother == "gs") {
255 using SeqSmoother = SeqGS<M, V, V>;
256 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
257 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
260 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
262 } else if (smoother == "sor") {
263 using SeqSmoother = SeqSOR<M, V, V>;
264 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
265 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
268 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
270 } else if (smoother == "ssor") {
271 using SeqSmoother = SeqSSOR<M, V, V>;
272 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
273 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
276 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
278 } else if (smoother == "ilun") {
279 using SeqSmoother = SeqILU<M, V, V>;
280 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
281 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
284 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
287 OPM_THROW(std::invalid_argument, "Properties: No smoother with name " + smoother + ".");
291 if constexpr (M::block_type::rows == 1 && M::block_type::cols == 1
292 && std::is_same_v<HYPRE_Real, typename V::field_type>) {
294 "hypre", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
295 return std::make_shared<linalg::HyprePreconditioner<M, V, V, C>>(op.getmat(), prm, comm);
305 const std::function<V()> weightsCalculator,
306 std::size_t pressureIndex,
308 assert(weightsCalculator);
309 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
310 OPM_THROW(std::logic_error,
311 "Pressure index out of bounds. It needs to specified for CPR");
313 using Scalar = typename V::field_type;
315 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
316 op, prm, weightsCalculator, pressureIndex, comm);
318 F::addCreator( "cprt",
321 const std::function<V()> weightsCalculator,
322 std::size_t pressureIndex,
324 assert(weightsCalculator);
325 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
326 OPM_THROW(std::logic_error,
327 "Pressure index out of bounds. It needs to specified for CPR");
329 using Scalar = typename V::field_type;
331 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
332 op, prm, weightsCalculator, pressureIndex, comm);
340 if constexpr (std::is_same_v<O, WellModelGhostLastMatrixAdapter<M, V, V, true>>) {
341 F::addCreator( "cprw",
344 const std::function<V()> weightsCalculator,
345 std::size_t pressureIndex,
347 assert(weightsCalculator);
348 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
349 OPM_THROW(std::logic_error,
350 "Pressure index out of bounds. It needs to specified for CPR");
352 using Scalar = typename V::field_type;
354 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
355 op, prm, weightsCalculator, pressureIndex, comm);
361 addGpuPreconditioners();
367 static void addGpuPreconditioners()
372 using M = typename F::Matrix;
373 using V = typename F::Vector;
381 F::addCreator( "gpuilu0", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
382 const double w = prm.get< double>( "relaxation", 1.0);
383 using field_type = typename V::field_type;
384 using GpuILU0 = typename gpuistl::
386 auto gpuILU0 = std::make_shared<GpuILU0>(op.getmat(), w);
388 auto adapted = std::make_shared<gpuistl::PreconditionerAdapter<V, V, GpuILU0>>(gpuILU0);
389 auto wrapped = std::make_shared<gpuistl::GpuBlockPreconditioner<V, V, Comm>>(adapted, comm);
393 F::addCreator( "gpujac", []( const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
394 const double w = prm.get< double>( "relaxation", 1.0);
395 using field_type = typename V::field_type;
397 typename gpuistl::GpuJac<gpuistl::GpuSparseMatrixWrapper<field_type>, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
400 gpuistl::GpuVector<field_type>, GpuJac, M>;
402 auto gpuJac = std::make_shared<MatrixOwner>(op.getmat(), w);
404 auto adapted = std::make_shared<gpuistl::PreconditionerAdapter<V, V, MatrixOwner>>(gpuJac);
405 auto wrapped = std::make_shared<gpuistl::GpuBlockPreconditioner<V, V, Comm>>(adapted, comm);
409 F::addCreator( "gpudilu", []( const O& op, [[maybe_unused]] const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
410 const bool split_matrix = prm.get< bool>( "split_matrix", true);
411 const bool tune_gpu_kernels = prm.get< bool>( "tune_gpu_kernels", true);
412 const int mixed_precision_scheme = prm.get< int>( "mixed_precision_scheme", 0);
413 const bool reorder = prm.get< bool>( "reorder", true);
414 using field_type = typename V::field_type;
415 using GpuDILU = typename gpuistl::GpuDILU<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
417 gpuistl::GpuVector<field_type>, GpuDILU, M>;
421 auto gpuDILU = std::make_shared<MatrixOwner>(op.getmat(), op.getmat(), split_matrix, tune_gpu_kernels, mixed_precision_scheme, reorder);
423 auto adapted = std::make_shared<gpuistl::PreconditionerAdapter<V, V, MatrixOwner>>(gpuDILU);
424 auto wrapped = std::make_shared<gpuistl::GpuBlockPreconditioner<V, V, Comm>>(adapted, comm);
428 F::addCreator( "opmgpuilu0", []( const O& op, [[maybe_unused]] const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
429 const bool split_matrix = prm.get< bool>( "split_matrix", true);
430 const bool tune_gpu_kernels = prm.get< bool>( "tune_gpu_kernels", true);
431 const int mixed_precision_scheme = prm.get< int>( "mixed_precision_scheme", 0);
432 using field_type = typename V::field_type;
433 using OpmGpuILU0 = typename gpuistl::OpmGpuILU0<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
436 gpuistl::GpuVector<field_type>, OpmGpuILU0, M>;
440 auto gpuilu0 = std::make_shared<MatrixOwner>(op.getmat(), op.getmat(), split_matrix, tune_gpu_kernels, mixed_precision_scheme);
442 auto adapted = std::make_shared<gpuistl::PreconditionerAdapter<V, V, MatrixOwner>>(gpuilu0);
443 auto wrapped = std::make_shared<gpuistl::GpuBlockPreconditioner<V, V, Comm>>(adapted, comm);
454 using M = typename F::Matrix;
455 using V = typename F::Vector;
457 const double w = prm. get< double>( "relaxation", 1.0);
458 const bool redblack = prm. get< bool>( "redblack", false);
459 const bool reorder_spheres = prm. get< bool>( "reorder_spheres", false);
463 assert(num_interior <= op.getmat().N());
464 return std::make_shared<ParallelOverlappingILU0<M, V, V, Comm>>(
465 op.getmat(), comm, w, MILU_VARIANT::ILU, num_interior, redblack, reorder_spheres);
467 return std::make_shared<ParallelOverlappingILU0<M, V, V, Comm>>(
478 std::size_t interior_count = 0;
479 std::size_t highest_interior_index = 0;
480 const auto& is = comm.indexSet();
481 for ( const auto& ind : is) {
482 if (Comm::OwnerSet::contains(ind.local().attribute())) {
484 highest_interior_index = std::max(highest_interior_index, ind.local().local());
487 if (highest_interior_index + 1 == interior_count) {
488 return interior_count;
Dune::OwnerOverlapCopyCommunication< int, int > Comm Definition: FlexibleSolver_impl.hpp:404
Parallel algebraic multigrid based on agglomeration. Definition: amgcpr.hh:88
Definition: PreconditionerWithUpdate.hpp:45
The OpenMP thread parallelized DILU preconditioner. Definition: DILU.hpp:53
A two-step version of an overlapping Schwarz preconditioner using one step ILU0 as. Definition: ParallelOverlappingILU0.hpp:131
Definition: PreconditionerFactory.hpp:64
std::shared_ptr< Dune::PreconditionerWithUpdate< Vector, Vector > > PrecPtr The type of pointer returned by create(). Definition: PreconditionerFactory.hpp:71
Definition: PressureBhpTransferPolicy.hpp:100
Definition: PressureTransferPolicy.hpp:55
Hierarchical collection of key/value pairs. Definition: PropertyTree.hpp:39
T get(const std::string &key) const
Convert a CPU matrix to a GPU matrix and use a CUDA preconditioner on the GPU. Definition: PreconditionerCPUMatrixToGPUMatrix.hpp:42
Definition: fvbaseprimaryvariables.hh:161
Definition: blackoilbioeffectsmodules.hh:45
MILU_VARIANT Definition: MILU.hpp:34
@ ILU Do not perform modified ILU.
std::shared_ptr< Amg > makeAmgCpr(const PropertyTree &prm, Args &&... args) Definition: StandardPreconditioners_mpi.hpp:94
constexpr int max_gpu_instantiated_block_size Definition: is_gpu_operator.hpp:87
auto setUseFixedOrder(C &criterion, bool booleanValue) -> decltype(criterion.setUseFixedOrder(booleanValue)) Definition: StandardPreconditioners_mpi.hpp:83
MILU_VARIANT convertString2Milu(const std::string &milu)
Dune::Amg::CoarsenCriterion< CriterionBase > Criterion Definition: PreconditionerFactory.hpp:47
static Criterion criterion(const PropertyTree &prm) Definition: StandardPreconditioners_mpi.hpp:103
std::shared_ptr< Dune::PreconditionerWithUpdate< Vector, Vector > > PrecPtr Definition: PreconditionerFactory.hpp:44
static PrecPtr makeAmgPreconditioner(const Operator &op, const PropertyTree &prm, bool useKamg=false) Definition: StandardPreconditioners_mpi.hpp:130
static auto args(const PropertyTree &prm) Definition: StandardPreconditioners_mpi.hpp:63
Definition: StandardPreconditioners_mpi.hpp:46
static auto args(const PropertyTree &prm) Definition: StandardPreconditioners_mpi.hpp:47
Definition: StandardPreconditioners_mpi.hpp:148
static PreconditionerFactory< Operator, Comm >::PrecPtr createParILU(const Operator &op, const PropertyTree &prm, const Comm &comm, const int ilulevel) Definition: StandardPreconditioners_mpi.hpp:451
static std::size_t interiorIfGhostLast(const Comm &comm) Definition: StandardPreconditioners_mpi.hpp:476
static void add() Definition: StandardPreconditioners_mpi.hpp:149
|