Skip to content

Commit f7668dc

Browse files
author
Robert Kloefkorn
committed
[feature][FemSolverBackend] Added FemSolverBackend to allow to testing
of PETSc solvers.
1 parent 1452b57 commit f7668dc

File tree

5 files changed

+797
-2
lines changed

5 files changed

+797
-2
lines changed

opm/models/discretization/common/fvbasediscretization.hh

+2
Original file line numberDiff line numberDiff line change
@@ -1787,6 +1787,8 @@ public:
17871787
}
17881788
return *adaptationManager_;
17891789
}
1790+
1791+
const DiscreteFunctionSpace& space() const { return space_; }
17901792
#endif
17911793

17921794
const Opm::Timer& prePostProcessTimer() const

opm/models/discretization/common/fvbaselinearizer.hh

-2
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,6 @@ class FvBaseLinearizer
9595

9696
typedef GlobalEqVector Vector;
9797

98-
typedef typename SparseMatrixAdapter::IstlMatrix IstlMatrix;
99-
10098
enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
10199
enum { historySize = GET_PROP_VALUE(TypeTag, TimeDiscHistorySize) };
102100

+333
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
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+
*/
23+
/*!
24+
* \file
25+
* \copydoc Ewoms::Linear::AmgXSolverBackend
26+
*/
27+
#ifndef EWOMS_AMGX_SOLVER_BACKEND_HH
28+
#define EWOMS_AMGX_SOLVER_BACKEND_HH
29+
30+
#include <ewoms/disc/common/fvbaseproperties.hh>
31+
32+
#if USE_AMGX_SOLVERS
33+
34+
#if !HAVE_PETSC || !HAVE_AMGXSOLVER
35+
#error "PETSc and AmgXSolver is needed for the AMGX solver backend"
36+
#endif
37+
38+
#define DISABLE_AMG_DIRECTSOLVER 1
39+
#include <dune/fem/function/petscdiscretefunction.hh>
40+
#include <ewoms/common/genericguard.hh>
41+
#include <ewoms/common/propertysystem.hh>
42+
#include <ewoms/common/parametersystem.hh>
43+
44+
#include <dune/grid/io/file/vtk/vtkwriter.hh>
45+
46+
#include <dune/common/fvector.hh>
47+
48+
49+
#include <ewoms/linear/parallelbicgstabbackend.hh>
50+
#include <ewoms/linear/istlsolverwrappers.hh>
51+
52+
#include <AmgXSolver.hpp>
53+
54+
#include <sstream>
55+
#include <memory>
56+
#include <iostream>
57+
58+
namespace Ewoms {
59+
namespace Linear {
60+
template <class TypeTag>
61+
class AmgXSolverBackend;
62+
}} // namespace Linear, Ewoms
63+
64+
65+
BEGIN_PROPERTIES
66+
67+
NEW_TYPE_TAG(AmgXSolverBackend);
68+
69+
SET_TYPE_PROP(AmgXSolverBackend,
70+
LinearSolverBackend,
71+
Ewoms::Linear::AmgXSolverBackend<TypeTag>);
72+
73+
NEW_PROP_TAG(LinearSolverTolerance);
74+
NEW_PROP_TAG(LinearSolverAbsTolerance);
75+
NEW_PROP_TAG(LinearSolverMaxIterations);
76+
NEW_PROP_TAG(LinearSolverVerbosity);
77+
NEW_PROP_TAG(LinearSolverMaxError);
78+
NEW_PROP_TAG(LinearSolverOverlapSize);
79+
//! The order of the sequential preconditioner
80+
NEW_PROP_TAG(PreconditionerOrder);
81+
82+
//! The relaxation factor of the preconditioner
83+
NEW_PROP_TAG(PreconditionerRelaxation);
84+
85+
//! Solver mode for AMGX solver
86+
NEW_PROP_TAG(AmgxSolverMode);
87+
88+
//! Filename for AMGX solver configuration
89+
NEW_PROP_TAG(AmgxSolverConfigFileName);
90+
91+
//! Filename for DUNE-FEM solver parameters
92+
NEW_PROP_TAG(FemSolverParameterFileName);
93+
94+
//! make the linear solver shut up by default
95+
SET_INT_PROP(AmgXSolverBackend, LinearSolverVerbosity, 0);
96+
97+
//! set the default number of maximum iterations for the linear solver
98+
SET_INT_PROP(AmgXSolverBackend, LinearSolverMaxIterations, 1000);
99+
100+
SET_SCALAR_PROP(AmgXSolverBackend, LinearSolverMaxError, 1e7);
101+
102+
//! set the default overlap size to 2
103+
SET_INT_PROP(AmgXSolverBackend, LinearSolverOverlapSize, 2);
104+
105+
//! set the preconditioner order to 0 by default
106+
SET_INT_PROP(AmgXSolverBackend, PreconditionerOrder, 0);
107+
108+
//! set the preconditioner relaxation parameter to 1.0 by default
109+
SET_SCALAR_PROP(AmgXSolverBackend, PreconditionerRelaxation, 1.0);
110+
111+
//! make the linear solver shut up by default
112+
SET_SCALAR_PROP(AmgXSolverBackend, LinearSolverTolerance, 0.01);
113+
114+
//! make the linear solver shut up by default
115+
SET_SCALAR_PROP(AmgXSolverBackend, LinearSolverAbsTolerance, 0.01);
116+
117+
//! set default solver mode for AMGX solver configuratrion
118+
SET_STRING_PROP(AmgXSolverBackend, AmgxSolverMode, "dDDI");
119+
120+
//! set default filename for AMGX solver configuratrion
121+
SET_STRING_PROP(AmgXSolverBackend, AmgxSolverConfigFileName, "amgxconfig.json");
122+
123+
//! set the preconditioner relaxation parameter to 1.0 by default
124+
SET_STRING_PROP(AmgXSolverBackend, FemSolverParameterFileName, "");
125+
126+
END_PROPERTIES
127+
128+
namespace Ewoms {
129+
namespace Linear {
130+
/*!
131+
* \ingroup Linear
132+
*
133+
* \brief Provides a linear solver backend that utilizes the AMG-X package.
134+
*/
135+
template <class TypeTag>
136+
class AmgXSolverBackend
137+
{
138+
protected:
139+
typedef typename GET_PROP_TYPE(TypeTag, LinearSolverBackend) Implementation;
140+
141+
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
142+
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
143+
typedef typename GET_PROP_TYPE(TypeTag, SparseMatrixAdapter) LinearOperator;
144+
typedef typename GET_PROP_TYPE(TypeTag, GlobalEqVector) Vector;
145+
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
146+
147+
typedef typename GET_PROP_TYPE(TypeTag, DiscreteFunctionSpace) DiscreteFunctionSpace;
148+
typedef typename GET_PROP_TYPE(TypeTag, DiscreteFunction) DiscreteFunction;
149+
150+
// discrete function to wrap what is used as Vector in eWoms
151+
typedef Dune::Fem::ISTLBlockVectorDiscreteFunction<DiscreteFunctionSpace>
152+
VectorWrapperDiscreteFunction;
153+
typedef Dune::Fem::PetscDiscreteFunction<DiscreteFunctionSpace>
154+
PetscDiscreteFunctionType;
155+
156+
enum { dimWorld = GridView::dimensionworld };
157+
158+
public:
159+
AmgXSolverBackend(Simulator& simulator)
160+
: simulator_(simulator)
161+
, space_(simulator.vanguard().gridPart())
162+
, amgxSolver_()
163+
, rhs_(nullptr)
164+
, iterations_(0)
165+
{
166+
std::string paramFileName = EWOMS_GET_PARAM(TypeTag, std::string, FemSolverParameterFileName);
167+
if (paramFileName != "")
168+
Dune::Fem::Parameter::append(paramFileName);
169+
}
170+
171+
~AmgXSolverBackend()
172+
{
173+
cleanup_();
174+
if (A_) {
175+
::Dune::Petsc::MatDestroy(A_.operator ->());
176+
A_.reset();
177+
}
178+
}
179+
180+
/*!
181+
* \brief Register all run-time parameters for the linear solver.
182+
*/
183+
static void registerParameters()
184+
{
185+
EWOMS_REGISTER_PARAM(TypeTag, Scalar, LinearSolverTolerance,
186+
"The maximum allowed error between of the linear solver");
187+
EWOMS_REGISTER_PARAM(TypeTag, Scalar, LinearSolverAbsTolerance,
188+
"The maximum allowed error between of the linear solver");
189+
EWOMS_REGISTER_PARAM(TypeTag, int, LinearSolverMaxIterations,
190+
"The maximum number of iterations of the linear solver");
191+
EWOMS_REGISTER_PARAM(TypeTag, int, LinearSolverVerbosity,
192+
"The verbosity level of the linear solver");
193+
EWOMS_REGISTER_PARAM(TypeTag, unsigned, LinearSolverOverlapSize,
194+
"The size of the algebraic overlap for the linear solver");
195+
196+
EWOMS_REGISTER_PARAM(TypeTag, Scalar, LinearSolverMaxError,
197+
"The maximum residual error which the linear solver tolerates"
198+
" without giving up");
199+
200+
EWOMS_REGISTER_PARAM(TypeTag, int, PreconditionerOrder,
201+
"The order of the preconditioner");
202+
EWOMS_REGISTER_PARAM(TypeTag, Scalar, PreconditionerRelaxation,
203+
"The relaxation factor of the preconditioner");
204+
205+
EWOMS_REGISTER_PARAM(TypeTag, std::string, AmgxSolverMode,
206+
"The name of the solver mode for AMGX");
207+
EWOMS_REGISTER_PARAM(TypeTag, std::string, AmgxSolverConfigFileName,
208+
"The name of the file which contains the AMGX solver configuration");
209+
210+
EWOMS_REGISTER_PARAM(TypeTag, std::string, FemSolverParameterFileName,
211+
"The name of the file which contains the parameters for the DUNE-FEM solvers");
212+
213+
}
214+
215+
/*!
216+
* \brief Causes the solve() method to discared the structure of the linear system of
217+
* equations the next time it is called.
218+
*/
219+
void eraseMatrix()
220+
{ cleanup_(); }
221+
222+
void prepare(const LinearOperator& op, Vector& b)
223+
{
224+
//Scalar linearSolverTolerance = EWOMS_GET_PARAM(TypeTag, Scalar, LinearSolverTolerance);
225+
//Scalar linearSolverAbsTolerance = EWOMS_GET_PARAM(TypeTag, Scalar, LinearSolverAbsTolerance);
226+
227+
if (!amgxSolver_) {
228+
// reset linear solver
229+
std::string mode = EWOMS_GET_PARAM(TypeTag, std::string, AmgxSolverMode);
230+
std::string solverconfig = EWOMS_GET_PARAM(TypeTag, std::string, AmgxSolverConfigFileName);
231+
232+
amgxSolver_.reset(new AmgXSolver());
233+
amgxSolver_->initialize(PETSC_COMM_WORLD, mode, solverconfig);
234+
235+
if (!A_) {
236+
A_.reset(new Mat());
237+
}
238+
239+
// convert MATBAIJ to MATAIJ which is needed by AmgXSolver
240+
::Dune::Petsc::ErrorCheck(::MatConvert(op.petscMatrix(), MATAIJ, MAT_INITIAL_MATRIX, A_.operator ->()));
241+
// set up the matrix used by AmgX
242+
amgxSolver_->setA(*A_);
243+
}
244+
245+
// store pointer to right hand side
246+
rhs_ = &b;
247+
}
248+
249+
/*!
250+
* \brief Actually solve the linear system of equations.
251+
*
252+
* \return true if the residual reduction could be achieved, else false.
253+
*/
254+
bool solve(Vector& x)
255+
{
256+
// wrap x into discrete function X (no copy)
257+
VectorWrapperDiscreteFunction X("FSB::x", space_, x);
258+
VectorWrapperDiscreteFunction B("FSB::rhs", space_, *rhs_);
259+
260+
if (!petscRhs_)
261+
petscRhs_.reset(new PetscDiscreteFunctionType("AMGX::rhs", space_));
262+
263+
if (!petscX_)
264+
petscX_.reset(new PetscDiscreteFunctionType("AMGX::X", space_));
265+
266+
petscRhs_->assign(B);
267+
petscX_->assign(X);
268+
269+
// solve with right hand side rhs and store in x
270+
Vec& p = *(petscX_->petscVec());
271+
Vec& rhs = *(petscRhs_->petscVec());
272+
273+
try {
274+
amgxSolver_->solve(p, rhs);
275+
}
276+
catch (...) {
277+
OPM_THROW(Opm::NumericalIssue, "AmgXSolver: no convergence of linear solver!");
278+
}
279+
280+
// copy result to ewoms solution
281+
X.assign(*petscX_);
282+
283+
amgxSolver_->getIters(iterations_);
284+
285+
// return the result of the solver
286+
return true;
287+
}
288+
289+
/*!
290+
* \brief Return number of iterations used during last solve.
291+
*/
292+
size_t iterations () const {
293+
return iterations_;
294+
}
295+
296+
protected:
297+
Implementation& asImp_()
298+
{ return *static_cast<Implementation *>(this); }
299+
300+
const Implementation& asImp_() const
301+
{ return *static_cast<const Implementation *>(this); }
302+
303+
void cleanup_()
304+
{
305+
if (amgxSolver_) {
306+
amgxSolver_->finalize();
307+
amgxSolver_.reset();
308+
}
309+
310+
rhs_ = nullptr;
311+
312+
petscRhs_.reset();
313+
petscX_.reset();
314+
}
315+
316+
const Simulator& simulator_;
317+
318+
DiscreteFunctionSpace space_;
319+
std::unique_ptr<Mat> A_;
320+
321+
std::unique_ptr<PetscDiscreteFunctionType> petscRhs_;
322+
std::unique_ptr<PetscDiscreteFunctionType> petscX_;
323+
324+
std::unique_ptr<AmgXSolver> amgxSolver_;
325+
326+
Vector* rhs_;
327+
int iterations_;
328+
};
329+
}} // namespace Linear, Ewoms
330+
331+
#endif // HAVE_DUNE_FEM
332+
333+
#endif

0 commit comments

Comments
 (0)