From f7668dc635568b61f1c2ba4a1d966bdf47c432d4 Mon Sep 17 00:00:00 2001 From: Robert Kloefkorn Date: Wed, 2 Oct 2019 13:53:08 +0200 Subject: [PATCH] [feature][FemSolverBackend] Added FemSolverBackend to allow to testing of PETSc solvers. --- .../common/fvbasediscretization.hh | 2 + .../discretization/common/fvbaselinearizer.hh | 2 - opm/simulators/linalg/amgxsolverbackend.hh | 333 ++++++++++++++++ opm/simulators/linalg/femsolverbackend.hh | 361 ++++++++++++++++++ .../linalg/femsparsematrixadapter.hh | 101 +++++ 5 files changed, 797 insertions(+), 2 deletions(-) create mode 100644 opm/simulators/linalg/amgxsolverbackend.hh create mode 100644 opm/simulators/linalg/femsolverbackend.hh create mode 100644 opm/simulators/linalg/femsparsematrixadapter.hh diff --git a/opm/models/discretization/common/fvbasediscretization.hh b/opm/models/discretization/common/fvbasediscretization.hh index e2b00b6e9b..b17326a4b5 100644 --- a/opm/models/discretization/common/fvbasediscretization.hh +++ b/opm/models/discretization/common/fvbasediscretization.hh @@ -1787,6 +1787,8 @@ public: } return *adaptationManager_; } + + const DiscreteFunctionSpace& space() const { return space_; } #endif const Opm::Timer& prePostProcessTimer() const diff --git a/opm/models/discretization/common/fvbaselinearizer.hh b/opm/models/discretization/common/fvbaselinearizer.hh index 07690d169f..9295dfd60c 100644 --- a/opm/models/discretization/common/fvbaselinearizer.hh +++ b/opm/models/discretization/common/fvbaselinearizer.hh @@ -95,8 +95,6 @@ class FvBaseLinearizer typedef GlobalEqVector Vector; - typedef typename SparseMatrixAdapter::IstlMatrix IstlMatrix; - enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) }; enum { historySize = GET_PROP_VALUE(TypeTag, TimeDiscHistorySize) }; diff --git a/opm/simulators/linalg/amgxsolverbackend.hh b/opm/simulators/linalg/amgxsolverbackend.hh new file mode 100644 index 0000000000..58acca222d --- /dev/null +++ b/opm/simulators/linalg/amgxsolverbackend.hh @@ -0,0 +1,333 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/* + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + + Consult the COPYING file in the top-level source directory of this + module for the precise wording of the license and the list of + copyright holders. +*/ +/*! + * \file + * \copydoc Ewoms::Linear::AmgXSolverBackend + */ +#ifndef EWOMS_AMGX_SOLVER_BACKEND_HH +#define EWOMS_AMGX_SOLVER_BACKEND_HH + +#include + +#if USE_AMGX_SOLVERS + +#if !HAVE_PETSC || !HAVE_AMGXSOLVER +#error "PETSc and AmgXSolver is needed for the AMGX solver backend" +#endif + +#define DISABLE_AMG_DIRECTSOLVER 1 +#include +#include +#include +#include + +#include + +#include + + +#include +#include + +#include + +#include +#include +#include + +namespace Ewoms { +namespace Linear { +template +class AmgXSolverBackend; +}} // namespace Linear, Ewoms + + +BEGIN_PROPERTIES + +NEW_TYPE_TAG(AmgXSolverBackend); + +SET_TYPE_PROP(AmgXSolverBackend, + LinearSolverBackend, + Ewoms::Linear::AmgXSolverBackend); + +NEW_PROP_TAG(LinearSolverTolerance); +NEW_PROP_TAG(LinearSolverAbsTolerance); +NEW_PROP_TAG(LinearSolverMaxIterations); +NEW_PROP_TAG(LinearSolverVerbosity); +NEW_PROP_TAG(LinearSolverMaxError); +NEW_PROP_TAG(LinearSolverOverlapSize); +//! The order of the sequential preconditioner +NEW_PROP_TAG(PreconditionerOrder); + +//! The relaxation factor of the preconditioner +NEW_PROP_TAG(PreconditionerRelaxation); + +//! Solver mode for AMGX solver +NEW_PROP_TAG(AmgxSolverMode); + +//! Filename for AMGX solver configuration +NEW_PROP_TAG(AmgxSolverConfigFileName); + +//! Filename for DUNE-FEM solver parameters +NEW_PROP_TAG(FemSolverParameterFileName); + +//! make the linear solver shut up by default +SET_INT_PROP(AmgXSolverBackend, LinearSolverVerbosity, 0); + +//! set the default number of maximum iterations for the linear solver +SET_INT_PROP(AmgXSolverBackend, LinearSolverMaxIterations, 1000); + +SET_SCALAR_PROP(AmgXSolverBackend, LinearSolverMaxError, 1e7); + +//! set the default overlap size to 2 +SET_INT_PROP(AmgXSolverBackend, LinearSolverOverlapSize, 2); + +//! set the preconditioner order to 0 by default +SET_INT_PROP(AmgXSolverBackend, PreconditionerOrder, 0); + +//! set the preconditioner relaxation parameter to 1.0 by default +SET_SCALAR_PROP(AmgXSolverBackend, PreconditionerRelaxation, 1.0); + +//! make the linear solver shut up by default +SET_SCALAR_PROP(AmgXSolverBackend, LinearSolverTolerance, 0.01); + +//! make the linear solver shut up by default +SET_SCALAR_PROP(AmgXSolverBackend, LinearSolverAbsTolerance, 0.01); + +//! set default solver mode for AMGX solver configuratrion +SET_STRING_PROP(AmgXSolverBackend, AmgxSolverMode, "dDDI"); + +//! set default filename for AMGX solver configuratrion +SET_STRING_PROP(AmgXSolverBackend, AmgxSolverConfigFileName, "amgxconfig.json"); + +//! set the preconditioner relaxation parameter to 1.0 by default +SET_STRING_PROP(AmgXSolverBackend, FemSolverParameterFileName, ""); + +END_PROPERTIES + +namespace Ewoms { +namespace Linear { +/*! + * \ingroup Linear + * + * \brief Provides a linear solver backend that utilizes the AMG-X package. + */ +template +class AmgXSolverBackend +{ +protected: + typedef typename GET_PROP_TYPE(TypeTag, LinearSolverBackend) Implementation; + + typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, SparseMatrixAdapter) LinearOperator; + typedef typename GET_PROP_TYPE(TypeTag, GlobalEqVector) Vector; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, DiscreteFunctionSpace) DiscreteFunctionSpace; + typedef typename GET_PROP_TYPE(TypeTag, DiscreteFunction) DiscreteFunction; + + // discrete function to wrap what is used as Vector in eWoms + typedef Dune::Fem::ISTLBlockVectorDiscreteFunction + VectorWrapperDiscreteFunction; + typedef Dune::Fem::PetscDiscreteFunction + PetscDiscreteFunctionType; + + enum { dimWorld = GridView::dimensionworld }; + +public: + AmgXSolverBackend(Simulator& simulator) + : simulator_(simulator) + , space_(simulator.vanguard().gridPart()) + , amgxSolver_() + , rhs_(nullptr) + , iterations_(0) + { + std::string paramFileName = EWOMS_GET_PARAM(TypeTag, std::string, FemSolverParameterFileName); + if (paramFileName != "") + Dune::Fem::Parameter::append(paramFileName); + } + + ~AmgXSolverBackend() + { + cleanup_(); + if (A_) { + ::Dune::Petsc::MatDestroy(A_.operator ->()); + A_.reset(); + } + } + + /*! + * \brief Register all run-time parameters for the linear solver. + */ + static void registerParameters() + { + EWOMS_REGISTER_PARAM(TypeTag, Scalar, LinearSolverTolerance, + "The maximum allowed error between of the linear solver"); + EWOMS_REGISTER_PARAM(TypeTag, Scalar, LinearSolverAbsTolerance, + "The maximum allowed error between of the linear solver"); + EWOMS_REGISTER_PARAM(TypeTag, int, LinearSolverMaxIterations, + "The maximum number of iterations of the linear solver"); + EWOMS_REGISTER_PARAM(TypeTag, int, LinearSolverVerbosity, + "The verbosity level of the linear solver"); + EWOMS_REGISTER_PARAM(TypeTag, unsigned, LinearSolverOverlapSize, + "The size of the algebraic overlap for the linear solver"); + + EWOMS_REGISTER_PARAM(TypeTag, Scalar, LinearSolverMaxError, + "The maximum residual error which the linear solver tolerates" + " without giving up"); + + EWOMS_REGISTER_PARAM(TypeTag, int, PreconditionerOrder, + "The order of the preconditioner"); + EWOMS_REGISTER_PARAM(TypeTag, Scalar, PreconditionerRelaxation, + "The relaxation factor of the preconditioner"); + + EWOMS_REGISTER_PARAM(TypeTag, std::string, AmgxSolverMode, + "The name of the solver mode for AMGX"); + EWOMS_REGISTER_PARAM(TypeTag, std::string, AmgxSolverConfigFileName, + "The name of the file which contains the AMGX solver configuration"); + + EWOMS_REGISTER_PARAM(TypeTag, std::string, FemSolverParameterFileName, + "The name of the file which contains the parameters for the DUNE-FEM solvers"); + + } + + /*! + * \brief Causes the solve() method to discared the structure of the linear system of + * equations the next time it is called. + */ + void eraseMatrix() + { cleanup_(); } + + void prepare(const LinearOperator& op, Vector& b) + { + //Scalar linearSolverTolerance = EWOMS_GET_PARAM(TypeTag, Scalar, LinearSolverTolerance); + //Scalar linearSolverAbsTolerance = EWOMS_GET_PARAM(TypeTag, Scalar, LinearSolverAbsTolerance); + + if (!amgxSolver_) { + // reset linear solver + std::string mode = EWOMS_GET_PARAM(TypeTag, std::string, AmgxSolverMode); + std::string solverconfig = EWOMS_GET_PARAM(TypeTag, std::string, AmgxSolverConfigFileName); + + amgxSolver_.reset(new AmgXSolver()); + amgxSolver_->initialize(PETSC_COMM_WORLD, mode, solverconfig); + + if (!A_) { + A_.reset(new Mat()); + } + + // convert MATBAIJ to MATAIJ which is needed by AmgXSolver + ::Dune::Petsc::ErrorCheck(::MatConvert(op.petscMatrix(), MATAIJ, MAT_INITIAL_MATRIX, A_.operator ->())); + // set up the matrix used by AmgX + amgxSolver_->setA(*A_); + } + + // store pointer to right hand side + rhs_ = &b; + } + + /*! + * \brief Actually solve the linear system of equations. + * + * \return true if the residual reduction could be achieved, else false. + */ + bool solve(Vector& x) + { + // wrap x into discrete function X (no copy) + VectorWrapperDiscreteFunction X("FSB::x", space_, x); + VectorWrapperDiscreteFunction B("FSB::rhs", space_, *rhs_); + + if (!petscRhs_) + petscRhs_.reset(new PetscDiscreteFunctionType("AMGX::rhs", space_)); + + if (!petscX_) + petscX_.reset(new PetscDiscreteFunctionType("AMGX::X", space_)); + + petscRhs_->assign(B); + petscX_->assign(X); + + // solve with right hand side rhs and store in x + Vec& p = *(petscX_->petscVec()); + Vec& rhs = *(petscRhs_->petscVec()); + + try { + amgxSolver_->solve(p, rhs); + } + catch (...) { + OPM_THROW(Opm::NumericalIssue, "AmgXSolver: no convergence of linear solver!"); + } + + // copy result to ewoms solution + X.assign(*petscX_); + + amgxSolver_->getIters(iterations_); + + // return the result of the solver + return true; + } + + /*! + * \brief Return number of iterations used during last solve. + */ + size_t iterations () const { + return iterations_; + } + +protected: + Implementation& asImp_() + { return *static_cast(this); } + + const Implementation& asImp_() const + { return *static_cast(this); } + + void cleanup_() + { + if (amgxSolver_) { + amgxSolver_->finalize(); + amgxSolver_.reset(); + } + + rhs_ = nullptr; + + petscRhs_.reset(); + petscX_.reset(); + } + + const Simulator& simulator_; + + DiscreteFunctionSpace space_; + std::unique_ptr A_; + + std::unique_ptr petscRhs_; + std::unique_ptr petscX_; + + std::unique_ptr amgxSolver_; + + Vector* rhs_; + int iterations_; +}; +}} // namespace Linear, Ewoms + +#endif // HAVE_DUNE_FEM + +#endif diff --git a/opm/simulators/linalg/femsolverbackend.hh b/opm/simulators/linalg/femsolverbackend.hh new file mode 100644 index 0000000000..d2a001453d --- /dev/null +++ b/opm/simulators/linalg/femsolverbackend.hh @@ -0,0 +1,361 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/* + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + + Consult the COPYING file in the top-level source directory of this + module for the precise wording of the license and the list of + copyright holders. +*/ +/*! + * \file + * \copydoc Opm::Linear::FemSolverBackend + */ +#ifndef OPM_FEM_SOLVER_BACKEND_HH +#define OPM_FEM_SOLVER_BACKEND_HH + +#include + +#define DISABLE_AMG_DIRECTSOLVER 1 +#include +#include +#if HAVE_PETSC +#include +#endif + +#if HAVE_VIENNACL +#include +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace Opm { +namespace Linear { +template +class FemSolverBackend; +}} // namespace Linear, Opm + + +BEGIN_PROPERTIES + +NEW_TYPE_TAG(FemSolverBackend); + +SET_TYPE_PROP(FemSolverBackend, + LinearSolverBackend, + Opm::Linear::FemSolverBackend); + +NEW_PROP_TAG(DiscreteFunction); +NEW_PROP_TAG(SparseMatrixAdapter); + +//NEW_PROP_TAG(LinearSolverTolerance); +NEW_PROP_TAG(LinearSolverMaxIterations); +NEW_PROP_TAG(LinearSolverVerbosity); +NEW_PROP_TAG(LinearSolverMaxError); +NEW_PROP_TAG(LinearSolverOverlapSize); +//! The order of the sequential preconditioner +NEW_PROP_TAG(PreconditionerOrder); + +//! The relaxation factor of the preconditioner +NEW_PROP_TAG(PreconditionerRelaxation); + +//! Filename for DUNE-FEM solver parameters +NEW_PROP_TAG(FemSolverParameterFileName); + +//! make the linear solver shut up by default +SET_INT_PROP(FemSolverBackend, LinearSolverVerbosity, 0); + +//! set the default number of maximum iterations for the linear solver +SET_INT_PROP(FemSolverBackend, LinearSolverMaxIterations, 1000); + +SET_SCALAR_PROP(FemSolverBackend, LinearSolverMaxError, 1e7); + +//! set the default overlap size to 2 +SET_INT_PROP(FemSolverBackend, LinearSolverOverlapSize, 2); + +//! set the preconditioner order to 0 by default +SET_INT_PROP(FemSolverBackend, PreconditionerOrder, 0); + +//! set the preconditioner relaxation parameter to 1.0 by default +SET_SCALAR_PROP(FemSolverBackend, PreconditionerRelaxation, 1.0); + +//! set the preconditioner relaxation parameter to 1.0 by default +SET_STRING_PROP(FemSolverBackend, FemSolverParameterFileName, ""); + +//! make the linear solver shut up by default +//SET_SCALAR_PROP(FemSolverBackend, LinearSolverTolerance, 0.01); + +SET_PROP(FemSolverBackend, DiscreteFunction) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, DiscreteFunctionSpace) DiscreteFunctionSpace; + + //typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; +public: + // discrete function storing solution data + typedef Dune::Fem::ISTLBlockVectorDiscreteFunction type; +}; + +//! Set the type of a global jacobian matrix for linear solvers that are based on +//! dune-istl. +SET_PROP(FemSolverBackend, SparseMatrixAdapter) +{ +private: + typedef typename GET_PROP_TYPE(TypeTag, DiscreteFunctionSpace) DiscreteFunctionSpace; + //typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + // discrete function storing solution data + typedef Dune::Fem::ISTLBlockVectorDiscreteFunction DiscreteFunction; + +public: + typedef Opm::Linear::FemSparseRowMatrixAdapter< DiscreteFunction > type; +}; + + +END_PROPERTIES + +namespace Opm { +namespace Linear { +/*! + * \ingroup Linear + * + * \brief Uses the dune-fem infrastructure to solve the linear system of equations. + */ +template +class FemSolverBackend +{ +protected: + typedef typename GET_PROP_TYPE(TypeTag, LinearSolverBackend) Implementation; + + typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator; + typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar; + typedef typename GET_PROP_TYPE(TypeTag, SparseMatrixAdapter) SparseMatrixAdapter; + typedef typename GET_PROP_TYPE(TypeTag, GlobalEqVector) Vector; + typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView; + + typedef typename GET_PROP_TYPE(TypeTag, DiscreteFunctionSpace) DiscreteFunctionSpace; + typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables; + // discrete function storing solution data + typedef Dune::Fem::ISTLBlockVectorDiscreteFunction DiscreteFunction; + + // discrete function to wrap what is used as Vector in eWoms + typedef Dune::Fem::ISTLBlockVectorDiscreteFunction + VectorWrapperDiscreteFunction; + + template + struct SolverSelector; + + template + struct SolverSelector< d, FemSparseRowMatrixAdapter< DF > > + { + typedef Dune::Fem::KrylovInverseOperator type; + }; + +#if HAVE_PETSC + template + struct SolverSelector > + { + typedef Dune::Fem::PetscInverseOperator type; + }; +#endif + + template + struct SolverSelector > + { + typedef Dune::Fem::ISTLBICGSTABOp type; + }; + + // select solver type depending on linear operator type + typedef typename SolverSelector<0, SparseMatrixAdapter>::type InverseLinearOperator; + + enum { dimWorld = GridView::dimensionworld }; + +public: + FemSolverBackend(Simulator& simulator) + : simulator_(simulator) + , invOp_() + , rhs_(nullptr) + , space_(simulator.vanguard().gridPart()) + { + std::string paramFileName;// = EWOMS_GET_PARAM(TypeTag, std::string, FemSolverParameterFileName); + if (paramFileName != "") + Dune::Fem::Parameter::append(paramFileName); + else { + // default parameters + Dune::Fem::Parameter::append("fem.solver.errormeasure", "residualreduction"); + Dune::Fem::Parameter::append("fem.solver.verbose", "true"); + Dune::Fem::Parameter::append("fem.verboserank", "0"); + + // Krylov solver + Dune::Fem::Parameter::append("fem.solver.method", "bicgstab"); + + // Preconditioner + Dune::Fem::Parameter::append("fem.solver.preconditioning.method", "ilu"); + Dune::Fem::Parameter::append("fem.solver.preconditioning.level", "0"); + Dune::Fem::Parameter::append("fem.solver.preconditioning.relaxation", "0.9"); + } + } + + ~FemSolverBackend() + { cleanup_(); } + + /*! + * \brief Register all run-time parameters for the linear solver. + */ + static void registerParameters() + { + EWOMS_REGISTER_PARAM(TypeTag, Scalar, LinearSolverTolerance, + "The maximum allowed error between of the linear solver"); + /* + EWOMS_REGISTER_PARAM(TypeTag, int, LinearSolverMaxIterations, + "The maximum number of iterations of the linear solver"); + EWOMS_REGISTER_PARAM(TypeTag, int, LinearSolverVerbosity, + "The verbosity level of the linear solver"); + EWOMS_REGISTER_PARAM(TypeTag, unsigned, LinearSolverOverlapSize, + "The size of the algebraic overlap for the linear solver"); + + EWOMS_REGISTER_PARAM(TypeTag, Scalar, LinearSolverMaxError, + "The maximum residual error which the linear solver tolerates" + " without giving up"); + + EWOMS_REGISTER_PARAM(TypeTag, int, PreconditionerOrder, + "The order of the preconditioner"); + EWOMS_REGISTER_PARAM(TypeTag, Scalar, PreconditionerRelaxation, + "The relaxation factor of the preconditioner"); + + EWOMS_REGISTER_PARAM(TypeTag, std::string, FemSolverParameterFileName, + "The name of the file which contains the parameters for the DUNE-FEM solvers"); + + */ + } + + /*! + * \brief Causes the solve() method to discared the structure of the linear system of + * equations the next time it is called. + */ + void eraseMatrix() + { cleanup_(); } + + void prepare(const SparseMatrixAdapter& op, Vector& b) + { + Scalar linearSolverTolerance = EWOMS_GET_PARAM(TypeTag, Scalar, LinearSolverTolerance); + Scalar linearSolverAbsTolerance = this->simulator_.model().newtonMethod().tolerance() / 100000.0; + //Scalar linearSolverTolerance = 1e-3;//EWOMS_GET_PARAM(TypeTag, Scalar, LinearSolverTolerance); + //Scalar linearSolverAbsTolerance = this->simulator_.model().newtonMethod().tolerance() / 100000.0; + + // reset linear solver + if (!invOp_) + invOp_.reset(new InverseLinearOperator(linearSolverTolerance, linearSolverAbsTolerance)); + + setMatrix(op); + setResidual(b); + + // not needed + asImp_().rescale_(); + } + + /*! + * \brief Assign values to the internal data structure for the residual vector. + * + * This method also cares about synchronizing that vector with the peer processes. + */ + void setResidual(const Vector& b) + { rhs_ = &b ; } + + /*! + * \brief Retrieve the synchronized internal residual vector. + * + * This only deals with entries which are local to the current process. + */ + void getResidual(Vector& b) const + { + assert(rhs_); + b = *rhs_; + } + + /*! + * \brief Sets the values of the residual's Jacobian matrix. + * + * This method also synchronizes the data structure across the processes which are + * involved in the simulation run. + */ + void setMatrix(const SparseMatrixAdapter& op) + { + invOp_->bind(op); + } + + + /*! + * \brief Actually solve the linear system of equations. + * + * \return true if the residual reduction could be achieved, else false. + */ + bool solve(Vector& x) + { + // wrap x into discrete function X (no copy) + VectorWrapperDiscreteFunction X("FSB::x", space_, x); + assert(rhs_); + VectorWrapperDiscreteFunction B("FSB::rhs", space_, *rhs_); + + // solve with right hand side rhs and store in x + (*invOp_)(B, X); + + // return the result of the solver + return invOp_->iterations() < 0 ? false : true; + } + + /*! + * \brief Return number of iterations used during last solve. + */ + size_t iterations () const + { + assert(invOp_); + return invOp_->iterations(); + } + +protected: + Implementation& asImp_() + { return *static_cast(this); } + + const Implementation& asImp_() const + { return *static_cast(this); } + + void rescale_() + { } + + void cleanup_() + { + invOp_.reset(); + rhs_ = nullptr; + } + + const Simulator& simulator_; + std::unique_ptr invOp_; + const Vector* rhs_; + DiscreteFunctionSpace space_; +}; +}} // namespace Linear, Opm + +#endif diff --git a/opm/simulators/linalg/femsparsematrixadapter.hh b/opm/simulators/linalg/femsparsematrixadapter.hh new file mode 100644 index 0000000000..e76af5d380 --- /dev/null +++ b/opm/simulators/linalg/femsparsematrixadapter.hh @@ -0,0 +1,101 @@ +// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +// vi: set et ts=4 sw=4 sts=4: +/* + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + + Consult the COPYING file in the top-level source directory of this + module for the precise wording of the license and the list of + copyright holders. +*/ +/*! + * \file + * \copydoc Opm::Linear::FemSparseMatrixAdapter + */ +#ifndef OPM_FEM_SPARSE_MATRIX_ADAPTER_HH +#define OPM_FEM_SPARSE_MATRIX_ADAPTER_HH + +// this code only works with dune-fem available +#if HAVE_DUNE_FEM + +// the following implementation of FemSparseMatrixAdapter only works for +// dune-fem version 2.7 or higher +#if DUNE_VERSION_NEWER(DUNE_FEM, 2, 7) +#include + +#if HAVE_PETSC +#include +#endif + +#include +#include + + +namespace Opm { +namespace Linear { + +/*! + * \ingroup Linear + * \brief A sparse matrix interface backend for linear operators from dune-fem. + * + * \note LinearOperators from dune-fem implement most methods needed for SparseMatrixAdapter + * and here we simply add a few forwarding methods. + */ +template +struct FemSparseMatrixAdapter : public LinearOperator +{ + typedef LinearOperator ParentType; + typedef typename LinearOperator :: MatrixType Matrix; + typedef typename ParentType :: MatrixBlockType MatrixBlock; + + typedef typename LinearOperator :: RangeFunctionType :: RangeFieldType Scalar; + + template + FemSparseMatrixAdapter( const Simulator& simulator ) + : LinearOperator("Opm::Jacobian", simulator.model().space(), simulator.model().space() ) + {} + + void commit() + { + this->flushAssembly(); + } + + template< class LocalBlock > + void addToBlock ( const size_t row, const size_t col, const LocalBlock& block ) + { + this->addBlock( row, col, block ); + } + + void clearRow( const size_t row, const Scalar diag = 1.0 ) { this->unitRow( row ); } +}; + +template +using FemSparseRowMatrixAdapter = FemSparseMatrixAdapter< Dune::Fem::SparseRowLinearOperator< DiscreteFunction, DiscreteFunction > >; + +#if HAVE_PETSC +template +using FemPetscMatrixAdapter = FemSparseMatrixAdapter< Dune::Fem::PetscLinearOperator< DiscreteFunction, DiscreteFunction > >; +#endif + +#if HAVE_DUNE_ISTL +template +using FemISTLMatrixAdapter = FemSparseMatrixAdapter< Dune::Fem::ISTLLinearOperator< DiscreteFunction, DiscreteFunction > >; +#endif + +}} // namespace Linear, Opm + +#endif // DUNE_VERSION_NEWER(DUNE_FEM, 2, 7) +#endif // HAVE_DUNE_FEM +#endif