mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-08-05 09:57:18 -05:00
- taking pullrequest information into account
- Moving transfere level to be template of OwningTwolevelPrecontitioner
This commit is contained in:
committed by
Atgeirr Flø Rasmussen
parent
8f4cf8a952
commit
4ead854b69
@@ -326,8 +326,8 @@ namespace Opm
|
||||
EWOMS_REGISTER_PARAM(TypeTag, bool, LinearSolverIgnoreConvergenceFailure, "Continue with the simulation like nothing happened after the linear solver did not converge");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, bool, ScaleLinearSystem, "Scale linear system according to equation scale and primary variable types");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, int, CprMaxEllIter, "MaxIterations of the elliptic pressure part of the cpr solver");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, int, CprReuseSetup, "Reuse preconditioner setup. Valid options are 0: recreate the preconditioner for every linear solve, 1: recreate once every timestep, 2: recreate if last linear solve took more than 10 iterations, 3: never recreate, 4: recreated wevery CprReuseInterval");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, int, CprReuseInterval, "Reuse preconditioner interval. used with CprReuseSetup 4");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, int, CprReuseSetup, "Reuse preconditioner setup. Valid options are 0: recreate the preconditioner for every linear solve, 1: recreate once every timestep, 2: recreate if last linear solve took more than 10 iterations, 3: never recreate, 4: recreated every CprReuseInterval");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, int, CprReuseInterval, "Rese preconditioner interval. Used with CprReuseSetup 4");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, std::string, Linsolver, "Configuration of solver. Valid options are: ilu0 (default), cpr (an alias for cpr_trueimpes), cpr_quasiimpes, cpr_trueimpes or amg. Alternatively, you can request a configuration to be read from a JSON file by giving the filename here, ending with '.json.'");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, std::string, AcceleratorMode, "Use GPU (cusparseSolver or openclSolver) or FPGA (fpgaSolver) as the linear solver, usage: '--accelerator-mode=[none|cusparse|opencl|fpga|amgcl]'");
|
||||
EWOMS_REGISTER_PARAM(TypeTag, int, BdaDeviceId, "Choose device ID for cusparseSolver or openclSolver, use 'nvidia-smi' or 'clinfo' to determine valid IDs");
|
||||
|
||||
@@ -479,7 +479,6 @@ namespace Opm
|
||||
|| preconditionerType == "cprw" || preconditionerType == "cprwt") {
|
||||
const bool transpose = preconditionerType == "cprt" || preconditionerType == "cprwt";
|
||||
const auto weightsType = prm_.get("preconditioner.weight_type"s, "quasiimpes"s);
|
||||
const auto pressureIndex = this->prm_.get("preconditioner.pressure_var_index", 1);
|
||||
if (weightsType == "quasiimpes") {
|
||||
// weights will be created as default in the solver
|
||||
// assignment p = pressureIndex prevent compiler warning about
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
|
||||
#include <opm/simulators/linalg/PreconditionerWithUpdate.hpp>
|
||||
#include <opm/simulators/linalg/PressureSolverPolicy.hpp>
|
||||
#include <opm/simulators/linalg/PressureTransferPolicy.hpp>
|
||||
#include <opm/simulators/linalg/getQuasiImpesWeights.hpp>
|
||||
#include <opm/simulators/linalg/twolevelmethodcpr.hh>
|
||||
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
@@ -75,13 +73,14 @@ std::ostream& operator<<(std::ostream& out,
|
||||
/// and preconditioner factory.
|
||||
template <class OperatorType,
|
||||
class VectorType,
|
||||
bool transpose = false,
|
||||
class LevelTransferPolicy,
|
||||
class Communication = Dune::Amg::SequentialInformation>
|
||||
class OwningTwoLevelPreconditioner : public Dune::PreconditionerWithUpdate<VectorType, VectorType>
|
||||
{
|
||||
public:
|
||||
using MatrixType = typename OperatorType::matrix_type;
|
||||
using PrecFactory = Opm::PreconditionerFactory<OperatorType, Communication>;
|
||||
using AbstractOperatorType = Dune::AssembledLinearOperator<MatrixType, VectorType, VectorType>;
|
||||
|
||||
OwningTwoLevelPreconditioner(const OperatorType& linearoperator, const Opm::PropertyTree& prm,
|
||||
const std::function<VectorType()> weightsCalculator,
|
||||
@@ -94,14 +93,14 @@ public:
|
||||
, comm_(nullptr)
|
||||
, weightsCalculator_(weightsCalculator)
|
||||
, weights_(weightsCalculator())
|
||||
, levelTransferPolicy_(dummy_comm_, weights_, pressureIndex)
|
||||
, coarseSolverPolicy_(prm.get_child_optional("coarsesolver")? prm.get_child("coarsesolver") : Opm::PropertyTree())
|
||||
, levelTransferPolicy_(dummy_comm_, weights_, prm, pressureIndex)
|
||||
, coarseSolverPolicy_(prm.get_child_optional("coarsesolver") ? prm.get_child("coarsesolver") : Opm::PropertyTree())
|
||||
, twolevel_method_(linearoperator,
|
||||
finesmoother_,
|
||||
levelTransferPolicy_,
|
||||
coarseSolverPolicy_,
|
||||
prm.get<int>("pre_smooth", transpose? 1 : 0),
|
||||
prm.get<int>("post_smooth", transpose? 0 : 1))
|
||||
prm.get<int>("pre_smooth", 0),
|
||||
prm.get<int>("post_smooth", 1))
|
||||
, prm_(prm)
|
||||
{
|
||||
if (prm.get<int>("verbosity", 0) > 10) {
|
||||
@@ -126,14 +125,14 @@ public:
|
||||
, comm_(&comm)
|
||||
, weightsCalculator_(weightsCalculator)
|
||||
, weights_(weightsCalculator())
|
||||
, levelTransferPolicy_(*comm_, weights_, pressureIndex)
|
||||
, coarseSolverPolicy_(prm.get_child_optional("coarsesolver")? prm.get_child("coarsesolver") : Opm::PropertyTree())
|
||||
, levelTransferPolicy_(*comm_, weights_, prm, pressureIndex)
|
||||
, coarseSolverPolicy_(prm.get_child_optional("coarsesolver") ? prm.get_child("coarsesolver") : Opm::PropertyTree())
|
||||
, twolevel_method_(linearoperator,
|
||||
finesmoother_,
|
||||
levelTransferPolicy_,
|
||||
coarseSolverPolicy_,
|
||||
prm.get<int>("pre_smooth", transpose? 1 : 0),
|
||||
prm.get<int>("post_smooth", transpose? 0 : 1))
|
||||
prm.get<int>("pre_smooth", 0),
|
||||
prm.get<int>("post_smooth", 1))
|
||||
, prm_(prm)
|
||||
{
|
||||
if (prm.get<int>("verbosity", 0) > 10 && comm.communicator().rank() == 0) {
|
||||
@@ -173,17 +172,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
using PressureMatrixType = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||
using PressureVectorType = Dune::BlockVector<Dune::FieldVector<double, 1>>;
|
||||
using SeqCoarseOperatorType = Dune::MatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType>;
|
||||
using ParCoarseOperatorType
|
||||
= Dune::OverlappingSchwarzOperator<PressureMatrixType, PressureVectorType, PressureVectorType, Communication>;
|
||||
using CoarseOperatorType = std::conditional_t<std::is_same<Communication, Dune::Amg::SequentialInformation>::value,
|
||||
SeqCoarseOperatorType,
|
||||
ParCoarseOperatorType>;
|
||||
using LevelTransferPolicy = Opm::PressureTransferPolicy<OperatorType, CoarseOperatorType, Communication, transpose>;
|
||||
using CoarseSolverPolicy = Dune::Amg::PressureSolverPolicy<CoarseOperatorType,
|
||||
FlexibleSolver<CoarseOperatorType>,
|
||||
using CoarseOperator = typename LevelTransferPolicy::CoarseOperator;
|
||||
using CoarseSolverPolicy = Dune::Amg::PressureSolverPolicy<CoarseOperator,
|
||||
FlexibleSolver<CoarseOperator>,
|
||||
LevelTransferPolicy>;
|
||||
using TwoLevelMethod
|
||||
= Dune::Amg::TwoLevelMethodCpr<OperatorType, CoarseSolverPolicy, Dune::Preconditioner<VectorType, VectorType>>;
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
|
||||
|
||||
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 3 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <opm/simulators/linalg/PreconditionerWithUpdate.hpp>
|
||||
#include <opm/simulators/linalg/PressureSolverPolicy.hpp>
|
||||
#include <opm/simulators/linalg/PressureBhpTransferPolicy.hpp>
|
||||
#include <opm/simulators/linalg/getQuasiImpesWeights.hpp>
|
||||
#include <opm/simulators/linalg/twolevelmethodcpr.hh>
|
||||
|
||||
#include <opm/common/ErrorMacros.hpp>
|
||||
|
||||
#include <dune/common/fmatrix.hh>
|
||||
#include <dune/istl/bcrsmatrix.hh>
|
||||
#include <dune/istl/paamg/amg.hh>
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include <fstream>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
// Circular dependency between PreconditionerFactory [which can make an OwningTwoLevelPreconditioner]
|
||||
// and OwningTwoLevelPreconditioner [which uses PreconditionerFactory to choose the fine-level smoother]
|
||||
// must be broken, accomplished by forward-declaration here.
|
||||
//template <class Operator, class Comm = Dune::Amg::SequentialInformation>
|
||||
//class PreconditionerFactory;
|
||||
}
|
||||
|
||||
namespace Dune
|
||||
{
|
||||
|
||||
|
||||
// Must forward-declare FlexibleSolver as we want to use it as solver for the pressure system.
|
||||
template <class Operator>
|
||||
class FlexibleSolver;
|
||||
|
||||
// template <typename T, typename A, int i>
|
||||
// std::ostream& operator<<(std::ostream& out,
|
||||
// const BlockVector< FieldVector< T, i >, A >& vector)
|
||||
// {
|
||||
// Dune::writeMatrixMarket(vector, out);
|
||||
// return out;
|
||||
// }
|
||||
|
||||
// template <typename T, typename A, int i>
|
||||
// std::istream& operator>>(std::istream& input,
|
||||
// BlockVector< FieldVector< T, i >, A >& vector)
|
||||
// {
|
||||
// Dune::readMatrixMarket(vector, input);
|
||||
// return input;
|
||||
// }
|
||||
|
||||
/// A version of the two-level preconditioner that is:
|
||||
/// - Self-contained, because it owns its policy components.
|
||||
/// - Flexible, because it uses the runtime-flexible solver
|
||||
/// and preconditioner factory.
|
||||
template <class OperatorType,
|
||||
class VectorType,
|
||||
bool transpose = false,
|
||||
class Communication = Dune::Amg::SequentialInformation>
|
||||
class OwningTwoLevelPreconditionerWell : public Dune::PreconditionerWithUpdate<VectorType, VectorType>
|
||||
{
|
||||
public:
|
||||
using MatrixType = typename OperatorType::matrix_type;
|
||||
using PrecFactory = Opm::PreconditionerFactory<OperatorType, Communication>;
|
||||
using AbstractOperatorType = Dune::AssembledLinearOperator<MatrixType, VectorType, VectorType>;
|
||||
|
||||
OwningTwoLevelPreconditionerWell(const OperatorType& linearoperator,
|
||||
const Opm::PropertyTree& prm,
|
||||
const std::function<VectorType()> weightsCalculator,
|
||||
const std::size_t pressureIndex)
|
||||
: linear_operator_(linearoperator)
|
||||
, finesmoother_(PrecFactory::create(linearoperator,
|
||||
prm.get_child_optional("finesmoother")?
|
||||
prm.get_child("finesmoother") : Opm::PropertyTree()))
|
||||
, comm_(nullptr)
|
||||
, weightsCalculator_(weightsCalculator)
|
||||
, weights_(weightsCalculator())
|
||||
, levelTransferPolicy_(dummy_comm_, weights_, prm, pressureIndex)
|
||||
, coarseSolverPolicy_(prm.get_child_optional("coarsesolver") ? prm.get_child("coarsesolver") : Opm::PropertyTree())
|
||||
, twolevel_method_(linearoperator,
|
||||
finesmoother_,
|
||||
levelTransferPolicy_,
|
||||
coarseSolverPolicy_,
|
||||
prm.get<int>("pre_smooth", transpose? 1 : 0),
|
||||
prm.get<int>("post_smooth", transpose? 0 : 1))
|
||||
, prm_(prm)
|
||||
{
|
||||
if (prm.get<int>("verbosity", 0) > 10) {
|
||||
std::string filename = prm.get<std::string>("weights_filename", "impes_weights.txt");
|
||||
std::ofstream outfile(filename);
|
||||
if (!outfile) {
|
||||
OPM_THROW(std::ofstream::failure, "Could not write weights to file " << filename << ".");
|
||||
}
|
||||
Dune::writeMatrixMarket(weights_, outfile);
|
||||
}
|
||||
}
|
||||
|
||||
OwningTwoLevelPreconditionerWell(const OperatorType& linearoperator,
|
||||
const Opm::PropertyTree& prm,
|
||||
const std::function<VectorType()> weightsCalculator,
|
||||
const std::size_t pressureIndex,
|
||||
const Communication& comm)
|
||||
: linear_operator_(linearoperator)
|
||||
, finesmoother_(PrecFactory::create(linearoperator,
|
||||
prm.get_child_optional("finesmoother")?
|
||||
prm.get_child("finesmoother") : Opm::PropertyTree(), comm))
|
||||
, comm_(&comm)
|
||||
, weightsCalculator_(weightsCalculator)
|
||||
, weights_(weightsCalculator())
|
||||
, levelTransferPolicy_(*comm_, weights_, prm, pressureIndex)
|
||||
, coarseSolverPolicy_(prm.get_child_optional("coarsesolver") ? prm.get_child("coarsesolver") : Opm::PropertyTree())
|
||||
, twolevel_method_(linearoperator,
|
||||
finesmoother_,
|
||||
levelTransferPolicy_,
|
||||
coarseSolverPolicy_,
|
||||
prm.get<int>("pre_smooth", transpose? 1 : 0),
|
||||
prm.get<int>("post_smooth", transpose? 0 : 1))
|
||||
, prm_(prm)
|
||||
{
|
||||
if (prm.get<int>("verbosity", 0) > 10 && comm.communicator().rank() == 0) {
|
||||
auto filename = prm.get<std::string>("weights_filename", "impes_weights.txt");
|
||||
std::ofstream outfile(filename);
|
||||
if (!outfile) {
|
||||
OPM_THROW(std::ofstream::failure, "Could not write weights to file " << filename << ".");
|
||||
}
|
||||
Dune::writeMatrixMarket(weights_, outfile);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void pre(VectorType& x, VectorType& b) override
|
||||
{
|
||||
twolevel_method_.pre(x, b);
|
||||
}
|
||||
|
||||
virtual void apply(VectorType& v, const VectorType& d) override
|
||||
{
|
||||
twolevel_method_.apply(v, d);
|
||||
}
|
||||
|
||||
virtual void post(VectorType& x) override
|
||||
{
|
||||
twolevel_method_.post(x);
|
||||
}
|
||||
|
||||
virtual void update() override
|
||||
{
|
||||
weights_ = weightsCalculator_();
|
||||
updateImpl(comm_);
|
||||
}
|
||||
|
||||
virtual Dune::SolverCategory::Category category() const override
|
||||
{
|
||||
return linear_operator_.category();
|
||||
}
|
||||
|
||||
private:
|
||||
using PressureMatrixType = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||
using PressureVectorType = Dune::BlockVector<Dune::FieldVector<double, 1>>;
|
||||
using SeqCoarseOperatorType = Dune::MatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType>;
|
||||
using ParCoarseOperatorType
|
||||
= Dune::OverlappingSchwarzOperator<PressureMatrixType, PressureVectorType, PressureVectorType, Communication>;
|
||||
using CoarseOperatorType = std::conditional_t<std::is_same<Communication, Dune::Amg::SequentialInformation>::value,
|
||||
SeqCoarseOperatorType,
|
||||
ParCoarseOperatorType>;
|
||||
using LevelTransferPolicy = Opm::PressureBhpTransferPolicy<OperatorType, CoarseOperatorType, Communication, transpose>;
|
||||
using CoarseSolverPolicy = Dune::Amg::PressureSolverPolicy<CoarseOperatorType,
|
||||
FlexibleSolver<CoarseOperatorType>,
|
||||
LevelTransferPolicy>;
|
||||
using TwoLevelMethod
|
||||
= Dune::Amg::TwoLevelMethodCpr<OperatorType, CoarseSolverPolicy, Dune::Preconditioner<VectorType, VectorType>>;
|
||||
|
||||
// Handling parallel vs serial instantiation of preconditioner factory.
|
||||
template <class Comm>
|
||||
void updateImpl(const Comm*)
|
||||
{
|
||||
// Parallel case.
|
||||
// using ParOperatorType = Dune::OverlappingSchwarzOperator<MatrixType, VectorType, VectorType, Comm>;
|
||||
// auto op_prec = std::make_shared<ParOperatorType>(linear_operator_.getmat(), *comm_);
|
||||
auto child = prm_.get_child_optional("finesmoother");
|
||||
finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : Opm::PropertyTree(), *comm_);
|
||||
twolevel_method_.updatePreconditioner(finesmoother_, coarseSolverPolicy_);
|
||||
// linearoperator_for_precond_ = op_prec;
|
||||
}
|
||||
|
||||
void updateImpl(const Dune::Amg::SequentialInformation*)
|
||||
{
|
||||
// Serial case.
|
||||
// using SeqOperatorType = Dune::MatrixAdapter<MatrixType, VectorType, VectorType>;
|
||||
// auto op_prec = std::make_shared<SeqOperatorType>(linear_operator_.getmat());
|
||||
auto child = prm_.get_child_optional("finesmoother");
|
||||
finesmoother_ = PrecFactory::create(linear_operator_, child ? *child : Opm::PropertyTree());
|
||||
twolevel_method_.updatePreconditioner(finesmoother_, coarseSolverPolicy_);
|
||||
// linearoperator_for_precond_ = op_prec;
|
||||
}
|
||||
|
||||
const OperatorType& linear_operator_;
|
||||
std::shared_ptr<Dune::Preconditioner<VectorType, VectorType>> finesmoother_;
|
||||
const Communication* comm_;
|
||||
std::function<VectorType()> weightsCalculator_;
|
||||
VectorType weights_;
|
||||
LevelTransferPolicy levelTransferPolicy_;
|
||||
CoarseSolverPolicy coarseSolverPolicy_;
|
||||
TwoLevelMethod twolevel_method_;
|
||||
Opm::PropertyTree prm_;
|
||||
Communication dummy_comm_;
|
||||
//std::shared_ptr<AbstractOperatorType> linearoperator_for_precond_;
|
||||
};
|
||||
|
||||
} // namespace Dune
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -24,13 +24,16 @@
|
||||
|
||||
#include <opm/simulators/linalg/OwningBlockPreconditioner.hpp>
|
||||
#include <opm/simulators/linalg/OwningTwoLevelPreconditioner.hpp>
|
||||
#include <opm/simulators/linalg/OwningTwoLevelPreconditionerWell.hpp>
|
||||
#include <opm/simulators/linalg/ParallelOverlappingILU0.hpp>
|
||||
#include <opm/simulators/linalg/PreconditionerWithUpdate.hpp>
|
||||
#include <opm/simulators/linalg/PropertyTree.hpp>
|
||||
#include <opm/simulators/linalg/amgcpr.hh>
|
||||
#include <opm/simulators/linalg/WellOperators.hpp>
|
||||
|
||||
#include <opm/simulators/linalg/PressureTransferPolicy.hpp>
|
||||
#include <opm/simulators/linalg/PressureBhpTransferPolicy.hpp>
|
||||
|
||||
|
||||
#include <dune/istl/paamg/amg.hh>
|
||||
#include <dune/istl/paamg/kamg.hh>
|
||||
#include <dune/istl/paamg/fastamg.hh>
|
||||
@@ -320,7 +323,8 @@ private:
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||
}
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, false, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
|
||||
using LevelTransferPolicy = Opm::PressureTransferPolicy<O, Comm, false>;
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
|
||||
});
|
||||
doAddCreator("cprt", [](const O& op, const P& prm, const std::function<Vector()> weightsCalculator, std::size_t pressureIndex, const C& comm) {
|
||||
assert(weightsCalculator);
|
||||
@@ -328,7 +332,8 @@ private:
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||
}
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, true, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
|
||||
using LevelTransferPolicy = Opm::PressureTransferPolicy<O, Comm, true>;
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(op, prm, weightsCalculator, pressureIndex, comm);
|
||||
});
|
||||
|
||||
if constexpr (std::is_same_v<O, WellModelGhostLastMatrixAdapter<M, V, V, true>>) {
|
||||
@@ -338,16 +343,8 @@ private:
|
||||
if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
|
||||
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||
}
|
||||
return std::make_shared<OwningTwoLevelPreconditionerWell<O, V, false, Comm>>(
|
||||
op, prm, weightsCalculator, pressureIndex, comm);
|
||||
});
|
||||
doAddCreator("cprwt",
|
||||
[](const O& op, const P& prm, const std::function<Vector()> weightsCalculator, std::size_t pressureIndex, const C& comm) {
|
||||
assert(weightsCalculator);
|
||||
if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
|
||||
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||
}
|
||||
return std::make_shared<OwningTwoLevelPreconditionerWell<O, V, true, Comm>>(
|
||||
using LevelTransferPolicy = Opm::PressureBhpTransferPolicy<O, Comm, false>;
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy, Comm>>(
|
||||
op, prm, weightsCalculator, pressureIndex, comm);
|
||||
});
|
||||
}
|
||||
@@ -477,13 +474,8 @@ private:
|
||||
if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
|
||||
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||
}
|
||||
return std::make_shared<OwningTwoLevelPreconditionerWell<O, V, false>>(op, prm, weightsCalculator, pressureIndex);
|
||||
});
|
||||
doAddCreator("cprwt", [](const O& op, const P& prm, const std::function<Vector()>& weightsCalculator, std::size_t pressureIndex) {
|
||||
if (pressureIndex == std::numeric_limits<std::size_t>::max()) {
|
||||
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||
}
|
||||
return std::make_shared<OwningTwoLevelPreconditionerWell<O, V, true>>(op, prm, weightsCalculator, pressureIndex);
|
||||
using LevelTransferPolicy = Opm::PressureBhpTransferPolicy<O, Dune::Amg::SequentialInformation, false>;
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(op, prm, weightsCalculator, pressureIndex);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -492,14 +484,16 @@ private:
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||
}
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, false>>(op, prm, weightsCalculator, pressureIndex);
|
||||
using LevelTransferPolicy = Opm::PressureTransferPolicy<O, Dune::Amg::SequentialInformation, false>;
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(op, prm, weightsCalculator, pressureIndex);
|
||||
});
|
||||
doAddCreator("cprt", [](const O& op, const P& prm, const std::function<Vector()>& weightsCalculator, std::size_t pressureIndex) {
|
||||
if (pressureIndex == std::numeric_limits<std::size_t>::max())
|
||||
{
|
||||
OPM_THROW(std::logic_error, "Pressure index out of bounds. It needs to specified for CPR");
|
||||
}
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, true>>(op, prm, weightsCalculator, pressureIndex);
|
||||
using LevelTransferPolicy = Opm::PressureTransferPolicy<O, Dune::Amg::SequentialInformation, true>;
|
||||
return std::make_shared<OwningTwoLevelPreconditioner<O, V, LevelTransferPolicy>>(op, prm, weightsCalculator, pressureIndex);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -66,13 +66,24 @@ namespace Opm
|
||||
commRW->remoteIndices().template rebuild<true>();
|
||||
//commRW->clearInterfaces(); may need this for correct rebuild
|
||||
}
|
||||
namespace Details {
|
||||
using PressureMatrixType = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||
using PressureVectorType = Dune::BlockVector<Dune::FieldVector<double, 1>>;
|
||||
using SeqCoarseOperatorType = Dune::MatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType>;
|
||||
template <class Comm>
|
||||
using ParCoarseOperatorType
|
||||
= Dune::OverlappingSchwarzOperator<PressureMatrixType, PressureVectorType, PressureVectorType, Comm>;
|
||||
template <class Comm>
|
||||
using CoarseOperatorType = std::conditional_t<std::is_same<Comm, Dune::Amg::SequentialInformation>::value,
|
||||
SeqCoarseOperatorType,
|
||||
ParCoarseOperatorType<Comm>>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class FineOperator, class CoarseOperator, class Communication, bool transpose = false>
|
||||
class PressureBhpTransferPolicy : public Dune::Amg::LevelTransferPolicyCpr<FineOperator, CoarseOperator>
|
||||
template <class FineOperator, class Communication, bool transpose = false>
|
||||
class PressureBhpTransferPolicy : public Dune::Amg::LevelTransferPolicyCpr<FineOperator, Details::CoarseOperatorType<Communication>>
|
||||
{
|
||||
public:
|
||||
typedef typename Details::CoarseOperatorType<Communication> CoarseOperator;
|
||||
typedef Dune::Amg::LevelTransferPolicyCpr<FineOperator, CoarseOperator> ParentType;
|
||||
typedef Communication ParallelInformation;
|
||||
typedef typename FineOperator::domain_type FineVectorType;
|
||||
|
||||
@@ -28,16 +28,33 @@
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
template <class FineOperator, class CoarseOperator, class Communication, bool transpose = false>
|
||||
class PressureTransferPolicy : public Dune::Amg::LevelTransferPolicyCpr<FineOperator, CoarseOperator>
|
||||
namespace Details {
|
||||
using PressureMatrixType = Dune::BCRSMatrix<Dune::FieldMatrix<double, 1, 1>>;
|
||||
using PressureVectorType = Dune::BlockVector<Dune::FieldVector<double, 1>>;
|
||||
using SeqCoarseOperatorType = Dune::MatrixAdapter<PressureMatrixType, PressureVectorType, PressureVectorType>;
|
||||
template <class Comm>
|
||||
using ParCoarseOperatorType
|
||||
= Dune::OverlappingSchwarzOperator<PressureMatrixType, PressureVectorType, PressureVectorType, Comm>;
|
||||
template <class Comm>
|
||||
using CoarseOperatorType = std::conditional_t<std::is_same<Comm, Dune::Amg::SequentialInformation>::value,
|
||||
SeqCoarseOperatorType,
|
||||
ParCoarseOperatorType<Comm>>;
|
||||
}
|
||||
|
||||
template <class FineOperator, class Communication, bool transpose = false>
|
||||
class PressureTransferPolicy : public Dune::Amg::LevelTransferPolicyCpr<FineOperator, Details::CoarseOperatorType<Communication>>
|
||||
{
|
||||
public:
|
||||
typedef typename Details::CoarseOperatorType<Communication> CoarseOperator;
|
||||
typedef Dune::Amg::LevelTransferPolicyCpr<FineOperator, CoarseOperator> ParentType;
|
||||
typedef Communication ParallelInformation;
|
||||
typedef typename FineOperator::domain_type FineVectorType;
|
||||
|
||||
public:
|
||||
PressureTransferPolicy(const Communication& comm, const FineVectorType& weights, int pressure_var_index)
|
||||
PressureTransferPolicy(const Communication& comm,
|
||||
const FineVectorType& weights,
|
||||
const Opm::PropertyTree& /*prm*/,
|
||||
int pressure_var_index)
|
||||
: communication_(&const_cast<Communication&>(comm))
|
||||
, weights_(weights)
|
||||
, pressure_var_index_(pressure_var_index)
|
||||
|
||||
@@ -398,7 +398,7 @@ namespace Opm {
|
||||
|
||||
int reportStepIndex() const;
|
||||
|
||||
void assembleWellEq(const double dt, Opm::DeferredLogger& deferred_logger);
|
||||
void assembleWellEq(const double dt, DeferredLogger& deferred_logger);
|
||||
|
||||
bool maybeDoGasLiftOptimize(DeferredLogger& deferred_logger);
|
||||
|
||||
|
||||
@@ -1190,12 +1190,12 @@ namespace Opm {
|
||||
{
|
||||
int nw = this->numLocalWellsEnd();
|
||||
int rdofs = local_num_cells_;
|
||||
for(int i=0; i < nw; i++){
|
||||
for ( int i = 0; i < nw; i++ ){
|
||||
int wdof = rdofs + i;
|
||||
jacobian[wdof][wdof] = 1.0;// better scaling ?
|
||||
}
|
||||
|
||||
for (const auto& well : well_container_) {
|
||||
for ( const auto& well : well_container_ ) {
|
||||
well->addWellPressureEquations(jacobian, weights, pressureVarIndex, use_well_weights, this->wellState());
|
||||
}
|
||||
}
|
||||
@@ -1226,7 +1226,7 @@ namespace Opm {
|
||||
std::vector<int> cartesianToCompressed(size, -1);
|
||||
auto begin = globalCell.begin();
|
||||
|
||||
for ( auto cell = begin, end= globalCell.end(); cell != end; ++cell )
|
||||
for ( auto cell = begin, end = globalCell.end(); cell != end; ++cell )
|
||||
{
|
||||
cartesianToCompressed[ *cell ] = cell - begin;
|
||||
}
|
||||
@@ -1258,13 +1258,12 @@ namespace Opm {
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! compressed_well_perforations.empty() )
|
||||
{
|
||||
std::sort(compressed_well_perforations.begin(),
|
||||
compressed_well_perforations.end());
|
||||
// also include wells with no perforations in case
|
||||
std::sort(compressed_well_perforations.begin(),
|
||||
compressed_well_perforations.end());
|
||||
|
||||
wells.push_back(compressed_well_perforations);
|
||||
}
|
||||
wells.push_back(compressed_well_perforations);
|
||||
|
||||
}
|
||||
return wells;
|
||||
}
|
||||
|
||||
@@ -431,7 +431,7 @@ namespace Opm
|
||||
// clear all entries
|
||||
this->duneB_ = 0.0;
|
||||
this->duneC_ = 0.0;
|
||||
this->invDuneD_ = 0.0;
|
||||
this->duneD_ = 0.0;
|
||||
this->resWell_ = 0.0;
|
||||
|
||||
assembleWellEqWithoutIterationImpl(ebosSimulator, dt, well_state, group_state, deferred_logger);
|
||||
@@ -490,7 +490,7 @@ namespace Opm
|
||||
for (int pvIdx = 0; pvIdx < this->numWellEq_; ++pvIdx) {
|
||||
// also need to consider the efficiency factor when manipulating the jacobians.
|
||||
this->duneC_[0][cell_idx][pvIdx][componentIdx] -= cq_s_effective.derivative(pvIdx+Indices::numEq); // intput in transformed matrix
|
||||
this->invDuneD_[0][0][componentIdx][pvIdx] += cq_s_effective.derivative(pvIdx+Indices::numEq);
|
||||
this->duneD_[0][0][componentIdx][pvIdx] += cq_s_effective.derivative(pvIdx+Indices::numEq);
|
||||
}
|
||||
|
||||
for (int pvIdx = 0; pvIdx < Indices::numEq; ++pvIdx) {
|
||||
@@ -524,8 +524,8 @@ namespace Opm
|
||||
ws.vaporized_wat_rate = comm.sum(ws.vaporized_wat_rate);
|
||||
}
|
||||
|
||||
// accumulate resWell_ and invDuneD_ in parallel to get effects of all perforations (might be distributed)
|
||||
wellhelpers::sumDistributedWellEntries(this->invDuneD_[0][0], this->resWell_[0],
|
||||
// accumulate resWell_ and duneD_ in parallel to get effects of all perforations (might be distributed)
|
||||
wellhelpers::sumDistributedWellEntries(this->duneD_[0][0], this->resWell_[0],
|
||||
this->parallel_well_info_.communication());
|
||||
// add vol * dF/dt + Q to the well equations;
|
||||
for (int componentIdx = 0; componentIdx < numWellConservationEq; ++componentIdx) {
|
||||
@@ -538,7 +538,7 @@ namespace Opm
|
||||
}
|
||||
resWell_loc -= this->getQs(componentIdx) * this->well_efficiency_factor_;
|
||||
for (int pvIdx = 0; pvIdx < this->numWellEq_; ++pvIdx) {
|
||||
this->invDuneD_[0][0][componentIdx][pvIdx] += resWell_loc.derivative(pvIdx+Indices::numEq);
|
||||
this->duneD_[0][0][componentIdx][pvIdx] += resWell_loc.derivative(pvIdx+Indices::numEq);
|
||||
}
|
||||
this->resWell_[0][componentIdx] += resWell_loc.value();
|
||||
}
|
||||
@@ -550,7 +550,7 @@ namespace Opm
|
||||
|
||||
// do the local inversion of D.
|
||||
try {
|
||||
this->duneD_ = this->invDuneD_; // Not strictly need if not cpr with well contributions is used
|
||||
this->invDuneD_ = this->duneD_; // Not strictly need if not cpr with well contributions is used
|
||||
Dune::ISTLUtility::invertMatrix(this->invDuneD_[0][0]);
|
||||
} catch( ... ) {
|
||||
OPM_DEFLOG_THROW(NumericalIssue,"Error when inverting local well equations for well " + name(), deferred_logger);
|
||||
@@ -2167,6 +2167,7 @@ namespace Opm
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename TypeTag>
|
||||
void
|
||||
StandardWell<TypeTag>::addWellPressureEquations(PressureMatrix& jacobian,
|
||||
@@ -2175,6 +2176,17 @@ namespace Opm
|
||||
const bool use_well_weights,
|
||||
const WellState& well_state) const
|
||||
{
|
||||
// This adds pressure quation for cpr
|
||||
// For use_well_weights=true
|
||||
// weights lamda = inv(D)'v v = 0 v(bhpInd) = 1
|
||||
// the well equations are summed i lambda' B(:,pressureVarINd) -> B lambda'*D(:,bhpInd) -> D
|
||||
// For use_well_weights = false
|
||||
// weights lambda = \sum_i w /n where ths sum is over weights of all perforation cells
|
||||
// in the case of pressure controlled trivial equations are used and bhp C=B=0
|
||||
// then the flow part of the well equations are summed lambda'*B(1:n,pressureVarInd) -> B lambda'*D(1:n,bhpInd) -> D
|
||||
// For bouth
|
||||
// C -> w'C(:,bhpInd) where w is weights of the perforation cell
|
||||
|
||||
// Add the well contributions in cpr
|
||||
// use_well_weights is a quasiimpes formulation which is not implemented in multisegment
|
||||
int bhp_var_index = Bhp;
|
||||
@@ -2183,7 +2195,7 @@ namespace Opm
|
||||
assert(this->duneC_.M() == weights.size());
|
||||
const int welldof_ind = this->duneC_.M() + this->index_of_well_;
|
||||
// do not assume anything about pressure controlled with use_well_weights (work fine with the assumtion also)
|
||||
if(not(this->isPressureControlled(well_state)) || use_well_weights){
|
||||
if( not( this->isPressureControlled(well_state) ) || use_well_weights ){
|
||||
// make coupling for reservoir to well
|
||||
for (auto colC = this->duneC_[0].begin(), endC = this->duneC_[0].end(); colC != endC; ++colC) {
|
||||
const auto row_ind = colC.index();
|
||||
@@ -2207,7 +2219,7 @@ namespace Opm
|
||||
bweights[0] = 0.0;
|
||||
double diagElem = 0;
|
||||
{
|
||||
if(use_well_weights){
|
||||
if ( use_well_weights ){
|
||||
// calculate weighs and set diagonal element
|
||||
//NB! use this options without treating pressure controlled separated
|
||||
//NB! calculate quasiimpes well weights NB do not work well with trueimpes reservoir weights
|
||||
@@ -2224,14 +2236,14 @@ namespace Opm
|
||||
}
|
||||
abs_max = std::max(abs_max, std::fabs(bweights[0][i]));
|
||||
}
|
||||
assert(abs_max>0.0);
|
||||
assert( abs_max > 0.0 );
|
||||
for (size_t i = 0; i < blockSz; ++i) {
|
||||
bweights[0][i] /= abs_max;
|
||||
}
|
||||
diagElem = 1.0/abs_max;
|
||||
}else{
|
||||
// set diagonal element
|
||||
if(this->isPressureControlled(well_state)){
|
||||
if( this->isPressureControlled(well_state) ){
|
||||
bweights[0][blockSz-1] = 1.0;
|
||||
diagElem = 1.0;// better scaling could have used the calculation below if weights were calculated
|
||||
}else{
|
||||
@@ -2251,7 +2263,7 @@ namespace Opm
|
||||
//
|
||||
jacobian[welldof_ind][welldof_ind] = diagElem;
|
||||
// set the matrix elements for well reservoir coupling
|
||||
if(not(this->isPressureControlled(well_state)) || use_well_weights){
|
||||
if( not( this->isPressureControlled(well_state) ) || use_well_weights ){
|
||||
for (auto colB = this->duneB_[0].begin(), endB = this->duneB_[0].end(); colB != endB; ++colB) {
|
||||
const auto col_index = colB.index();
|
||||
const auto& bw = bweights[0];
|
||||
@@ -2446,8 +2458,8 @@ namespace Opm
|
||||
|
||||
this->resWell_[0][pskin_index] = eq_pskin.value();
|
||||
for (int pvIdx = 0; pvIdx < this->numWellEq_; ++pvIdx) {
|
||||
this->invDuneD_[0][0][wat_vel_index][pvIdx] = eq_wat_vel.derivative(pvIdx+Indices::numEq);
|
||||
this->invDuneD_[0][0][pskin_index][pvIdx] = eq_pskin.derivative(pvIdx+Indices::numEq);
|
||||
this->duneD_[0][0][wat_vel_index][pvIdx] = eq_wat_vel.derivative(pvIdx+Indices::numEq);
|
||||
this->duneD_[0][0][pskin_index][pvIdx] = eq_pskin.derivative(pvIdx+Indices::numEq);
|
||||
}
|
||||
|
||||
// the water velocity is impacted by the reservoir primary varaibles. It needs to enter matrix B
|
||||
|
||||
Reference in New Issue
Block a user