Merge pull request #5284 from multitalentloes/fix_fast_amg_wrapper

Fix fast amg wrapper and generalize RebuildOnUpdatePreconditioner
This commit is contained in:
Atgeirr Flø Rasmussen 2024-04-17 08:05:02 +02:00 committed by GitHub
commit d3b22323f1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 20 deletions

View File

@ -177,7 +177,7 @@ struct StandardPreconditioners {
const int n = prm.get<int>("ilulevel", 0);
const double w = prm.get<double>("relaxation", 1.0);
const bool resort = prm.get<bool>("resort", false);
return wrapBlockPreconditioner<RebuildOnUpdatePreconditioner<Dune::SeqILU<M, V, V>, const M&>>(
return wrapBlockPreconditioner<RebuildOnUpdatePreconditioner<Dune::SeqILU<M, V, V>>>(
comm, op.getmat(), n, w, resort);
});
F::addCreator("DILU", [](const O& op, const P& prm, const std::function<V()>&, std::size_t, const C& comm) {
@ -425,7 +425,7 @@ struct StandardPreconditioners<Operator, Dune::Amg::SequentialInformation> {
const double w = prm.get<double>("relaxation", 1.0);
const int n = prm.get<int>("ilulevel", 0);
const bool resort = prm.get<bool>("resort", false);
return getRebuildOnUpdateWrapper<Dune::SeqILU<M, V, V>, const M&>(op.getmat(), n, w, resort);
return getRebuildOnUpdateWrapper<Dune::SeqILU<M, V, V>>(op.getmat(), n, w, resort);
});
F::addCreator("ParOverILU0", [](const O& op, const P& prm, const std::function<V()>&, std::size_t) {
const double w = prm.get<double>("relaxation", 1.0);
@ -523,7 +523,7 @@ struct StandardPreconditioners<Operator, Dune::Amg::SequentialInformation> {
Dune::Amg::Parameters parms;
parms.setNoPreSmoothSteps(1);
parms.setNoPostSmoothSteps(1);
return getDummyUpdateWrapper<Dune::Amg::FastAMG<O, V>>(op, crit, parms);
return getRebuildOnUpdateWrapper<Dune::Amg::FastAMG<O, V>>(op, crit, parms);
});
}
if constexpr (std::is_same_v<O, WellModelMatrixAdapter<M, V, V, false>>) {

View File

@ -84,18 +84,51 @@ getDummyUpdateWrapper(Args&&... args)
return std::make_shared<DummyUpdatePreconditioner<OriginalPreconditioner>>(std::forward<Args>(args)...);
}
template <class OriginalPreconditioner, class Matrix>
/// @brief Interface class ensuring make function is overriden
/// @tparam OriginalPreconditioner - An arbitrary Preconditioner type
template <class OriginalPreconditioner>
struct GeneralPreconditionerMaker {
virtual std::unique_ptr<
Preconditioner<typename OriginalPreconditioner::domain_type, typename OriginalPreconditioner::range_type>>
make() = 0;
};
/// @brief Struct implementing a make function which creates a preconditioner
/// Can create arbitrary preconditioners using parameter packs as template arguments
/// @tparam OriginalPreconditioner - An arbitrary preconditioner type
/// @tparam ...Args - All arguments needed to construct the preconditioner of choice
template <class OriginalPreconditioner, class... Args>
struct PreconditionerMaker : public GeneralPreconditionerMaker<OriginalPreconditioner> {
using GenericPreconditioner = Preconditioner<typename OriginalPreconditioner::domain_type, typename OriginalPreconditioner::range_type>;
PreconditionerMaker(Args&&... args)
: args_(args...)
{
}
std::unique_ptr<GenericPreconditioner>
make() override
{
// return std::unique_ptr<GenericPreconditioner> {new auto(std::make_from_tuple<OriginalPreconditioner>(args_))};
return std::apply(
[](auto&&... args) {
return std::make_unique<OriginalPreconditioner>(std::forward<Args>(args)...);
}, args_);
}
std::tuple<Args...> args_;
};
/// @brief Wrapper class of preconditioners that should be reconstructed on update
/// @tparam OriginalPreconditioner - Preconditioner of your choice
template <class OriginalPreconditioner>
class RebuildOnUpdatePreconditioner : public PreconditionerWithUpdate<typename OriginalPreconditioner::domain_type,
typename OriginalPreconditioner::range_type>
{
public:
RebuildOnUpdatePreconditioner(const Matrix &mat, const int n, const double w, const bool resort)
: orig_precond_(std::make_unique<OriginalPreconditioner>(mat, n, w, resort))
, mat_(mat)
, n_(n)
, w_(w)
, resort_(resort)
template<class... Args>
RebuildOnUpdatePreconditioner(Args... args)
: preconditioner_maker_(std::make_unique<PreconditionerMaker<OriginalPreconditioner, Args...>>(std::forward<Args>(args)...))
{
update();
}
using X = typename OriginalPreconditioner::domain_type;
@ -124,22 +157,28 @@ public:
// Rebuild the preconditioner on update
void update() override
{
orig_precond_ = std::make_unique<OriginalPreconditioner>(mat_, n_, w_, resort_);
orig_precond_ = preconditioner_maker_->make();
}
private:
std::unique_ptr<OriginalPreconditioner> orig_precond_;
const Matrix &mat_;
const int n_;
const double w_;
const bool resort_;
using AbstractMakerType = GeneralPreconditionerMaker<OriginalPreconditioner>;
using GenericPreconditioner = Preconditioner<typename OriginalPreconditioner::domain_type, typename OriginalPreconditioner::range_type>;
std::unique_ptr<AbstractMakerType> preconditioner_maker_;
std::unique_ptr<GenericPreconditioner> orig_precond_;
};
template <class OriginalPreconditioner, class Matrix>
std::shared_ptr<RebuildOnUpdatePreconditioner<OriginalPreconditioner, Matrix>>
getRebuildOnUpdateWrapper(const Matrix &mat, const int n, const double w, const bool resort)
/// @brief Wrapper function creating and return a shared pointer to a preconditioner which is reconstructed on update
/// @tparam OriginalPreconditioner - Preconditioner of your choice
/// @tparam ...Args - Types of the arguments needed in the preconditioner constructed
/// @param ...args - Arguments needed to construct the preconditioner of choice
/// @return Shared pointer to preconditioner which has an update function that reconstrcuts the preconditioner
template <class OriginalPreconditioner, class... Args>
auto
getRebuildOnUpdateWrapper(Args... args)
{
return std::make_shared<RebuildOnUpdatePreconditioner<OriginalPreconditioner, Matrix>>(mat, n, w, resort);
return std::make_shared<RebuildOnUpdatePreconditioner<OriginalPreconditioner>>(
std::forward<Args>(args)...);
}
} // namespace Dune