From 727f836fbb397374399ade100084ed6980a159ce Mon Sep 17 00:00:00 2001
From: podlesny <podlesny@mi.fu-berlin.de>
Date: Fri, 5 Jul 2019 17:52:01 +0200
Subject: [PATCH] .

---
 .../levelpatchpreconditioner.hh               |  7 ++
 .../multilevelpatchpreconditioner.hh          | 38 ++++++++--
 .../preconditioners/nbodycontacttransfer.cc   | 58 +++++++++------
 src/spatial-solving/tnnmg/CMakeLists.txt      |  1 +
 src/spatial-solving/tnnmg/linearcorrection.hh | 74 +++++++++++++++++++
 src/spatial-solving/tnnmg/linearization.hh    |  8 +-
 src/spatial-solving/tnnmg/tnnmgstep.hh        | 31 ++++----
 7 files changed, 168 insertions(+), 49 deletions(-)
 create mode 100644 src/spatial-solving/tnnmg/linearcorrection.hh

diff --git a/src/spatial-solving/preconditioners/levelpatchpreconditioner.hh b/src/spatial-solving/preconditioners/levelpatchpreconditioner.hh
index 52d5f1d1..a8216abd 100644
--- a/src/spatial-solving/preconditioners/levelpatchpreconditioner.hh
+++ b/src/spatial-solving/preconditioners/levelpatchpreconditioner.hh
@@ -176,6 +176,13 @@ class LevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorTy
         return patches_.size();
     }
 
+    size_t level() const {
+        return level_;
+    }
+
+    size_t fineLevel() const {
+        return fineContactNetwork_.level();
+    }
 };
 
 #endif
diff --git a/src/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh b/src/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh
index 3d1f9afc..9bab0af7 100644
--- a/src/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh
+++ b/src/spatial-solving/preconditioners/multilevelpatchpreconditioner.hh
@@ -9,9 +9,8 @@
 
 #include <dune/solvers/iterationsteps/lineariterationstep.hh>
 
-#include "nbodytransfer.hh"
+#include "nbodycontacttransfer.hh"
 #include "levelpatchpreconditioner.hh"
-#include <dune/faultnetworks/dgmgtransfer.hh>
 
 template <class ContactNetwork, class PatchSolver, class MatrixType, class VectorType>
 class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, VectorType> {
@@ -24,7 +23,9 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
     using LevelGlobalPreconditioner = LevelPatchPreconditioner<LevelContactNetwork, PatchSolver, MatrixType, VectorType>;
     using BitVector = typename LinearIterationStep<MatrixType, VectorType>::BitVector;
 
-    using MGTransfer = ;
+    using MGTransfer = NBodyContactTransfer<ContactNetwork, VectorType>;
+
+    static const int dim = ContactNetwork::dim;
 
     const ContactNetwork& contactNetwork_;
     const Dune::BitSetVector<1>& activeLevels_;
@@ -40,6 +41,7 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
 
     PatchSolver coarseSolver_;
 
+    std::vector<BitVector> recompute_;
     std::vector<std::shared_ptr<MGTransfer>> mgTransfer_; //TODO
 
 public:
@@ -54,7 +56,6 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
 
         // init level patch preconditioners and multigrid transfer
         levelPatchPreconditioners_.resize(0);
-        mgTransfer_.resize(0);
 
         int maxLevel = -1;
         for (size_t i=0; i<activeLevels_.size(); i++) {
@@ -89,13 +90,38 @@ class MultilevelPatchPreconditioner : public LinearIterationStep<MatrixType, Vec
         levelRhs_.resize(size());
 
         // init multigrid transfer
-        for (size_t i=0; i<levelPatchPreconditioners_.size(); i++) {
-            mgTransfer_.push_back(std::make_shared<MGTransfer>(...));
+        mgTransfer_.resize(levelPatchPreconditioners_.size());
+        for (size_t i=0; i<mgTransfer_.size(); i++) {
+            mgTransfer_[i] = std::make_shared<MGTransfer>();
+            mgTransfer_.setup(contactNetwork_, levelPatchPreconditioners_[i]->level(), levelPatchPreconditioners_[i]->fineLevel());
         }
+
+        //TODO
         mgTransfer_.push_back(std::make_shared<MGTransfer>(coarseGlobalPreconditioner_->basis(), *allFaultBasis_));
+
+        // Remove any recompute filed so that initially the full transferoperator is assembled
+        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
+        recompute_.resize(size());
+        recompute_[recompute_.size()-1] = contactNetwork_.nBodyAssembler().totalHasObstacle_;
+        for (size_t i=mgTransfer_.size(); i>=1; i--)
+            mgTransfer_[i-1]->restrict(recompute_[i], recompute_[i-1]);
+
+        for (size_t i=0; i<this->mgTransfer_.size(); i++)
+            std::dynamic_pointer_cast<TruncatedMGTransfer<VectorType> >(mgTransfer_[i])->setRecomputeBitField(&recompute_[i]);
+
     }
 
 
+   void setIgnore(const BitVector& i) override {
+       this->setIgnore(i);
+
+       auto mgTransfer = std::dynamic_pointer_cast<TruncatedMGTransfer<VectorType> >(this->mgTransfer_[level-1]);
+             mgTransfer->setCriticalBitField(&critical);
+   }
+
    void setProblem(const MatrixType& mat, VectorType& x, const VectorType& rhs) override {
         this->setProblem(mat, x, rhs);
 
diff --git a/src/spatial-solving/preconditioners/nbodycontacttransfer.cc b/src/spatial-solving/preconditioners/nbodycontacttransfer.cc
index 961ee3f5..0f0a58c5 100644
--- a/src/spatial-solving/preconditioners/nbodycontacttransfer.cc
+++ b/src/spatial-solving/preconditioners/nbodycontacttransfer.cc
@@ -11,20 +11,7 @@
 #include <dune/solvers/transferoperators/densemultigridtransfer.hh>
 
 template<class ContactNetwork, class VectorType>
-void NBodyContactTransfer<ContactNetwork, VectorType>::setup(const ContactNetwork& contactNetwork, const int coarseLevel, const int fineLevel)
-
-        (const std::vector<const GridType*>& grids, int colevel,
-                                                         const std::vector<const MatrixType*>& mortarTransferOperator,
-                                                         const CoordSystemVector& fineLocalCoordSystems,
-                                                         const std::vector<const BitSetVector<1>*>& fineHasObstacle,
-                                                         const std::vector<std::array<int,2> >& gridIdx)
-
-transfer->setup(*grids[0], *grids[1], i,
-                        contactAssembler.contactCoupling_[0]->mortarLagrangeMatrix(),
-                        contactAssembler.localCoordSystems_,
-                        *contactAssembler.contactCoupling_[0]->nonmortarBoundary().getVertices());
-
-{
+void NBodyContactTransfer<ContactNetwork, VectorType>::setup(const ContactNetwork& contactNetwork, const int coarseLevel, const int fineLevel) {
     const size_t nBodies     = contactNetwork.nBodies();
     const size_t nCouplings = contactNetwork.nCouplings();
 
@@ -69,23 +56,48 @@ transfer->setup(*grids[0], *grids[1], i,
     //   Combine the submatrices
     // ///////////////////////////////////
 
-    if (fineLevel == contactNetwork.maxLevel())
-        combineSubMatrices(submat, mortarTransferOperator, fineLocalCoordSystems, fineHasObstacle, gridIdx);
-    else
-        Dune::MatrixVector::BlockMatrixView<MatrixType>::setupBlockMatrix(submat, this->matrix_);
+    /*
+            (const std::vector<const GridType*>& grids, int colevel,
+                                                             const std::vector<const MatrixType*>& mortarTransferOperator,
+                                                             const CoordSystemVector& fineLocalCoordSystems,
+                                                             const std::vector<const BitSetVector<1>*>& fineHasObstacle,
+                                                             const std::vector<std::array<int,2> >& gridIdx)
 
-    for (size_t i=0; i<nBodies; i++) {
-        if (fL[i]==0) {
-            delete(submat[i]);
+    transfer->setup(*grids[0], *grids[1], i,
+                            contactAssembler.contactCoupling_[0]->mortarLagrangeMatrix(),
+                            contactAssembler.localCoordSystems_,
+                            *);
+
+    */
+
+    if (fineLevel == contactNetwork.size()-1) {
+        const auto& nBodyAssembler = contactNetwork.nBodyAssembler();
+        const auto& contactCouplings = nBodyAssembler.getContactCouplings();
+
+        const std::vector<const MatrixType*> mortarTransferOperators(nBodyAssembler.nCouplings());
+        const std::vector<const BitSetVector<1>*> fineHasObstacle(nBodyAssembler.nCouplings());
+        const std::vector<std::array<int,2> > gridIdx(nBodyAssembler.nCouplings());
+
+        for (size_t i=0; i<nBodyAssembler.nCouplings(); i++) {
+            mortarTransferOperators[i] = &contactCouplings[i]->mortarLagrangeMatrix();
+            fineHasObstacle[i] = contactCouplings[i]->nonmortarBoundary().getVertices();
+            gridIdx[i] = nBodyAssembler.getCoupling(i).gridIdx_;
         }
+
+        combineSubMatrices(submat, mortarTransferOperators, nBodyAssembler.getLocalCoordSystems(), fineHasObstacle, gridIdx);
+    } else {
+        Dune::MatrixVector::BlockMatrixView<MatrixType>::setupBlockMatrix(submat, this->matrix_);
     }
 
-    // Delete separate transfer objects
     for (size_t i=0; i<nBodies; i++) {
+        if (fL[i] <= cL[i]) {
+            delete(submat[i]);
+        }
         delete(gridTransfer[i]);
     }
 }
 
+/*
 template<class VectorType>
 template<class GridType>
 void NBodyContactTransfer<VectorType>::setupHierarchy(std::vector<std::shared_ptr<NonSmoothNewtonContactTransfer<VectorType> > >& mgTransfers,
@@ -159,7 +171,7 @@ void NBodyContactTransfer<VectorType>::setupHierarchy(std::vector<std::shared_pt
         for (size_t j=0; j<gridTransfer[i].size(); j++)
             delete(gridTransfer[i][j]);
 }
-
+*/
 
 template<class VectorType>
 void NBodyContactTransfer<VectorType>::combineSubMatrices(const std::vector<const MatrixType*>& submat,
diff --git a/src/spatial-solving/tnnmg/CMakeLists.txt b/src/spatial-solving/tnnmg/CMakeLists.txt
index 25682fc9..698f4e86 100644
--- a/src/spatial-solving/tnnmg/CMakeLists.txt
+++ b/src/spatial-solving/tnnmg/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_custom_target(dune-tectonic_spatial-solving_tnnmg_src SOURCES
   functional.hh
   linearization.hh
+  linearcorrection.hh
   linesearchsolver.hh
   localbisectionsolver.hh
   localproblem.hh
diff --git a/src/spatial-solving/tnnmg/linearcorrection.hh b/src/spatial-solving/tnnmg/linearcorrection.hh
new file mode 100644
index 00000000..2f99d1ad
--- /dev/null
+++ b/src/spatial-solving/tnnmg/linearcorrection.hh
@@ -0,0 +1,74 @@
+#ifndef DUNE_TNNMG_ITERATIONSTEPS_LINEARCORRECTION_HH
+#define DUNE_TNNMG_ITERATIONSTEPS_LINEARCORRECTION_HH 1
+
+#include <functional>
+#include <memory>
+
+#include <dune/solvers/iterationsteps/lineariterationstep.hh>
+#include <dune/solvers/solvers/iterativesolver.hh>
+#include <dune/solvers/solvers/linearsolver.hh>
+#include <dune/solvers/common/canignore.hh>
+
+/**
+ * \brief linear correction step for use by \ref TNNMGStep
+ *
+ * The function object should solve the linear equation \f$ A x = b \f$.
+ * The ignore bitfield identifies the dofs to be truncated by the
+ * linear solver. The truncation dofs are passed by setting its ignore
+ * member.
+ * Be aware that full rows or columns of `A` might contain only zeroes.
+ */
+template<typename Matrix, typename Vector>
+using LinearCorrection = std::function<void(const Matrix& A, Vector& x, const Vector& b, const Dune::Solvers::DefaultBitVector_t<Vector>& ignore)>;
+
+template<typename Matrix, typename Vector>
+LinearCorrection<Matrix, Vector>
+makeLinearCorrection(std::shared_ptr< Dune::Solvers::LinearSolver<Matrix, Vector> > linearSolver)
+{
+  return [=](const Matrix& A, Vector& x, const Vector& b, const Dune::Solvers::DefaultBitVector_t<Vector>& ignore) {
+
+    auto canIgnoreCast = std::dynamic_pointer_cast<CanIgnore<Dune::Solvers::DefaultBitVector_t<Vector>>>( linearSolver );
+    if (canIgnoreCast)
+      canIgnoreCast->setIgnore(ignore);
+    else
+      DUNE_THROW(Dune::Exception, "LinearCorrection: linearSolver cannot set ignore member!");
+
+    linearSolver->setProblem(A, x, b);
+    linearSolver->preprocess();
+    linearSolver->solve();
+  };
+}
+
+template<typename Matrix, typename Vector>
+LinearCorrection<Matrix, Vector>
+makeLinearCorrection(std::shared_ptr< Dune::Solvers::IterativeSolver<Vector> > iterativeSolver)
+{
+  return [=](const Matrix& A, Vector& x, const Vector& b, const Dune::Solvers::DefaultBitVector_t<Vector>& ignore) {
+    using LinearIterationStep = Dune::Solvers::LinearIterationStep<Matrix, Vector>;
+
+    auto linearIterationStep = dynamic_cast<LinearIterationStep*>(&iterativeSolver->getIterationStep());
+    if (not linearIterationStep)
+      DUNE_THROW(Dune::Exception, "iterative solver must use a linear iteration step");
+
+    linearIterationStep->setIgnore(ignore);
+    linearIterationStep->setProblem(A, x, b);
+    iterativeSolver->preprocess();
+    iterativeSolver->solve();
+  };
+}
+
+template<typename Matrix, typename Vector>
+LinearCorrection<Matrix, Vector>
+makeLinearCorrection(std::shared_ptr< Dune::Solvers::LinearIterationStep<Matrix, Vector> > linearIterationStep, int nIterationSteps = 1)
+{
+  return [=](const Matrix& A, Vector& x, const Vector& b, const Dune::Solvers::DefaultBitVector_t<Vector>& ignore) {
+    linearIterationStep->setIgnore(ignore);
+    linearIterationStep->setProblem(A, x, b);
+    linearIterationStep->preprocess();
+
+    for (int i = 0; i < nIterationSteps; ++i)
+      linearIterationStep->iterate();
+  };
+}
+
+#endif
diff --git a/src/spatial-solving/tnnmg/linearization.hh b/src/spatial-solving/tnnmg/linearization.hh
index 73b90b42..8dcecd15 100644
--- a/src/spatial-solving/tnnmg/linearization.hh
+++ b/src/spatial-solving/tnnmg/linearization.hh
@@ -144,13 +144,11 @@ class Linearization {
       // -grad is needed for Newton step
       negativeGradient_ *= -1;
 
-
-
       // truncate gradient and hessian
-      truncateVector(negativeGradient_, truncationFlags_);
-      truncateMatrix(hessian_, truncationFlags_, truncationFlags_);
+      // truncateVector(negativeGradient_, truncationFlags_);
+      // truncateMatrix(hessian_, truncationFlags_, truncationFlags_);
 
-      //print(hessian_, "Hessian:");
+      // the actual truncation is done by the solver of linearized problem
   }
 
 
diff --git a/src/spatial-solving/tnnmg/tnnmgstep.hh b/src/spatial-solving/tnnmg/tnnmgstep.hh
index 6846b234..dc2ca30d 100644
--- a/src/spatial-solving/tnnmg/tnnmgstep.hh
+++ b/src/spatial-solving/tnnmg/tnnmgstep.hh
@@ -15,10 +15,11 @@
 #include <dune/solvers/solvers/linearsolver.hh>
 #include <dune/solvers/common/canignore.hh>
 
-#include "localproblem.hh"
+#include <dune/solvers/solvers/umfpacksolver.hh>
 
+#include "localproblem.hh"
 
-#include <dune/tnnmg/iterationsteps/linearcorrection.hh>
+#include "linearcorrection.hh"
 
 #include <dune/tectonic/../../src/utils/debugutils.hh>
 
@@ -65,7 +66,7 @@ class TNNMGStep :
   : Base(x),
     f_(&f),
     nonlinearSmoother_(nonlinearSmoother),
-    //linearCorrection_(makeLinearCorrection<ConstrainedMatrix>(iterativeSolver)),
+    linearCorrection_(makeLinearCorrection<ConstrainedMatrix>(iterativeSolver)),
     projection_(projection),
     lineSolver_(lineSolver)
   {}
@@ -85,7 +86,7 @@ class TNNMGStep :
   : Base(x),
     f_(&f),
     nonlinearSmoother_(nonlinearSmoother),
-    linearSolver_(linearSolver),
+    linearCorrection_(makeLinearCorrection(linearSolver)),
     projection_(projection),
     lineSolver_(lineSolver)
   {}
@@ -106,7 +107,7 @@ class TNNMGStep :
   : Base(x),
     f_(&f),
     nonlinearSmoother_(nonlinearSmoother),
-    //linearCorrection_(makeLinearCorrection(linearIterationStep, noOfLinearIterationSteps)),
+    linearCorrection_(makeLinearCorrection(linearIterationStep, noOfLinearIterationSteps)),
     projection_(projection),
     lineSolver_(lineSolver)
   {}
@@ -165,21 +166,21 @@ class TNNMGStep :
 
   //  std::cout << "- computing linear correction..." << std::endl;
 
-  /*  auto canIgnoreCast = std::dynamic_pointer_cast<CanIgnore<Dune::Solvers::DefaultBitVector_t<Vector>>>( linearSolver_ );
-    if (canIgnoreCast)
-      canIgnoreCast->setIgnore(*this->ignoreNodes_);*/
+    linearCorrection_(A, constrainedCorrection_, r, linearization_->truncated());
 
-    LocalProblem<ConstrainedMatrix, ConstrainedVector> localProblem(A, r, *this->ignoreNodes_);
-    Vector newR;
-    localProblem.getLocalRhs(constrainedCorrection_, newR);
+    LocalProblem<ConstrainedMatrix, ConstrainedVector> localProblem(A, r, linearization_->truncated());
+    Vector newR, constrainedCorrection_compare;
+    Solvers::resizeInitializeZero(constrainedCorrection_compare, r);
+    localProblem.getLocalRhs(constrainedCorrection_compare, newR);
 
     /*print(*this->ignoreNodes_, "ignoreNodes:");
     print(A, "A:");
     print(localProblem.getMat(), "localMat:");*/
+    auto directSolver = std::make_shared<Dune::Solvers::UMFPackSolver<ConstrainedMatrix, ConstrainedVector>>();
 
-    linearSolver_->setProblem(localProblem.getMat(), constrainedCorrection_, newR);
-    linearSolver_->preprocess();
-    linearSolver_->solve();
+    directSolver->setProblem(localProblem.getMat(), constrainedCorrection_compare, newR);
+    directSolver->preprocess();
+    directSolver->solve();
 
    // linearCorrection_(A, constrainedCorrection_, r);
 
@@ -249,7 +250,7 @@ class TNNMGStep :
   std::shared_ptr<Linearization> linearization_;
 
   //! \brief linear correction
-  std::shared_ptr<LinearSolver> linearSolver_;
+  LinearCorrection<ConstrainedMatrix, ConstrainedVector> linearCorrection_;
 
   typename Linearization::ConstrainedVector constrainedCorrection_;
   Vector correction_;
-- 
GitLab