NewtonBlackølInterationInterleaved: NewtonBlackølInterationInterleavedImpl implements

the Iteration for a fixed number of cell variabled which is then used by the
NewtonBlackølInterationInterleaved class via a switch-case over the actually existing
numbers.
This commit is contained in:
Robert Kloefkorn
2015-10-07 17:48:27 +02:00
parent 62511215d4
commit c485e3fdc7
2 changed files with 419 additions and 329 deletions

View File

@@ -3,6 +3,7 @@
Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services
Copyright 2015 NTNU Copyright 2015 NTNU
Copyright 2015 Statoil AS Copyright 2015 Statoil AS
Copyright 2015 IRIS AS
This file is part of the Open Porous Media project (OPM). This file is part of the Open Porous Media project (OPM).
@@ -30,6 +31,13 @@
#include <opm/core/utility/Exceptions.hpp> #include <opm/core/utility/Exceptions.hpp>
#include <opm/core/linalg/ParallelIstlInformation.hpp> #include <opm/core/linalg/ParallelIstlInformation.hpp>
#include <dune/istl/scalarproducts.hh>
#include <dune/istl/operators.hh>
#include <dune/istl/preconditioners.hh>
#include <dune/istl/solvers.hh>
#include <dune/istl/owneroverlapcopy.hh>
#include <dune/istl/paamg/amg.hh>
#include <opm/common/utility/platform_dependent/disable_warnings.h> #include <opm/common/utility/platform_dependent/disable_warnings.h>
#if HAVE_UMFPACK #if HAVE_UMFPACK
#include <Eigen/UmfPackSupport> #include <Eigen/UmfPackSupport>
@@ -48,12 +56,47 @@ namespace Opm
typedef ADB::M M; typedef ADB::M M;
namespace detail {
/**
* Simple binary operator that always returns 0.1
* It is used to get the sparsity pattern for our
* interleaved system, and is marginally faster than using
* operator+=.
*/
template<typename Scalar> struct PointOneOp {
EIGEN_EMPTY_STRUCT_CTOR(PointOneOp)
Scalar operator()(const Scalar& a, const Scalar& b) const { return 0.1; }
};
}
/// This class solves the fully implicit black-oil system by
/// solving the reduced system (after eliminating well variables)
/// as a block-structured matrix (one block for all cell variables) for a fixed
/// number of cell variables np .
template <int np>
class NewtonIterationBlackoilInterleavedImpl : public NewtonIterationBlackoilInterface
{
typedef Dune::FieldVector<double, np > VectorBlockType;
typedef Dune::FieldMatrix<double, np, np> MatrixBlockType;
typedef Dune::BCRSMatrix <MatrixBlockType> Mat;
typedef Dune::BlockVector<VectorBlockType> Vector;
public:
typedef NewtonIterationBlackoilInterface :: SolutionVector SolutionVector;
/// Construct a system solver. /// Construct a system solver.
NewtonIterationBlackoilInterleaved::NewtonIterationBlackoilInterleaved(const parameter::ParameterGroup& param, /// \param[in] param parameters controlling the behaviour of
const boost::any& parallelInformation_arg) /// the preconditioning and choice of
/// linear solvers.
/// Parameters:
/// cpr_relax (default 1.0) relaxation for the preconditioner
/// cpr_ilu_n (default 0) use ILU(n) for preconditioning of the linear system
/// cpr_use_amg (default false) if true, use AMG preconditioner for elliptic part
/// cpr_use_bicgstab (default true) if true, use BiCGStab (else use CG) for elliptic part
/// \param[in] parallelInformation In the case of a parallel run
/// with dune-istl the information about the parallelization.
NewtonIterationBlackoilInterleavedImpl(const parameter::ParameterGroup& param,
const boost::any& parallelInformation_arg=boost::any())
: iterations_( 0 ), : iterations_( 0 ),
parallelInformation_(parallelInformation_arg), parallelInformation_(parallelInformation_arg),
newton_use_gmres_( param.getDefault("newton_use_gmres", false ) ), newton_use_gmres_( param.getDefault("newton_use_gmres", false ) ),
@@ -64,8 +107,188 @@ namespace Opm
{ {
} }
/// Solve the system of linear equations Ax = b, with A being the
/// combined derivative matrix of the residual and b
/// being the residual itself.
/// \param[in] residual residual object containing A and b.
/// \return the solution x
/// \copydoc NewtonIterationBlackoilInterface::iterations
int iterations () const { return iterations_; }
/// \copydoc NewtonIterationBlackoilInterface::parallelInformation
const boost::any& parallelInformation() const { return parallelInformation_; }
public:
/// \brief construct the CPR preconditioner and the solver.
/// \tparam P The type of the parallel information.
/// \param parallelInformation the information about the parallelization.
template<int category=Dune::SolverCategory::sequential, class O, class POrComm>
void constructPreconditionerAndSolve(O& opA,
Vector& x, Vector& istlb,
const POrComm& parallelInformation_arg,
Dune::InverseOperatorResult& result) const
{
// Construct scalar product.
typedef Dune::ScalarProductChooser<Vector, POrComm, category> ScalarProductChooser;
typedef std::unique_ptr<typename ScalarProductChooser::ScalarProduct> SPPointer;
SPPointer sp(ScalarProductChooser::construct(parallelInformation_arg));
// Construct preconditioner.
auto precond = constructPrecond(opA, parallelInformation_arg);
// Communicate if parallel.
parallelInformation_arg.copyOwnerToAll(istlb, istlb);
// Solve.
solve(opA, x, istlb, *sp, *precond, result);
}
typedef Dune::SeqILU0<Mat, Vector, Vector> SeqPreconditioner;
template <class Operator>
std::unique_ptr<SeqPreconditioner> constructPrecond(Operator& opA, const Dune::Amg::SequentialInformation&) const
{
const double relax = 1.0;
std::unique_ptr<SeqPreconditioner> precond(new SeqPreconditioner(opA.getmat(), relax));
return precond;
}
#if HAVE_MPI
typedef Dune::OwnerOverlapCopyCommunication<int, int> Comm;
typedef Dune::BlockPreconditioner<Vector, Vector, Comm, SeqPreconditioner> ParPreconditioner;
template <class Operator>
std::unique_ptr<ParPreconditioner,
AdditionalObjectDeleter<SeqPreconditioner> >
constructPrecond(Operator& opA, const Comm& comm) const
{
typedef AdditionalObjectDeleter<SeqPreconditioner> Deleter;
typedef std::unique_ptr<ParPreconditioner, Deleter> Pointer;
int ilu_setup_successful = 1;
std::string message;
const double relax = 1.0;
SeqPreconditioner* seq_precond = nullptr;
try {
seq_precond = new SeqPreconditioner(opA.getmat(), relax);
}
catch ( Dune::MatrixBlockError error )
{
message = error.what();
std::cerr<<"Exception occured on process " <<
comm.communicator().rank() << " during " <<
"setup of ILU0 preconditioner with message: " <<
message<<std::endl;
ilu_setup_successful = 0;
}
// Check whether there was a problem on some process
if ( comm.communicator().min(ilu_setup_successful) == 0 )
{
if ( seq_precond ) // not null if constructor succeeded
{
// prevent memory leak
delete seq_precond;
throw Dune::MatrixBlockError();
}
}
return Pointer(new ParPreconditioner(*seq_precond, comm),
Deleter(*seq_precond));
}
#endif
/// \brief Solve the system using the given preconditioner and scalar product.
template <class Operator, class ScalarProd, class Precond>
void solve(Operator& opA, Vector& x, Vector& istlb, ScalarProd& sp, Precond& precond, Dune::InverseOperatorResult& result) const
{
// TODO: Revise when linear solvers interface opm-core is done
// Construct linear solver.
// GMRes solver
if ( newton_use_gmres_ ) {
Dune::RestartedGMResSolver<Vector> linsolve(opA, sp, precond,
linear_solver_reduction_, linear_solver_restart_, linear_solver_maxiter_, linear_solver_verbosity_);
// Solve system.
linsolve.apply(x, istlb, result);
}
else { // BiCGstab solver
Dune::BiCGSTABSolver<Vector> linsolve(opA, sp, precond,
linear_solver_reduction_, linear_solver_maxiter_, linear_solver_verbosity_);
// Solve system.
linsolve.apply(x, istlb, result);
}
}
void formInterleavedSystem(const std::vector<LinearisedBlackoilResidual::ADB>& eqs,
Mat& istlA) const
{
assert( np == int(eqs.size()) );
// Find sparsity structure as union of basic block sparsity structures,
// corresponding to the jacobians with respect to pressure.
// Use our custom PointOneOp to get to the union structure.
// Note that we only iterate over the pressure derivatives on purpose.
Eigen::SparseMatrix<double, Eigen::ColMajor> col_major = eqs[0].derivative()[0].getSparse();
detail::PointOneOp<double> point_one;
for (int phase = 1; phase < np; ++phase) {
const AutoDiffMatrix::SparseRep& mat = eqs[phase].derivative()[0].getSparse();
col_major = col_major.binaryExpr(mat, point_one);
}
// Automatically convert the column major structure to a row-major structure
Eigen::SparseMatrix<double, Eigen::RowMajor> row_major = col_major;
const int size = row_major.rows();
assert(size == row_major.cols());
// Create ISTL matrix with interleaved rows and columns (block structured).
istlA.setSize(row_major.rows(), row_major.cols(), row_major.nonZeros());
istlA.setBuildMode(Mat::row_wise);
const int* ia = row_major.outerIndexPtr();
const int* ja = row_major.innerIndexPtr();
const typename Mat::CreateIterator endrow = istlA.createend();
for (typename Mat::CreateIterator row = istlA.createbegin(); row != endrow; ++row) {
const int ri = row.index();
for (int i = ia[ri]; i < ia[ri + 1]; ++i) {
row.insert(ja[i]);
}
}
// Set all blocks to zero.
for (int row = 0; row < size; ++row) {
for (int col_ix = ia[row]; col_ix < ia[row + 1]; ++col_ix) {
const int col = ja[col_ix];
istlA[row][col] = 0.0;
}
}
/**
* Go through all jacobians, and insert in correct spot
*
* The straight forward way to do this would be to run through each
* element in the output matrix, and set all block entries by gathering
* from all "input matrices" (derivatives).
*
* A faster alternative is to instead run through each "input matrix" and
* insert its elements in the correct spot in the output matrix.
*
*/
for (int col = 0; col < size; ++col) {
for (int p1 = 0; p1 < np; ++p1) {
for (int p2 = 0; p2 < np; ++p2) {
// Note that that since these are CSC and not CSR matrices,
// ja contains row numbers instead of column numbers.
const AutoDiffMatrix::SparseRep& s = eqs[p1].derivative()[p2].getSparse();
const int* ia = s.outerIndexPtr();
const int* ja = s.innerIndexPtr();
const double* sa = s.valuePtr();
for (int elem_ix = ia[col]; elem_ix < ia[col + 1]; ++elem_ix) {
const int row = ja[elem_ix];
istlA[row][col][p1][p2] = sa[elem_ix];
}
}
}
}
}
/// Solve the linear system Ax = b, with A being the /// Solve the linear system Ax = b, with A being the
@@ -73,11 +296,11 @@ namespace Opm
/// being the residual itself. /// being the residual itself.
/// \param[in] residual residual object containing A and b. /// \param[in] residual residual object containing A and b.
/// \return the solution x /// \return the solution x
NewtonIterationBlackoilInterleaved::SolutionVector SolutionVector computeNewtonIncrement(const LinearisedBlackoilResidual& residual) const
NewtonIterationBlackoilInterleaved::computeNewtonIncrement(const LinearisedBlackoilResidual& residual) const
{ {
// Build the vector of equations. // Build the vector of equations.
const int np = residual.material_balance_eq.size(); //const int np = residual.material_balance_eq.size();
assert( np == int(residual.material_balance_eq.size()) );
std::vector<ADB> eqs; std::vector<ADB> eqs;
eqs.reserve(np + 2); eqs.reserve(np + 2);
for (int phase = 0; phase < np; ++phase) { for (int phase = 0; phase < np; ++phase) {
@@ -134,9 +357,9 @@ namespace Opm
const int size = istlA.N(); const int size = istlA.N();
Vector istlb(size); Vector istlb(size);
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
istlb[i][0] = b(i); for( int p = 0, idx = i; p<np; ++p, idx += size ) {
istlb[i][1] = b(size + i); istlb[i][p] = b(idx);
istlb[i][2] = b(2*size + i); }
} }
// System solution // System solution
@@ -144,7 +367,7 @@ namespace Opm
x = 0.0; x = 0.0;
Dune::InverseOperatorResult result; Dune::InverseOperatorResult result;
// Parallel version is deactivated until we figure out how to do it properly. // Parallel version is deactivated until we figure out how to do it properly.
#if HAVE_MPI #if HAVE_MPI
if (parallelInformation_.type() == typeid(ParallelISTLInformation)) if (parallelInformation_.type() == typeid(ParallelISTLInformation))
{ {
@@ -181,9 +404,9 @@ namespace Opm
// Copy solver output to dx. // Copy solver output to dx.
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
dx(i) = x[i][0]; for( int p=0, idx = i; p<np; ++p, idx += size ) {
dx(size + i) = x[i][1]; dx(idx) = x[i][p];
dx(2*size + i) = x[i][2]; }
} }
if ( hasWells ) { if ( hasWells ) {
@@ -195,96 +418,81 @@ namespace Opm
return dx; return dx;
} }
protected:
mutable int iterations_;
boost::any parallelInformation_;
const bool newton_use_gmres_;
const double linear_solver_reduction_;
const int linear_solver_maxiter_;
const int linear_solver_restart_;
const int linear_solver_verbosity_;
}; // end NewtonIterationBlackoilInterleavedImpl
namespace detail { /// Construct a system solver.
/** NewtonIterationBlackoilInterleaved::NewtonIterationBlackoilInterleaved(const parameter::ParameterGroup& param,
* Simple binary operator that always returns 0.1 const boost::any& parallelInformation_arg)
* It is used to get the sparsity pattern for our : newtonIncrement_( 6 ),
* interleaved system, and is marginally faster than using param_( param ),
* operator+=. parallelInformation_(parallelInformation_arg),
*/ iterations_( 0 )
template<typename Scalar> struct PointOneOp {
EIGEN_EMPTY_STRUCT_CTOR(PointOneOp)
Scalar operator()(const Scalar& a, const Scalar& b) const { return 0.1; }
};
}
void NewtonIterationBlackoilInterleaved::formInterleavedSystem(const std::vector<ADB>& eqs,
Mat& istlA) const
{ {
const int np = eqs.size();
// Find sparsity structure as union of basic block sparsity structures,
// corresponding to the jacobians with respect to pressure.
// Use our custom PointOneOp to get to the union structure.
// Note that we only iterate over the pressure derivatives on purpose.
Eigen::SparseMatrix<double, Eigen::ColMajor> col_major = eqs[0].derivative()[0].getSparse();
detail::PointOneOp<double> point_one;
for (int phase = 1; phase < np; ++phase) {
const AutoDiffMatrix::SparseRep& mat = eqs[phase].derivative()[0].getSparse();
col_major = col_major.binaryExpr(mat, point_one);
}
// Automatically convert the column major structure to a row-major structure
Eigen::SparseMatrix<double, Eigen::RowMajor> row_major = col_major;
const int size = row_major.rows();
assert(size == row_major.cols());
// Create ISTL matrix with interleaved rows and columns (block structured).
assert(np == 3);
istlA.setSize(row_major.rows(), row_major.cols(), row_major.nonZeros());
istlA.setBuildMode(Mat::row_wise);
const int* ia = row_major.outerIndexPtr();
const int* ja = row_major.innerIndexPtr();
for (Mat::CreateIterator row = istlA.createbegin(); row != istlA.createend(); ++row) {
const int ri = row.index();
for (int i = ia[ri]; i < ia[ri + 1]; ++i) {
row.insert(ja[i]);
}
}
// Set all blocks to zero.
for (int row = 0; row < size; ++row) {
for (int col_ix = ia[row]; col_ix < ia[row + 1]; ++col_ix) {
const int col = ja[col_ix];
istlA[row][col] = 0.0;
}
}
/**
* Go through all jacobians, and insert in correct spot
*
* The straight forward way to do this would be to run through each
* element in the output matrix, and set all block entries by gathering
* from all "input matrices" (derivatives).
*
* A faster alternative is to instead run through each "input matrix" and
* insert its elements in the correct spot in the output matrix.
*
*/
for (int col = 0; col < size; ++col) {
for (int p1 = 0; p1 < np; ++p1) {
for (int p2 = 0; p2 < np; ++p2) {
// Note that that since these are CSC and not CSR matrices,
// ja contains row numbers instead of column numbers.
const AutoDiffMatrix::SparseRep& s = eqs[p1].derivative()[p2].getSparse();
const int* ia = s.outerIndexPtr();
const int* ja = s.innerIndexPtr();
const double* sa = s.valuePtr();
for (int elem_ix = ia[col]; elem_ix < ia[col + 1]; ++elem_ix) {
const int row = ja[elem_ix];
istlA[row][col][p1][p2] = sa[elem_ix];
}
}
}
}
} }
/// Solve the linear system Ax = b, with A being the
/// combined derivative matrix of the residual and b
/// being the residual itself.
/// \param[in] residual residual object containing A and b.
/// \return the solution x
NewtonIterationBlackoilInterleaved::SolutionVector
NewtonIterationBlackoilInterleaved::computeNewtonIncrement(const LinearisedBlackoilResidual& residual) const
{
// get np and call appropriate template method
const int np = residual.material_balance_eq.size();
switch( np )
{
case 2:
return computeNewtonIncrementImpl< 2 >( residual );
case 3:
return computeNewtonIncrementImpl< 3 >( residual );
case 4:
return computeNewtonIncrementImpl< 4 >( residual );
case 5:
return computeNewtonIncrementImpl< 5 >( residual );
case 6:
return computeNewtonIncrementImpl< 6 >( residual );
default:
OPM_THROW(std::runtime_error,"computeNewtonIncrement: number of variables not supported yet. Consult the code to add a case for np = " << np);
return SolutionVector();
}
}
/// Solve the linear system Ax = b, with A being the
/// combined derivative matrix of the residual and b
/// being the residual itself.
/// \param[in] residual residual object containing A and b.
/// \return the solution x
template <int np>
NewtonIterationBlackoilInterleaved::SolutionVector
NewtonIterationBlackoilInterleaved::computeNewtonIncrementImpl(const LinearisedBlackoilResidual& residual) const
{
assert( np < int(newtonIncrement_.size()) );
// create NewtonIncrement with fixed np
if( ! newtonIncrement_[ np ] )
newtonIncrement_[ np ].reset( new NewtonIterationBlackoilInterleavedImpl< np >( param_, parallelInformation_ ) );
// compute newton increment
SolutionVector dx = newtonIncrement_[ np ]->computeNewtonIncrement( residual );
// get number of linear iterations
iterations_ = newtonIncrement_[ np ]->iterations();
return dx;
}
const boost::any& NewtonIterationBlackoilInterleaved::parallelInformation() const const boost::any& NewtonIterationBlackoilInterleaved::parallelInformation() const
@@ -294,7 +502,5 @@ namespace Opm
} // namespace Opm } // namespace Opm

View File

@@ -4,6 +4,7 @@
Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services Copyright 2015 Dr. Blatt - HPC-Simulation-Software & Services
Copyright 2015 NTNU Copyright 2015 NTNU
Copyright 2015 Statoil AS Copyright 2015 Statoil AS
Copyright 2015 IRIS AS
This file is part of the Open Porous Media project (OPM). This file is part of the Open Porous Media project (OPM).
@@ -32,13 +33,6 @@
#include <opm/common/utility/platform_dependent/disable_warnings.h> #include <opm/common/utility/platform_dependent/disable_warnings.h>
#include <dune/istl/scalarproducts.hh>
#include <dune/istl/operators.hh>
#include <dune/istl/preconditioners.hh>
#include <dune/istl/solvers.hh>
#include <dune/istl/owneroverlapcopy.hh>
#include <dune/istl/paamg/amg.hh>
#include <opm/common/utility/platform_dependent/reenable_warnings.h> #include <opm/common/utility/platform_dependent/reenable_warnings.h>
#include <memory> #include <memory>
@@ -51,11 +45,6 @@ namespace Opm
/// as a block-structured matrix (one block for all cell variables). /// as a block-structured matrix (one block for all cell variables).
class NewtonIterationBlackoilInterleaved : public NewtonIterationBlackoilInterface class NewtonIterationBlackoilInterleaved : public NewtonIterationBlackoilInterface
{ {
typedef Dune::FieldVector<double, 3 > VectorBlockType;
typedef Dune::FieldMatrix<double, 3, 3> MatrixBlockType;
typedef Dune::BCRSMatrix <MatrixBlockType> Mat;
typedef Dune::BlockVector<VectorBlockType> Vector;
public: public:
/// Construct a system solver. /// Construct a system solver.
@@ -86,118 +75,13 @@ namespace Opm
virtual const boost::any& parallelInformation() const; virtual const boost::any& parallelInformation() const;
private: private:
template <int np>
SolutionVector computeNewtonIncrementImpl( const LinearisedBlackoilResidual& residual ) const;
/// \brief construct the CPR preconditioner and the solver. mutable std::vector< std::unique_ptr< NewtonIterationBlackoilInterface > > newtonIncrement_;
/// \tparam P The type of the parallel information. const parameter::ParameterGroup& param_;
/// \param parallelInformation the information about the parallelization.
template<int category=Dune::SolverCategory::sequential, class O, class POrComm>
void constructPreconditionerAndSolve(O& opA,
Vector& x, Vector& istlb,
const POrComm& parallelInformation_arg,
Dune::InverseOperatorResult& result) const
{
// Construct scalar product.
typedef Dune::ScalarProductChooser<Vector, POrComm, category> ScalarProductChooser;
typedef std::unique_ptr<typename ScalarProductChooser::ScalarProduct> SPPointer;
SPPointer sp(ScalarProductChooser::construct(parallelInformation_arg));
// Construct preconditioner.
auto precond = constructPrecond(opA, parallelInformation_arg);
// Communicate if parallel.
parallelInformation_arg.copyOwnerToAll(istlb, istlb);
// Solve.
solve(opA, x, istlb, *sp, *precond, result);
}
typedef Dune::SeqILU0<Mat, Vector, Vector> SeqPreconditioner;
template <class Operator>
std::unique_ptr<SeqPreconditioner> constructPrecond(Operator& opA, const Dune::Amg::SequentialInformation&) const
{
const double relax = 1.0;
std::unique_ptr<SeqPreconditioner>
precond(new SeqPreconditioner(opA.getmat(), relax));
return precond;
}
#if HAVE_MPI
typedef Dune::OwnerOverlapCopyCommunication<int, int> Comm;
typedef Dune::BlockPreconditioner<Vector, Vector, Comm, SeqPreconditioner> ParPreconditioner;
template <class Operator>
std::unique_ptr<ParPreconditioner,
AdditionalObjectDeleter<SeqPreconditioner> >
constructPrecond(Operator& opA, const Comm& comm) const
{
typedef AdditionalObjectDeleter<SeqPreconditioner> Deleter;
typedef std::unique_ptr<ParPreconditioner, Deleter> Pointer;
int ilu_setup_successful = 1;
std::string message;
const double relax = 1.0;
SeqPreconditioner* seq_precond = nullptr;
try {
seq_precond = new SeqPreconditioner(opA.getmat(),
relax);
}
catch ( Dune::MatrixBlockError error )
{
message = error.what();
std::cerr<<"Exception occured on process " <<
comm.communicator().rank() << " during " <<
"setup of ILU0 preconditioner with message: " <<
message<<std::endl;
ilu_setup_successful = 0;
}
// Check whether there was a problem on some process
if ( comm.communicator().min(ilu_setup_successful) == 0 )
{
if ( seq_precond ) // not null if constructor succeeded
{
// prevent memory leak
delete seq_precond;
}
throw Dune::MatrixBlockError();
}
return Pointer(new ParPreconditioner(*seq_precond, comm),
Deleter(*seq_precond));
}
#endif
/// \brief Solve the system using the given preconditioner and scalar product.
template <class Operator, class ScalarProd, class Precond>
void solve(Operator& opA, Vector& x, Vector& istlb, ScalarProd& sp, Precond& precond, Dune::InverseOperatorResult& result) const
{
// TODO: Revise when linear solvers interface opm-core is done
// Construct linear solver.
// GMRes solver
if ( newton_use_gmres_ ) {
Dune::RestartedGMResSolver<Vector> linsolve(opA, sp, precond,
linear_solver_reduction_, linear_solver_restart_, linear_solver_maxiter_, linear_solver_verbosity_);
// Solve system.
linsolve.apply(x, istlb, result);
}
else { // BiCGstab solver
Dune::BiCGSTABSolver<Vector> linsolve(opA, sp, precond,
linear_solver_reduction_, linear_solver_maxiter_, linear_solver_verbosity_);
// Solve system.
linsolve.apply(x, istlb, result);
}
}
void formInterleavedSystem(const std::vector<LinearisedBlackoilResidual::ADB>& eqs,
Mat& istlA) const;
mutable int iterations_;
boost::any parallelInformation_; boost::any parallelInformation_;
mutable int iterations_;
const bool newton_use_gmres_;
const double linear_solver_reduction_;
const int linear_solver_maxiter_;
const int linear_solver_restart_;
const int linear_solver_verbosity_;
}; };
} // namespace Opm } // namespace Opm