Skip to content
Snippets Groups Projects
levelpatchpreconditioner.hh 7.65 KiB
Newer Older
podlesny's avatar
.
podlesny committed
#ifndef LEVEL_PATCH_PRECONDITIONER_HH
#define LEVEL_PATCH_PRECONDITIONER_HH

#include <string>

#include <dune/common/timer.hh>
#include <dune/common/fvector.hh>
#include <dune/common/bitsetvector.hh>

#include <dune/solvers/iterationsteps/lineariterationstep.hh>
podlesny's avatar
.  
podlesny committed
#include <dune/solvers/common/numproc.hh>
podlesny's avatar
.
podlesny committed

#include "../../data-structures/levelcontactnetwork.hh"

#include "supportpatchfactory.hh"
podlesny's avatar
.  
podlesny committed
#include "../tnnmg/localproblem.hh"
podlesny's avatar
.
podlesny committed

#include <dune/localfunctions/lagrange/pqkfactory.hh>

#include <dune/fufem/boundarypatch.hh>
#include <dune/fufem/functiontools/boundarydofs.hh>

podlesny's avatar
.  
podlesny committed
enum MPPMode {additive, multiplicative};
inline
std::istream& operator>>(std::istream& lhs, MPPMode& e)
{
  std::string s;
  lhs >> s;

  if (s == "additive" || s == "1")
    e = MPPMode::additive;
  else if (s == "multiplicative" || s == "0")
    e = MPPMode::multiplicative;
  else
    lhs.setstate(std::ios_base::failbit);

  return lhs;
}
podlesny's avatar
.
podlesny committed

podlesny's avatar
podlesny committed
template <class LevelContactNetwork, class PatchSolver, class MatrixType, class VectorType>
podlesny's avatar
.
podlesny committed
class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorType> {

public:
podlesny's avatar
podlesny committed
    static const int dim = LevelContactNetwork::dim;
podlesny's avatar
.
podlesny committed

private:
    using Base = LinearIterationStep<MatrixType, VectorType>;

podlesny's avatar
podlesny committed
    using ctype = typename LevelContactNetwork::ctype;
podlesny's avatar
.
podlesny committed

podlesny's avatar
podlesny committed
    using PatchFactory = SupportPatchFactory<LevelContactNetwork>;
    using Patch = typename PatchFactory::Patch;
podlesny's avatar
.
podlesny committed

podlesny's avatar
.  
podlesny committed
    const MPPMode mode_;
podlesny's avatar
.
podlesny committed

podlesny's avatar
podlesny committed
    const LevelContactNetwork& levelContactNetwork_;
    const LevelContactNetwork& fineContactNetwork_;

    const int level_;
podlesny's avatar
.
podlesny committed

podlesny's avatar
podlesny committed
    PatchFactory patchFactory_;
podlesny's avatar
.
podlesny committed
    std::vector<Patch> patches_;

podlesny's avatar
.  
podlesny committed
    std::shared_ptr<PatchSolver> patchSolver_;
podlesny's avatar
.
podlesny committed
    size_t patchDepth_;

public:

podlesny's avatar
podlesny committed
    // for each coarse patch given by levelContactNetwork: set up local problem, compute local correction
    LevelPatchPreconditioner(const LevelContactNetwork& levelContactNetwork,
                             const LevelContactNetwork& fineContactNetwork,
podlesny's avatar
.  
podlesny committed
                             const MPPMode mode = additive) :
podlesny's avatar
podlesny committed
            mode_(mode),
            levelContactNetwork_(levelContactNetwork),
            fineContactNetwork_(fineContactNetwork),
            level_(levelContactNetwork_.level()),
            patchFactory_(levelContactNetwork_, fineContactNetwork_) {

podlesny's avatar
.
podlesny committed
        setPatchDepth();
podlesny's avatar
.  
podlesny committed
        this->verbosity_ = NumProc::QUIET;
podlesny's avatar
.
podlesny committed
    }

    // build support patches
    void build() {
podlesny's avatar
podlesny committed
        size_t totalNVertices = 0;
        for (size_t i=0; i<levelContactNetwork_.nBodies(); i++) {
            totalNVertices += levelContactNetwork_.body(i)->nVertices();
        }
podlesny's avatar
.
podlesny committed

podlesny's avatar
podlesny committed
        patches_.resize(totalNVertices);
podlesny's avatar
.
podlesny committed

        // init local fine level corrections
podlesny's avatar
.  
podlesny committed
        Dune::Timer timer;
podlesny's avatar
.  
podlesny committed
        if (this->verbosity_ == NumProc::FULL) {
podlesny's avatar
.
podlesny committed
            std::cout << std::endl;
            std::cout << "---------------------------------------------" << std::endl;
            std::cout << "Initializing local fine grid corrections! Level: " << level_ << std::endl;

podlesny's avatar
.  
podlesny committed

podlesny's avatar
.
podlesny committed
            timer.reset();
            timer.start();
        }

podlesny's avatar
podlesny committed
        Dune::BitSetVector<1> vertexVisited(totalNVertices);
        vertexVisited.unsetAll();
podlesny's avatar
.
podlesny committed

podlesny's avatar
.  
podlesny committed
        const auto& levelIndices = patchFactory_.coarseIndices();

podlesny's avatar
podlesny committed
        for (size_t bodyIdx=0; bodyIdx<levelContactNetwork_.nBodies(); bodyIdx++) {
            const auto& gridView = levelContactNetwork_.body(bodyIdx)->gridView();
podlesny's avatar
.
podlesny committed

podlesny's avatar
.  
podlesny committed
            //printDofLocation(gridView);

podlesny's avatar
podlesny committed
            for (const auto& e : elements(gridView)) {
                const auto& refElement = Dune::ReferenceElements<double, dim>::general(e.type());

                for (size_t i=0; i<refElement.size(dim); i++) {
podlesny's avatar
.  
podlesny committed
                    auto globalIdx = levelIndices.vertexIndex(bodyIdx, e, i);
podlesny's avatar
podlesny committed

                    if (!vertexVisited[globalIdx][0]) {
                        vertexVisited[globalIdx][0] = true;
                        patchFactory_.build(bodyIdx, e, i, patches_[globalIdx], patchDepth_);
podlesny's avatar
.  
podlesny committed

                        /*print(patches_[globalIdx], "patch:");

                        size_t c = 0;
                        for (size_t j=0; j<levelContactNetwork_.nBodies(); j++) {
                            const auto& gv = fineContactNetwork_.body(j)->gridView();

                            printDofLocation(gv);

                            Dune::BlockVector<Dune::FieldVector<ctype, 1>> patchVec(gv.size(dim));
                            for (size_t l=0; l<patchVec.size(); l++) {
                                if (patches_[globalIdx][c++][0]) {
                                    patchVec[l][0] = 1;
                                }
                            }

                            //print(patchVec, "patchVec");

                            // output patch
                            writeToVTK(gv, patchVec, "", "level_" + std::to_string(level_) + "_patch_" + std::to_string(globalIdx) + "_body_" + std::to_string(j));
                        }*/
podlesny's avatar
.
podlesny committed
            }
        }

podlesny's avatar
.  
podlesny committed
        if (this->verbosity_ == NumProc::FULL) {
podlesny's avatar
.
podlesny committed
            std::cout << std::endl;
            std::cout << "Total setup time: " << timer.elapsed() << " seconds." << std::endl;
            std::cout << "---------------------------------------------" << std::endl;
            timer.stop();
        }

podlesny's avatar
.  
podlesny committed
        if (this->verbosity_ != NumProc::QUIET) {
podlesny's avatar
.
podlesny committed
            std::cout << "Level: " << level_ << " LevelPatchPreconditioner::build() - SUCCESS" << std::endl;
        }
    }

podlesny's avatar
.  
podlesny committed
    void setPatchSolver(std::shared_ptr<PatchSolver> patchSolver) {
        patchSolver_ = patchSolver;
podlesny's avatar
.  
podlesny committed
    }

podlesny's avatar
.
podlesny committed
    void setPatchDepth(const size_t patchDepth = 0) {
        patchDepth_ = patchDepth;
    }

podlesny's avatar
.  
podlesny committed
    void setVerbosity(NumProc::VerbosityMode verbosity) {
podlesny's avatar
.
podlesny committed
        this->verbosity_ = verbosity;
    }

    virtual void iterate() {
        if (mode_ == additive)
            iterateAdd();
        else
            iterateMult();
    }

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

podlesny's avatar
.  
podlesny committed
        for (const auto& p : patches_) {
            x = 0;

podlesny's avatar
.  
podlesny committed
            auto ignore = this->ignore();
            for (size_t i=0; i<ignore.size(); i++) {
                for (size_t d=0; d<dim; d++) {
                   if (p[i][d])
                       ignore[i][d] = true;
                }
            }

podlesny's avatar
.  
podlesny committed
            auto& step = patchSolver_->getIterationStep();
podlesny's avatar
.  
podlesny committed
            dynamic_cast<LinearIterationStep<MatrixType, VectorType>&>(step).setProblem(*this->mat_, x, *this->rhs_);
podlesny's avatar
.  
podlesny committed
            step.setIgnore(ignore);
podlesny's avatar
.  
podlesny committed

            patchSolver_->check();
            patchSolver_->preprocess();
            patchSolver_->solve();

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

podlesny's avatar
.  
podlesny committed


podlesny's avatar
.  
podlesny committed
            /*LocalProblem<MatrixType, VectorType> localProblem(*this->mat_, *this->rhs_, ignore);
podlesny's avatar
.  
podlesny committed
            Vector newR;
podlesny's avatar
.  
podlesny committed
            localProblem.getLocalRhs(x, newR); */
podlesny's avatar
.  
podlesny committed

podlesny's avatar
.  
podlesny committed
            /*print(ignore, "ignore:");
podlesny's avatar
.  
podlesny committed
            print(*this->mat_, "Mat:");
            print(localProblem.getMat(), "localMat:");*/

podlesny's avatar
.  
podlesny committed
            /*patchSolver_->setProblem(localProblem.getMat(), x, newR);
podlesny's avatar
.  
podlesny committed
            patchSolver_->preprocess();
            patchSolver_->solve();

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

    void iterateMult() {
        *(this->x_) = 0;
podlesny's avatar
.  
podlesny committed
/*
podlesny's avatar
.
podlesny committed
        VectorType x = *(this->x_);
        for (size_t i=0; i<patches_.size(); i++) {
            VectorType updatedRhs(*(this->rhs_));
            this->mat_->mmv(*(this->x_), updatedRhs);

            patchSolver_.setProblem(*this->mat_, *(this->x_), updatedRhs);
            patchSolver_.setIgnore(patches_[i]);
            patchSolver_.solve();

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

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

podlesny's avatar
.  
podlesny committed
    size_t level() const {
        return level_;
    }

    size_t fineLevel() const {
        return fineContactNetwork_.level();
    }
podlesny's avatar
.
podlesny committed
};

#endif