parallelamgbackend.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18
19 Consult the COPYING file in the top-level source directory of this
20 module for the precise wording of the license and the list of
21 copyright holders.
22*/
27#ifndef EWOMS_PARALLEL_AMG_BACKEND_HH
28#define EWOMS_PARALLEL_AMG_BACKEND_HH
29
30#include "linalgproperties.hh"
32#include "bicgstabsolver.hh"
33#include "combinedcriterion.hh"
35
36#include <dune/istl/bcrsmatrix.hh>
37#include <dune/istl/paamg/amg.hh>
38#include <dune/istl/paamg/pinfo.hh>
39#include <dune/istl/owneroverlapcopy.hh>
40
41#include <memory>
42#include <tuple>
43#include <utility>
44
45namespace Opm::Linear {
46template <class TypeTag>
47class ParallelAmgBackend;
48} // namespace Opm::Linear
49
50namespace Opm::Properties {
51
52// Create new type tags
53namespace TTag {
54struct ParallelAmgLinearSolver { using InheritsFrom = std::tuple<ParallelBaseLinearSolver>; };
55} // end namespace TTag
56
59template<class TypeTag>
60struct AmgCoarsenTarget<TypeTag, TTag::ParallelAmgLinearSolver> { static constexpr int value = 5000; };
61
62template<class TypeTag>
63struct LinearSolverMaxError<TypeTag, TTag::ParallelAmgLinearSolver>
64{
66 static constexpr type value = 1e7;
67};
68
69template<class TypeTag>
70struct LinearSolverBackend<TypeTag, TTag::ParallelAmgLinearSolver>
72
73} // namespace Opm::Properties
74
75namespace Opm {
76namespace Linear {
83template <class TypeTag>
85{
87
94
95 using ParallelOperator = typename ParentType::ParallelOperator;
96 using OverlappingVector = typename ParentType::OverlappingVector;
97 using ParallelPreconditioner = typename ParentType::ParallelPreconditioner;
98 using ParallelScalarProduct = typename ParentType::ParallelScalarProduct;
99
100 static constexpr int numEq = getPropValue<TypeTag, Properties::NumEq>();
101 using VectorBlock = Dune::FieldVector<LinearSolverScalar, numEq>;
102 using MatrixBlock = typename SparseMatrixAdapter::MatrixBlock;
103 using IstlMatrix = typename SparseMatrixAdapter::IstlMatrix;
104
105 using Vector = Dune::BlockVector<VectorBlock>;
106
107 // define the smoother used for the AMG and specify its
108 // arguments
109 using SequentialSmoother = Dune::SeqSOR<IstlMatrix, Vector, Vector>;
110// using SequentialSmoother = Dune::SeqSSOR<IstlMatrix,Vector,Vector>;
111// using SequentialSmoother = Dune::SeqJac<IstlMatrix,Vector,Vector>;
112// using SequentialSmoother = Dune::SeqILU<IstlMatrix,Vector,Vector>;
113
114#if HAVE_MPI
115 using OwnerOverlapCopyCommunication = Dune::OwnerOverlapCopyCommunication<Opm::Linear::Index>;
116 using FineOperator = Dune::OverlappingSchwarzOperator<IstlMatrix,
117 Vector,
118 Vector,
119 OwnerOverlapCopyCommunication>;
120 using FineScalarProduct = Dune::OverlappingSchwarzScalarProduct<Vector,
121 OwnerOverlapCopyCommunication>;
122 using ParallelSmoother = Dune::BlockPreconditioner<Vector,
123 Vector,
124 OwnerOverlapCopyCommunication,
125 SequentialSmoother>;
126 using AMG = Dune::Amg::AMG<FineOperator,
127 Vector,
128 ParallelSmoother,
129 OwnerOverlapCopyCommunication>;
130#else
131 using FineOperator = Dune::MatrixAdapter<IstlMatrix, Vector, Vector>;
132 using FineScalarProduct = Dune::SeqScalarProduct<Vector>;
133 using ParallelSmoother = SequentialSmoother;
134 using AMG = Dune::Amg::AMG<FineOperator, Vector, ParallelSmoother>;
135#endif
136
137 using RawLinearSolver = BiCGStabSolver<ParallelOperator,
138 OverlappingVector,
139 AMG> ;
140
141 static_assert(std::is_same<SparseMatrixAdapter, IstlSparseMatrixAdapter<MatrixBlock> >::value,
142 "The ParallelAmgBackend linear solver backend requires the IstlSparseMatrixAdapter");
143
144public:
145 ParallelAmgBackend(const Simulator& simulator)
146 : ParentType(simulator)
147 { }
148
149 static void registerParameters()
150 {
152
153 Parameters::registerParam<TypeTag, Properties::LinearSolverMaxError>
154 ("The maximum residual error which the linear solver tolerates "
155 "without giving up");
156 Parameters::registerParam<TypeTag, Properties::AmgCoarsenTarget>
157 ("The coarsening target for the agglomerations of "
158 "the AMG preconditioner");
159 }
160
161protected:
163
164 std::shared_ptr<AMG> preparePreconditioner_()
165 {
166#if HAVE_MPI
167 // create and initialize DUNE's OwnerOverlapCopyCommunication
168 // using the domestic overlap
169 istlComm_ = std::make_shared<OwnerOverlapCopyCommunication>(MPI_COMM_WORLD);
170 setupAmgIndexSet_(this->overlappingMatrix_->overlap(), istlComm_->indexSet());
171 istlComm_->remoteIndices().template rebuild<false>();
172#endif
173
174 // create the parallel scalar product and the parallel operator
175#if HAVE_MPI
176 fineOperator_ = std::make_shared<FineOperator>(*this->overlappingMatrix_, *istlComm_);
177#else
178 fineOperator_ = std::make_shared<FineOperator>(*this->overlappingMatrix_);
179#endif
180
181 setupAmg_();
182
183 return amg_;
184 }
185
187 { /* nothing to do */ }
188
189 std::shared_ptr<RawLinearSolver> prepareSolver_(ParallelOperator& parOperator,
190 ParallelScalarProduct& parScalarProduct,
191 AMG& parPreCond)
192 {
193 const auto& gridView = this->simulator_.gridView();
194 using CCC = CombinedCriterion<OverlappingVector, decltype(gridView.comm())>;
195
196 Scalar linearSolverTolerance = Parameters::get<TypeTag, Properties::LinearSolverTolerance>();
197 Scalar linearSolverAbsTolerance = Parameters::get<TypeTag, Properties::LinearSolverAbsTolerance>();
198 if(linearSolverAbsTolerance < 0.0)
199 linearSolverAbsTolerance = this->simulator_.model().newtonMethod().tolerance()/100.0;
200
201 convCrit_.reset(new CCC(gridView.comm(),
202 /*residualReductionTolerance=*/linearSolverTolerance,
203 /*absoluteResidualTolerance=*/linearSolverAbsTolerance,
204 Parameters::get<TypeTag, Properties::LinearSolverMaxError>()));
205
206 auto bicgstabSolver =
207 std::make_shared<RawLinearSolver>(parPreCond, *convCrit_, parScalarProduct);
208
209 int verbosity = 0;
210 if (parOperator.overlap().myRank() == 0)
211 verbosity = Parameters::get<TypeTag, Properties::LinearSolverVerbosity>();
212 bicgstabSolver->setVerbosity(verbosity);
213 bicgstabSolver->setMaxIterations(Parameters::get<TypeTag, Properties::LinearSolverMaxIterations>());
214 bicgstabSolver->setLinearOperator(&parOperator);
215 bicgstabSolver->setRhs(this->overlappingb_);
216
217 return bicgstabSolver;
218 }
219
220 std::pair<bool,int> runSolver_(std::shared_ptr<RawLinearSolver> solver)
221 {
222 bool converged = solver->apply(*this->overlappingx_);
223 return std::make_pair(converged, int(solver->report().iterations()));
224 }
225
227 { /* nothing to do */ }
228
229#if HAVE_MPI
230 template <class ParallelIndexSet>
231 void setupAmgIndexSet_(const Overlap& overlap, ParallelIndexSet& istlIndices)
232 {
233 using GridAttributes = Dune::OwnerOverlapCopyAttributeSet;
234 using GridAttributeSet = Dune::OwnerOverlapCopyAttributeSet::AttributeSet;
235
236 // create DUNE's ParallelIndexSet from a domestic overlap
237 istlIndices.beginResize();
238 for (Index curIdx = 0; static_cast<size_t>(curIdx) < overlap.numDomestic(); ++curIdx) {
239 GridAttributeSet gridFlag =
240 overlap.iAmMasterOf(curIdx)
241 ? GridAttributes::owner
242 : GridAttributes::copy;
243
244 // an index is used by other processes if it is in the
245 // domestic or in the foreign overlap.
246 bool isShared = overlap.isInOverlap(curIdx);
247
248 assert(curIdx == overlap.globalToDomestic(overlap.domesticToGlobal(curIdx)));
249 istlIndices.add(/*globalIdx=*/overlap.domesticToGlobal(curIdx),
250 Dune::ParallelLocalIndex<GridAttributeSet>(static_cast<size_t>(curIdx),
251 gridFlag,
252 isShared));
253 }
254 istlIndices.endResize();
255 }
256#endif
257
258 // trailing return type with decltype used for detecting existence of setUseFixedOrder member function by overloading the setUseFixedOrder function
259 template <typename C>
260 auto setUseFixedOrder(C criterion, bool booleanValue) -> decltype(criterion.setUseFixedOrder(booleanValue))
261 {
262 return criterion.setUseFixedOrder(booleanValue); // Set flag to ensure that the matrices in the AMG hierarchy are constructed with deterministic indices.
263 }
264 template <typename C>
265 void setUseFixedOrder(C, ...)
266 {
267 // do nothing, since the function setUseFixedOrder does not exist yet
268 }
269
271 {
272 if (amg_)
273 amg_.reset();
274
275 int verbosity = 0;
276 if (this->simulator_.vanguard().gridView().comm().rank() == 0)
277 verbosity = Parameters::get<TypeTag, Properties::LinearSolverVerbosity>();
278
279 using SmootherArgs = typename Dune::Amg::SmootherTraits<ParallelSmoother>::Arguments;
280
281 SmootherArgs smootherArgs;
282 smootherArgs.iterations = 1;
283 smootherArgs.relaxationFactor = 1.0;
284
285 // specify the coarsen criterion:
286 //
287 // using CoarsenCriterion =
288 // Dune::Amg::CoarsenCriterion<Dune::Amg::SymmetricCriterion<IstlMatrix,
289 // Dune::Amg::FirstDiagonal>>
290 using CoarsenCriterion = Dune::Amg::
291 CoarsenCriterion<Dune::Amg::SymmetricCriterion<IstlMatrix, Dune::Amg::FrobeniusNorm> >;
292 int coarsenTarget = Parameters::get<TypeTag, Properties::AmgCoarsenTarget>();
293 CoarsenCriterion coarsenCriterion(/*maxLevel=*/15, coarsenTarget);
294 coarsenCriterion.setDefaultValuesAnisotropic(GridView::dimension,
295 /*aggregateSizePerDim=*/3);
296 if (verbosity > 0)
297 coarsenCriterion.setDebugLevel(1);
298 else
299 coarsenCriterion.setDebugLevel(0); // make the AMG shut up
300
301 // reduce the minium coarsen rate (default is 1.2)
302 coarsenCriterion.setMinCoarsenRate(1.05);
303 // coarsenCriterion.setAccumulate(Dune::Amg::noAccu);
304 coarsenCriterion.setAccumulate(Dune::Amg::atOnceAccu);
305 coarsenCriterion.setSkipIsolated(false);
306 setUseFixedOrder(coarsenCriterion, true); // If possible, set flag to ensure that the matrices in the AMG hierarchy are constructed with deterministic indices.
307
308// instantiate the AMG preconditioner
309#if HAVE_MPI
310 amg_ = std::make_shared<AMG>(*fineOperator_, coarsenCriterion, smootherArgs, *istlComm_);
311#else
312 amg_ = std::make_shared<AMG>(*fineOperator_, coarsenCriterion, smootherArgs);
313#endif
314 }
315
316 std::unique_ptr<ConvergenceCriterion<OverlappingVector> > convCrit_;
317
318 std::shared_ptr<FineOperator> fineOperator_;
319 std::shared_ptr<AMG> amg_;
320
321#if HAVE_MPI
322 std::shared_ptr<OwnerOverlapCopyCommunication> istlComm_;
323#endif
324};
325
326} // namespace Linear
327} // namespace Opm
328
329#endif
Implements a preconditioned stabilized BiCG linear solver.
Definition: bicgstabsolver.hh:54
Convergence criterion which looks at the absolute value of the residual and fails if the linear solve...
Definition: combinedcriterion.hh:56
Provides a linear solver backend using the parallel algebraic multi-grid (AMG) linear solver from DUN...
Definition: parallelamgbackend.hh:85
std::shared_ptr< AMG > preparePreconditioner_()
Definition: parallelamgbackend.hh:164
std::shared_ptr< RawLinearSolver > prepareSolver_(ParallelOperator &parOperator, ParallelScalarProduct &parScalarProduct, AMG &parPreCond)
Definition: parallelamgbackend.hh:189
void cleanupSolver_()
Definition: parallelamgbackend.hh:226
std::pair< bool, int > runSolver_(std::shared_ptr< RawLinearSolver > solver)
Definition: parallelamgbackend.hh:220
auto setUseFixedOrder(C criterion, bool booleanValue) -> decltype(criterion.setUseFixedOrder(booleanValue))
Definition: parallelamgbackend.hh:260
std::unique_ptr< ConvergenceCriterion< OverlappingVector > > convCrit_
Definition: parallelamgbackend.hh:316
void setupAmgIndexSet_(const Overlap &overlap, ParallelIndexSet &istlIndices)
Definition: parallelamgbackend.hh:231
friend ParentType
Definition: parallelamgbackend.hh:162
std::shared_ptr< FineOperator > fineOperator_
Definition: parallelamgbackend.hh:318
static void registerParameters()
Definition: parallelamgbackend.hh:149
std::shared_ptr< AMG > amg_
Definition: parallelamgbackend.hh:319
void setUseFixedOrder(C,...)
Definition: parallelamgbackend.hh:265
void cleanupPreconditioner_()
Definition: parallelamgbackend.hh:186
ParallelAmgBackend(const Simulator &simulator)
Definition: parallelamgbackend.hh:145
void setupAmg_()
Definition: parallelamgbackend.hh:270
std::shared_ptr< OwnerOverlapCopyCommunication > istlComm_
Definition: parallelamgbackend.hh:322
Provides the common code which is required by most linear solvers.
Definition: parallelbasebackend.hh:109
GetPropType< TypeTag, Properties::OverlappingVector > OverlappingVector
Definition: parallelbasebackend.hh:122
Opm::Linear::OverlappingScalarProduct< OverlappingVector, Overlap > ParallelScalarProduct
Definition: parallelbasebackend.hh:129
OverlappingVector * overlappingx_
Definition: parallelbasebackend.hh:383
static void registerParameters()
Register all run-time parameters for the linear solver.
Definition: parallelbasebackend.hh:153
Opm::Linear::OverlappingOperator< OverlappingMatrix, OverlappingVector, OverlappingVector > ParallelOperator
Definition: parallelbasebackend.hh:132
OverlappingVector * overlappingb_
Definition: parallelbasebackend.hh:382
OverlappingMatrix * overlappingMatrix_
Definition: parallelbasebackend.hh:381
Opm::Linear::OverlappingPreconditioner< SequentialPreconditioner, Overlap > ParallelPreconditioner
Definition: parallelbasebackend.hh:128
const Simulator & simulator_
Definition: parallelbasebackend.hh:377
Declares the properties required by the black oil model.
Definition: bicgstabsolver.hh:42
int Index
The type of an index of a degree of freedom.
Definition: overlaptypes.hh:44
Definition: blackoilmodel.hh:72
Definition: blackoilboundaryratevector.hh:37
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:242
Definition: linalgproperties.hh:106
The type of the linear solver to be used.
Definition: linalgproperties.hh:38
GetPropType< TypeTag, Scalar > type
Definition: parallelamgbackend.hh:65
Definition: linalgproperties.hh:108
Definition: parallelamgbackend.hh:54
std::tuple< ParallelBaseLinearSolver > InheritsFrom
Definition: parallelamgbackend.hh:54