opm-simulators
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 <config.h>
22 
23 #include <opm/common/ErrorMacros.hpp>
24 #include <opm/common/TimingMacros.hpp>
25 
26 #include <opm/simulators/linalg/PreconditionerFactory.hpp>
27 
28 #include <opm/simulators/linalg/DILU.hpp>
29 #include <opm/simulators/linalg/ExtraSmoothers.hpp>
30 #include <opm/simulators/linalg/FlexibleSolver.hpp>
31 #include <opm/simulators/linalg/FlowLinearSolverParameters.hpp>
32 #include <opm/simulators/linalg/OwningBlockPreconditioner.hpp>
33 #include <opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp>
34 #include <opm/simulators/linalg/ParallelOverlappingILU0.hpp>
35 #include <opm/simulators/linalg/PressureBhpTransferPolicy.hpp>
36 #include <opm/simulators/linalg/PressureTransferPolicy.hpp>
37 #include <opm/simulators/linalg/PropertyTree.hpp>
38 #include <opm/simulators/linalg/WellOperators.hpp>
40 #include <opm/simulators/linalg/ilufirstelement.hh>
41 #include <opm/simulators/linalg/matrixblock.hh>
42 
43 #include <dune/common/unused.hh>
44 #include <dune/istl/owneroverlapcopy.hh>
45 #include <dune/istl/paamg/amg.hh>
46 #include <dune/istl/paamg/fastamg.hh>
47 #include <dune/istl/paamg/kamg.hh>
48 #include <dune/istl/preconditioners.hh>
49 
50 // Include all cuistl/GPU preconditioners inside of this headerfile
51 #include <opm/simulators/linalg/PreconditionerFactoryGPUIncludeWrapper.hpp>
52 
53 #if HAVE_HYPRE
54 #include <opm/simulators/linalg/HyprePreconditioner.hpp>
55 #endif
56 
57 #if HAVE_AMGX
58 #include <opm/simulators/linalg/AmgxPreconditioner.hpp>
59 #endif
60 
61 #include <cassert>
62 
63 #include <opm/simulators/linalg/StandardPreconditioners.hpp>
64 
65 namespace Opm {
66 
67 
68 
69 template <class Operator, class Comm>
70 PreconditionerFactory<Operator, Comm>::PreconditionerFactory()
71 {
72 }
73 
74 
75 template <class Operator, class Comm>
76 PreconditionerFactory<Operator, Comm>&
77 PreconditionerFactory<Operator, Comm>::instance()
78 {
79  static PreconditionerFactory singleton;
80  return singleton;
81 }
82 
83 template <class Operator, class Comm>
85 PreconditionerFactory<Operator, Comm>::doCreate(const Operator& op,
86  const PropertyTree& prm,
87  const std::function<Vector()> weightsCalculator,
88  std::size_t pressureIndex)
89 {
90  if (!defAdded_) {
91  StandardPreconditioners<Operator, Comm>::add();
92  defAdded_ = true;
93  }
94  std::string type = prm.get<std::string>("type", "paroverilu0");
95  // We use lower case as the internal canonical representation of solver names
96  std::ranges::transform(type, type.begin(), ::tolower);
97  auto it = creators_.find(type);
98  if (it == creators_.end()) {
99  std::ostringstream msg;
100  msg << "Preconditioner type " << type << " is not registered in the factory. Available types are: ";
101  for (const auto& prec : creators_) {
102  msg << prec.first << ' ';
103  }
104  msg << std::endl;
105  OPM_THROW(std::invalid_argument, msg.str());
106  }
107  return it->second(op, prm, weightsCalculator, pressureIndex);
108 }
109 
110 template <class Operator, class Comm>
112 PreconditionerFactory<Operator, Comm>::doCreate(const Operator& op,
113  const PropertyTree& prm,
114  const std::function<Vector()> weightsCalculator,
115  std::size_t pressureIndex,
116  const Comm& comm)
117 {
118  if (!defAdded_) {
119  StandardPreconditioners<Operator, Comm>::add();
120  defAdded_ = true;
121  }
122  std::string type = prm.get<std::string>("type", "paroverilu0");
123  // We use lower case as the internal canonical representation of solver names
124  std::ranges::transform(type, type.begin(), ::tolower);
125  auto it = parallel_creators_.find(type);
126  if (it == parallel_creators_.end()) {
127  std::ostringstream msg;
128  msg << "Parallel preconditioner type " << type << " is not registered in the factory. Available types are: ";
129  for (const auto& prec : parallel_creators_) {
130  msg << prec.first << ' ';
131  }
132  msg << std::endl;
133  OPM_THROW(std::invalid_argument, msg.str());
134  }
135  return it->second(op, prm, weightsCalculator, pressureIndex, comm);
136 }
137 
138 template <class Operator, class Comm>
139 void
140 PreconditionerFactory<Operator, Comm>::doAddCreator(const std::string& type, Creator c)
141 {
142  creators_[type] = c;
143 }
144 
145 template <class Operator, class Comm>
146 void
147 PreconditionerFactory<Operator, Comm>::doAddCreator(const std::string& type, ParCreator c)
148 {
149  parallel_creators_[type] = c;
150 }
151 
152 template <class Operator, class Comm>
155  const PropertyTree& prm,
156  const std::function<Vector()>& weightsCalculator,
157  std::size_t pressureIndex)
158 {
159  return instance().doCreate(op, prm, weightsCalculator, pressureIndex);
160 }
161 
162 template <class Operator, class Comm>
165  const PropertyTree& prm,
166  const std::function<Vector()>& weightsCalculator,
167  const Comm& comm,
168  std::size_t pressureIndex)
169 {
170  return instance().doCreate(op, prm, weightsCalculator, pressureIndex, comm);
171 }
172 
173 
174 template <class Operator, class Comm>
177  const PropertyTree& prm,
178  const Comm& comm,
179  std::size_t pressureIndex)
180 {
181  return instance().doCreate(op, prm, std::function<Vector()>(), pressureIndex, comm);
182 }
183 
184 template <class Operator, class Comm>
185 void
187 {
188  instance().doAddCreator(type, creator);
189 }
190 
191 template <class Operator, class Comm>
192 void
193 PreconditionerFactory<Operator, Comm>::addCreator(const std::string& type, ParCreator creator)
194 {
195  instance().doAddCreator(type, creator);
196 }
197 
198 using CommSeq = Dune::Amg::SequentialInformation;
199 
200 template<class Scalar, int Dim>
201 using OpFSeq = Dune::MatrixAdapter<Dune::BCRSMatrix<Dune::FieldMatrix<Scalar, Dim, Dim>>,
202  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
203  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>>;
204 template<class Scalar, int Dim>
205 using OpBSeq = Dune::MatrixAdapter<Dune::BCRSMatrix<MatrixBlock<Scalar, Dim, Dim>>,
206  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
207  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>>;
208 
209 template<class Scalar, int Dim, bool overlap>
211  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
212  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>>;
213 
214 template<class Scalar, int Dim, bool overlap>
216  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
217  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
218  overlap>;
219 
220 #if HAVE_MPI
221 using CommPar = Dune::OwnerOverlapCopyCommunication<int, int>;
222 
223 template<class Scalar, int Dim>
224 using OpFPar = Dune::OverlappingSchwarzOperator<Dune::BCRSMatrix<Dune::FieldMatrix<Scalar, Dim, Dim>>,
225  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
226  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
227  CommPar>;
228 
229 template<class Scalar, int Dim>
230 using OpBPar = Dune::OverlappingSchwarzOperator<Dune::BCRSMatrix<MatrixBlock<Scalar, Dim, Dim>>,
231  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
232  Dune::BlockVector<Dune::FieldVector<Scalar, Dim>>,
233  CommPar>;
234 template<class Scalar, int Dim>
236  Dune::BlockVector<Dune::FieldVector<Scalar,Dim>>,
237  Dune::BlockVector<Dune::FieldVector<Scalar,Dim>>,
238  CommPar>;
239 
240 template<class Scalar, int Dim>
242  Dune::BlockVector<Dune::FieldVector<Scalar,Dim>>,
243  Dune::BlockVector<Dune::FieldVector<Scalar,Dim>>,
244  CommPar>;
245 
246 #define INSTANTIATE_PF_PAR(T,Dim) \
247  template class PreconditionerFactory<OpBSeq<T,Dim>, CommPar>; \
248  template class PreconditionerFactory<OpFPar<T,Dim>, CommPar>; \
249  template class PreconditionerFactory<OpBPar<T,Dim>, CommPar>; \
250  template class PreconditionerFactory<OpGLFPar<T,Dim>, CommPar>; \
251  template class PreconditionerFactory<OpGLBPar<T,Dim>, CommPar>; \
252  template class PreconditionerFactory<OpW<T,Dim, false>, CommPar>; \
253  template class PreconditionerFactory<OpWG<T,Dim, true>, CommPar>; \
254  template class PreconditionerFactory<OpBPar<T,Dim>, CommSeq>; \
255  template class PreconditionerFactory<OpGLBPar<T,Dim>, CommSeq>;
256 #endif
257 
258 #define INSTANTIATE_PF_SEQ(T,Dim) \
259  template class PreconditionerFactory<OpFSeq<T,Dim>, CommSeq>; \
260  template class PreconditionerFactory<OpBSeq<T,Dim>, CommSeq>; \
261  template class PreconditionerFactory<OpW<T,Dim, false>, CommSeq>; \
262  template class PreconditionerFactory<OpWG<T,Dim, true>, CommSeq>;
263 
264 #if HAVE_MPI
265 #define INSTANTIATE_PF(T,Dim) \
266  INSTANTIATE_PF_PAR(T,Dim) \
267  INSTANTIATE_PF_SEQ(T,Dim)
268 #else
269 #define INSTANTIATE_PF(T,Dim) INSTANTIATE_PF_SEQ(T,Dim)
270 #endif
271 
272 } // namespace Opm
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:298
Adapter to combine a matrix and another linear operator into a combined linear operator.
Definition: WellOperators.hpp:224
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
The AMG preconditioner.
static void addCreator(const std::string &type, Creator creator)
Add a creator for a serial preconditioner to the PreconditionerFactory.
Definition: PreconditionerFactory_impl.hpp:186
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 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:154
Dune linear operator that assumes ghost rows are ordered after interior rows.
Definition: WellOperators.hpp:401
Hierarchical collection of key/value pairs.
Definition: PropertyTree.hpp:38
std::shared_ptr< Dune::PreconditionerWithUpdate< Vector, Vector > > PrecPtr
The type of pointer returned by create().
Definition: PreconditionerFactory.hpp:71