Skip to content
Snippets Groups Projects
levelpatchpreconditioner.hh 6.89 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>

#include <dune/faultnetworks/assemblers/globalfaultassembler.hh>
#include <dune/faultnetworks/localproblem.hh>
#include <dune/faultnetworks/levelinterfacenetwork.hh>
#include <dune/faultnetworks/utils/debugutils.hh>

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

template <class BasisType, class LocalAssembler, class LocalInterfaceAssembler, class MatrixType, class VectorType>
class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorType> {

public:
podlesny's avatar
.  
podlesny committed
    enum Mode {ADDITIVE, MULTIPLICATIVE};
podlesny's avatar
podlesny committed
    enum BoundaryMode {homogeneous, fromIterate};
podlesny's avatar
.  
podlesny committed
    enum Direction {FORWARD, BACKWARD, SYMMETRIC};
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
protected:
podlesny's avatar
podlesny committed
    typedef typename BasisType::GridView GridView;
    typedef typename GridView::Grid GridType;

    const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork_;
podlesny's avatar
.  
podlesny committed
    const BasisType& patchLevelBasis_;
podlesny's avatar
podlesny committed
    const LocalAssembler& localAssembler_;
    const std::vector<std::shared_ptr<LocalInterfaceAssembler>>& localInterfaceAssemblers_;
podlesny's avatar
.  
podlesny committed

podlesny's avatar
podlesny committed
    const Mode mode_;
podlesny's avatar
.  
podlesny committed
    Direction multDirection_;
podlesny's avatar
podlesny committed

    const GridType& grid_;
    const int level_;
    const BasisType basis_;

    size_t patchDepth_;
    BoundaryMode boundaryMode_;

    MatrixType matrix_;
    std::vector<std::shared_ptr<OscLocalProblem<MatrixType, VectorType>> > localProblems_;

podlesny's avatar
.  
podlesny committed
public:
    LevelPatchPreconditioner(const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork,
podlesny's avatar
.  
podlesny committed
                             const BasisType& patchLevelBasis,
podlesny's avatar
.  
podlesny committed
                             const LocalAssembler& localAssembler,
                             const std::vector<std::shared_ptr<LocalInterfaceAssembler>>& localInterfaceAssemblers,
podlesny's avatar
.  
podlesny committed
                             const Mode mode = LevelPatchPreconditioner::Mode::ADDITIVE) :
podlesny's avatar
.  
podlesny committed
          levelInterfaceNetwork_(levelInterfaceNetwork),
podlesny's avatar
.  
podlesny committed
          patchLevelBasis_(patchLevelBasis),
podlesny's avatar
.  
podlesny committed
          localAssembler_(localAssembler),
          localInterfaceAssemblers_(localInterfaceAssemblers),
          mode_(mode),
          grid_(levelInterfaceNetwork_.grid()),
          level_(levelInterfaceNetwork_.level()),
          basis_(levelInterfaceNetwork_)
    {
podlesny's avatar
.  
podlesny committed
        assert(localInterfaceAssemblers_.size() == levelInterfaceNetwork_.size());
podlesny's avatar
.  
podlesny committed
        setPatchDepth();
        setBoundaryMode();
podlesny's avatar
.  
podlesny committed
        setDirection();
podlesny's avatar
.  
podlesny committed
        setup();
podlesny's avatar
podlesny committed
    }

podlesny's avatar
.  
podlesny committed
    // has to setup localProblems_
    virtual void build() = 0;

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

    void setBoundaryMode(const BoundaryMode boundaryMode = LevelPatchPreconditioner::BoundaryMode::homogeneous) {
        boundaryMode_ = boundaryMode;
    }

    virtual void setProblem(const MatrixType& mat, VectorType& x, const VectorType& rhs) {
        this->x_ = &x;
        this->rhs_ = &rhs;
        this->mat_ = Dune::stackobject_to_shared_ptr(mat);

        for (size_t i=0; i<localProblems_.size(); i++) {
            if (boundaryMode_ == BoundaryMode::homogeneous)
                localProblems_[i]->updateRhs(rhs);
            else
                localProblems_[i]->updateRhsAndBoundary(rhs, x);
        }
    }

podlesny's avatar
.  
podlesny committed
    void setDirection(Direction dir = SYMMETRIC) {
        multDirection_ = dir;
    }

    virtual void iterate() {
podlesny's avatar
.  
podlesny committed
        if (mode_ == ADDITIVE)
podlesny's avatar
podlesny committed
            iterateAdd();
        else
podlesny's avatar
.  
podlesny committed
            iterateMult();
podlesny's avatar
.  
podlesny committed
    }

    const BasisType& basis() const {
        return basis_;
    }

    const GridView& gridView() const {
        return basis_.getGridView();
    }

    const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork() const {
        return levelInterfaceNetwork_;
    }

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

podlesny's avatar
.  
podlesny committed
private:
podlesny's avatar
.  
podlesny committed
    void setup() {
        // assemble stiffness matrix for entire level including all faults
        GlobalFaultAssembler<BasisType, BasisType> globalFaultAssembler(basis_, basis_, levelInterfaceNetwork_);
        globalFaultAssembler.assembleOperator(localAssembler_, localInterfaceAssemblers_, matrix_);

        // set boundary conditions
        Dune::BitSetVector<1> globalBoundaryDofs;
        BoundaryPatch<GridView> boundaryPatch(levelInterfaceNetwork_.levelGridView(), true);
        constructBoundaryDofs(boundaryPatch, basis_, globalBoundaryDofs);

        typedef typename MatrixType::row_type RowType;
        typedef typename RowType::ConstIterator ColumnIterator;

        for(size_t i=0; i<globalBoundaryDofs.size(); i++) {
            if(!globalBoundaryDofs[i][0])
                continue;

            RowType& row = matrix_[i];

            ColumnIterator cIt    = row.begin();
            ColumnIterator cEndIt = row.end();

            for(; cIt!=cEndIt; ++cIt) {
                row[cIt.index()] = 0;
            }
            row[i] = 1;
        }
    }

podlesny's avatar
podlesny committed
    void iterateAdd() {
podlesny's avatar
.  
podlesny committed
        //*(this->x_) = 0;
podlesny's avatar
podlesny committed

        VectorType it, x;
        for (size_t i=0; i<localProblems_.size(); i++) {
            localProblems_[i]->solve(it);
            localProblems_[i]->prolong(it, x);

            /*if (i==5) {
                writeToVTK(basis_, x, "/storage/mi/podlesny/data/faultnetworks/iterates/", "exactvertexdata_patchDepth_"+std::to_string(patchDepth_));
            }*/

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

podlesny's avatar
.  
podlesny committed
    void iterateMult() {
        if (multDirection_ != BACKWARD) {
podlesny's avatar
.  
podlesny committed
            for (size_t i=0; i<localProblems_.size(); i++)
                iterateStep(i);
        }

podlesny's avatar
.  
podlesny committed
        if (multDirection_ != Direction::FORWARD)
podlesny's avatar
.  
podlesny committed
            for (size_t i=localProblems_.size()-1; i>=0 && i<localProblems_.size(); i--)
                iterateStep(i);
    }

    void iterateStep(size_t i) {
podlesny's avatar
.  
podlesny committed
        //*(this->x_) = 0;
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        auto& localProblem = *localProblems_[i];
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        VectorType v, v1, v2, v3;
podlesny's avatar
.  
podlesny committed
        localProblem.restrict(*(this->x_), v);
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        v1.resize(localProblem.getLocalMat().N());
        localProblem.getLocalMat().mv(v, v1);
        v3.resize(matrix_.N());
        matrix_.mv(*(this->x_), v3);
        localProblem.restrict(v3, v2);

        //print(v1, "v1");
        //print(v2, "v2");

        VectorType r1;
        localProblem.restrict(*(this->rhs_), r1);
        Dune::MatrixVector::subtractProduct(r1, localProblem.getLocalMat(), v);

        /*localProblem.updateLocalRhs(r);
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        VectorType x;
        localProblem.solve(x);
        v += x;
podlesny's avatar
podlesny committed

podlesny's avatar
.  
podlesny committed
        localProblem.updateVector(v, *(this->x_));*/

        VectorType localR;
        VectorType r = *(this->rhs_);
        Dune::MatrixVector::subtractProduct(r, matrix_, *(this->x_));
        localProblem.restrict(r, localR);

       // print(r1, "r1");
       // print(localR, "localR");

        localProblem.updateLocalRhs(localR);

        VectorType x;
        localProblem.solve(x);

        //VectorType v;
        localProblem.prolong(x, v);
        *(this->x_) += v;
podlesny's avatar
podlesny committed
    }
};

#endif