PreconditionerFactory_impl.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#include <config.h>
22
23#include <opm/common/ErrorMacros.hpp>
24#include <opm/common/TimingMacros.hpp>
25
27
41
42#include <dune/common/unused.hh>
43#include <dune/istl/owneroverlapcopy.hh>
44#include <dune/istl/paamg/amg.hh>
45#include <dune/istl/paamg/fastamg.hh>
46#include <dune/istl/paamg/kamg.hh>
47#include <dune/istl/preconditioners.hh>
48
49// Include all cuistl/GPU preconditioners inside of this headerfile
51
52
53namespace Opm {
54
55template <class Smoother>
57{
58 static auto args(const PropertyTree& prm)
59 {
60 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
61 SmootherArgs smootherArgs;
62 smootherArgs.iterations = prm.get<int>("iterations", 1);
63 // smootherArgs.overlap=SmootherArgs::vertex;
64 // smootherArgs.overlap=SmootherArgs::none;
65 // smootherArgs.overlap=SmootherArgs::aggregate;
66 smootherArgs.relaxationFactor = prm.get<double>("relaxation", 1.0);
67 return smootherArgs;
68 }
69};
70
71template <class M, class V, class C>
73{
74 static auto args(const PropertyTree& prm)
75 {
77 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
78 SmootherArgs smootherArgs;
79 smootherArgs.iterations = prm.get<int>("iterations", 1);
80 const int iluwitdh = prm.get<int>("iluwidth", 0);
81 smootherArgs.setN(iluwitdh);
82 const MILU_VARIANT milu = convertString2Milu(prm.get<std::string>("milutype", std::string("ilu")));
83 smootherArgs.setMilu(milu);
84 // smootherArgs.overlap=SmootherArgs::vertex;
85 // smootherArgs.overlap=SmootherArgs::none;
86 // smootherArgs.overlap=SmootherArgs::aggregate;
87 smootherArgs.relaxationFactor = prm.get<double>("relaxation", 1.0);
88 return smootherArgs;
89 }
90};
91
92// trailing return type with decltype used for detecting existence of setUseFixedOrder member function by overloading the setUseFixedOrder function
93template <typename C>
94auto setUseFixedOrder(C criterion, bool booleanValue) -> decltype(criterion.setUseFixedOrder(booleanValue))
95{
96 return criterion.setUseFixedOrder(booleanValue); // Set flag to ensure that the matrices in the AMG hierarchy are constructed with deterministic indices.
97}
98template <typename C>
99void setUseFixedOrder(C, ...)
100{
101 // do nothing, since the function setUseFixedOrder does not exist yet
102}
103
104template <class Operator, class Comm, class Matrix, class Vector>
107{
108 Criterion criterion(15, prm.get<int>("coarsenTarget", 1200));
109 criterion.setDefaultValuesIsotropic(2);
110 criterion.setAlpha(prm.get<double>("alpha", 0.33));
111 criterion.setBeta(prm.get<double>("beta", 1e-5));
112 criterion.setMaxLevel(prm.get<int>("maxlevel", 15));
113 criterion.setSkipIsolated(prm.get<bool>("skip_isolated", false));
114 criterion.setNoPreSmoothSteps(prm.get<int>("pre_smooth", 1));
115 criterion.setNoPostSmoothSteps(prm.get<int>("post_smooth", 1));
116 criterion.setDebugLevel(prm.get<int>("verbosity", 0));
117 // As the default we request to accumulate data to 1 process always as our matrix
118 // graph might be unsymmetric and hence not supported by the PTScotch/ParMetis
119 // calls in DUNE. Accumulating to 1 skips PTScotch/ParMetis
120 criterion.setAccumulate(static_cast<Dune::Amg::AccumulationMode>(prm.get<int>("accumulate", 1)));
121 criterion.setProlongationDampingFactor(prm.get<double>("prolongationdamping", 1.6));
122 criterion.setMaxDistance(prm.get<int>("maxdistance", 2));
123 criterion.setMaxConnectivity(prm.get<int>("maxconnectivity", 15));
124 criterion.setMaxAggregateSize(prm.get<int>("maxaggsize", 6));
125 criterion.setMinAggregateSize(prm.get<int>("minaggsize", 4));
126 setUseFixedOrder(criterion, true); // If possible, set flag to ensure that the matrices in the AMG hierarchy are constructed with deterministic indices.
127 return criterion;
128}
129
130template <class Operator, class Comm, class Matrix, class Vector>
131template <class Smoother>
134 const PropertyTree& prm,
135 bool useKamg)
136{
137 auto crit = criterion(prm);
139 if (useKamg) {
141 return std::make_shared<Type>(
142 op, crit, sargs, prm.get<std::size_t>("max_krylov", 1), prm.get<double>("min_reduction", 1e-1));
143 } else {
145 return std::make_shared<Type>(op, crit, sargs);
146 }
147}
148
149template <class Operator, class Comm>
151 static void add()
152 {
153 using namespace Dune;
154 using O = Operator;
155 using C = Comm;
157 using M = typename F::Matrix;
158 using V = typename F::Vector;
159 using P = PropertyTree;
160 F::addCreator("ILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
161 return createParILU(op, prm, comm, 0);
162 });
163 F::addCreator("ParOverILU0",
164 [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
165 return createParILU(op, prm, comm, prm.get<int>("ilulevel", 0));
166 });
167 F::addCreator("ILUn", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
168 return createParILU(op, prm, comm, prm.get<int>("ilulevel", 0));
169 });
170 F::addCreator("DuneILU", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
171 const int n = prm.get<int>("ilulevel", 0);
172 const double w = prm.get<double>("relaxation", 1.0);
173 const bool resort = prm.get<bool>("resort", false);
174 return wrapBlockPreconditioner<RebuildOnUpdatePreconditioner<Dune::SeqILU<M, V, V>>>(
175 comm, op.getmat(), n, w, resort);
176 });
177 F::addCreator("DILU", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
178 DUNE_UNUSED_PARAMETER(prm);
179 return wrapBlockPreconditioner<MultithreadDILU<M, V, V>>(comm, op.getmat());
180 });
181 F::addCreator("Jac", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
182 const int n = prm.get<int>("repeats", 1);
183 const double w = prm.get<double>("relaxation", 1.0);
184 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqJac<M, V, V>>>(comm, op.getmat(), n, w);
185 });
186 F::addCreator("GS", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
187 const int n = prm.get<int>("repeats", 1);
188 const double w = prm.get<double>("relaxation", 1.0);
189 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqGS<M, V, V>>>(comm, op.getmat(), n, w);
190 });
191 F::addCreator("SOR", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
192 const int n = prm.get<int>("repeats", 1);
193 const double w = prm.get<double>("relaxation", 1.0);
194 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqSOR<M, V, V>>>(comm, op.getmat(), n, w);
195 });
196 F::addCreator("SSOR", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
197 const int n = prm.get<int>("repeats", 1);
198 const double w = prm.get<double>("relaxation", 1.0);
199 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqSSOR<M, V, V>>>(comm, op.getmat(), n, w);
200 });
201
202 // Only add AMG preconditioners to the factory if the operator
203 // is the overlapping schwarz operator. This could be extended
204 // later, but at this point no other operators are compatible
205 // with the AMG hierarchy construction.
206 if constexpr (std::is_same_v<O, Dune::OverlappingSchwarzOperator<M, V, V, C>> ||
207 std::is_same_v<O, Opm::GhostLastMatrixAdapter<M, V, V, C>>) {
208 F::addCreator("amg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
209 using PrecPtr = std::shared_ptr<Dune::PreconditionerWithUpdate<V, V>>;
210 const std::string smoother = prm.get<std::string>("smoother", "ParOverILU0");
211 // TODO: merge this with ILUn, and possibly simplify the factory to only work with ILU?
212 if (smoother == "ILU0" || smoother == "ParOverILU0") {
214 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
216 PrecPtr prec = std::make_shared<Dune::Amg::AMGCPR<O, V, Smoother, C>>(op, crit, sargs, comm);
217 return prec;
218 } else if (smoother == "DILU") {
219 using SeqSmoother = Dune::MultithreadDILU<M, V, V>;
220 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
221 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
222 SmootherArgs sargs;
223 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
224 PrecPtr prec = std::make_shared<Dune::Amg::AMGCPR<O, V, Smoother, C>>(op, crit, sargs, comm);
225 return prec;
226 } else if (smoother == "Jac") {
227 using SeqSmoother = SeqJac<M, V, V>;
228 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
229 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
230 SmootherArgs sargs;
231 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
232 PrecPtr prec = std::make_shared<Dune::Amg::AMGCPR<O, V, Smoother, C>>(op, crit, sargs, comm);
233 return prec;
234 } else if (smoother == "GS") {
235 using SeqSmoother = SeqGS<M, V, V>;
236 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
237 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
238 SmootherArgs sargs;
239 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
240 PrecPtr prec = std::make_shared<Dune::Amg::AMGCPR<O, V, Smoother, C>>(op, crit, sargs, comm);
241 return prec;
242 } else if (smoother == "SOR") {
243 using SeqSmoother = SeqSOR<M, V, V>;
244 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
245 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
246 SmootherArgs sargs;
247 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
248 PrecPtr prec = std::make_shared<Dune::Amg::AMGCPR<O, V, Smoother, C>>(op, crit, sargs, comm);
249 return prec;
250 } else if (smoother == "SSOR") {
251 using SeqSmoother = SeqSSOR<M, V, V>;
252 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
253 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
254 SmootherArgs sargs;
255 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
256 PrecPtr prec = std::make_shared<Dune::Amg::AMGCPR<O, V, Smoother, C>>(op, crit, sargs, comm);
257 return prec;
258 } else if (smoother == "ILUn") {
259 using SeqSmoother = SeqILU<M, V, V>;
260 using Smoother = Dune::BlockPreconditioner<V, V, C, SeqSmoother>;
261 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
262 SmootherArgs sargs;
263 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
264 PrecPtr prec = std::make_shared<Dune::Amg::AMGCPR<O, V, Smoother, C>>(op, crit, sargs, comm);
265 return prec;
266 } else {
267 OPM_THROW(std::invalid_argument, "Properties: No smoother with name " + smoother + ".");
268 }
269 });
270 }
271
272 F::addCreator("cpr",
273 [](const O& op,
274 const P& prm,
275 const std::function<V()> weightsCalculator,
276 std::size_t pressureIndex,
277 const C& comm) {
278 assert(weightsCalculator);
279 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
280 OPM_THROW(std::logic_error,
281 "Pressure index out of bounds. It needs to specified for CPR");
282 }
283 using Scalar = typename V::field_type;
284 using LevelTransferPolicy = PressureTransferPolicy<O, Comm, Scalar, false>;
285 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
286 op, prm, weightsCalculator, pressureIndex, comm);
287 });
288 F::addCreator("cprt",
289 [](const O& op,
290 const P& prm,
291 const std::function<V()> weightsCalculator,
292 std::size_t pressureIndex,
293 const C& comm) {
294 assert(weightsCalculator);
295 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
296 OPM_THROW(std::logic_error,
297 "Pressure index out of bounds. It needs to specified for CPR");
298 }
299 using Scalar = typename V::field_type;
300 using LevelTransferPolicy = PressureTransferPolicy<O, Comm, Scalar, true>;
301 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
302 op, prm, weightsCalculator, pressureIndex, comm);
303 });
304
305 if constexpr (std::is_same_v<O, WellModelGhostLastMatrixAdapter<M, V, V, true>>) {
306 F::addCreator("cprw",
307 [](const O& op,
308 const P& prm,
309 const std::function<V()> weightsCalculator,
310 std::size_t pressureIndex,
311 const C& comm) {
312 assert(weightsCalculator);
313 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
314 OPM_THROW(std::logic_error,
315 "Pressure index out of bounds. It needs to specified for CPR");
316 }
317 using Scalar = typename V::field_type;
318 using LevelTransferPolicy = PressureBhpTransferPolicy<O, Comm, Scalar, false>;
319 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
320 op, prm, weightsCalculator, pressureIndex, comm);
321 });
322 }
323
324#if HAVE_CUDA
325 F::addCreator("GPUILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
326 const double w = prm.get<double>("relaxation", 1.0);
327 using field_type = typename V::field_type;
328 using GpuILU0 = typename gpuistl::
329 GpuSeqILU0<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
330 auto gpuILU0 = std::make_shared<GpuILU0>(op.getmat(), w);
331
332 auto adapted = std::make_shared<gpuistl::PreconditionerAdapter<V, V, GpuILU0>>(gpuILU0);
333 auto wrapped = std::make_shared<gpuistl::GpuBlockPreconditioner<V, V, Comm>>(adapted, comm);
334 return wrapped;
335 });
336
337 F::addCreator("GPUJAC", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
338 const double w = prm.get<double>("relaxation", 1.0);
339 using field_type = typename V::field_type;
340 using GpuJac =
341 typename gpuistl::GpuJac<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
342 auto gpuJac = std::make_shared<GpuJac>(op.getmat(), w);
343
344 auto adapted = std::make_shared<gpuistl::PreconditionerAdapter<V, V, GpuJac>>(gpuJac);
345 auto wrapped = std::make_shared<gpuistl::GpuBlockPreconditioner<V, V, Comm>>(adapted, comm);
346 return wrapped;
347 });
348
349 F::addCreator("GPUDILU", [](const O& op, [[maybe_unused]] const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
350 const bool split_matrix = prm.get<bool>("split_matrix", true);
351 const bool tune_gpu_kernels = prm.get<bool>("tune_gpu_kernels", true);
352 using field_type = typename V::field_type;
353 using GpuDILU = typename gpuistl::GpuDILU<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
354 auto gpuDILU = std::make_shared<GpuDILU>(op.getmat(), split_matrix, tune_gpu_kernels);
355
356 auto adapted = std::make_shared<gpuistl::PreconditionerAdapter<V, V, GpuDILU>>(gpuDILU);
357 auto wrapped = std::make_shared<gpuistl::GpuBlockPreconditioner<V, V, Comm>>(adapted, comm);
358 return wrapped;
359 });
360
361 F::addCreator("OPMGPUILU0", [](const O& op, [[maybe_unused]] const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
362 const bool split_matrix = prm.get<bool>("split_matrix", true);
363 const bool tune_gpu_kernels = prm.get<bool>("tune_gpu_kernels", true);
364 using field_type = typename V::field_type;
365 using OpmGpuILU0 = typename gpuistl::OpmGpuILU0<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
366 auto gpuilu0 = std::make_shared<OpmGpuILU0>(op.getmat(), split_matrix, tune_gpu_kernels);
367
368 auto adapted = std::make_shared<gpuistl::PreconditionerAdapter<V, V, OpmGpuILU0>>(gpuilu0);
369 auto wrapped = std::make_shared<gpuistl::GpuBlockPreconditioner<V, V, Comm>>(adapted, comm);
370 return wrapped;
371 });
372#endif
373 }
374
375
377 createParILU(const Operator& op, const PropertyTree& prm, const Comm& comm, const int ilulevel)
378 {
380 using M = typename F::Matrix;
381 using V = typename F::Vector;
382
383 const double w = prm.get<double>("relaxation", 1.0);
384 const bool redblack = prm.get<bool>("redblack", false);
385 const bool reorder_spheres = prm.get<bool>("reorder_spheres", false);
386 // Already a parallel preconditioner. Need to pass comm, but no need to wrap it in a BlockPreconditioner.
387 if (ilulevel == 0) {
388 const std::size_t num_interior = interiorIfGhostLast(comm);
389 return std::make_shared<ParallelOverlappingILU0<M, V, V, Comm>>(
390 op.getmat(), comm, w, MILU_VARIANT::ILU, num_interior, redblack, reorder_spheres);
391 } else {
392 return std::make_shared<ParallelOverlappingILU0<M, V, V, Comm>>(
393 op.getmat(), comm, ilulevel, w, MILU_VARIANT::ILU, redblack, reorder_spheres);
394 }
395 }
396
401 static std::size_t interiorIfGhostLast(const Comm& comm)
402 {
403 std::size_t interior_count = 0;
404 std::size_t highest_interior_index = 0;
405 const auto& is = comm.indexSet();
406 for (const auto& ind : is) {
407 if (Comm::OwnerSet::contains(ind.local().attribute())) {
408 ++interior_count;
409 highest_interior_index = std::max(highest_interior_index, ind.local().local());
410 }
411 }
412 if (highest_interior_index + 1 == interior_count) {
413 return interior_count;
414 } else {
415 return is.size();
416 }
417 }
418};
419
420template <class Operator>
421struct StandardPreconditioners<Operator, Dune::Amg::SequentialInformation> {
422 static void add()
423 {
424 using namespace Dune;
425 using O = Operator;
426 using C = Dune::Amg::SequentialInformation;
428 using M = typename F::Matrix;
429 using V = typename F::Vector;
430 using P = PropertyTree;
431 F::addCreator("ILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
432 const double w = prm.get<double>("relaxation", 1.0);
433 return std::make_shared<ParallelOverlappingILU0<M, V, V, C>>(
434 op.getmat(), 0, w, MILU_VARIANT::ILU);
435 });
436 F::addCreator("DuneILU", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
437 const double w = prm.get<double>("relaxation", 1.0);
438 const int n = prm.get<int>("ilulevel", 0);
439 const bool resort = prm.get<bool>("resort", false);
440 return getRebuildOnUpdateWrapper<Dune::SeqILU<M, V, V>>(op.getmat(), n, w, resort);
441 });
442 F::addCreator("ParOverILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
443 const double w = prm.get<double>("relaxation", 1.0);
444 const int n = prm.get<int>("ilulevel", 0);
445 return std::make_shared<ParallelOverlappingILU0<M, V, V, C>>(
446 op.getmat(), n, w, MILU_VARIANT::ILU);
447 });
448 F::addCreator("ILUn", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
449 const int n = prm.get<int>("ilulevel", 0);
450 const double w = prm.get<double>("relaxation", 1.0);
451 return std::make_shared<ParallelOverlappingILU0<M, V, V, C>>(
452 op.getmat(), n, w, MILU_VARIANT::ILU);
453 });
454 F::addCreator("DILU", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
455 DUNE_UNUSED_PARAMETER(prm);
456 return std::make_shared<MultithreadDILU<M, V, V>>(op.getmat());
457 });
458 F::addCreator("Jac", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
459 const int n = prm.get<int>("repeats", 1);
460 const double w = prm.get<double>("relaxation", 1.0);
461 return getDummyUpdateWrapper<SeqJac<M, V, V>>(op.getmat(), n, w);
462 });
463 F::addCreator("GS", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
464 const int n = prm.get<int>("repeats", 1);
465 const double w = prm.get<double>("relaxation", 1.0);
466 return getDummyUpdateWrapper<SeqGS<M, V, V>>(op.getmat(), n, w);
467 });
468 F::addCreator("SOR", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
469 const int n = prm.get<int>("repeats", 1);
470 const double w = prm.get<double>("relaxation", 1.0);
471 return getDummyUpdateWrapper<SeqSOR<M, V, V>>(op.getmat(), n, w);
472 });
473 F::addCreator("SSOR", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
474 const int n = prm.get<int>("repeats", 1);
475 const double w = prm.get<double>("relaxation", 1.0);
476 return getDummyUpdateWrapper<SeqSSOR<M, V, V>>(op.getmat(), n, w);
477 });
478
479 // Only add AMG preconditioners to the factory if the operator
480 // is an actual matrix operator.
481 if constexpr (std::is_same_v<O, Dune::MatrixAdapter<M, V, V>>) {
482 F::addCreator("amg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
483 const std::string smoother = prm.get<std::string>("smoother", "ParOverILU0");
484 if (smoother == "ILU0" || smoother == "ParOverILU0") {
485 using Smoother = SeqILU<M, V, V>;
486 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm);
487 } else if (smoother == "Jac") {
488 using Smoother = SeqJac<M, V, V>;
489 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm);
490 } else if (smoother == "GS") {
491 using Smoother = SeqGS<M, V, V>;
492 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm);
493 } else if (smoother == "DILU") {
494 using Smoother = MultithreadDILU<M, V, V>;
495 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm);
496 } else if (smoother == "SOR") {
497 using Smoother = SeqSOR<M, V, V>;
498 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm);
499 } else if (smoother == "SSOR") {
500 using Smoother = SeqSSOR<M, V, V>;
501 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm);
502 } else if (smoother == "ILUn") {
503 using Smoother = SeqILU<M, V, V>;
504 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm);
505 } else {
506 OPM_THROW(std::invalid_argument, "Properties: No smoother with name " + smoother + ".");
507 }
508 });
509 F::addCreator("kamg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
510 const std::string smoother = prm.get<std::string>("smoother", "ParOverILU0");
511 if (smoother == "ILU0" || smoother == "ParOverILU0") {
512 using Smoother = SeqILU<M, V, V>;
513 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
514 } else if (smoother == "Jac") {
515 using Smoother = SeqJac<M, V, V>;
516 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
517 } else if (smoother == "SOR") {
518 using Smoother = SeqSOR<M, V, V>;
519 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
520 } else if (smoother == "GS") {
521 using Smoother = SeqGS<M, V, V>;
522 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
523 } else if (smoother == "SSOR") {
524 using Smoother = SeqSSOR<M, V, V>;
525 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
526 } else if (smoother == "ILUn") {
527 using Smoother = SeqILU<M, V, V>;
528 return AMGHelper<O, C, M, V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
529 } else {
530 OPM_THROW(std::invalid_argument, "Properties: No smoother with name " + smoother + ".");
531 }
532 });
533 F::addCreator("famg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
534 if constexpr (std::is_same_v<typename V::field_type, float>) {
535 OPM_THROW(std::logic_error, "famg requires UMFPack which is not available for floats");
536 return nullptr;
537 } else {
538 auto crit = AMGHelper<O, C, M, V>::criterion(prm);
539 Dune::Amg::Parameters parms;
540 parms.setNoPreSmoothSteps(1);
541 parms.setNoPostSmoothSteps(1);
542 return getRebuildOnUpdateWrapper<Dune::Amg::FastAMG<O, V>>(op, crit, parms);
543 }
544 });
545 }
546 if constexpr (std::is_same_v<O, WellModelMatrixAdapter<M, V, V, false>>) {
547 F::addCreator(
548 "cprw",
549 [](const O& op, const P& prm, const std::function<V()>& weightsCalculator, std::size_t pressureIndex) {
550 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
551 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
552 }
553 using Scalar = typename V::field_type;
554 using LevelTransferPolicy
556 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(
557 op, prm, weightsCalculator, pressureIndex);
558 });
559 }
560
561 F::addCreator(
562 "cpr",
563 [](const O& op, const P& prm, const std::function<V()>& weightsCalculator, std::size_t pressureIndex) {
564 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
565 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
566 }
567 using Scalar = typename V::field_type;
569 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(
570 op, prm, weightsCalculator, pressureIndex);
571 });
572 F::addCreator(
573 "cprt",
574 [](const O& op, const P& prm, const std::function<V()>& weightsCalculator, std::size_t pressureIndex) {
575 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
576 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
577 }
578 using Scalar = typename V::field_type;
580 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(
581 op, prm, weightsCalculator, pressureIndex);
582 });
583
584#if HAVE_CUDA
585 F::addCreator("GPUILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
586 const double w = prm.get<double>("relaxation", 1.0);
587 using field_type = typename V::field_type;
588 using GpuILU0 = typename gpuistl::
589 GpuSeqILU0<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
590 return std::make_shared<gpuistl::PreconditionerAdapter<V, V, GpuILU0>>(
591 std::make_shared<GpuILU0>(op.getmat(), w));
592 });
593
594 F::addCreator("GPUILU0Float", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
595 const double w = prm.get<double>("relaxation", 1.0);
596 using block_type = typename V::block_type;
597 using VTo = Dune::BlockVector<Dune::FieldVector<float, block_type::dimension>>;
598 using matrix_type_to =
599 typename Dune::BCRSMatrix<Dune::FieldMatrix<float, block_type::dimension, block_type::dimension>>;
600 using GpuILU0 = typename gpuistl::
601 GpuSeqILU0<matrix_type_to, gpuistl::GpuVector<float>, gpuistl::GpuVector<float>>;
604 auto converted = std::make_shared<Converter>(op.getmat());
605 auto adapted = std::make_shared<Adapter>(std::make_shared<GpuILU0>(converted->getConvertedMatrix(), w));
606 converted->setUnderlyingPreconditioner(adapted);
607 return converted;
608 });
609
610 F::addCreator("GPUJAC", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
611 const double w = prm.get<double>("relaxation", 1.0);
612 using field_type = typename V::field_type;
613 using GPUJac =
614 typename gpuistl::GpuJac<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
615 return std::make_shared<gpuistl::PreconditionerAdapter<V, V, GPUJac>>(
616 std::make_shared<GPUJac>(op.getmat(), w));
617 });
618
619 F::addCreator("OPMGPUILU0", [](const O& op, [[maybe_unused]] const P& prm, const std::function<V()>&, std::size_t) {
620 const bool split_matrix = prm.get<bool>("split_matrix", true);
621 const bool tune_gpu_kernels = prm.get<bool>("tune_gpu_kernels", true);
622 using field_type = typename V::field_type;
623 using GPUILU0 = typename gpuistl::OpmGpuILU0<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
624
625 return std::make_shared<gpuistl::PreconditionerAdapter<V, V, GPUILU0>>(std::make_shared<GPUILU0>(op.getmat(), split_matrix, tune_gpu_kernels));
626 });
627
628 F::addCreator("GPUDILU", [](const O& op, [[maybe_unused]] const P& prm, const std::function<V()>&, std::size_t) {
629 const bool split_matrix = prm.get<bool>("split_matrix", true);
630 const bool tune_gpu_kernels = prm.get<bool>("tune_gpu_kernels", true);
631 using field_type = typename V::field_type;
632 using GPUDILU = typename gpuistl::GpuDILU<M, gpuistl::GpuVector<field_type>, gpuistl::GpuVector<field_type>>;
633 return std::make_shared<gpuistl::PreconditionerAdapter<V, V, GPUDILU>>(std::make_shared<GPUDILU>(op.getmat(), split_matrix, tune_gpu_kernels));
634 });
635
636 F::addCreator("GPUDILUFloat", [](const O& op, [[maybe_unused]] const P& prm, const std::function<V()>&, std::size_t) {
637 const bool split_matrix = prm.get<bool>("split_matrix", true);
638 const bool tune_gpu_kernels = prm.get<bool>("tune_gpu_kernels", true);
639 using block_type = typename V::block_type;
640 using VTo = Dune::BlockVector<Dune::FieldVector<float, block_type::dimension>>;
641 using matrix_type_to = typename Dune::BCRSMatrix<Dune::FieldMatrix<float, block_type::dimension, block_type::dimension>>;
642 using GpuDILU = typename gpuistl::GpuDILU<matrix_type_to, gpuistl::GpuVector<float>, gpuistl::GpuVector<float>>;
645 auto converted = std::make_shared<Converter>(op.getmat());
646 auto adapted = std::make_shared<Adapter>(std::make_shared<GpuDILU>(converted->getConvertedMatrix(), split_matrix, tune_gpu_kernels));
647 converted->setUnderlyingPreconditioner(adapted);
648 return converted;
649 });
650#endif
651 }
652};
653
654template <class Operator, class Comm>
655PreconditionerFactory<Operator, Comm>::PreconditionerFactory()
656{
657}
658
659
660template <class Operator, class Comm>
661PreconditionerFactory<Operator, Comm>&
662PreconditionerFactory<Operator, Comm>::instance()
663{
664 static PreconditionerFactory singleton;
665 return singleton;
666}
667
668template <class Operator, class Comm>
670PreconditionerFactory<Operator, Comm>::doCreate(const Operator& op,
671 const PropertyTree& prm,
672 const std::function<Vector()> weightsCalculator,
673 std::size_t pressureIndex)
674{
675 if (!defAdded_) {
677 defAdded_ = true;
678 }
679 const std::string& type = prm.get<std::string>("type", "ParOverILU0");
680 auto it = creators_.find(type);
681 if (it == creators_.end()) {
682 std::ostringstream msg;
683 msg << "Preconditioner type " << type << " is not registered in the factory. Available types are: ";
684 for (const auto& prec : creators_) {
685 msg << prec.first << ' ';
686 }
687 msg << std::endl;
688 OPM_THROW(std::invalid_argument, msg.str());
689 }
690 return it->second(op, prm, weightsCalculator, pressureIndex);
691}
692
693template <class Operator, class Comm>
695PreconditionerFactory<Operator, Comm>::doCreate(const Operator& op,
696 const PropertyTree& prm,
697 const std::function<Vector()> weightsCalculator,
698 std::size_t pressureIndex,
699 const Comm& comm)
700{
701 if (!defAdded_) {
703 defAdded_ = true;
704 }
705 const std::string& type = prm.get<std::string>("type", "ParOverILU0");
706 auto it = parallel_creators_.find(type);
707 if (it == parallel_creators_.end()) {
708 std::ostringstream msg;
709 msg << "Parallel preconditioner type " << type << " is not registered in the factory. Available types are: ";
710 for (const auto& prec : parallel_creators_) {
711 msg << prec.first << ' ';
712 }
713 msg << std::endl;
714 OPM_THROW(std::invalid_argument, msg.str());
715 }
716 return it->second(op, prm, weightsCalculator, pressureIndex, comm);
717}
718
719template <class Operator, class Comm>
720void
721PreconditionerFactory<Operator, Comm>::doAddCreator(const std::string& type, Creator c)
722{
723 creators_[type] = c;
724}
725
726template <class Operator, class Comm>
727void
728PreconditionerFactory<Operator, Comm>::doAddCreator(const std::string& type, ParCreator c)
729{
730 parallel_creators_[type] = c;
731}
732
733template <class Operator, class Comm>
736 const PropertyTree& prm,
737 const std::function<Vector()>& weightsCalculator,
738 std::size_t pressureIndex)
739{
740 return instance().doCreate(op, prm, weightsCalculator, pressureIndex);
741}
742
743template <class Operator, class Comm>
746 const PropertyTree& prm,
747 const std::function<Vector()>& weightsCalculator,
748 const Comm& comm,
749 std::size_t pressureIndex)
750{
751 return instance().doCreate(op, prm, weightsCalculator, pressureIndex, comm);
752}
753
754
755template <class Operator, class Comm>
758 const PropertyTree& prm,
759 const Comm& comm,
760 std::size_t pressureIndex)
761{
762 return instance().doCreate(op, prm, std::function<Vector()>(), pressureIndex, comm);
763}
764
765template <class Operator, class Comm>
766void
768{
769 instance().doAddCreator(type, creator);
770}
771
772template <class Operator, class Comm>
773void
775{
776 instance().doAddCreator(type, creator);
777}
778
779using CommSeq = Dune::Amg::SequentialInformation;
780
781template<class Scalar, int Dim>
782using OpFSeq = Dune::MatrixAdapter<Dune::BCRSMatrix<Dune::FieldMatrix<Scalar, Dim, Dim>>,
783 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
784 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>>;
785template<class Scalar, int Dim>
786using OpBSeq = Dune::MatrixAdapter<Dune::BCRSMatrix<MatrixBlock<Scalar, Dim, Dim>>,
787 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
788 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>>;
789
790template<class Scalar, int Dim, bool overlap>
792 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
793 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
794 overlap>;
795
796template<class Scalar, int Dim, bool overlap>
798 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
799 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
800 overlap>;
801
802#if HAVE_MPI
803using CommPar = Dune::OwnerOverlapCopyCommunication<int, int>;
804
805template<class Scalar, int Dim>
806using OpFPar = Dune::OverlappingSchwarzOperator<Dune::BCRSMatrix<Dune::FieldMatrix<Scalar, Dim, Dim>>,
807 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
808 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
809 CommPar>;
810
811template<class Scalar, int Dim>
812using OpBPar = Dune::OverlappingSchwarzOperator<Dune::BCRSMatrix<MatrixBlock<Scalar, Dim, Dim>>,
813 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
814 Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
815 CommPar>;
816template<class Scalar, int Dim>
818 Dune::BlockVector<Dune::FieldVector<Scalar,Dim>>,
819 Dune::BlockVector<Dune::FieldVector<Scalar,Dim>>,
820 CommPar>;
821
822template<class Scalar, int Dim>
824 Dune::BlockVector<Dune::FieldVector<Scalar,Dim>>,
825 Dune::BlockVector<Dune::FieldVector<Scalar,Dim>>,
826 CommPar>;
827
828#define INSTANTIATE_PF_PAR(T,Dim) \
829 template class PreconditionerFactory<OpBSeq<T,Dim>, CommPar>; \
830 template class PreconditionerFactory<OpFPar<T,Dim>, CommPar>; \
831 template class PreconditionerFactory<OpBPar<T,Dim>, CommPar>; \
832 template class PreconditionerFactory<OpGLFPar<T,Dim>, CommPar>; \
833 template class PreconditionerFactory<OpGLBPar<T,Dim>, CommPar>; \
834 template class PreconditionerFactory<OpW<T,Dim, false>, CommPar>; \
835 template class PreconditionerFactory<OpWG<T,Dim, true>, CommPar>; \
836 template class PreconditionerFactory<OpBPar<T,Dim>, CommSeq>; \
837 template class PreconditionerFactory<OpGLBPar<T,Dim>, CommSeq>;
838#endif
839
840#define INSTANTIATE_PF_SEQ(T,Dim) \
841 template class PreconditionerFactory<OpFSeq<T,Dim>, CommSeq>; \
842 template class PreconditionerFactory<OpBSeq<T,Dim>, CommSeq>; \
843 template class PreconditionerFactory<OpW<T,Dim, false>, CommSeq>; \
844 template class PreconditionerFactory<OpWG<T,Dim, true>, CommSeq>;
845
846#if HAVE_MPI
847#define INSTANTIATE_PF(T,Dim) \
848 INSTANTIATE_PF_PAR(T,Dim) \
849 INSTANTIATE_PF_SEQ(T,Dim)
850#else
851#define INSTANTIATE_PF(T,Dim) INSTANTIATE_PF_SEQ(T,Dim)
852#endif
853
854} // namespace Opm
Dune::OwnerOverlapCopyCommunication< int, int > Comm
Definition: FlexibleSolver_impl.hpp:285
The AMG preconditioner.
Parallel algebraic multigrid based on agglomeration.
Definition: amgcpr.hh:88
Definition: PreconditionerWithUpdate.hpp:43
The OpenMP thread parallelized DILU preconditioner.
Definition: DILU.hpp:53
Dune linear operator that assumes ghost rows are ordered after interior rows. Avoids some computation...
Definition: WellOperators.hpp:340
A two-step version of an overlapping Schwarz preconditioner using one step ILU0 as.
Definition: ParallelOverlappingILU0.hpp:131
Definition: PreconditionerFactory.hpp:64
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:735
std::function< PrecPtr(const Operator &, const PropertyTree &, const std::function< Vector()> &, std::size_t, const Comm &)> ParCreator
Definition: PreconditionerFactory.hpp:77
typename Operator::domain_type Vector
Definition: PreconditionerFactory.hpp:68
std::function< PrecPtr(const Operator &, const PropertyTree &, const std::function< Vector()> &, std::size_t)> Creator
The type of creator functions passed to addCreator().
Definition: PreconditionerFactory.hpp:75
static void addCreator(const std::string &type, Creator creator)
Definition: PreconditionerFactory_impl.hpp:767
std::shared_ptr< Dune::PreconditionerWithUpdate< Vector, Vector > > PrecPtr
The type of pointer returned by create().
Definition: PreconditionerFactory.hpp:71
Definition: PressureBhpTransferPolicy.hpp:99
Definition: PressureTransferPolicy.hpp:55
Definition: PropertyTree.hpp:37
T get(const std::string &key) const
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:237
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:143
DILU preconditioner on the GPU.
Definition: GpuDILU.hpp:44
Jacobi preconditioner on the GPU.
Definition: GpuJac.hpp:47
ILU0 preconditioner on the GPU.
Definition: OpmGpuILU0.hpp:46
Makes a CUDA preconditioner available to a CPU simulator.
Definition: PreconditionerAdapter.hpp:43
Converts the field type (eg. double to float) to benchmark single precision preconditioners.
Definition: PreconditionerConvertFieldTypeAdapter.hpp:86
Definition: fvbaseprimaryvariables.hh:141
Definition: blackoilboundaryratevector.hh:37
MILU_VARIANT
Definition: MILU.hpp:34
@ ILU
Do not perform modified ILU.
Dune::MatrixAdapter< Dune::BCRSMatrix< MatrixBlock< Scalar, Dim, Dim > >, Dune::BlockVector< Dune::FieldVector< Scalar, Dim > >, Dune::BlockVector< Dune::FieldVector< Scalar, Dim > > > OpBSeq
Definition: PreconditionerFactory_impl.hpp:788
Dune::OverlappingSchwarzOperator< Dune::BCRSMatrix< MatrixBlock< Scalar, Dim, Dim > >, Dune::BlockVector< Dune::FieldVector< Scalar, Dim > >, Dune::BlockVector< Dune::FieldVector< Scalar, Dim > >, CommPar > OpBPar
Definition: PreconditionerFactory_impl.hpp:815
Dune::MatrixAdapter< Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, Dim, Dim > >, Dune::BlockVector< Dune::FieldVector< Scalar, Dim > >, Dune::BlockVector< Dune::FieldVector< Scalar, Dim > > > OpFSeq
Definition: PreconditionerFactory_impl.hpp:784
auto setUseFixedOrder(C criterion, bool booleanValue) -> decltype(criterion.setUseFixedOrder(booleanValue))
Definition: PreconditionerFactory_impl.hpp:94
Dune::Amg::SequentialInformation CommSeq
Definition: PreconditionerFactory_impl.hpp:779
MILU_VARIANT convertString2Milu(const std::string &milu)
Dune::OverlappingSchwarzOperator< Dune::BCRSMatrix< Dune::FieldMatrix< Scalar, Dim, Dim > >, Dune::BlockVector< Dune::FieldVector< Scalar, Dim > >, Dune::BlockVector< Dune::FieldVector< Scalar, Dim > >, CommPar > OpFPar
Definition: PreconditionerFactory_impl.hpp:809
Dune::OwnerOverlapCopyCommunication< int, int > CommPar
Definition: PreconditionerFactory_impl.hpp:803
Definition: PreconditionerFactory.hpp:43
Dune::Amg::CoarsenCriterion< CriterionBase > Criterion
Definition: PreconditionerFactory.hpp:47
static Criterion criterion(const PropertyTree &prm)
Definition: PreconditionerFactory_impl.hpp:106
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: PreconditionerFactory_impl.hpp:133
static auto args(const PropertyTree &prm)
Definition: PreconditionerFactory_impl.hpp:74
Definition: PreconditionerFactory_impl.hpp:57
static auto args(const PropertyTree &prm)
Definition: PreconditionerFactory_impl.hpp:58
static void add()
Definition: PreconditionerFactory_impl.hpp:422
Definition: PreconditionerFactory_impl.hpp:150
static std::size_t interiorIfGhostLast(const Comm &comm)
Definition: PreconditionerFactory_impl.hpp:401
static PreconditionerFactory< Operator, Comm >::PrecPtr createParILU(const Operator &op, const PropertyTree &prm, const Comm &comm, const int ilulevel)
Definition: PreconditionerFactory_impl.hpp:377
static void add()
Definition: PreconditionerFactory_impl.hpp:151