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 
43 namespace Opm {
44 
45 template<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 
61 template<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 
82 template <class Operator, class Comm, class Matrix, class Vector>
83 typename 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 
107 template <class Operator, class Comm, class Matrix, class Vector>
108 template <class Smoother>
109 typename AMGHelper<Operator, Comm, Matrix, Vector>::PrecPtr
110 AMGHelper<Operator,Comm,Matrix,Vector>::
111 makeAmgPreconditioner(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 
128 template<class Operator, class Comm>
130 {
131  static void add()
132  {
133  using namespace Dune;
134  using O = Operator;
135  using C = Comm;
136  using F = PreconditionerFactory<O,C>;
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);
181  auto sargs = AMGSmootherArgsHelper<Smoother>::args(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 
267 template<class Operator>
268 struct 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;
275  using F = PreconditionerFactory<O,C>;
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 
418 template <class Operator, class Comm>
420 {
421 }
422 
423 
424 template <class Operator, class Comm>
425 PreconditionerFactory<Operator,Comm>&
426 PreconditionerFactory<Operator,Comm>::instance()
427 {
428  static PreconditionerFactory singleton;
429  return singleton;
430 }
431 
432 template <class Operator, class Comm>
434 PreconditionerFactory<Operator,Comm>::
435 doCreate(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 
457 template <class Operator, class Comm>
459 PreconditionerFactory<Operator,Comm>::
460 doCreate(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 
483 template <class Operator, class Comm>
484 void PreconditionerFactory<Operator,Comm>::
485 doAddCreator(const std::string& type, Creator c)
486 {
487  creators_[type] = c;
488 }
489 
490 template <class Operator, class Comm>
491 void PreconditionerFactory<Operator,Comm>::
492 doAddCreator(const std::string& type, ParCreator c)
493 {
494  parallel_creators_[type] = c;
495 }
496 
497 template <class Operator, class Comm>
500 create(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 
507 template <class Operator, class Comm>
510 create(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 
518 template <class Operator, class Comm>
521 create(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 
527 template <class Operator, class Comm>
529 addCreator(const std::string& type, Creator creator)
530 {
531  instance().doAddCreator(type, creator);
532 }
533 
534 template <class Operator, class Comm>
536 addCreator(const std::string& type, ParCreator creator)
537 {
538  instance().doAddCreator(type, creator);
539 }
540 
541 using CommSeq = Dune::Amg::SequentialInformation;
542 
543 template<int Dim>
544 using OpFSeq = Dune::MatrixAdapter<Dune::BCRSMatrix<Dune::FieldMatrix<double,Dim,Dim>>,
545  Dune::BlockVector<Dune::FieldVector<double,Dim>>,
546  Dune::BlockVector<Dune::FieldVector<double,Dim>>>;
547 template<int Dim>
548 using 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 
552 template<int Dim, bool overlap>
554  Dune::BlockVector<Dune::FieldVector<double,Dim>>,
555  Dune::BlockVector<Dune::FieldVector<double,Dim>>,
556  overlap>;
557 
558 template<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
565 using CommPar = Dune::OwnerOverlapCopyCommunication<int,int>;
566 
567 template<int Dim>
568 using 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 
573 template<int Dim>
574 using 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