Skip to content
Snippets Groups Projects
makelinearsolver.hh 4.09 KiB
Newer Older
#ifndef DUNE_TECTONIC_SPATIAL_SOLVING_MAKELINEARSOLVER_HH
#define DUNE_TECTONIC_SPATIAL_SOLVING_MAKELINEARSOLVER_HH

#include <dune/common/parametertree.hh>

#include <dune/solvers/norms/energynorm.hh>
#include <dune/solvers/iterationsteps/multigridstep.hh>
#include <dune/solvers/iterationsteps/cgstep.hh>
#include <dune/solvers/solvers/loopsolver.hh>

#include "preconditioners/multilevelpatchpreconditioner.hh"

template <class ContactNetwork, class VectorType>
auto makeLinearSolver(const Dune::ParameterTree& parset, const ContactNetwork& contactNetwork) {
    // make linear solver for linear correction in TNNMGStep
    using Vector = VectorType;
    using Matrix = typename ContactNetwork::Matrix;

        /* old, pre multi threading, was unused
        using Norm =  EnergyNorm<Matrix, Vector>;
        using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, Matrix, Vector>;
        using LinearSolver = typename Dune::Solvers::LoopSolver<Vector>;

        const auto& preconditionerParset = parset_.sub("solver.tnnmg.linear.preconditioner");

        Dune::BitSetVector<1> activeLevels(contactNetwork_.nLevels(), true);
        Preconditioner preconditioner(preconditionerParset, contactNetwork_, activeLevels);
        preconditioner.setPatchDepth(preconditionerParset.template get<size_t>("patchDepth"));
        preconditioner.build();

        auto cgStep = std::make_shared<Dune::Solvers::CGStep<Matrix, Vector>>();
        cgStep->setPreconditioner(preconditioner);

        Norm norm(*cgStep);

        return std::make_shared<LinearSolver>(cgStep, parset_.template get<int>("solver.tnnmg.main.multi"), parset_.template get<double>("solver.tnnmg.linear.tolerance"), norm, Solver::QUIET);
        */

        // patch preconditioner only needs to be computed once per advance()
        // make linear solver for linear correction in TNNMGStep
        using Norm = EnergyNorm<Matrix, Vector>;
        using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, Matrix, Vector>;
        using LinearSolver = typename Dune::Solvers::LoopSolver<Vector>;

        /*const auto& preconditionerParset = parset_.sub("solver.tnnmg.preconditioner");

        Dune::BitSetVector<1> activeLevels(contactNetwork_.nLevels(), true);
        Preconditioner preconditioner(preconditionerParset, contactNetwork_, activeLevels);
        preconditioner.setPatchDepth(preconditionerParset.template get<size_t>("patchDepth"));
        preconditioner.build();

        auto cgStep = std::make_shared<Dune::Solvers::CGStep<Matrix, Vector>>();
        cgStep->setPreconditioner(preconditioner);

        Norm norm(*cgStep);

        auto linearSolver = std::make_shared<LinearSolver>(cgStep, parset_.template get<int>("solver.tnnmg.main.multi"), parset_.template get<double>("solver.tnnmg.preconditioner.basesolver.tolerance"), norm, Solver::QUIET);
        */


        // transfer operators need to be recomputed on change due to setDeformation()
        using TransferOperator = NBodyContactTransfer<ContactNetwork, Vector>;
        using TransferOperators = std::vector<std::shared_ptr<TransferOperator>>;

        TransferOperators transfer(contactNetwork.nLevels()-1);
        for (size_t i=0; i<transfer.size(); i++) {
            transfer[i] = std::make_shared<TransferOperator>();
            transfer[i]->setup(contactNetwork, i, i+1);
        }

        // Remove any recompute filed so that initially the full transferoperator is assembled
        for (size_t i=0; i<transfer.size(); i++)
            std::dynamic_pointer_cast<TruncatedMGTransfer<Vector> >(transfer[i])->setRecomputeBitField(nullptr);

        auto linearMultigridStep = std::make_shared<Dune::Solvers::MultigridStep<Matrix, Vector> >();
        linearMultigridStep->setMGType(1, 3, 3);
        linearMultigridStep->setSmoother(TruncatedBlockGSStep<Matrix, Vector>());
        linearMultigridStep->setTransferOperators(transfer);

        return std::make_shared<LinearSolver>(linearMultigridStep, parset.template get<int>("solver.tnnmg.main.multi"), parset.template get<double>("solver.tnnmg.preconditioner.basesolver.tolerance"), Norm(*linearMultigridStep), Solver::QUIET);