changes to make true impes work with flexible solver

Cherry-picked commit 7da5ce4fec33. Which got cleaned up
(deleted trailing whitespace, tabs) and made compilable with recent changes.
This commit is contained in:
hnil 2019-08-21 10:50:57 +02:00 committed by Markus Blatt
parent 4a6814d6bc
commit bfa859c099
7 changed files with 117 additions and 16 deletions

View File

@ -65,6 +65,19 @@ class ISTLSolverEbosFlexible
#endif #endif
using SolverType = Dune::FlexibleSolver<MatrixType, VectorType>; using SolverType = Dune::FlexibleSolver<MatrixType, VectorType>;
// for quasiImpesWeights
typedef typename GET_PROP_TYPE(TypeTag, GlobalEqVector) Vector;
typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
//typedef typename GET_PROP_TYPE(TypeTag, EclWellModel) WellModel;
//typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
typedef typename SparseMatrixAdapter::IstlMatrix Matrix;
typedef typename SparseMatrixAdapter::MatrixBlock MatrixBlockType;
typedef typename Vector::block_type BlockVector;
typedef typename GET_PROP_TYPE(TypeTag, Evaluation) Evaluation;
typedef typename GET_PROP_TYPE(TypeTag, ThreadManager) ThreadManager;
typedef typename GridView::template Codim<0>::Entity Element;
typedef typename GET_PROP_TYPE(TypeTag, ElementContext) ElementContext;
public: public:
static void registerParameters() static void registerParameters()
@ -135,6 +148,30 @@ public:
assert(recreate_solver == false); assert(recreate_solver == false);
// Never recreate solver. // Never recreate solver.
} }
if( prm_.get<std::string>("preconditioner.type") == "cpr" ||
prm_.get<std::string>("preconditioner.type") == "cprt"
)
{
bool transpose = false;
if(prm_.get<std::string>("preconditioner.type") == "cprt"){
transpose = true;
}
if(prm_.get<std::string>("preconditioner.weight_type") == "quasiimpes") {
VectorType weights = Opm::Amg::getQuasiImpesWeights<MatrixType, VectorType>(
mat.istlMatrix(),
prm_.get<int>("preconditioner.pressure_var_index"), transpose);
prm_.put("preconditioner.weights",weights);
}else if(prm_.get<std::string>("preconditioner.weight_type") == "trueimpes" ){
VectorType weights =
this->getTrueImpesWeights(b, prm_.get<int>("preconditioner.pressure_var_index"));
prm_.put("preconditioner.weights",weights);
}else{
throw std::runtime_error("no such weights implemented for cpr");
}
}
if (recreate_solver || !solver_) { if (recreate_solver || !solver_) {
if (isParallel()) { if (isParallel()) {
@ -146,7 +183,7 @@ public:
} }
rhs_ = b; rhs_ = b;
} else { } else {
solver_->preconditioner().update(); solver_->preconditioner().update(prm_);
rhs_ = b; rhs_ = b;
} }
} }
@ -204,6 +241,47 @@ protected:
} }
} }
VectorType getTrueImpesWeights(const VectorType& b,const int pressureVarIndex)
{
VectorType weights(b.size());
BlockVector rhs(0.0);
rhs[pressureVarIndex] = 1.0;
int index = 0;
ElementContext elemCtx(simulator_);
const auto& vanguard = simulator_.vanguard();
auto elemIt = vanguard.gridView().template begin</*codim=*/0>();
const auto& elemEndIt = vanguard.gridView().template end</*codim=*/0>();
for (; elemIt != elemEndIt; ++elemIt) {
const Element& elem = *elemIt;
elemCtx.updatePrimaryStencil(elem);
elemCtx.updatePrimaryIntensiveQuantities(/*timeIdx=*/0);
const int numEq = MatrixType::block_type::rows;
Dune::FieldVector<Evaluation, numEq> storage;
unsigned threadId = ThreadManager::threadId();
simulator_.model().localLinearizer(threadId).localResidual().computeStorage(storage,elemCtx,/*spaceIdx=*/0, /*timeIdx=*/0);
Scalar extrusionFactor = elemCtx.intensiveQuantities(0, /*timeIdx=*/0).extrusionFactor();
Scalar scvVolume = elemCtx.stencil(/*timeIdx=*/0).subControlVolume(0).volume() * extrusionFactor;
Scalar storage_scale = scvVolume / elemCtx.simulator().timeStepSize();
MatrixBlockType block;
double pressure_scale = 50e5;
for (int ii = 0; ii < numEq; ++ii) {
for (int jj = 0; jj < numEq; ++jj) {
block[ii][jj] = storage[ii].derivative(jj)/storage_scale;
if (jj == pressureVarIndex) {
block[ii][jj] *= pressure_scale;
}
}
}
BlockVector bweights;
MatrixBlockType block_transpose = Opm::transposeDenseMatrix(block);
block_transpose.solve(bweights, rhs);
bweights /= 1000.0; // given normal densities this scales weights to about 1.
weights[index] = bweights;
++index;
}
return weights;
}
const Simulator& simulator_; const Simulator& simulator_;

View File

@ -63,9 +63,9 @@ public:
} }
// The update() function does nothing for a wrapped preconditioner. // The update() function does nothing for a wrapped preconditioner.
virtual void update() override virtual void update(const boost::property_tree::ptree& p) override
{ {
orig_precond_.update(); orig_precond_.update(p);
} }
private: private:

View File

@ -53,6 +53,21 @@ namespace Dune
template <class MatrixTypeT, class VectorTypeT> template <class MatrixTypeT, class VectorTypeT>
class FlexibleSolver; 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: /// A version of the two-level preconditioner that is:
/// - Self-contained, because it owns its policy components. /// - Self-contained, because it owns its policy components.
@ -73,8 +88,7 @@ public:
: linear_operator_(linearoperator) : linear_operator_(linearoperator)
, finesmoother_(PrecFactory::create(linearoperator, prm.get_child("finesmoother"))) , finesmoother_(PrecFactory::create(linearoperator, prm.get_child("finesmoother")))
, comm_(nullptr) , comm_(nullptr)
, weights_(Opm::Amg::getQuasiImpesWeights<MatrixType, VectorType>( , weights_(prm.get<VectorType>("weights"))
linearoperator.getmat(), prm.get<int>("pressure_var_index"), transpose))
, levelTransferPolicy_(dummy_comm_, weights_, prm.get<int>("pressure_var_index")) , levelTransferPolicy_(dummy_comm_, weights_, prm.get<int>("pressure_var_index"))
, coarseSolverPolicy_(prm.get_child("coarsesolver")) , coarseSolverPolicy_(prm.get_child("coarsesolver"))
, twolevel_method_(linearoperator, , twolevel_method_(linearoperator,
@ -98,8 +112,7 @@ public:
: linear_operator_(linearoperator) : linear_operator_(linearoperator)
, finesmoother_(PrecFactory::create(linearoperator, prm.get_child("finesmoother"), comm)) , finesmoother_(PrecFactory::create(linearoperator, prm.get_child("finesmoother"), comm))
, comm_(&comm) , comm_(&comm)
, weights_(Opm::Amg::getQuasiImpesWeights<MatrixType, VectorType>( , weights_(prm.get<VectorType>("weights"))
linearoperator.getmat(), prm.get<int>("pressure_var_index"), transpose))
, levelTransferPolicy_(*comm_, weights_, prm.get<int>("pressure_var_index")) , levelTransferPolicy_(*comm_, weights_, prm.get<int>("pressure_var_index"))
, coarseSolverPolicy_(prm.get_child("coarsesolver")) , coarseSolverPolicy_(prm.get_child("coarsesolver"))
, twolevel_method_(linearoperator, , twolevel_method_(linearoperator,
@ -110,6 +123,8 @@ public:
transpose ? 0 : 1) transpose ? 0 : 1)
, prm_(prm) , prm_(prm)
{ {
//Opm::Amg::getQuasiImpesWeights<MatrixType, VectorType>(
// linearoperator.getmat(), prm.get<int>("pressure_var_index"), transpose))
if (prm.get<int>("verbosity") > 10) { if (prm.get<int>("verbosity") > 10) {
std::ofstream outfile(prm.get<std::string>("weights_filename")); std::ofstream outfile(prm.get<std::string>("weights_filename"));
if (!outfile) { if (!outfile) {
@ -134,10 +149,11 @@ public:
twolevel_method_.post(x); twolevel_method_.post(x);
} }
virtual void update() override virtual void update(const boost::property_tree::ptree& prm) override
{ {
Opm::Amg::getQuasiImpesWeights<MatrixType, VectorType>( //Opm::Amg::getQuasiImpesWeights<MatrixType, VectorType>(
linear_operator_.getmat(), prm_.get<int>("pressure_var_index"), transpose, weights_); // linear_operator_.getmat(), prm_.get<int>("pressure_var_index"), transpose, weights_);
weights_ = prm.get<VectorType>("weights");
updateImpl(comm_); updateImpl(comm_);
} }

View File

@ -921,7 +921,7 @@ public:
DUNE_UNUSED_PARAMETER(x); DUNE_UNUSED_PARAMETER(x);
} }
virtual void update() override virtual void update(const boost::property_tree::ptree& = boost::property_tree::ptree()) override
{ {
// (For older DUNE versions the communicator might be // (For older DUNE versions the communicator might be
// invalid if redistribution in AMG happened on the coarset level. // invalid if redistribution in AMG happened on the coarset level.

View File

@ -22,7 +22,7 @@
#include <dune/istl/preconditioner.hh> #include <dune/istl/preconditioner.hh>
#include <memory> #include <memory>
#include <boost/property_tree/ptree.hpp>
namespace Dune namespace Dune
{ {
@ -31,7 +31,7 @@ template <class X, class Y>
class PreconditionerWithUpdate : public Preconditioner<X, Y> class PreconditionerWithUpdate : public Preconditioner<X, Y>
{ {
public: public:
virtual void update() = 0; virtual void update(const boost::property_tree::ptree& pt) = 0;
}; };
template <class OriginalPreconditioner> template <class OriginalPreconditioner>
@ -69,7 +69,7 @@ public:
} }
// The update() function does nothing for a wrapped preconditioner. // The update() function does nothing for a wrapped preconditioner.
virtual void update() override virtual void update(const boost::property_tree::ptree& /* pt */) override
{ {
} }

View File

@ -84,7 +84,8 @@ namespace Amg
void updatePreconditioner() void updatePreconditioner()
{ {
linsolver_->preconditioner().update(); pt::ptree prm;
linsolver_->preconditioner().update(prm);
} }
private: private:

View File

@ -239,8 +239,9 @@ namespace Dune
/** /**
* @brief Update the coarse solver and the hierarchies. * @brief Update the coarse solver and the hierarchies.
*/ */
virtual void update(); virtual void update(const boost::property_tree::ptree& prm);
virtual void update();
/** /**
* @brief Check whether the coarse solver used is a direct solver. * @brief Check whether the coarse solver used is a direct solver.
* @return True if the coarse level solver is a direct solver. * @return True if the coarse level solver is a direct solver.
@ -468,6 +469,11 @@ namespace Dune
update(); update();
} }
template<class M, class X, class S, class PI, class A>
void AMGCPR<M,X,S,PI,A>::update(const boost::property_tree::ptree& /* prm */)
{
update();
}
template<class M, class X, class S, class PI, class A> template<class M, class X, class S, class PI, class A>
void AMGCPR<M,X,S,PI,A>::update() void AMGCPR<M,X,S,PI,A>::update()
{ {