mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Support for multiple linear solvers.
This commit is contained in:
parent
79b417beb5
commit
6ee90b3f8f
@ -594,21 +594,86 @@ namespace Opm {
|
|||||||
|
|
||||||
auto& ebosJac = ebosSimulator_.model().linearizer().jacobian().istlMatrix();
|
auto& ebosJac = ebosSimulator_.model().linearizer().jacobian().istlMatrix();
|
||||||
auto& ebosResid = ebosSimulator_.model().linearizer().residual();
|
auto& ebosResid = ebosSimulator_.model().linearizer().residual();
|
||||||
|
|
||||||
// set initial guess
|
|
||||||
x = 0.0;
|
|
||||||
|
|
||||||
auto& ebosSolver = ebosSimulator_.model().newtonMethod().linearSolver();
|
auto& ebosSolver = ebosSimulator_.model().newtonMethod().linearSolver();
|
||||||
Dune::Timer perfTimer;
|
|
||||||
perfTimer.start();
|
std::cerr<<"Hello there!!!"<<std::to_string(ebosSolver.getSolveCount())<<std::endl;
|
||||||
ebosSolver.prepare(ebosJac, ebosResid);
|
if (ebosSolver.getSolveCount()%100==0) {
|
||||||
linear_solve_setup_time_ = perfTimer.stop();
|
|
||||||
ebosSolver.setResidual(ebosResid);
|
if ( terminal_output_ ) {
|
||||||
// actually, the error needs to be calculated after setResidual in order to
|
OpmLog::debug("Running speed test");
|
||||||
// account for parallelization properly. since the residual of ECFV
|
}
|
||||||
// discretizations does not need to be synchronized across processes to be
|
Dune::Timer perfTimer;
|
||||||
// consistent, this is not relevant for OPM-flow...
|
|
||||||
ebosSolver.solve(x);
|
auto ebosJacCopy = ebosJac;
|
||||||
|
auto ebosResidCopy = ebosResid;
|
||||||
|
|
||||||
|
// solve with linear solver 0
|
||||||
|
x = 0.0;
|
||||||
|
BVector x0(x);
|
||||||
|
ebosSolver.setActiveSolver(0);
|
||||||
|
perfTimer.start();
|
||||||
|
ebosSolver.prepare(ebosJac, ebosResid);
|
||||||
|
auto linear_solve_setup_time0 = perfTimer.stop();
|
||||||
|
perfTimer.reset();
|
||||||
|
ebosSolver.setResidual(ebosResid);
|
||||||
|
perfTimer.start();
|
||||||
|
ebosSolver.solve(x0);
|
||||||
|
auto time0 = perfTimer.stop();
|
||||||
|
perfTimer.reset();
|
||||||
|
|
||||||
|
// reset matrix to the original and Rhs
|
||||||
|
ebosJac = ebosJacCopy;
|
||||||
|
ebosResid = ebosResidCopy;
|
||||||
|
|
||||||
|
// solve with linear solver 1
|
||||||
|
x = 0.0;
|
||||||
|
BVector x1(x);
|
||||||
|
ebosSolver.setActiveSolver(1);
|
||||||
|
perfTimer.start();
|
||||||
|
ebosSolver.prepare(ebosJac, ebosResid);
|
||||||
|
auto linear_solve_setup_time1 = perfTimer.stop();
|
||||||
|
perfTimer.reset();
|
||||||
|
ebosSolver.setResidual(ebosResid);
|
||||||
|
perfTimer.start();
|
||||||
|
ebosSolver.solve(x1);
|
||||||
|
auto time1 = perfTimer.stop();
|
||||||
|
perfTimer.reset();
|
||||||
|
|
||||||
|
if ( terminal_output_ ) {
|
||||||
|
OpmLog::debug("Solver time 0: " + std::to_string(time0) + "\n");
|
||||||
|
OpmLog::debug("Solver time 1: " + std::to_string(time1) + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int fastest_solver = time0 < time1 ? 0 : 1;
|
||||||
|
grid_.comm().broadcast(&fastest_solver, 1, 0);
|
||||||
|
if ( terminal_output_ ) {
|
||||||
|
OpmLog::debug("Using solver " + std::to_string(fastest_solver));
|
||||||
|
}
|
||||||
|
if (fastest_solver == 0) {
|
||||||
|
linear_solve_setup_time_ = linear_solve_setup_time0;
|
||||||
|
x=x0;
|
||||||
|
} else {
|
||||||
|
linear_solve_setup_time_ = linear_solve_setup_time1;
|
||||||
|
x=x1;
|
||||||
|
}
|
||||||
|
ebosSolver.setActiveSolver(fastest_solver);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// set initial guess
|
||||||
|
x = 0.0;
|
||||||
|
|
||||||
|
Dune::Timer perfTimer;
|
||||||
|
perfTimer.start();
|
||||||
|
ebosSolver.prepare(ebosJac, ebosResid);
|
||||||
|
linear_solve_setup_time_ = perfTimer.stop();
|
||||||
|
ebosSolver.setResidual(ebosResid);
|
||||||
|
// actually, the error needs to be calculated after setResidual in order to
|
||||||
|
// account for parallelization properly. since the residual of ECFV
|
||||||
|
// discretizations does not need to be synchronized across processes to be
|
||||||
|
// consistent, this is not relevant for OPM-flow...
|
||||||
|
ebosSolver.solve(x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
calls_( 0 ),
|
calls_( 0 ),
|
||||||
converged_(false),
|
converged_(false),
|
||||||
matrix_(nullptr),
|
matrix_(nullptr),
|
||||||
parameters_(parameters),
|
parameters_{parameters},
|
||||||
forceSerial_(forceSerial)
|
forceSerial_(forceSerial)
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
@ -199,19 +199,46 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
: simulator_(simulator),
|
: simulator_(simulator),
|
||||||
iterations_( 0 ),
|
iterations_( 0 ),
|
||||||
calls_( 0 ),
|
calls_( 0 ),
|
||||||
|
solveCount_(0),
|
||||||
converged_(false),
|
converged_(false),
|
||||||
matrix_(nullptr)
|
matrix_(nullptr)
|
||||||
{
|
{
|
||||||
parameters_.template init<TypeTag>(simulator_.vanguard().eclState().getSimulationConfig().useCPR());
|
parameters_.resize(1);
|
||||||
|
parameters_[0].template init<TypeTag>(simulator_.vanguard().eclState().getSimulationConfig().useCPR());
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initialize(bool have_gpu = false)
|
void initialize(bool have_gpu = false)
|
||||||
{
|
{
|
||||||
OPM_TIMEBLOCK(IstlSolverEbos);
|
OPM_TIMEBLOCK(IstlSolverEbos);
|
||||||
prm_ = setupPropertyTree(parameters_,
|
// prm_ = setupPropertyTree(parameters_,
|
||||||
EWOMS_PARAM_IS_SET(TypeTag, int, LinearSolverMaxIter),
|
// EWOMS_PARAM_IS_SET(TypeTag, int, LinearSolverMaxIter),
|
||||||
EWOMS_PARAM_IS_SET(TypeTag, double, LinearSolverReduction));
|
// EWOMS_PARAM_IS_SET(TypeTag, double, LinearSolverReduction));
|
||||||
|
// ------------ the following is hard coded for testing purposes!!!
|
||||||
|
prm_.clear();
|
||||||
|
parameters_.clear();
|
||||||
|
{
|
||||||
|
FlowLinearSolverParameters para;
|
||||||
|
para.init<TypeTag>(false);
|
||||||
|
para.linsolver_ = "cprw";
|
||||||
|
parameters_.push_back(para);
|
||||||
|
prm_.push_back(setupPropertyTree(parameters_[0],
|
||||||
|
EWOMS_PARAM_IS_SET(TypeTag, int, LinearSolverMaxIter),
|
||||||
|
EWOMS_PARAM_IS_SET(TypeTag, double, LinearSolverReduction)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
FlowLinearSolverParameters para;
|
||||||
|
para.init<TypeTag>(false);
|
||||||
|
para.linsolver_ = "ilu0";
|
||||||
|
parameters_.push_back(para);
|
||||||
|
prm_.push_back(setupPropertyTree(parameters_[1],
|
||||||
|
EWOMS_PARAM_IS_SET(TypeTag, int, LinearSolverMaxIter),
|
||||||
|
EWOMS_PARAM_IS_SET(TypeTag, double, LinearSolverReduction)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
flexibleSolver_.resize(prm_.size());
|
||||||
|
// ------------
|
||||||
|
|
||||||
const bool on_io_rank = (simulator_.gridView().comm().rank() == 0);
|
const bool on_io_rank = (simulator_.gridView().comm().rank() == 0);
|
||||||
#if HAVE_MPI
|
#if HAVE_MPI
|
||||||
@ -234,13 +261,19 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
OPM_THROW_NOLOG(std::runtime_error, msg);
|
OPM_THROW_NOLOG(std::runtime_error, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
flexibleSolver_.interiorCellNum_ = detail::numMatrixRowsToUseInSolver(simulator_.vanguard().grid(), true);
|
const int interiorCellNum_ = detail::numMatrixRowsToUseInSolver(simulator_.vanguard().grid(), true);
|
||||||
|
for (auto& f : flexibleSolver_) {
|
||||||
|
f.interiorCellNum_ = interiorCellNum_;
|
||||||
|
}
|
||||||
|
|
||||||
// Print parameters to PRT/DBG logs.
|
// Print parameters to PRT/DBG logs.
|
||||||
if (on_io_rank && parameters_.linear_solver_print_json_definition_) {
|
if (on_io_rank && parameters_[activeSolverNum_].linear_solver_print_json_definition_) {
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "Property tree for linear solver:\n";
|
os << "Property tree for linear solvers:\n";
|
||||||
prm_.write_json(os, true);
|
for (std::size_t i = 0; i<prm_.size(); i++) {
|
||||||
|
prm_[i].write_json(os, true);
|
||||||
|
std::cerr<< "debug: ["<<i<<"] : " << os.str() <<std::endl;
|
||||||
|
}
|
||||||
OpmLog::note(os.str());
|
OpmLog::note(os.str());
|
||||||
}
|
}
|
||||||
if(have_gpu){
|
if(have_gpu){
|
||||||
@ -256,6 +289,23 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setActiveSolver(const int num)
|
||||||
|
{
|
||||||
|
if (num>prm_.size()-1) {
|
||||||
|
OPM_THROW(std::logic_error,"Solver number"+std::to_string(num)+"not available.");
|
||||||
|
}
|
||||||
|
activeSolverNum_ = num;
|
||||||
|
auto cc = Dune::MPIHelper::getCollectiveCommunication();
|
||||||
|
if (cc.rank() == 0) {
|
||||||
|
OpmLog::note("Active solver = "+std::to_string(activeSolverNum_)+"\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int numAvailableSolvers()
|
||||||
|
{
|
||||||
|
return activeSolverNum_;
|
||||||
|
}
|
||||||
|
|
||||||
void prepare(const SparseMatrixAdapter& M, Vector& b)
|
void prepare(const SparseMatrixAdapter& M, Vector& b)
|
||||||
{
|
{
|
||||||
prepare(M.istlMatrix(), b);
|
prepare(M.istlMatrix(), b);
|
||||||
@ -290,7 +340,8 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
}
|
}
|
||||||
rhs_ = &b;
|
rhs_ = &b;
|
||||||
|
|
||||||
if (isParallel() && prm_.get<std::string>("preconditioner.type") != "ParOverILU0") {
|
// TODO: check all solvers, not just one.
|
||||||
|
if (isParallel() && prm_[activeSolverNum_].template get<std::string>("preconditioner.type") != "ParOverILU0") {
|
||||||
detail::makeOverlapRowsInvalid(getMatrix(), overlapRows_);
|
detail::makeOverlapRowsInvalid(getMatrix(), overlapRows_);
|
||||||
}
|
}
|
||||||
prepareFlexibleSolver();
|
prepareFlexibleSolver();
|
||||||
@ -312,12 +363,21 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
// matrix_ = &M.istlMatrix(); // Must be handled in prepare() instead.
|
// matrix_ = &M.istlMatrix(); // Must be handled in prepare() instead.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getSolveCount() const {
|
||||||
|
return solveCount_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetSolveCount() {
|
||||||
|
solveCount_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool solve(Vector& x)
|
bool solve(Vector& x)
|
||||||
{
|
{
|
||||||
OPM_TIMEBLOCK(istlSolverEbosSolve);
|
OPM_TIMEBLOCK(istlSolverEbosSolve);
|
||||||
|
++solveCount_;
|
||||||
calls_ += 1;
|
calls_ += 1;
|
||||||
// Write linear system if asked for.
|
// Write linear system if asked for.
|
||||||
const int verbosity = prm_.get<int>("verbosity", 0);
|
const int verbosity = prm_[activeSolverNum_].get("verbosity", 0);
|
||||||
const bool write_matrix = verbosity > 10;
|
const bool write_matrix = verbosity > 10;
|
||||||
if (write_matrix) {
|
if (write_matrix) {
|
||||||
Helper::writeSystem(simulator_, //simulator is only used to get names
|
Helper::writeSystem(simulator_, //simulator is only used to get names
|
||||||
@ -330,8 +390,8 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
Dune::InverseOperatorResult result;
|
Dune::InverseOperatorResult result;
|
||||||
{
|
{
|
||||||
OPM_TIMEBLOCK(flexibleSolverApply);
|
OPM_TIMEBLOCK(flexibleSolverApply);
|
||||||
assert(flexibleSolver_.solver_);
|
assert(flexibleSolver_[activeSolverNum_].solver_);
|
||||||
flexibleSolver_.solver_->apply(x, *rhs_, result);
|
flexibleSolver_[activeSolverNum_].solver_->apply(x, *rhs_, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check convergence, iterations etc.
|
// Check convergence, iterations etc.
|
||||||
@ -366,7 +426,7 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
iterations_ = result.iterations;
|
iterations_ = result.iterations;
|
||||||
converged_ = result.converged;
|
converged_ = result.converged;
|
||||||
if(!converged_){
|
if(!converged_){
|
||||||
if(result.reduction < parameters_.relaxed_linear_solver_reduction_){
|
if(result.reduction < parameters_[activeSolverNum_].relaxed_linear_solver_reduction_){
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss<< "Full linear solver tolerance not achived. The reduction is:" << result.reduction
|
ss<< "Full linear solver tolerance not achived. The reduction is:" << result.reduction
|
||||||
<< " after " << result.iterations << " iterations ";
|
<< " after " << result.iterations << " iterations ";
|
||||||
@ -375,7 +435,7 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for failure of linear solver.
|
// Check for failure of linear solver.
|
||||||
if (!parameters_.ignoreConvergenceFailure_ && !converged_) {
|
if (!parameters_[activeSolverNum_].ignoreConvergenceFailure_ && !converged_) {
|
||||||
const std::string msg("Convergence failure for linear solver.");
|
const std::string msg("Convergence failure for linear solver.");
|
||||||
OPM_THROW_NOLOG(NumericalProblem, msg);
|
OPM_THROW_NOLOG(NumericalProblem, msg);
|
||||||
}
|
}
|
||||||
@ -402,21 +462,21 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
|
|
||||||
if (!useWellConn_) {
|
if (!useWellConn_) {
|
||||||
auto wellOp = std::make_unique<WellModelOperator>(simulator_.problem().wellModel());
|
auto wellOp = std::make_unique<WellModelOperator>(simulator_.problem().wellModel());
|
||||||
flexibleSolver_.wellOperator_ = std::move(wellOp);
|
flexibleSolver_[activeSolverNum_].wellOperator_ = std::move(wellOp);
|
||||||
}
|
}
|
||||||
OPM_TIMEBLOCK(flexibleSolverCreate);
|
OPM_TIMEBLOCK(flexibleSolverCreate);
|
||||||
flexibleSolver_.create(getMatrix(),
|
flexibleSolver_[activeSolverNum_].create(getMatrix(),
|
||||||
isParallel(),
|
isParallel(),
|
||||||
prm_,
|
prm_[activeSolverNum_],
|
||||||
pressureIndex,
|
pressureIndex,
|
||||||
trueFunc,
|
trueFunc,
|
||||||
forceSerial_,
|
forceSerial_,
|
||||||
*comm_);
|
*comm_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OPM_TIMEBLOCK(flexibleSolverUpdate);
|
OPM_TIMEBLOCK(flexibleSolverUpdate);
|
||||||
flexibleSolver_.pre_->update();
|
flexibleSolver_[activeSolverNum_].pre_->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,36 +487,39 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
{
|
{
|
||||||
// Decide if we should recreate the solver or just do
|
// Decide if we should recreate the solver or just do
|
||||||
// a minimal preconditioner update.
|
// a minimal preconditioner update.
|
||||||
if (!flexibleSolver_.solver_) {
|
if (flexibleSolver_.empty()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this->parameters_.cpr_reuse_setup_ == 0) {
|
if (!flexibleSolver_[activeSolverNum_].solver_) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (this->parameters_[activeSolverNum_].cpr_reuse_setup_ == 0) {
|
||||||
// Always recreate solver.
|
// Always recreate solver.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (this->parameters_.cpr_reuse_setup_ == 1) {
|
if (this->parameters_[activeSolverNum_].cpr_reuse_setup_ == 1) {
|
||||||
// Recreate solver on the first iteration of every timestep.
|
// Recreate solver on the first iteration of every timestep.
|
||||||
const int newton_iteration = this->simulator_.model().newtonMethod().numIterations();
|
const int newton_iteration = this->simulator_.model().newtonMethod().numIterations();
|
||||||
return newton_iteration == 0;
|
return newton_iteration == 0;
|
||||||
}
|
}
|
||||||
if (this->parameters_.cpr_reuse_setup_ == 2) {
|
if (this->parameters_[activeSolverNum_].cpr_reuse_setup_ == 2) {
|
||||||
// Recreate solver if the last solve used more than 10 iterations.
|
// Recreate solver if the last solve used more than 10 iterations.
|
||||||
return this->iterations() > 10;
|
return this->iterations() > 10;
|
||||||
}
|
}
|
||||||
if (this->parameters_.cpr_reuse_setup_ == 3) {
|
if (this->parameters_[activeSolverNum_].cpr_reuse_setup_ == 3) {
|
||||||
// Recreate solver if the last solve used more than 10 iterations.
|
// Recreate solver if the last solve used more than 10 iterations.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this->parameters_.cpr_reuse_setup_ == 4) {
|
if (this->parameters_[activeSolverNum_].cpr_reuse_setup_ == 4) {
|
||||||
// Recreate solver every 'step' solve calls.
|
// Recreate solver every 'step' solve calls.
|
||||||
const int step = this->parameters_.cpr_reuse_interval_;
|
const int step = this->parameters_[activeSolverNum_].cpr_reuse_interval_;
|
||||||
const bool create = ((calls_ % step) == 0);
|
const bool create = ((calls_ % step) == 0);
|
||||||
return create;
|
return create;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If here, we have an invalid parameter.
|
// If here, we have an invalid parameter.
|
||||||
const bool on_io_rank = (simulator_.gridView().comm().rank() == 0);
|
const bool on_io_rank = (simulator_.gridView().comm().rank() == 0);
|
||||||
std::string msg = "Invalid value: " + std::to_string(this->parameters_.cpr_reuse_setup_)
|
std::string msg = "Invalid value: " + std::to_string(this->parameters_[activeSolverNum_].cpr_reuse_setup_)
|
||||||
+ " for --cpr-reuse-setup parameter, run with --help to see allowed values.";
|
+ " for --cpr-reuse-setup parameter, run with --help to see allowed values.";
|
||||||
if (on_io_rank) {
|
if (on_io_rank) {
|
||||||
OpmLog::error(msg);
|
OpmLog::error(msg);
|
||||||
@ -496,6 +559,7 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
const Simulator& simulator_;
|
const Simulator& simulator_;
|
||||||
mutable int iterations_;
|
mutable int iterations_;
|
||||||
mutable int calls_;
|
mutable int calls_;
|
||||||
|
mutable int solveCount_;
|
||||||
mutable bool converged_;
|
mutable bool converged_;
|
||||||
std::any parallelInformation_;
|
std::any parallelInformation_;
|
||||||
|
|
||||||
@ -503,15 +567,16 @@ std::unique_ptr<Matrix> blockJacobiAdjacency(const Grid& grid,
|
|||||||
Matrix* matrix_;
|
Matrix* matrix_;
|
||||||
Vector *rhs_;
|
Vector *rhs_;
|
||||||
|
|
||||||
detail::FlexibleSolverInfo<Matrix,Vector,CommunicationType> flexibleSolver_;
|
int activeSolverNum_ = 0;
|
||||||
|
std::vector<detail::FlexibleSolverInfo<Matrix,Vector,CommunicationType>> flexibleSolver_;
|
||||||
std::vector<int> overlapRows_;
|
std::vector<int> overlapRows_;
|
||||||
std::vector<int> interiorRows_;
|
std::vector<int> interiorRows_;
|
||||||
|
|
||||||
bool useWellConn_;
|
bool useWellConn_;
|
||||||
|
|
||||||
FlowLinearSolverParameters parameters_;
|
std::vector<FlowLinearSolverParameters> parameters_;
|
||||||
bool forceSerial_ = false;
|
bool forceSerial_ = false;
|
||||||
PropertyTree prm_;
|
std::vector<PropertyTree> prm_;
|
||||||
|
|
||||||
std::shared_ptr< CommunicationType > comm_;
|
std::shared_ptr< CommunicationType > comm_;
|
||||||
}; // end ISTLSolver
|
}; // end ISTLSolver
|
||||||
|
@ -30,8 +30,8 @@ namespace Opm
|
|||||||
struct FlowLinearSolverParameters;
|
struct FlowLinearSolverParameters;
|
||||||
|
|
||||||
PropertyTree setupPropertyTree(FlowLinearSolverParameters p,
|
PropertyTree setupPropertyTree(FlowLinearSolverParameters p,
|
||||||
bool LinearSolverMaxIterSet,
|
bool linearSolverMaxIterSet,
|
||||||
bool CprMaxEllIterSet);
|
bool linearSolverReductionSet);
|
||||||
|
|
||||||
PropertyTree setupCPRW(const std::string& conf, const FlowLinearSolverParameters& p);
|
PropertyTree setupCPRW(const std::string& conf, const FlowLinearSolverParameters& p);
|
||||||
PropertyTree setupCPR(const std::string& conf, const FlowLinearSolverParameters& p);
|
PropertyTree setupCPR(const std::string& conf, const FlowLinearSolverParameters& p);
|
||||||
|
Loading…
Reference in New Issue
Block a user