From fbd31be585f14394d18d8e5ce6a1ceeb81745a3e Mon Sep 17 00:00:00 2001
From: podlesny <podlesny@mi.fu-berlin.de>
Date: Tue, 9 Jul 2019 17:34:01 +0200
Subject: [PATCH] .

---
 src/CMakeLists.txt                            |  2 +-
 src/data-structures/program_state.hh          | 20 +---
 src/multi-body-problem.cc                     |  2 +-
 .../levelpatchpreconditioner.hh               | 29 ++++--
 .../multilevelpatchpreconditioner.hh          | 94 +++++++++++--------
 .../preconditioners/nbodycontacttransfer.cc   | 12 +--
 src/spatial-solving/solverfactory.cc          | 14 ++-
 src/spatial-solving/solverfactory.hh          |  3 +
 src/spatial-solving/solverfactory_tmpl.cc     | 12 ++-
 9 files changed, 104 insertions(+), 84 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 26276d41..e7cf62d6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -47,7 +47,7 @@ set(MSW_SOURCE_FILES
   multi-body-problem-data/grid/mygrids.cc
   multi-body-problem-data/grid/simplexmanager.cc
   multi-body-problem.cc
-  spatial-solving/solverfactory.cc
+  #spatial-solving/solverfactory.cc
   spatial-solving/fixedpointiterator.cc
   #spatial-solving/solverfactory_old.cc
   time-stepping/adaptivetimestepper.cc
diff --git a/src/data-structures/program_state.hh b/src/data-structures/program_state.hh
index 22a2ddfe..e9db4feb 100644
--- a/src/data-structures/program_state.hh
+++ b/src/data-structures/program_state.hh
@@ -13,7 +13,6 @@
 #include <dune/solvers/norms/energynorm.hh>
 #include <dune/solvers/solvers/loopsolver.hh>
 #include <dune/solvers/iterationsteps/cgstep.hh>
-#include <dune/solvers/iterationsteps/blockgssteps.hh>
 
 #include <dune/tectonic/bodydata.hh>
 
@@ -97,24 +96,11 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
     using Matrix = typename ContactNetwork::Matrix;
     const auto& nBodyAssembler = contactNetwork.nBodyAssembler();
 
-    // set patch preconditioner for linear correction in TNNMG method
-    using PatchSolver = typename Dune::Solvers::LoopSolver<Vector, BitVector>;
-    using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, PatchSolver, Matrix, Vector>;
-
     const auto& preconditionerParset = parset.sub("solver.tnnmg.linear.preconditioner");
 
-    auto gsStep = Dune::Solvers::BlockGSStepFactory<Matrix, Vector>::create(Dune::Solvers::BlockGS::LocalSolvers::direct(0.0));
-    PatchSolver patchSolver(gsStep,
-                               preconditionerParset.get<size_t>("maximumIterations"),
-                               preconditionerParset.get<double>("tolerance"),
-                               nullptr,
-                               preconditionerParset.get<Solver::VerbosityMode>("verbosity"),
-                               false); // absolute error
-
+    using Preconditioner = MultilevelPatchPreconditioner<ContactNetwork, Matrix, Vector>;
     Dune::BitSetVector<1> activeLevels(contactNetwork.nLevels(), true);
-    Preconditioner preconditioner(contactNetwork, activeLevels, preconditionerParset.get<MPPMode>("mode"));
-    preconditioner.setPatchSolver(std::forward<PatchSolver>(patchSolver));
-    preconditioner.setPatchDepth(preconditionerParset.get<size_t>("patchDepth"));
+    Preconditioner preconditioner(preconditionerParset, contactNetwork, activeLevels);
     preconditioner.build();
 
     using LinearSolver = typename Dune::Solvers::LoopSolver<Vector, BitVector>;
@@ -124,7 +110,7 @@ template <class VectorTEMPLATE, class ScalarVectorTEMPLATE> class ProgramState {
     linearSolverStep.setPreconditioner(preconditioner);
 
     EnergyNorm<Matrix, Vector> energyNorm(linearSolverStep);
-    LinearSolver linearSolver(linearSolverStep, parset.get<size_t>("linear.maximumIterations"), parset.get<double>("linear.tolerance"), energyNorm, Solver::QUIET);
+    LinearSolver linearSolver(linearSolverStep, parset.get<size_t>("solver.tnnmg.linear.maximumIterations"), parset.get<double>("solver.tnnmg.linear.tolerance"), energyNorm, Solver::QUIET);
 
     // Solving a linear problem with a multigrid solver
     auto const solveLinearProblem = [&](
diff --git a/src/multi-body-problem.cc b/src/multi-body-problem.cc
index 6682374d..4215f278 100644
--- a/src/multi-body-problem.cc
+++ b/src/multi-body-problem.cc
@@ -268,7 +268,7 @@ int main(int argc, char *argv[]) {
     } */
 
     std::cout << "Done! :)" << std::endl;
-    return 1;
+    //return 1;
 
     //printMortarBasis<Vector>(contactNetwork.nBodyAssembler());
 
diff --git a/src/spatial-solving/preconditioners/levelpatchpreconditioner.hh b/src/spatial-solving/preconditioners/levelpatchpreconditioner.hh
index 0b0f6b59..bd5ff1a2 100644
--- a/src/spatial-solving/preconditioners/levelpatchpreconditioner.hh
+++ b/src/spatial-solving/preconditioners/levelpatchpreconditioner.hh
@@ -19,12 +19,27 @@
 #include <dune/fufem/boundarypatch.hh>
 #include <dune/fufem/functiontools/boundarydofs.hh>
 
+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;
+}
 
 template <class LevelContactNetwork, class PatchSolver, class MatrixType, class VectorType>
 class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorType> {
 
 public:
-    enum Mode {additive, multiplicative};
     static const int dim = LevelContactNetwork::dim;
 
 private:
@@ -35,7 +50,7 @@ class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorTy
     using PatchFactory = SupportPatchFactory<LevelContactNetwork>;
     using Patch = typename PatchFactory::Patch;
 
-    const Mode mode_;
+    const MPPMode mode_;
 
     const LevelContactNetwork& levelContactNetwork_;
     const LevelContactNetwork& fineContactNetwork_;
@@ -53,7 +68,7 @@ class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorTy
     // for each coarse patch given by levelContactNetwork: set up local problem, compute local correction
     LevelPatchPreconditioner(const LevelContactNetwork& levelContactNetwork,
                              const LevelContactNetwork& fineContactNetwork,
-                             const Mode mode = LevelPatchPreconditioner::Mode::additive) :
+                             const MPPMode mode = additive) :
             mode_(mode),
             levelContactNetwork_(levelContactNetwork),
             fineContactNetwork_(fineContactNetwork),
@@ -119,8 +134,8 @@ class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorTy
         }
     }
 
-    void setPatchSolver(PatchSolver&& patchSolver) {
-        patchSolver_ = Dune::Solvers::wrap_own_share<PatchSolver>(std::forward<PatchSolver>(patchSolver));
+    void setPatchSolver(std::shared_ptr<PatchSolver> patchSolver) {
+        patchSolver_ = patchSolver;
     }
 
     void setPatchDepth(const size_t patchDepth = 0) {
@@ -146,14 +161,14 @@ class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorTy
             x = 0;
 
             auto& step = patchSolver_->getIterationStep();
-            step.setProblem(this->mat_, x, this->rhs_);
+            dynamic_cast<LinearIterationStep<MatrixType, VectorType>&>(step).setProblem(*this->mat_, x, *this->rhs_);
             step.setIgnore(p);
 
             patchSolver_->check();
             patchSolver_->preprocess();
             patchSolver_->solve();
 
-            *(this->x_) += patchSolver_->getSol();
+            *(this->x_) += step.getSol();
         }
     }
 
diff --git a/src/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh b/src/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh
index 6e4ef3bf..d16c2a65 100644
--- a/src/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh
+++ b/src/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh
@@ -6,20 +6,25 @@
 #include <dune/common/timer.hh>
 #include <dune/common/fvector.hh>
 #include <dune/common/bitsetvector.hh>
+#include <dune/common/parametertree.hh>
 
+#include <dune/solvers/norms/energynorm.hh>
+#include <dune/solvers/solvers/loopsolver.hh>
+#include <dune/solvers/iterationsteps/blockgssteps.hh>
+#include <dune/solvers/iterationsteps/cgstep.hh>
 #include <dune/solvers/iterationsteps/lineariterationstep.hh>
 
 #include "nbodycontacttransfer.hh"
 #include "levelpatchpreconditioner.hh"
 
-enum MPPMode {additive, multiplicative};
-
-template <class ContactNetwork, class PatchSolver, class MatrixType, class VectorType>
+template <class ContactNetwork, class MatrixType, class VectorType>
 class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorType> {
 public:
     //struct Mode { enum ModeType {additive, multiplicative}; };
 
 private:
+    using PatchSolver = typename Dune::Solvers::LoopSolver<Vector, BitVector>;
+
     using LevelContactNetwork = typename ContactNetwork::LevelContactNetwork;
     using LevelPatchPreconditioner = LevelPatchPreconditioner<LevelContactNetwork, PatchSolver, MatrixType, VectorType>;
     using BitVector = typename LinearIterationStep<MatrixType, VectorType>::BitVector;
@@ -38,21 +43,20 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
     std::vector<MatrixType> levelMat_;
     std::vector<VectorType> levelX_;
     std::vector<VectorType> levelRhs_;
-    std::vector<BitVector> levelIgnore_;
 
-    std::unique_ptr<PatchSolver> coarseSolver_;
+    std::vector<std::shared_ptr<PatchSolver>> levelSolvers_;
 
     std::vector<BitVector> recompute_;
     std::vector<BitVector> truncation_;
     std::vector<std::shared_ptr<MGTransfer>> mgTransfer_; //TODO
 
 public:
-    MultilevelPatchPreconditioner(const ContactNetwork& contactNetwork,
-                                  const Dune::BitSetVector<1>& activeLevels,
-                                  const MPPMode mode = additive) :
+    MultilevelPatchPreconditioner(const Dune::ParameterTree& parset,
+                                  const ContactNetwork& contactNetwork,
+                                  const Dune::BitSetVector<1>& activeLevels) :
           contactNetwork_(contactNetwork),
           activeLevels_(activeLevels),
-          mode_(mode) {
+          mode_(parset.get<MPPMode>("mode")){
 
         assert(activeLevels.size() == contactNetwork_.nLevels());
 
@@ -70,17 +74,12 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
 
         const int coarsestLevel = maxLevel;
 
-        MPPMode levelMode = additive;
-        if (mode_ != additive){
-            levelMode = multiplicative;
-        }
-
         for (size_t i=maxLevel+1; i<activeLevels_.size(); i++) {
             if (activeLevels_[i][0]) {
                 // init local patch preconditioners on each level
-                const auto& fineNetwork = contactNetwork_.level(i);
-                levelPatchPreconditioners_.push_back(std::make_shared<LevelPatchPreconditioner>(*contactNetwork_.level(maxLevel), fineNetwork, levelMode));
-
+                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"));
                 maxLevel = i;
             }
         }
@@ -88,6 +87,30 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
         levelX_.resize(size());
         levelRhs_.resize(size());
 
+        // init patch solvers
+        levelSolvers_.resize(size());
+        auto coarseStep = Dune::Solvers::BlockGSStepFactory<MatrixType, VectorType>::create(Dune::Solvers::BlockGS::LocalSolvers::direct(0.0));
+        EnergyNorm<MatrixType, VectorType> coarseEnergyNorm(coarseStep);
+        levelSolvers_[0] = std::make_shared<PatchSolver>(coarseStep,
+                                   parset.get<size_t>("maximumIterations"),
+                                   parset.get<double>("tolerance"),
+                                   coarseEnergyNorm,
+                                   parset.get<Solver::VerbosityMode>("verbosity"),
+                                   false); // absolute error
+
+        for (size_t i=1; i<levelSolvers_.size(); i++) {
+            auto gsStep = Dune::Solvers::BlockGSStepFactory<MatrixType, VectorType>::create(Dune::Solvers::BlockGS::LocalSolvers::direct(0.0));
+            EnergyNorm<MatrixType, VectorType> energyNorm(gsStep);
+            levelSolvers_[i] = std::make_shared<PatchSolver>(gsStep,
+                                       parset.get<size_t>("maximumIterations"),
+                                       parset.get<double>("tolerance"),
+                                       energyNorm,
+                                       parset.get<Solver::VerbosityMode>("verbosity"),
+                                       false); // absolute error
+            levelPatchPreconditioners_[i]->setPatchSolver(levelSolvers_[i]);
+        }
+
+
         // init multigrid transfer
         mgTransfer_.resize(levelPatchPreconditioners_.size()-1);
         for (size_t i=0; i<mgTransfer_.size(); i++) {
@@ -149,7 +172,10 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
         coarseTransfer.restrict(levelRhs_[1], levelRhs_[0]);
         coarseTransfer.galerkinRestrict(levelMat_[1], levelMat_[0]);
 
-        coarseSolver_.getIterationStep().setProblem(levelMat_[0], levelX_[0], levelRhs_[0]);
+        dynamic_cast<LinearIterationStep<MatrixType, VectorType>&>(levelSolvers_[0]->getIterationStep()).setProblem(levelMat_[0], levelX_[0], levelRhs_[0]);
+
+      //  EnergyNorm<MatrixType, VectorType> coarseErrorNorm(levelSolvers_[0]->getIterationStep());
+      //  levelSolvers_[0]->setErrorNorm(coarseErrorNorm);
     }
 
 
@@ -166,24 +192,20 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
         VectorType x;
 
         // solve coarse global problem
-        auto& coarseIgnore = levelIgnore_.back();
-        mgTransfer_.back()->restrict(this->ignore(), coarseIgnore);
-        coarseSolver_.getIterationStep().setIgnore(coarseIgnore);
+        auto& coarseSolver = levelSolvers_[0];
+        coarseSolver->getIterationStep().setIgnore(truncation_[0]);
 
-        coarseSolver_.check();
-        coarseSolver_.preprocess();
-        coarseSolver_.solve();
+        coarseSolver->check();
+        coarseSolver->preprocess();
+        coarseSolver->solve();
 
-        mgTransfer_.back()->prolong(coarseSolver_.getSol(), x);
+        mgTransfer_[0]->prolong(coarseSolver->getIterationStep().getSol(), x);
 
-        for (size_t i=levelPatchPreconditioners_.size()-2; i>=0; i--) {
+        for (size_t i=1; i<levelPatchPreconditioners_.size(); i++) {
             const auto& transfer = *mgTransfer_[i];
             auto& preconditioner = *levelPatchPreconditioners_[i];
 
-            auto& _ignore = levelIgnore_[i];
-            transfer.restrict(this->ignore(), _ignore);
-            preconditioner.setIgnore(_ignore);
-
+            preconditioner.setIgnore(truncation_[i]);
             preconditioner.iterate();
 
             x += preconditioner.getSol();
@@ -238,21 +260,13 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
     }
 
     void build() {
-        for (size_t i=0; i<levelPatchPreconditioners_.size(); i++) {
+        for (size_t i=1; i<levelPatchPreconditioners_.size(); i++) {
             levelPatchPreconditioners_[i]->build();
         }
     }
 
-    void setPatchSolver(PatchSolver&& patchSolver) { //TODO create copies of patch solver for each level
-        for (size_t i=0; i<levelPatchPreconditioners_.size(); i++) {
-            levelPatchPreconditioners_[i]->setPatchSolver(std::forward<PatchSolver>(patchSolver));
-        }
-
-        coarseSolver_ = Dune::Solvers::wrap_own_share<PatchSolver>(std::forward<PatchSolver>(patchSolver));
-    }
-
     void setPatchDepth(const size_t patchDepth = 0) {
-        for (size_t i=0; i<levelPatchPreconditioners_.size(); i++) {
+        for (size_t i=1; i<levelPatchPreconditioners_.size(); i++) {
             levelPatchPreconditioners_[i]->setPatchDepth(patchDepth);
         }
     }
diff --git a/src/spatial-solving/preconditioners/nbodycontacttransfer.cc b/src/spatial-solving/preconditioners/nbodycontacttransfer.cc
index 8fba1420..1bb9ce37 100644
--- a/src/spatial-solving/preconditioners/nbodycontacttransfer.cc
+++ b/src/spatial-solving/preconditioners/nbodycontacttransfer.cc
@@ -16,8 +16,8 @@ void NBodyContactTransfer<ContactNetwork, VectorType>::setup(const ContactNetwor
     const size_t nBodies     = contactNetwork.nBodies();
     const size_t nCouplings = contactNetwork.nCouplings();
 
-    const auto& coarseContactNetwork = contactNetwork.level(coarseLevel);
-    const auto& fineContactNetwork = contactNetwork.level(fineLevel);
+    const auto& coarseContactNetwork = *contactNetwork.level(coarseLevel);
+    const auto& fineContactNetwork = *contactNetwork.level(fineLevel);
 
     std::vector<size_t> maxL(nBodies), cL(nBodies), fL(nBodies);
 
@@ -71,13 +71,13 @@ void NBodyContactTransfer<ContactNetwork, VectorType>::setup(const ContactNetwor
 
     */
 
-    if (fineLevel == contactNetwork.size()-1) {
+    if (fineLevel == contactNetwork.nLevels()-1) {
         const auto& nBodyAssembler = contactNetwork.nBodyAssembler();
         const auto& contactCouplings = nBodyAssembler.getContactCouplings();
 
-        const std::vector<const MatrixType*> mortarTransferOperators(nBodyAssembler.nCouplings());
-        const std::vector<const Dune::BitSetVector<1>*> fineHasObstacle(nBodyAssembler.nCouplings());
-        const std::vector<std::array<int,2> > gridIdx(nBodyAssembler.nCouplings());
+        std::vector<const MatrixType*> mortarTransferOperators(nBodyAssembler.nCouplings());
+        std::vector<const Dune::BitSetVector<1>*> fineHasObstacle(nBodyAssembler.nCouplings());
+        std::vector<std::array<int,2> > gridIdx(nBodyAssembler.nCouplings());
 
         for (size_t i=0; i<nBodyAssembler.nCouplings(); i++) {
             mortarTransferOperators[i] = &contactCouplings[i]->mortarLagrangeMatrix();
diff --git a/src/spatial-solving/solverfactory.cc b/src/spatial-solving/solverfactory.cc
index 7b6875ce..77c31c1c 100644
--- a/src/spatial-solving/solverfactory.cc
+++ b/src/spatial-solving/solverfactory.cc
@@ -1,13 +1,11 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+//#ifdef HAVE_CONFIG_H
+//#include "config.h"
+//#endif
 
 #include <dune/solvers/common/wrapownshare.hh>
 #include <dune/solvers/iterationsteps/blockgssteps.hh>
 #include <dune/solvers/solvers/umfpacksolver.hh>
 
-#include "solverfactory.hh"
-
 #include "../utils/debugutils.hh"
 
 template <class Functional, class BitVector>
@@ -21,8 +19,8 @@ SolverFactory<Functional, BitVector>::SolverFactory(
 
     nonlinearSmoother_ = std::make_shared<NonlinearSmoother>(*J_, dummyIterate_, LocalSolver());
 
-    auto linearSolver = Dune::Solvers::wrap_own_share<LinearSolver>(std::forward<LinearSolver>(linearSolver));
-    tnnmgStep_ = std::make_shared<Step>(*J_, dummyIterate_, nonlinearSmoother_, linearSolver, DefectProjection(), LineSearchSolver());
+    auto linearSolver_ptr = Dune::Solvers::wrap_own_share<std::decay_t<LinearSolver>>(std::forward<LinearSolver>(linearSolver));
+    tnnmgStep_ = std::make_shared<Step>(*J_, dummyIterate_, nonlinearSmoother_, linearSolver_ptr, DefectProjection(), LineSearchSolver());
     tnnmgStep_->setPreSmoothingSteps(parset.get<int>("main.pre"));
     tnnmgStep_->setIgnore(ignoreNodes);
 }
@@ -40,4 +38,4 @@ auto SolverFactory<Functional, BitVector>::step()
     return tnnmgStep_;
 }
 
-#include "solverfactory_tmpl.cc"
+//#include "solverfactory_tmpl.cc"
diff --git a/src/spatial-solving/solverfactory.hh b/src/spatial-solving/solverfactory.hh
index 05235798..48e4a63c 100644
--- a/src/spatial-solving/solverfactory.hh
+++ b/src/spatial-solving/solverfactory.hh
@@ -55,4 +55,7 @@ class SolverFactory {
   // TNNMGStep
   std::shared_ptr<Step> tnnmgStep_;
 };
+
+#include "solverfactory.cc"
+
 #endif
diff --git a/src/spatial-solving/solverfactory_tmpl.cc b/src/spatial-solving/solverfactory_tmpl.cc
index 8e3b2a15..488c5191 100644
--- a/src/spatial-solving/solverfactory_tmpl.cc
+++ b/src/spatial-solving/solverfactory_tmpl.cc
@@ -19,14 +19,18 @@ using MySolverFactory = SolverFactory<MyFunctional, BitVector>;
 
 using MyLinearSolver = Dune::Solvers::LoopSolver<Vector, BitVector>;
 
+using MySolverFactory = SolverFactory<MyFunctional, BitVector>;
 template class SolverFactory<MyFunctional, BitVector>;
-template SolverFactory<MyFunctional, BitVector>::SolverFactory(Dune::ParameterTree const &,
+
+/*template<> SolverFactory<MyFunctional, BitVector>::SolverFactory(Dune::ParameterTree const &,
                                                                MyFunctional&,
                                                                MyLinearSolver&&,
-                                                               const BitVector&);
+                                                               const BitVector&);*/
 
 template class SolverFactory<MyZeroFunctional, BitVector>;
-template SolverFactory<MyZeroFunctional, BitVector>::SolverFactory(Dune::ParameterTree const &,
+
+/*template<>
+template<> SolverFactory<MyZeroFunctional, BitVector>::SolverFactory(Dune::ParameterTree const &,
                                                                MyZeroFunctional&,
                                                                MyLinearSolver&&,
-                                                               const BitVector&);
+                                                               const BitVector&);*/
-- 
GitLab