/* 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 . */ #ifndef OPM_PRECONDITIONERWITHUPDATE_HEADER_INCLUDED #define OPM_PRECONDITIONERWITHUPDATE_HEADER_INCLUDED #include #include namespace Dune { /// Interface class adding the update() method to the preconditioner interface. template class PreconditionerWithUpdate : public Preconditioner { public: virtual void update() = 0; }; template class DummyUpdatePreconditioner : public PreconditionerWithUpdate { public: template DummyUpdatePreconditioner(Args&&... args) : orig_precond_(std::forward(args)...) { } using X = typename OriginalPreconditioner::domain_type; using Y = typename OriginalPreconditioner::range_type; virtual void pre(X& x, Y& b) override { orig_precond_.pre(x, b); } virtual void apply(X& v, const Y& d) override { orig_precond_.apply(v, d); } virtual void post(X& x) override { orig_precond_.post(x); } virtual SolverCategory::Category category() const override { return orig_precond_.category(); } // The update() function does nothing for a wrapped preconditioner. virtual void update() override { } private: OriginalPreconditioner orig_precond_; }; template struct AbstractPreconditionerWithUpdateMaker { virtual std::unique_ptr> make() = 0; // virtual ~AbstractMaker() {}; }; template struct PreconditionerMaker : public AbstractPreconditionerWithUpdateMaker { PreconditionerMaker(Args&&... args) : args_(args...) { } std::unique_ptr> make() override { return std::unique_ptr>{new auto(std::make_from_tuple(args_))}; } std::tuple args_; }; // struct Contain // { // Contain() // { // } // template // void fill(Args&&... args) // { // using MakerType = Maker; // maker = std::make_unique(std::forward(args)...); // recreate(); // } // void recreate() // { // product = maker->make(); // } // std::unique_ptr maker; // std::unique_ptr product; // }; template std::shared_ptr> getDummyUpdateWrapper(Args&&... args) { return std::make_shared>(std::forward(args)...); } template class RebuildOnUpdatePreconditioner : public PreconditionerWithUpdate { public: RebuildOnUpdatePreconditioner(Args... args) : preconditioner_params_(args...), preconditioner_maker_(std::make_unique(std::forward(args)...)) { update(); } using X = typename OriginalPreconditioner::domain_type; using Y = typename OriginalPreconditioner::range_type; virtual void pre(X& x, Y& b) override { orig_precond_->pre(x, b); } virtual void apply(X& v, const Y& d) override { orig_precond_->apply(v, d); } virtual void post(X& x) override { orig_precond_->post(x); } virtual SolverCategory::Category category() const override { return orig_precond_->category(); } // Rebuild the preconditioner on update void update() override { // orig_precond_ = std::make_unique(mat_, n_, w_, resort_); orig_precond_ = preconditioner_maker_->make(); } private: using AbstractMakerType = AbstractPreconditionerWithUpdateMaker; using ConcreteMakerType = PreconditionerMaker; std::tuple preconditioner_params_; std::unique_ptr preconditioner_maker_; // std::unique_ptr preconditioner_maker_; // std::unique_ptr orig_precond_; std::unique_ptr> orig_precond_; }; template std::shared_ptr> getRebuildOnUpdateWrapper(Args... args) { return std::make_shared>(std::forward(args)...); } // template // std::shared_ptr> // getRebuildOnUpdateWrapper(const Matrix &mat, const int n, const double w, const bool resort) // { // return std::make_shared>(mat, n, w, resort); // } } // namespace Dune #endif // OPM_PRECONDITIONERWITHUPDATE_HEADER_INCLUDED