StandardPreconditioners_mpi.hpp
Go to the documentation of this file.
1/*
2 Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
3 Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
4
5 This file is part of the Open Porous Media project (OPM).
6
7 OPM is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 OPM is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with OPM. If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#ifndef OPM_STANDARDPRECONDITIONERS_MPI_HEADER
22#define OPM_STANDARDPRECONDITIONERS_MPI_HEADER
23
24#if HAVE_CUDA
25#if USE_HIP
26#include <opm/simulators/linalg/gpuistl_hip/PreconditionerCPUMatrixToGPUMatrix.hpp>
27#else
29#endif
30#endif
31
32#include <functional>
33#include <memory>
34#include <type_traits>
35#include <utility>
36
37#if HAVE_AVX2_EXTENSION
39#endif
40
41namespace Opm {
42
43
44template <class Smoother>
46{
47 static auto args(const PropertyTree& prm)
48 {
49 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
50 SmootherArgs smootherArgs;
51 smootherArgs.iterations = prm.get<int>("iterations", 1);
52 // smootherArgs.overlap=SmootherArgs::vertex;
53 // smootherArgs.overlap=SmootherArgs::none;
54 // smootherArgs.overlap=SmootherArgs::aggregate;
55 smootherArgs.relaxationFactor = prm.get<double>("relaxation", 1.0);
56 return smootherArgs;
57 }
58};
59
60template <class M, class V, class C>
62{
63 static auto args(const PropertyTree& prm)
64 {
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);
71 const MILU_VARIANT milu = convertString2Milu(prm.get<std::string>("milutype", std::string("ilu")));
72 smootherArgs.setMilu(milu);
73 // smootherArgs.overlap=SmootherArgs::vertex;
74 // smootherArgs.overlap=SmootherArgs::none;
75 // smootherArgs.overlap=SmootherArgs::aggregate;
76 smootherArgs.relaxationFactor = prm.get<double>("relaxation", 1.0);
77 return smootherArgs;
78 }
79};
80
81// trailing return type with decltype used for detecting existence of setUseFixedOrder member function by overloading the setUseFixedOrder function
82template <typename C>
83auto setUseFixedOrder(C& criterion, bool booleanValue) -> decltype(criterion.setUseFixedOrder(booleanValue))
84{
85 return criterion.setUseFixedOrder(booleanValue); // Set flag to ensure that the matrices in the AMG hierarchy are constructed with deterministic indices.
86}
87template <typename C>
88void setUseFixedOrder(C&, ...)
89{
90 // do nothing, since the function setUseFixedOrder does not exist yet
91}
92
93template <class Amg, class... Args>
94std::shared_ptr<Amg> makeAmgCpr(const PropertyTree& prm, Args&&... args)
95{
96 auto amg = std::make_shared<Amg>(std::forward<Args>(args)...);
97 amg->setDirichletPresolve(prm.get<bool>("dirichlet_presolve", false));
98 return amg;
99}
100
101template <class Operator, class Comm, class Matrix, class Vector>
104{
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));
114 // As the default we request to accumulate data to 1 process always as our matrix
115 // graph might be unsymmetric and hence not supported by the PTScotch/ParMetis
116 // calls in DUNE. Accumulating to 1 skips PTScotch/ParMetis
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));
123 setUseFixedOrder(criterion, true); // If possible, set flag to ensure that the matrices in the AMG hierarchy are constructed with deterministic indices.
124 return criterion;
125}
126
127template <class Operator, class Comm, class Matrix, class Vector>
128template <class Smoother>
131 const PropertyTree& prm,
132 bool useKamg)
133{
134 auto crit = criterion(prm);
136 if (useKamg) {
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));
140 } else {
142 return makeAmgCpr<Type>(prm, op, crit, sargs);
143 }
144}
145
146template <class Operator, class Comm, typename = void> // Note: Last argument is to allow partial specialization for GPU
148{
149 static void add()
150 {
151 using namespace Dune;
152 using O = Operator;
153 using C = Comm;
155 using M = typename F::Matrix;
156 using V = typename F::Vector;
157 using P = PropertyTree;
158 F::addCreator("ilu0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
159 return createParILU(op, prm, comm, 0);
160 });
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));
164 });
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));
167 });
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);
174 });
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());
178 });
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");
184 return nullptr;
185 } else {
186 return wrapBlockPreconditioner<MixedPreconditioner<M,V,V>>(comm, op.getmat());
187 }
188 });
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");
193 return nullptr;
194 } else {
195 return wrapBlockPreconditioner<MixedPreconditioner<M,V,V>>(comm, op.getmat(), true);
196 }
197 });
198#endif
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);
203 });
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);
208 });
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);
213 });
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);
218 });
219
220 // Only add AMG preconditioners to the factory if the operator
221 // is the overlapping schwarz operator or GhostLastMatrixAdapter. This could be extended
222 // later, but at this point no other operators are compatible
223 // with the AMG hierarchy construction.
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");
229 // Make the smoother type lowercase for internal canonical representation
230 std::ranges::transform(smoother, smoother.begin(), ::tolower);
231 // TODO: merge this with ILUn, and possibly simplify the factory to only work with ILU?
232 if (smoother == "ilu0" || smoother == "paroverilu0") {
234 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
236 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
237 return prec;
238 } else if (smoother == "dilu") {
239 using SeqSmoother = Dune::MultithreadDILU<M, V, V>;
240 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
241 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
242 SmootherArgs sargs;
243 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
244 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
245 return prec;
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;
250 SmootherArgs sargs;
251 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
252 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
253 return prec;
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;
258 SmootherArgs sargs;
259 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
260 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
261 return prec;
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;
266 SmootherArgs sargs;
267 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
268 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
269 return prec;
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;
274 SmootherArgs sargs;
275 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
276 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
277 return prec;
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;
282 SmootherArgs sargs;
283 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
284 PrecPtr prec = makeAmgCpr<Dune::Amg::AMGCPR<O, V, Smoother, C>>(prm, op, crit, sargs, comm);
285 return prec;
286 } else {
287 OPM_THROW(std::invalid_argument, "Properties: No smoother with name " + smoother + ".");
288 }
289 });
290#if HAVE_HYPRE
291 if constexpr (M::block_type::rows == 1 && M::block_type::cols == 1
292 && std::is_same_v<HYPRE_Real, typename V::field_type>) {
293 F::addCreator(
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);
296 });
297 }
298#endif
299 }
300
301
302 F::addCreator("cpr",
303 [](const O& op,
304 const P& prm,
305 const std::function<V()> weightsCalculator,
306 std::size_t pressureIndex,
307 const C& comm) {
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");
312 }
313 using Scalar = typename V::field_type;
314 using LevelTransferPolicy = PressureTransferPolicy<O, Comm, Scalar, false>;
315 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
316 op, prm, weightsCalculator, pressureIndex, comm);
317 });
318 F::addCreator("cprt",
319 [](const O& op,
320 const P& prm,
321 const std::function<V()> weightsCalculator,
322 std::size_t pressureIndex,
323 const C& comm) {
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");
328 }
329 using Scalar = typename V::field_type;
330 using LevelTransferPolicy = PressureTransferPolicy<O, Comm, Scalar, true>;
331 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
332 op, prm, weightsCalculator, pressureIndex, comm);
333 });
334
335 // Add CPRW only for the WellModelGhostLastMatrixAdapter, as the method requires that the
336 // operator has the addWellPressureEquations() method (and a few more) it can not be combined
337 // with a well-less operator such as GhostLastMatrixAdapter or OverlappingSchwarzOperator.
338 // For OPM Flow this corresponds to requiring --matrix-add-well-contributions=false
339 // (which is the default).
340 if constexpr (std::is_same_v<O, WellModelGhostLastMatrixAdapter<M, V, V, true>>) {
341 F::addCreator("cprw",
342 [](const O& op,
343 const P& prm,
344 const std::function<V()> weightsCalculator,
345 std::size_t pressureIndex,
346 const C& comm) {
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");
351 }
352 using Scalar = typename V::field_type;
353 using LevelTransferPolicy = PressureBhpTransferPolicy<O, Comm, Scalar, false>;
354 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
355 op, prm, weightsCalculator, pressureIndex, comm);
356 });
357 }
358
359#if HAVE_CUDA
360 if constexpr (V::block_type::dimension <= max_gpu_instantiated_block_size) {
361 addGpuPreconditioners();
362 }
363#endif // HAVE_CUDA
364 }
365
366#if HAVE_CUDA
367 static void addGpuPreconditioners()
368 {
369 using O = Operator;
370 using C = Comm;
372 using M = typename F::Matrix;
373 using V = typename F::Vector;
374 using P = PropertyTree;
375
376 // Here we create the *wrapped* GPU preconditioners
377 // meaning they will act as CPU preconditioners on the outside,
378 // but copy data back and forth to the GPU as needed.
379
380 // TODO: Make this use the GPU preconditioner factory once that is up and running.
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::
385 GpuSeqILU0<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
386 auto gpuILU0 = std::make_shared<GpuILU0>(op.getmat(), w);
387
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);
390 return wrapped;
391 });
392
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;
396 using GpuJac =
397 typename gpuistl::GpuJac<gpuistl::GpuSparseMatrixWrapper<field_type>, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
398
400 gpuistl::GpuVector<field_type>, GpuJac, M>;
401
402 auto gpuJac = std::make_shared<MatrixOwner>(op.getmat(), w);
403
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);
406 return wrapped;
407 });
408
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>;
418
419 // Note: op.getmat() is passed twice, because the GpuDILU needs both the CPU and GPU matrix.
420 // The first argument will be converted to a GPU matrix, and the second one is used as a CPU matrix.
421 auto gpuDILU = std::make_shared<MatrixOwner>(op.getmat(), op.getmat(), split_matrix, tune_gpu_kernels, mixed_precision_scheme, reorder);
422
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);
425 return wrapped;
426 });
427
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>>;
434
436 gpuistl::GpuVector<field_type>, OpmGpuILU0, M>;
437
438 // Note: op.getmat() is passed twice, because the OPMGPUILU0 needs both the CPU and GPU matrix.
439 // The first argument will be converted to a GPU matrix, and the second one is used as a CPU matrix.
440 auto gpuilu0 = std::make_shared<MatrixOwner>(op.getmat(), op.getmat(), split_matrix, tune_gpu_kernels, mixed_precision_scheme);
441
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);
444 return wrapped;
445 });
446 }
447#endif // HAVE_CUDA
448
449
451 createParILU(const Operator& op, const PropertyTree& prm, const Comm& comm, const int ilulevel)
452 {
454 using M = typename F::Matrix;
455 using V = typename F::Vector;
456
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);
460 // Already a parallel preconditioner. Need to pass comm, but no need to wrap it in a BlockPreconditioner.
461 if (ilulevel == 0) {
462 const std::size_t num_interior = interiorIfGhostLast(comm);
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);
466 } else {
467 return std::make_shared<ParallelOverlappingILU0<M, V, V, Comm>>(
468 op.getmat(), comm, ilulevel, w, MILU_VARIANT::ILU, redblack, reorder_spheres);
469 }
470 }
471
476 static std::size_t interiorIfGhostLast(const Comm& comm)
477 {
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())) {
483 ++interior_count;
484 highest_interior_index = std::max(highest_interior_index, ind.local().local());
485 }
486 }
487 if (highest_interior_index + 1 == interior_count) {
488 return interior_count;
489 } else {
490 return is.size();
491 }
492 }
493};
494
495
496} // namespace Opm
497
498#endif // OPM_STANDARDPRECONDITIONERS_MPI_HEADER
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