Skip to content
Snippets Groups Projects
multilevelpatchpreconditioner.hh 11.6 KiB
Newer Older
podlesny's avatar
podlesny committed
#ifndef MULTILEVEL_PATCH_PRECONDITIONER_HH
#define MULTILEVEL_PATCH_PRECONDITIONER_HH

#include <string>

#include <dune/common/timer.hh>
#include <dune/common/fvector.hh>
#include <dune/common/bitsetvector.hh>
podlesny's avatar
.  
podlesny committed
#include <dune/common/parametertree.hh>
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
#include <dune/solvers/norms/energynorm.hh>
#include <dune/solvers/solvers/loopsolver.hh>
podlesny's avatar
.  
podlesny committed
#include <dune/solvers/solvers/umfpacksolver.hh>
podlesny's avatar
.  
podlesny committed
#include <dune/solvers/iterationsteps/blockgssteps.hh>
podlesny's avatar
.  
podlesny committed
//#include <dune/solvers/iterationsteps/blockgsstep.hh>
podlesny's avatar
.  
podlesny committed
#include <dune/solvers/iterationsteps/cgstep.hh>
podlesny's avatar
podlesny committed
#include <dune/solvers/iterationsteps/lineariterationstep.hh>
podlesny's avatar
.  
podlesny committed
#include <dune/solvers/iterationsteps/truncatedblockgsstep.hh>
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
#include "nbodycontacttransfer.hh"
podlesny's avatar
.  
podlesny committed
#include "levelpatchpreconditioner.hh"
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
#include "../../utils/debugutils.hh"

podlesny's avatar
.  
podlesny committed
template <class ContactNetwork, class MatrixType, class VectorType>
podlesny's avatar
podlesny committed
class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorType> {
private:
podlesny's avatar
.  
podlesny committed
    using Base = LinearIterationStep<MatrixType, VectorType>;

podlesny's avatar
.  
podlesny committed
    using PatchSolver = LoopSolver<Vector, BitVector>;
    using PatchSolverStep = TruncatedBlockGSStep<MatrixType, VectorType>;
    using CoarseSolver = Dune::Solvers::UMFPackSolver<MatrixType, VectorType>;
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
    using LevelContactNetwork = typename ContactNetwork::LevelContactNetwork;
    using LevelPatchPreconditioner = LevelPatchPreconditioner<LevelContactNetwork, PatchSolver, MatrixType, VectorType>;
    using BitVector = typename LinearIterationStep<MatrixType, VectorType>::BitVector;
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
    using MGTransfer = NBodyContactTransfer<ContactNetwork, VectorType>;

    static const int dim = ContactNetwork::dim;
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
    const ContactNetwork& contactNetwork_;
    const Dune::BitSetVector<1>& activeLevels_;
podlesny's avatar
.  
podlesny committed
    const MPPMode mode_;
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
    std::vector<std::shared_ptr<LevelPatchPreconditioner>> levelPatchPreconditioners_;
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
    std::vector<MatrixType> levelMat_;
podlesny's avatar
podlesny committed
    std::vector<VectorType> levelX_;
    std::vector<VectorType> levelRhs_;

podlesny's avatar
.  
podlesny committed
    std::vector<BitVector> ignoreHierarchy_;

    std::vector<std::shared_ptr<EnergyNorm<MatrixType, VectorType>>> levelErrorNorms_;
    std::vector<std::shared_ptr<LinearIterationStep<MatrixType, VectorType>>> levelItSteps_;
podlesny's avatar
.  
podlesny committed
    std::vector<std::shared_ptr<PatchSolver>> levelSolvers_;
podlesny's avatar
.  
podlesny committed
    CoarseSolver coarseSolver_;
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
    //std::vector<BitVector> recompute_;
    std::vector<std::shared_ptr<MGTransfer>> mgTransfer_;
podlesny's avatar
podlesny committed

public:
podlesny's avatar
.  
podlesny committed
    MultilevelPatchPreconditioner(const Dune::ParameterTree& parset,
                                  const ContactNetwork& contactNetwork,
                                  const Dune::BitSetVector<1>& activeLevels) :
podlesny's avatar
.  
podlesny committed
          contactNetwork_(contactNetwork),
podlesny's avatar
podlesny committed
          activeLevels_(activeLevels),
podlesny's avatar
.  
podlesny committed
          mode_(parset.get<MPPMode>("mode")){
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        assert(activeLevels.size() == contactNetwork_.nLevels());
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        // init level patch preconditioners and multigrid transfer
podlesny's avatar
.  
podlesny committed
        levelPatchPreconditioners_.resize(1);
        levelPatchPreconditioners_[0] = nullptr; // blank level representing global coarse problem to make further indexing easier
podlesny's avatar
podlesny committed

        int maxLevel = -1;
        for (size_t i=0; i<activeLevels_.size(); i++) {
            if (activeLevels_[i][0]) {
                maxLevel = i;
                break;
            }
        }

        for (size_t i=maxLevel+1; i<activeLevels_.size(); i++) {
            if (activeLevels_[i][0]) {
                // init local patch preconditioners on each level
podlesny's avatar
.  
podlesny committed
                const auto& fineNetwork = *contactNetwork_.level(i);
                levelPatchPreconditioners_.push_back(std::make_shared<LevelPatchPreconditioner>(*contactNetwork_.level(maxLevel), fineNetwork, mode_));
                levelPatchPreconditioners_.back()->setPatchDepth(parset.get<size_t>("patchDepth"));
podlesny's avatar
podlesny committed
                maxLevel = i;
            }
        }

podlesny's avatar
.  
podlesny committed
        levelMat_.resize(size()-1);
podlesny's avatar
.  
podlesny committed
        levelX_.resize(size());
        levelRhs_.resize(size());
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        // init patch solvers
        levelSolvers_.resize(size());
podlesny's avatar
.  
podlesny committed
        levelItSteps_.resize(size());
        levelErrorNorms_.resize(size());
podlesny's avatar
.  
podlesny committed

        for (size_t i=1; i<levelSolvers_.size(); i++) {
podlesny's avatar
.  
podlesny committed
            //auto gsStep = Dune::Solvers::BlockGSStepFactory<MatrixType, VectorType>::create(Dune::Solvers::BlockGS::LocalSolvers::direct(0.0));
podlesny's avatar
.  
podlesny committed
            levelItSteps_[i] = std::make_shared<TruncatedBlockGSStep<MatrixType, VectorType>>(); //Dune::Solvers::BlockGSStepFactory<MatrixType, VectorType>::createPtr(Dune::Solvers::BlockGS::LocalSolvers::direct(0.0));
podlesny's avatar
.  
podlesny committed
            levelErrorNorms_[i] = std::make_shared<EnergyNorm<MatrixType, VectorType>>(*levelItSteps_[i].get());
podlesny's avatar
.  
podlesny committed
            levelSolvers_[i] = std::make_shared<PatchSolver>(*levelItSteps_[i].get(),
podlesny's avatar
.  
podlesny committed
                                       parset.get<size_t>("maximumIterations"),
                                       parset.get<double>("tolerance"),
podlesny's avatar
.  
podlesny committed
                                       *levelErrorNorms_[i].get(),
podlesny's avatar
.  
podlesny committed
                                       parset.get<Solver::VerbosityMode>("verbosity"));
podlesny's avatar
.  
podlesny committed
            levelPatchPreconditioners_[i]->setPatchSolver(levelSolvers_[i]);
        }

podlesny's avatar
podlesny committed
        // init multigrid transfer
podlesny's avatar
.  
podlesny committed
        mgTransfer_.resize(levelPatchPreconditioners_.size()-1);
podlesny's avatar
.  
podlesny committed
        for (size_t i=0; i<mgTransfer_.size(); i++) {
            mgTransfer_[i] = std::make_shared<MGTransfer>();
podlesny's avatar
.  
podlesny committed
            mgTransfer_[i]->setup(contactNetwork_, levelPatchPreconditioners_[i+1]->level(), levelPatchPreconditioners_[i+1]->fineLevel());
podlesny's avatar
podlesny committed
        }
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
        // from dune/contact/solvers/nsnewtonmgstep.cc
        /*// Remove any recompute filed so that initially the full transferoperator is assembled
podlesny's avatar
.  
podlesny committed
        for (size_t i=0; i<mgTransfer_.size(); i++)
            std::dynamic_pointer_cast<TruncatedMGTransfer<VectorType> >(mgTransfer_[i])->setRecomputeBitField(nullptr);

        // specify the subset of entries to be reassembled at each iteration
podlesny's avatar
.  
podlesny committed
        recompute_.resize(size());
podlesny's avatar
.  
podlesny committed
        recompute_[recompute_.size()-1] = contactNetwork_.nBodyAssembler().totalHasObstacle_;
podlesny's avatar
.  
podlesny committed
        for (int i=mgTransfer_.size(); i>=1; i--) {
            std::dynamic_pointer_cast<TruncatedMGTransfer<VectorType> >(mgTransfer_[i-1])->restrict(recompute_[i], recompute_[i-1]);
podlesny's avatar
.  
podlesny committed
          //  std::dynamic_pointer_cast<DenseMultigridTransfer<VectorType, BitVector, MatrixType> >(mgTransfer_[i])->restrict(recompute_[i+1], recompute_[i]);
podlesny's avatar
.  
podlesny committed

            //print(recompute_[i], "recompute: ");
        }

        for (size_t i=0; i<this->mgTransfer_.size(); i++)
            std::dynamic_pointer_cast<TruncatedMGTransfer<VectorType> >(mgTransfer_[i])->setRecomputeBitField(&recompute_[i]); */
podlesny's avatar
podlesny committed
    }

podlesny's avatar
.  
podlesny committed
   void setMatrix(const MatrixType& mat) override {
       Base::setMatrix(mat);

       ignoreHierarchy_.resize(size());
       ignoreHierarchy_.back() = Base::ignore();
       for (int i=mgTransfer_.size()-1; i>=0; i--) {
           std::dynamic_pointer_cast<TruncatedMGTransfer<VectorType> >(mgTransfer_[i])->restrictToFathers(ignoreHierarchy_[i+1], ignoreHierarchy_[i]);
       }

        size_t maxLevel = levelPatchPreconditioners_.size()-1;
        levelPatchPreconditioners_[maxLevel]->setMatrix(mat);

        for (int i=levelPatchPreconditioners_.size()-2; i>0; i--) {
            const auto& transfer = *mgTransfer_[i];

            transfer.galerkinRestrictSetOccupation(*levelPatchPreconditioners_[i+1]->getMatrix(), levelMat_[i]);
            transfer.galerkinRestrict(*levelPatchPreconditioners_[i+1]->getMatrix(), levelMat_[i]);
            levelPatchPreconditioners_[i]->setMatrix(levelMat_[i]);

            // Set solution vector sizes for the lower levels
            Dune::MatrixVector::resize(levelX_[i], levelMat_[i]);
            //Dune::MatrixVector::resize(levelRhs_[i], levelMat_[i]);
        }

        // set coarse global problem
        const auto& coarseTransfer = *mgTransfer_[0];
        const auto& fineMat = *levelPatchPreconditioners_[1]->getMatrix();
        coarseTransfer.galerkinRestrictSetOccupation(fineMat, levelMat_[0]);
        coarseTransfer.galerkinRestrict(fineMat, levelMat_[0]);

        Dune::MatrixVector::resize(levelX_[0], levelMat_[0]);
   }

podlesny's avatar
.  
podlesny committed
    void iterate() {
podlesny's avatar
.  
podlesny committed
        size_t maxLevel = levelPatchPreconditioners_.size()-1;
        levelX_[maxLevel] = *this->getIterate();
        levelRhs_[maxLevel] = *Base::rhs_;

        for (int i=levelPatchPreconditioners_.size()-2; i>0; i--) {
            const auto& transfer = *mgTransfer_[i];

            transfer.restrict(levelX_[i+1], levelX_[i]);
            transfer.restrict(levelRhs_[i+1], levelRhs_[i]);
        }

        // set coarse global problem
        const auto& coarseTransfer = *mgTransfer_[0];
        coarseTransfer.restrict(levelX_[1], levelX_[0]);
        coarseTransfer.restrict(levelRhs_[1], levelRhs_[0]);


podlesny's avatar
podlesny committed
        if (mode_ == additive)
            iterateAdd();
        else
            iterateMult();
    }

    void iterateAdd() {
        *(this->x_) = 0;	

        VectorType x;

podlesny's avatar
.  
podlesny committed
        // solve coarse global problem
podlesny's avatar
.  
podlesny committed
        LocalProblem<MatrixType, VectorType> localProblem(levelMat_[0], levelRhs_[0], ignoreHierarchy_[0]);
        Vector newR;
        localProblem.getLocalRhs(levelX_[0], newR);

podlesny's avatar
.  
podlesny committed
        coarseSolver_.setProblem(localProblem.getMat(), levelX_[0], newR);
        coarseSolver_.preprocess();
        coarseSolver_.solve();
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
        mgTransfer_[0]->prolong(levelX_[0], x);
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
        for (size_t i=1; i<levelPatchPreconditioners_.size()-1; i++) {
podlesny's avatar
.  
podlesny committed
            const auto& transfer = *mgTransfer_[i];
            auto& preconditioner = *levelPatchPreconditioners_[i];
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
            preconditioner.setIgnore(ignoreHierarchy_[i]);
            preconditioner.apply(levelX_[i], levelRhs_[i]);
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
            x += preconditioner.getSol();
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
            VectorType newX;
            transfer.prolong(x, newX);
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
            x = newX;
        }
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        auto& preconditioner = *levelPatchPreconditioners_.back();

        preconditioner.setIgnore(ignoreHierarchy_.back());
        preconditioner.apply(levelX_.back(), levelRhs_.back());

        x += preconditioner.getSol();

podlesny's avatar
.  
podlesny committed
        *(this->x_) = x;
podlesny's avatar
podlesny committed
    }


    void iterateMult() {
        *(this->x_) = 0;

podlesny's avatar
.  
podlesny committed
        DUNE_THROW(Dune::Exception, "Not implemented!");

podlesny's avatar
.  
podlesny committed
        /*
podlesny's avatar
podlesny committed
        VectorType x;

        for (int i=(levelPatchPreconditioners_.size()-1); i>=0; i--) {
            VectorType updatedRhs(*(this->rhs_));
            this->mat_->mmv(*(this->x_), updatedRhs);

            mgTransfer_[i]->restrict(*(this->x_), levelX_[i]);
            mgTransfer_[i]->restrict(updatedRhs, levelRhs_[i]);

            levelPatchPreconditioners_[i]->setProblem(*(this->mat_), levelX_[i], levelRhs_[i]);

            levelPatchPreconditioners_[i]->iterate();
            const VectorType& it = levelPatchPreconditioners_[i]->getSol();

            mgTransfer_[i]->prolong(it, x);

            *(this->x_) += x;
        }

        VectorType updatedCoarseRhs(*(this->rhs_));
        this->mat_->mmv(*(this->x_), updatedCoarseRhs);

        size_t j = levelPatchPreconditioners_.size();
        mgTransfer_[j]->restrict(*(this->x_), levelX_[j]);
        mgTransfer_[j]->restrict(updatedCoarseRhs, levelRhs_[j]);

        coarseGlobalPreconditioner_->setProblem(*(this->mat_), levelX_[j], levelRhs_[j]);
        coarseGlobalPreconditioner_->iterate();
        const VectorType& it = coarseGlobalPreconditioner_->getSol();

        mgTransfer_[j]->prolong(it, x);

podlesny's avatar
.  
podlesny committed
        *(this->x_) += x; */
podlesny's avatar
podlesny committed
    }

    void build() {
podlesny's avatar
.  
podlesny committed
        for (size_t i=1; i<levelPatchPreconditioners_.size(); i++) {
podlesny's avatar
podlesny committed
            levelPatchPreconditioners_[i]->build();
        }
    }

podlesny's avatar
.  
podlesny committed
    void setPatchDepth(const size_t patchDepth = 0) {
podlesny's avatar
.  
podlesny committed
        for (size_t i=1; i<levelPatchPreconditioners_.size(); i++) {
podlesny's avatar
.  
podlesny committed
            levelPatchPreconditioners_[i]->setPatchDepth(patchDepth);
        }
podlesny's avatar
podlesny committed
    }

podlesny's avatar
.  
podlesny committed
    auto contactNetwork() const {
        return contactNetwork_;
    }

podlesny's avatar
podlesny committed
    size_t size() const {
podlesny's avatar
.  
podlesny committed
        return levelPatchPreconditioners_.size();