My Project
PreconditionerFactory_impl.hpp
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 <opm/simulators/linalg/PreconditionerFactory.hpp>
22
23#include <opm/common/ErrorMacros.hpp>
24
25#include <opm/simulators/linalg/matrixblock.hh>
27#include <opm/simulators/linalg/FlexibleSolver.hpp>
28#include <opm/simulators/linalg/ilufirstelement.hh>
29#include <opm/simulators/linalg/OwningBlockPreconditioner.hpp>
30#include <opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp>
31#include <opm/simulators/linalg/ParallelOverlappingILU0.hpp>
32#include <opm/simulators/linalg/PressureBhpTransferPolicy.hpp>
33#include <opm/simulators/linalg/PressureTransferPolicy.hpp>
34#include <opm/simulators/linalg/PropertyTree.hpp>
35#include <opm/simulators/linalg/WellOperators.hpp>
36
37#include <dune/istl/owneroverlapcopy.hh>
38#include <dune/istl/preconditioners.hh>
39#include <dune/istl/paamg/amg.hh>
40#include <dune/istl/paamg/kamg.hh>
41#include <dune/istl/paamg/fastamg.hh>
42
43namespace Opm {
44
45template<class Smoother>
47{
48 static auto args(const PropertyTree& prm)
49 {
50 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
51 SmootherArgs smootherArgs;
52 smootherArgs.iterations = prm.get<int>("iterations", 1);
53 // smootherArgs.overlap=SmootherArgs::vertex;
54 // smootherArgs.overlap=SmootherArgs::none;
55 // smootherArgs.overlap=SmootherArgs::aggregate;
56 smootherArgs.relaxationFactor = prm.get<double>("relaxation", 1.0);
57 return smootherArgs;
58 }
59};
60
61template<class M, class V, class C>
63{
64 static auto args(const PropertyTree& prm)
65 {
67 using SmootherArgs = typename Dune::Amg::SmootherTraits<Smoother>::Arguments;
68 SmootherArgs smootherArgs;
69 smootherArgs.iterations = prm.get<int>("iterations", 1);
70 const int iluwitdh = prm.get<int>("iluwidth", 0);
71 smootherArgs.setN(iluwitdh);
72 const MILU_VARIANT milu = convertString2Milu(prm.get<std::string>("milutype", std::string("ilu")));
73 smootherArgs.setMilu(milu);
74 // smootherArgs.overlap=SmootherArgs::vertex;
75 // smootherArgs.overlap=SmootherArgs::none;
76 // smootherArgs.overlap=SmootherArgs::aggregate;
77 smootherArgs.relaxationFactor = prm.get<double>("relaxation", 1.0);
78 return smootherArgs;
79 }
80};
81
82template <class Operator, class Comm, class Matrix, class Vector>
83typename AMGHelper<Operator, Comm, Matrix, Vector>::Criterion
85{
86 Criterion criterion(15, prm.get<int>("coarsenTarget", 1200));
87 criterion.setDefaultValuesIsotropic(2);
88 criterion.setAlpha(prm.get<double>("alpha", 0.33));
89 criterion.setBeta(prm.get<double>("beta", 1e-5));
90 criterion.setMaxLevel(prm.get<int>("maxlevel", 15));
91 criterion.setSkipIsolated(prm.get<bool>("skip_isolated", false));
92 criterion.setNoPreSmoothSteps(prm.get<int>("pre_smooth", 1));
93 criterion.setNoPostSmoothSteps(prm.get<int>("post_smooth", 1));
94 criterion.setDebugLevel(prm.get<int>("verbosity", 0));
95 // As the default we request to accumulate data to 1 process always as our matrix
96 // graph might be unsymmetric and hence not supported by the PTScotch/ParMetis
97 // calls in DUNE. Accumulating to 1 skips PTScotch/ParMetis
98 criterion.setAccumulate(static_cast<Dune::Amg::AccumulationMode>(prm.get<int>("accumulate", 1)));
99 criterion.setProlongationDampingFactor(prm.get<double>("prolongationdamping", 1.6));
100 criterion.setMaxDistance(prm.get<int>("maxdistance", 2));
101 criterion.setMaxConnectivity(prm.get<int>("maxconnectivity", 15));
102 criterion.setMaxAggregateSize(prm.get<int>("maxaggsize", 6));
103 criterion.setMinAggregateSize(prm.get<int>("minaggsize", 4));
104 return criterion;
105}
106
107template <class Operator, class Comm, class Matrix, class Vector>
108template <class Smoother>
109typename AMGHelper<Operator, Comm, Matrix, Vector>::PrecPtr
110AMGHelper<Operator,Comm,Matrix,Vector>::
111makeAmgPreconditioner(const Operator& op,
112 const PropertyTree& prm,
113 bool useKamg)
114{
115 auto crit = criterion(prm);
116 auto sargs = AMGSmootherArgsHelper<Smoother>::args(prm);
117 if (useKamg) {
119 return std::make_shared<Type>(op, crit, sargs,
120 prm.get<size_t>("max_krylov", 1),
121 prm.get<double>("min_reduction", 1e-1));
122 } else {
124 return std::make_shared<Type>(op, crit, sargs);
125 }
126}
127
128template<class Operator, class Comm>
130{
131 static void add()
132 {
133 using namespace Dune;
134 using O = Operator;
135 using C = Comm;
137 using M = typename F::Matrix;
138 using V = typename F::Vector;
139 using P = PropertyTree;
140 F::addCreator("ILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
141 return createParILU(op, prm, comm, 0);
142 });
143 F::addCreator("ParOverILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
144 return createParILU(op, prm, comm, prm.get<int>("ilulevel", 0));
145 });
146 F::addCreator("ILUn", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
147 return createParILU(op, prm, comm, prm.get<int>("ilulevel", 0));
148 });
149 F::addCreator("Jac", [](const O& op, const P& prm, const std::function<V()>&,
150 std::size_t, const C& comm) {
151 const int n = prm.get<int>("repeats", 1);
152 const double w = prm.get<double>("relaxation", 1.0);
153 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqJac<M, V, V>>>(comm, op.getmat(), n, w);
154 });
155 F::addCreator("GS", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
156 const int n = prm.get<int>("repeats", 1);
157 const double w = prm.get<double>("relaxation", 1.0);
158 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqGS<M, V, V>>>(comm, op.getmat(), n, w);
159 });
160 F::addCreator("SOR", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
161 const int n = prm.get<int>("repeats", 1);
162 const double w = prm.get<double>("relaxation", 1.0);
163 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqSOR<M, V, V>>>(comm, op.getmat(), n, w);
164 });
165 F::addCreator("SSOR", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
166 const int n = prm.get<int>("repeats", 1);
167 const double w = prm.get<double>("relaxation", 1.0);
168 return wrapBlockPreconditioner<DummyUpdatePreconditioner<SeqSSOR<M, V, V>>>(comm, op.getmat(), n, w);
169 });
170
171 // Only add AMG preconditioners to the factory if the operator
172 // is the overlapping schwarz operator. This could be extended
173 // later, but at this point no other operators are compatible
174 // with the AMG hierarchy construction.
175 if constexpr (std::is_same_v<O, Dune::OverlappingSchwarzOperator<M, V, V, C>>) {
176 F::addCreator("amg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
177 const std::string smoother = prm.get<std::string>("smoother", "ParOverILU0");
178 if (smoother == "ILU0" || smoother == "ParOverILU0") {
180 auto crit = AMGHelper<O,C,M,V>::criterion(prm);
182 return std::make_shared<Dune::Amg::AMGCPR<O, V, Smoother, C>>(op, crit, sargs, comm);
183 } else {
184 OPM_THROW(std::invalid_argument, "Properties: No smoother with name " << smoother << ".");
185 }
186 });
187 }
188
189 F::addCreator("cpr", [](const O& op, const P& prm, const std::function<V()> weightsCalculator, std::size_t pressureIndex, const C& comm) {
190 assert(weightsCalculator);
191 if (pressureIndex == std::numeric_limits<std::size_t>::max())
192 {
193 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
194 }
195 using LevelTransferPolicy = Opm::PressureTransferPolicy<O, Comm, false>;
196 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
197 });
198 F::addCreator("cprt", [](const O& op, const P& prm, const std::function<V()> weightsCalculator, std::size_t pressureIndex, const C& comm) {
199 assert(weightsCalculator);
200 if (pressureIndex == std::numeric_limits<std::size_t>::max())
201 {
202 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
203 }
204 using LevelTransferPolicy = Opm::PressureTransferPolicy<O, Comm, true>;
205 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
206 });
207
208 if constexpr (std::is_same_v<O, WellModelGhostLastMatrixAdapter<M, V, V, true>>) {
209 F::addCreator("cprw",
210 [](const O& op, const P& prm, const std::function<V()> weightsCalculator, std::size_t pressureIndex, const C& comm) {
211 assert(weightsCalculator);
212 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
213 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
214 }
215 using LevelTransferPolicy = Opm::PressureBhpTransferPolicy<O, Comm, false>;
216 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
217 });
218 }
219 }
220
221
223 createParILU(const Operator& op, const PropertyTree& prm, const Comm& comm, const int ilulevel)
224 {
226 using M = typename F::Matrix;
227 using V = typename F::Vector;
228
229 const double w = prm.get<double>("relaxation", 1.0);
230 const bool redblack = prm.get<bool>("redblack", false);
231 const bool reorder_spheres = prm.get<bool>("reorder_spheres", false);
232 // Already a parallel preconditioner. Need to pass comm, but no need to wrap it in a BlockPreconditioner.
233 if (ilulevel == 0) {
234 const size_t num_interior = interiorIfGhostLast(comm);
235 return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V, Comm>>(
236 op.getmat(), comm, w, Opm::MILU_VARIANT::ILU, num_interior, redblack, reorder_spheres);
237 } else {
238 return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V, Comm>>(
239 op.getmat(), comm, ilulevel, w, Opm::MILU_VARIANT::ILU, redblack, reorder_spheres);
240 }
241 }
242
247 static size_t interiorIfGhostLast(const Comm& comm)
248 {
249 size_t interior_count = 0;
250 size_t highest_interior_index = 0;
251 const auto& is = comm.indexSet();
252 for (const auto& ind : is) {
253 if (Comm::OwnerSet::contains(ind.local().attribute())) {
254 ++interior_count;
255 highest_interior_index = std::max(highest_interior_index, ind.local().local());
256 }
257 }
258 if (highest_interior_index + 1 == interior_count) {
259 return interior_count;
260 } else {
261 return is.size();
262 }
263 }
264
265};
266
267template<class Operator>
268struct StandardPreconditioners<Operator,Dune::Amg::SequentialInformation>
269{
270 static void add()
271 {
272 using namespace Dune;
273 using O = Operator;
274 using C = Dune::Amg::SequentialInformation;
276 using M = typename F::Matrix;
277 using V = typename F::Vector;
278 using P = PropertyTree;
279 F::addCreator("ILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
280 const double w = prm.get<double>("relaxation", 1.0);
281 return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V, C>>(
282 op.getmat(), 0, w, Opm::MILU_VARIANT::ILU);
283 });
284 F::addCreator("ParOverILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
285 const double w = prm.get<double>("relaxation", 1.0);
286 const int n = prm.get<int>("ilulevel", 0);
287 return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V, C>>(
288 op.getmat(), n, w, Opm::MILU_VARIANT::ILU);
289 });
290 F::addCreator("ILUn", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
291 const int n = prm.get<int>("ilulevel", 0);
292 const double w = prm.get<double>("relaxation", 1.0);
293 return std::make_shared<Opm::ParallelOverlappingILU0<M, V, V, C>>(
294 op.getmat(), n, w, Opm::MILU_VARIANT::ILU);
295 });
296 F::addCreator("Jac", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
297 const int n = prm.get<int>("repeats", 1);
298 const double w = prm.get<double>("relaxation", 1.0);
299 return wrapPreconditioner<SeqJac<M, V, V>>(op.getmat(), n, w);
300 });
301 F::addCreator("GS", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
302 const int n = prm.get<int>("repeats", 1);
303 const double w = prm.get<double>("relaxation", 1.0);
304 return wrapPreconditioner<SeqGS<M, V, V>>(op.getmat(), n, w);
305 });
306 F::addCreator("SOR", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
307 const int n = prm.get<int>("repeats", 1);
308 const double w = prm.get<double>("relaxation", 1.0);
309 return wrapPreconditioner<SeqSOR<M, V, V>>(op.getmat(), n, w);
310 });
311 F::addCreator("SSOR", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
312 const int n = prm.get<int>("repeats", 1);
313 const double w = prm.get<double>("relaxation", 1.0);
314 return wrapPreconditioner<SeqSSOR<M, V, V>>(op.getmat(), n, w);
315 });
316
317 // Only add AMG preconditioners to the factory if the operator
318 // is an actual matrix operator.
319 if constexpr (std::is_same_v<O, Dune::MatrixAdapter<M, V, V>>) {
320 F::addCreator("amg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
321 const std::string smoother = prm.get<std::string>("smoother", "ParOverILU0");
322 if (smoother == "ILU0" || smoother == "ParOverILU0") {
323 #if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
324 using Smoother = SeqILU<M, V, V>;
325 #else
326 using Smoother = SeqILU0<M, V, V>;
327 #endif
328 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm);
329 } else if (smoother == "Jac") {
330 using Smoother = SeqJac<M, V, V>;
331 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm);
332 } else if (smoother == "SOR") {
333 using Smoother = SeqSOR<M, V, V>;
334 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm);
335 } else if (smoother == "SSOR") {
336 using Smoother = SeqSSOR<M, V, V>;
337 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm);
338 } else if (smoother == "ILUn") {
339 #if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
340 using Smoother = SeqILU<M, V, V>;
341 #else
342 using Smoother = SeqILUn<M, V, V>;
343 #endif
344 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm);
345 } else {
346 OPM_THROW(std::invalid_argument, "Properties: No smoother with name " << smoother << ".");
347 }
348 });
349 F::addCreator("kamg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
350 const std::string smoother = prm.get<std::string>("smoother", "ParOverILU0");
351 if (smoother == "ILU0" || smoother == "ParOverILU0") {
352 #if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
353 using Smoother = SeqILU<M, V, V>;
354 #else
355 using Smoother = SeqILU0<M, V, V>;
356 #endif
357 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
358 } else if (smoother == "Jac") {
359 using Smoother = SeqJac<M, V, V>;
360 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
361 } else if (smoother == "SOR") {
362 using Smoother = SeqSOR<M, V, V>;
363 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
364 // } else if (smoother == "GS") {
365 // using Smoother = SeqGS<M, V, V>;
366 // return makeAmgPreconditioner<Smoother>(op, prm, true);
367 } else if (smoother == "SSOR") {
368 using Smoother = SeqSSOR<M, V, V>;
369 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
370 } else if (smoother == "ILUn") {
371 #if DUNE_VERSION_NEWER(DUNE_ISTL, 2, 7)
372 using Smoother = SeqILU<M, V, V>;
373 #else
374 using Smoother = SeqILUn<M, V, V>;
375 #endif
376 return AMGHelper<O,C,M,V>::template makeAmgPreconditioner<Smoother>(op, prm, true);
377 } else {
378 OPM_THROW(std::invalid_argument, "Properties: No smoother with name " << smoother << ".");
379 }
380 });
381 F::addCreator("famg", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
382 auto crit = AMGHelper<O,C,M,V>::criterion(prm);
383 Dune::Amg::Parameters parms;
384 parms.setNoPreSmoothSteps(1);
385 parms.setNoPostSmoothSteps(1);
386 return wrapPreconditioner<Dune::Amg::FastAMG<O, V>>(op, crit, parms);
387 });
388 }
389 if constexpr (std::is_same_v<O, WellModelMatrixAdapter<M, V, V, false>>) {
390 F::addCreator("cprw", [](const O& op, const P& prm, const std::function<V()>& weightsCalculator, std::size_t pressureIndex) {
391 if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
392 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
393 }
395 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(op, prm, weightsCalculator, pressureIndex);
396 });
397 }
398
399 F::addCreator("cpr", [](const O& op, const P& prm, const std::function<V()>& weightsCalculator, std::size_t pressureIndex) {
400 if (pressureIndex == std::numeric_limits<std::size_t>::max())
401 {
402 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
403 }
405 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(op, prm, weightsCalculator, pressureIndex);
406 });
407 F::addCreator("cprt", [](const O& op, const P& prm, const std::function<V()>& weightsCalculator, std::size_t pressureIndex) {
408 if (pressureIndex == std::numeric_limits<std::size_t>::max())
409 {
410 OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
411 }
413 return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(op, prm, weightsCalculator, pressureIndex);
414 });
415 }
416};
417
418template <class Operator, class Comm>
420{
421}
422
423
424template <class Operator, class Comm>
425PreconditionerFactory<Operator,Comm>&
426PreconditionerFactory<Operator,Comm>::instance()
427{
428 static PreconditionerFactory singleton;
429 return singleton;
430}
431
432template <class Operator, class Comm>
434PreconditionerFactory<Operator,Comm>::
435doCreate(const Operator& op, const PropertyTree& prm,
436 const std::function<Vector()> weightsCalculator,
437 std::size_t pressureIndex)
438{
439 if (!defAdded_) {
440 StandardPreconditioners<Operator,Comm>::add();
441 defAdded_ = true;
442 }
443 const std::string& type = prm.get<std::string>("type", "ParOverILU0");
444 auto it = creators_.find(type);
445 if (it == creators_.end()) {
446 std::ostringstream msg;
447 msg << "Preconditioner type " << type << " is not registered in the factory. Available types are: ";
448 for (const auto& prec : creators_) {
449 msg << prec.first << ' ';
450 }
451 msg << std::endl;
452 OPM_THROW(std::invalid_argument, msg.str());
453 }
454 return it->second(op, prm, weightsCalculator, pressureIndex);
455}
456
457template <class Operator, class Comm>
459PreconditionerFactory<Operator,Comm>::
460doCreate(const Operator& op, const PropertyTree& prm,
461 const std::function<Vector()> weightsCalculator,
462 std::size_t pressureIndex, const Comm& comm)
463{
464 if (!defAdded_) {
465 StandardPreconditioners<Operator,Comm>::add();
466 defAdded_ = true;
467 }
468 const std::string& type = prm.get<std::string>("type", "ParOverILU0");
469 auto it = parallel_creators_.find(type);
470 if (it == parallel_creators_.end()) {
471 std::ostringstream msg;
472 msg << "Parallel preconditioner type " << type
473 << " is not registered in the factory. Available types are: ";
474 for (const auto& prec : parallel_creators_) {
475 msg << prec.first << ' ';
476 }
477 msg << std::endl;
478 OPM_THROW(std::invalid_argument, msg.str());
479 }
480 return it->second(op, prm, weightsCalculator, pressureIndex, comm);
481}
482
483template <class Operator, class Comm>
484void PreconditionerFactory<Operator,Comm>::
485doAddCreator(const std::string& type, Creator c)
486{
487 creators_[type] = c;
488}
489
490template <class Operator, class Comm>
491void PreconditionerFactory<Operator,Comm>::
492doAddCreator(const std::string& type, ParCreator c)
493{
494 parallel_creators_[type] = c;
495}
496
497template <class Operator, class Comm>
500create(const Operator& op, const PropertyTree& prm,
501 const std::function<Vector()>& weightsCalculator,
502 std::size_t pressureIndex)
503{
504 return instance().doCreate(op, prm, weightsCalculator, pressureIndex);
505}
506
507template <class Operator, class Comm>
510create(const Operator& op, const PropertyTree& prm,
511 const std::function<Vector()>& weightsCalculator, const Comm& comm,
512 std::size_t pressureIndex)
513{
514 return instance().doCreate(op, prm, weightsCalculator, pressureIndex, comm);
515}
516
517
518template <class Operator, class Comm>
521create(const Operator& op, const PropertyTree& prm, const Comm& comm,
522 std::size_t pressureIndex)
523{
524 return instance().doCreate(op, prm, std::function<Vector()>(), pressureIndex, comm);
525}
526
527template <class Operator, class Comm>
529addCreator(const std::string& type, Creator creator)
530{
531 instance().doAddCreator(type, creator);
532}
533
534template <class Operator, class Comm>
536addCreator(const std::string& type, ParCreator creator)
537{
538 instance().doAddCreator(type, creator);
539}
540
541using CommSeq = Dune::Amg::SequentialInformation;
542
543template<int Dim>
544using OpFSeq = Dune::MatrixAdapter<Dune::BCRSMatrix<Dune::FieldMatrix<double,Dim,Dim>>,
545 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
546 Dune::BlockVector<Dune::FieldVector<double,Dim>>>;
547template<int Dim>
548using OpBSeq = Dune::MatrixAdapter<Dune::BCRSMatrix<Opm::MatrixBlock<double,Dim,Dim>>,
549 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
550 Dune::BlockVector<Dune::FieldVector<double,Dim>>>;
551
552template<int Dim, bool overlap>
554 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
555 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
556 overlap>;
557
558template<int Dim, bool overlap>
560 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
561 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
562 overlap>;
563
564#if HAVE_MPI
565using CommPar = Dune::OwnerOverlapCopyCommunication<int,int>;
566
567template<int Dim>
568using OpFPar = Dune::OverlappingSchwarzOperator<Dune::BCRSMatrix<Dune::FieldMatrix<double,Dim,Dim>>,
569 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
570 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
571 CommPar>;
572
573template<int Dim>
574using OpBPar = Dune::OverlappingSchwarzOperator<Dune::BCRSMatrix<MatrixBlock<double,Dim,Dim>>,
575 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
576 Dune::BlockVector<Dune::FieldVector<double,Dim>>,
577 CommPar>;
578
579#define INSTANCE_PF_PAR(Dim) \
580 template class PreconditionerFactory<OpBSeq<Dim>,CommPar>; \
581 template class PreconditionerFactory<OpFPar<Dim>,CommPar>; \
582 template class PreconditionerFactory<OpBPar<Dim>,CommPar>; \
583 template class PreconditionerFactory<OpW<Dim,false>,CommPar>; \
584 template class PreconditionerFactory<OpWG<Dim,true>,CommPar>; \
585 template class PreconditionerFactory<OpBPar<Dim>,CommSeq>;
586#endif
587
588#define INSTANCE_PF_SEQ(Dim) \
589 template class PreconditionerFactory<OpFSeq<Dim>,CommSeq>; \
590 template class PreconditionerFactory<OpBSeq<Dim>,CommSeq>; \
591 template class PreconditionerFactory<OpW<Dim,false>,CommSeq>; \
592 template class PreconditionerFactory<OpWG<Dim,true>,CommSeq>;
593
594#if HAVE_MPI
595#define INSTANCE_PF(Dim) \
596 INSTANCE_PF_PAR(Dim) \
597 INSTANCE_PF_SEQ(Dim)
598#else
599#define INSTANCE_PF(Dim) \
600 INSTANCE_PF_SEQ(Dim)
601#endif
602}
The AMG preconditioner.
Parallel algebraic multigrid based on agglomeration.
Definition: amgcpr.hh:87
Definition: PreconditionerWithUpdate.hpp:40
A two-step version of an overlapping Schwarz preconditioner using one step ILU0 as.
Definition: ParallelOverlappingILU0.hpp:145
This is an object factory for creating preconditioners.
Definition: PreconditionerFactory.hpp:69
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:500
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:80
static void addCreator(const std::string &type, Creator creator)
Add a creator for a serial preconditioner to the PreconditionerFactory.
Definition: PreconditionerFactory_impl.hpp:529
std::shared_ptr< Dune::PreconditionerWithUpdate< Vector, Vector > > PrecPtr
The type of pointer returned by create().
Definition: PreconditionerFactory.hpp:76
Definition: PressureBhpTransferPolicy.hpp:86
Definition: PressureTransferPolicy.hpp:52
Definition: PropertyTree.hpp:37
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:209
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:123
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: BlackoilPhases.hpp:27
MILU_VARIANT
Definition: MILU.hpp:34
@ ILU
Do not perform modified ILU.
Definition: PreconditionerFactory.hpp:48
Definition: PreconditionerFactory_impl.hpp:47
Definition: PreconditionerFactory_impl.hpp:130
static size_t interiorIfGhostLast(const Comm &comm)
Helper method to determine if the local partitioning has the K interior cells from [0,...
Definition: PreconditionerFactory_impl.hpp:247