From 4c67f92379ca1bec8baa43acddc19d53712af843 Mon Sep 17 00:00:00 2001
From: podlesny <podlesny@zedat.fu-berlin.de>
Date: Tue, 2 Jun 2020 13:07:45 +0200
Subject: [PATCH] .

---
 .../cellpatchpreconditioner.hh                |   4 +-
 .../levelpatchpreconditioner.hh               |  85 +++++++-------
 .../multilevelpatchpreconditioner.hh          | 111 +++++++++++-------
 .../supportpatchpreconditioner.hh             |   3 +-
 src/cantorfaultnetworks/cantorfaultnetwork.cc |  13 +-
 .../sparsecantorfaultnetwork.cc               |   3 +-
 .../sparsecantorfaultnetwork.parset           |   4 +-
 src/geofaultnetworks/geofaultnetwork.cc       |  11 +-
 8 files changed, 130 insertions(+), 104 deletions(-)

diff --git a/dune/faultnetworks/preconditioners/cellpatchpreconditioner.hh b/dune/faultnetworks/preconditioners/cellpatchpreconditioner.hh
index e938979..8fc86fc 100644
--- a/dune/faultnetworks/preconditioners/cellpatchpreconditioner.hh
+++ b/dune/faultnetworks/preconditioners/cellpatchpreconditioner.hh
@@ -33,8 +33,10 @@ public:
 
         size_t cellCount = localToGlobal.size();
         this->localProblems_.resize(cellCount);
+
         for (size_t i=0; i<cellCount; i++) {
-            this->localProblems_[i] = std::make_shared<decltype(*(this->localProblems_[i]))>(this->matrix_, rhs, localToGlobal[i], boundaryDofs[i]);
+            using LocalProblemType = typename std::remove_reference<decltype(*(this->localProblems_[i]))>::type;
+            this->localProblems_[i] = std::make_shared<LocalProblemType>(this->matrix_, rhs, localToGlobal[i], boundaryDofs[i]);
         }
     }
 };
diff --git a/dune/faultnetworks/preconditioners/levelpatchpreconditioner.hh b/dune/faultnetworks/preconditioners/levelpatchpreconditioner.hh
index 331885d..d8c3090 100644
--- a/dune/faultnetworks/preconditioners/levelpatchpreconditioner.hh
+++ b/dune/faultnetworks/preconditioners/levelpatchpreconditioner.hh
@@ -25,14 +25,16 @@ public:
     enum BoundaryMode {homogeneous, fromIterate};
     enum Direction {FORWARD, BACKWARD, SYMMETRIC};
 
-private:
+protected:
     typedef typename BasisType::GridView GridView;
     typedef typename GridView::Grid GridType;
 
     const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork_;
     const LocalAssembler& localAssembler_;
     const std::vector<std::shared_ptr<LocalInterfaceAssembler>>& localInterfaceAssemblers_;
+
     const Mode mode_;
+    Direction multDirection_;
 
     const GridType& grid_;
     const int level_;
@@ -44,40 +46,6 @@ private:
     MatrixType matrix_;
     std::vector<std::shared_ptr<OscLocalProblem<MatrixType, VectorType>> > localProblems_;
 
-private:
-    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;
-        }
-    }
-
-public:
-    // has to setup localProblems_
-    virtual void build();
-
 public:
     LevelPatchPreconditioner(const LevelInterfaceNetwork<GridView>& levelInterfaceNetwork,
                              const LocalAssembler& localAssembler,
@@ -94,9 +62,13 @@ public:
         assert(localInterfaceAssemblers_.size() == levelInterfaceNetwork_.size());
         setPatchDepth();
         setBoundaryMode();
+        setDirection();
         setup();
     }
 
+    // has to setup localProblems_
+    virtual void build() = 0;
+
     void setPatchDepth(const size_t patchDepth = 0) {
         patchDepth_ = patchDepth;
     }
@@ -118,11 +90,15 @@ public:
         }
     }
 
-    virtual void iterate(Direction dir = SYMMETRIC) {
+    void setDirection(Direction dir = SYMMETRIC) {
+        multDirection_ = dir;
+    }
+
+    virtual void iterate() {
         if (mode_ == ADDITIVE)
             iterateAdd();
         else
-            iterateMult(dir);
+            iterateMult();
     }
 
     const BasisType& basis() const {
@@ -142,6 +118,35 @@ public:
     }
 
 private:
+    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;
+        }
+    }
+
     void iterateAdd() {
         //*(this->x_) = 0;
 
@@ -158,13 +163,13 @@ private:
         }
     }
 
-    void iterateMult(Direction dir) {
-        if (dir != BACKWARD) {
+    void iterateMult() {
+        if (multDirection_ != BACKWARD) {
             for (size_t i=0; i<localProblems_.size(); i++)
                 iterateStep(i);
         }
 
-        if (dir != Direction::FORWARD)
+        if (multDirection_ != Direction::FORWARD)
             for (size_t i=localProblems_.size()-1; i>=0 && i<localProblems_.size(); i--)
                 iterateStep(i);
     }
diff --git a/dune/faultnetworks/preconditioners/multilevelpatchpreconditioner.hh b/dune/faultnetworks/preconditioners/multilevelpatchpreconditioner.hh
index 87204de..106edb1 100644
--- a/dune/faultnetworks/preconditioners/multilevelpatchpreconditioner.hh
+++ b/dune/faultnetworks/preconditioners/multilevelpatchpreconditioner.hh
@@ -32,15 +32,19 @@ private:
     using GridType = typename GridView::Grid ;
     using BitVector = typename Dune::BitSetVector<1>;
 
-    const Dune::ParameterTree& parset_;
-
     const InterfaceNetwork<GridType>& interfaceNetwork_;
     const BitVector& activeLevels_;
     const std::vector<std::shared_ptr<LocalOperatorAssembler>>& localAssemblers_;
     const std::vector<std::vector<std::shared_ptr<LocalInterfaceAssembler>>>& localInterfaceAssemblers_;
 
+    // preconditioner parset settings
+    const Dune::ParameterTree& parset_;
     using Mode = typename LevelPatchPreconditionerType::Mode;
-    const Mode mode_;
+    Mode mode_;
+
+    using MultDirection = typename LevelPatchPreconditionerType::Direction;
+    MultDirection multDirection_;
+
 
     int itCounter_;
 
@@ -60,19 +64,13 @@ public:
                                   const std::vector<std::shared_ptr<LocalOperatorAssembler>>& localAssemblers,
                                   const std::vector<std::vector<std::shared_ptr<LocalInterfaceAssembler>>>& localInterfaceAssemblers,
                                   const Dune::ParameterTree& parset) :
-          parset_(parset),
           interfaceNetwork_(interfaceNetwork),
           activeLevels_(activeLevels),
           localAssemblers_(localAssemblers),
-          localInterfaceAssemblers_(localInterfaceAssemblers)
+          localInterfaceAssemblers_(localInterfaceAssemblers),
+          parset_(parset)
     {
-        const auto mode = parset_.get<std::string>("mode");
-        if (mode == "ADDITIVE") {
-            mode_ = Mode::ADDITIVE;
-        } else {
-            mode_ = Mode::MULTIPLICATIVE;
-        }
-
+        parseSettings();
 
         if (activeLevels_.size() > (size_t) interfaceNetwork.maxLevel() +1)
             DUNE_THROW(Dune::Exception, "MultilevelFaultPreconditioner: too many active levels; preconditioner supports at most (grid.maxLevel + 1) levels!");
@@ -157,6 +155,28 @@ public:
     }
 
 private:
+    void parseSettings() {
+        const auto mode = parset_.get<std::string>("mode");
+        if (mode == "ADDITIVE") {
+            mode_ = Mode::ADDITIVE;
+        } else if (mode == "MULTIPLICATIVE") {
+            mode_ = Mode::MULTIPLICATIVE;
+        } else {
+            DUNE_THROW(Dune::Exception, "MultilevelFaultPreconditioner::parseSettings unknown mode! Possible options: ADDITIVE , MULTIPLICATIVE");
+        }
+
+        auto multDirection = parset_.get<std::string>("multDirection");
+        if (multDirection == "FORWARD") {
+            multDirection_ = MultDirection::FORWARD;
+        } else if (multDirection == "BACKWARD") {
+            multDirection_ = MultDirection::BACKWARD;
+        } else if (multDirection == "SYMMETRIC") {
+            multDirection_ = MultDirection::SYMMETRIC;
+        } else {
+            DUNE_THROW(Dune::Exception, "MultilevelFaultPreconditioner::parseSettings unknown multDirection! Possible options: FORWARD , BACKWARD, SYMMETRIC");
+        }
+    }
+
     void iterateAdd() {
         //*(this->x_) = 0;
 
@@ -207,41 +227,13 @@ private:
 
 
     void iterateMult() {
-        *(this->x_) = 0;
-
-        VectorType x;
-
-        for (int i=(levelPatchPreconditioners_.size()-1); i>=0; i--) {
-            VectorType updatedRhs(*(this->rhs_));
-            this->mat_->mmv(*(this->x_), updatedRhs);
-
-            //print(updatedRhs, "globalRhs: ");
-
-            mgTransfer_[i]->restrict(*(this->x_), levelX_[i]);
-            mgTransfer_[i]->restrict(updatedRhs, levelRhs_[i]);
 
-            //print(levelRhs_[i], "levelLocalCoarseRhs: ");
-            //writeToVTK(levelPatchPreconditioners_[i]->basis(), levelRhs_[i], "/storage/mi/podlesny/data/faultnetworks/rhs/fine", "exactvertexdata_step_"+std::to_string(itCounter_));
-
-            levelPatchPreconditioners_[i]->setProblem(*(this->mat_), levelX_[i], levelRhs_[i]);
-
-            levelPatchPreconditioners_[i]->iterate();
-            const VectorType& it = levelPatchPreconditioners_[i]->getSol();
-
-            mgTransfer_[i]->prolong(it, x);
-
-            //writeToVTK(*allFaultBasis_, x, "/storage/mi/podlesny/data/faultnetworks/fineIterates/multilevel", "exactvertexdata_step_"+std::to_string(itCounter_));
-
-
-            *(this->x_) += x;
-        }
-
-        VectorType updatedCoarseRhs(*(this->rhs_));
-        this->mat_->mmv(*(this->x_), updatedCoarseRhs);
+        if (multDirection_ != MultDirection::FORWARD)
+            for (size_t i=levelPatchPreconditioners_.size()-1; i>=0 && i<levelPatchPreconditioners_.size(); i--)
+                iterateStep(i, MultDirection::BACKWARD);
 
         size_t j = levelPatchPreconditioners_.size();
         mgTransfer_[j]->restrict(*(this->x_), levelX_[j]);
-        mgTransfer_[j]->restrict(updatedCoarseRhs, levelRhs_[j]);
 
         //print(levelRhs_[j], "localCoarseRhs: ");
         //writeToVTK(coarseGlobalPreconditioner_->basis(), levelRhs_[j], "/storage/mi/podlesny/data/faultnetworks/rhs/coarse", "exactvertexdata_step_"+std::to_string(itCounter_));
@@ -250,15 +242,38 @@ private:
         coarseGlobalPreconditioner_->iterate();
         const VectorType& it = coarseGlobalPreconditioner_->getSol();
 
+        VectorType x;
         mgTransfer_[j]->prolong(it, x);
-
+        *(this->x_) += x;
         //writeToVTK(*allFaultBasis_, x, "/storage/mi/podlesny/data/faultnetworks/coarseIterates/multilevel", "exactvertexdata_step_"+std::to_string(itCounter_));
 
-        *(this->x_) += x;
+        if (multDirection_ != MultDirection::BACKWARD) {
+            for (size_t i=0; i<levelPatchPreconditioners_.size(); i++)
+                iterateStep(i, MultDirection::FORWARD);
+        }
 
         itCounter_++;
     }
 
+    void iterateStep(const size_t i, const MultDirection dir) {
+        mgTransfer_[i]->restrict(*(this->x_), levelX_[i]);
+
+        //print(levelRhs_[i], "levelLocalCoarseRhs: ");
+        //writeToVTK(levelPatchPreconditioners_[i]->basis(), levelRhs_[i], "/storage/mi/podlesny/data/faultnetworks/rhs/fine", "exactvertexdata_step_"+std::to_string(itCounter_));
+
+        levelPatchPreconditioners_[i]->setProblem(*(this->mat_), levelX_[i], levelRhs_[i]);
+
+        levelPatchPreconditioners_[i]->setDirection(dir);
+        levelPatchPreconditioners_[i]->iterate();
+        const VectorType& it = levelPatchPreconditioners_[i]->getSol();
+
+        VectorType x;
+        mgTransfer_[i]->prolong(it, x);
+        *(this->x_) += x;
+
+        //writeToVTK(*allFaultBasis_, x, "/storage/mi/podlesny/data/faultnetworks/fineIterates/multilevel", "exactvertexdata_step_"+std::to_string(itCounter_));
+    }
+
     auto setupLevelPreconditioners() {
         const auto preconditionerType = parset_.get<std::string>("patch");
         if (preconditionerType == "CELL") {
@@ -284,6 +299,8 @@ private:
 
             if (activeLevels_[i][0]) {
                 levelPatchPreconditioners_.push_back(std::make_shared<CellPreconditioner>(interfaceNetwork_.levelInterfaceNetwork(i), *localAssemblers_[i], localInterfaceAssemblers_[i], mode_));
+                levelPatchPreconditioners_.back()->setBoundaryMode(LevelPatchPreconditionerType::BoundaryMode::homogeneous);
+
                 maxLevel = i;
             }
         }
@@ -294,6 +311,8 @@ private:
     auto setupSupportPreconditioner() {
         using SupportPreconditioner = SupportPatchPreconditioner<BasisType, LocalOperatorAssembler, LocalInterfaceAssembler, MatrixType, VectorType>;
 
+        const auto patchDepth = parset_.get<size_t>("patchDepth");
+
         int maxLevel = 0;
 
         bool skip = true;
@@ -311,6 +330,8 @@ private:
                     levelPatchPreconditioners_.push_back(std::make_shared<SupportPreconditioner>(levelNetwork, coarseGlobalPreconditioner_->basis(), *localAssemblers_[i], localInterfaceAssemblers_[i], mode_));
                 } else {
                     levelPatchPreconditioners_.push_back(std::make_shared<SupportPreconditioner>(levelNetwork, levelPatchPreconditioners_.back()->basis(), *localAssemblers_[i], localInterfaceAssemblers_[i], mode_));
+                    levelPatchPreconditioners_.back()->setPatchDepth(patchDepth);
+                    levelPatchPreconditioners_.back()->setBoundaryMode(LevelPatchPreconditionerType::BoundaryMode::homogeneous);
                 }
 
                 maxLevel = i;
diff --git a/dune/faultnetworks/preconditioners/supportpatchpreconditioner.hh b/dune/faultnetworks/preconditioners/supportpatchpreconditioner.hh
index ea23ccd..7acb2c1 100644
--- a/dune/faultnetworks/preconditioners/supportpatchpreconditioner.hh
+++ b/dune/faultnetworks/preconditioners/supportpatchpreconditioner.hh
@@ -61,7 +61,8 @@ public:
             rhs.resize(this->matrix_.N());
             rhs = 0;
 
-            this->localProblems_[i] = std::make_shared<decltype(*(this->localProblems_[i]))>(this->matrix_, rhs, localToGlobal, boundaryDofs);
+            using LocalProblemType = typename std::remove_reference<decltype(*(this->localProblems_[i]))>::type;
+            this->localProblems_[i] = std::make_shared<LocalProblemType>(this->matrix_, rhs, localToGlobal, boundaryDofs);
         }
     }
 };
diff --git a/src/cantorfaultnetworks/cantorfaultnetwork.cc b/src/cantorfaultnetworks/cantorfaultnetwork.cc
index cf3fd4e..1dd5701 100644
--- a/src/cantorfaultnetworks/cantorfaultnetwork.cc
+++ b/src/cantorfaultnetworks/cantorfaultnetwork.cc
@@ -306,17 +306,16 @@ int main(int argc, char** argv) { try
         }
     }
 
-    typedef MultilevelPatchPreconditioner<DGBasis, LocalOscAssembler, LocalInterfaceAssembler, MatrixType, VectorType> MultilevelPatchPreconditioner;
-    typedef typename MultilevelPatchPreconditioner::LevelPatchPreconditionerType LevelPatchPreconditioner;
-    MultilevelPatchPreconditioner::Mode preconditionerMode = MultilevelPatchPreconditioner::Mode::additive;
+    const auto& preconditionerParset = parameterSet.sub("preconditioner");
+    using MultilevelPatchPreconditioner = MultilevelPatchPreconditioner<DGBasis, LocalOscAssembler, LocalInterfaceAssembler, MatrixType, VectorType>;
 
-    MultilevelPatchPreconditioner preconditioner(interfaceNetwork, activeLevels, localAssemblers, localIntersectionAssemblers, preconditionerMode);
-    for (size_t i=0; i<preconditioner.size()-1; i++) {
-        LevelPatchPreconditioner& levelFaultPreconditioner = *preconditioner.levelPatchPreconditioner(i);
+    MultilevelPatchPreconditioner preconditioner(interfaceNetwork, activeLevels, localAssemblers, localIntersectionAssemblers, preconditionerParset);
+    /*for (size_t i=0; i<preconditioner.size()-1; i++) {
+        auto& levelFaultPreconditioner = *preconditioner.levelPatchPreconditioner(i);
 
         levelFaultPreconditioner.setPatchDepth(patchDepth);
         levelFaultPreconditioner.setBoundaryMode(LevelPatchPreconditioner::BoundaryMode::homogeneous);
-    }
+    }*/
     preconditioner.build();
 
     std::cout << "Setup complete, starting preconditioned cg iteration!" << std::endl;
diff --git a/src/cantorfaultnetworks/sparsecantorfaultnetwork.cc b/src/cantorfaultnetworks/sparsecantorfaultnetwork.cc
index cc13b28..4ecac4b 100644
--- a/src/cantorfaultnetworks/sparsecantorfaultnetwork.cc
+++ b/src/cantorfaultnetworks/sparsecantorfaultnetwork.cc
@@ -109,7 +109,6 @@ int main(int argc, char** argv) { try
     const size_t maxCantorLevel = problemParameters.get<size_t>("maxCantorLevel");
 
     const double c = problemParameters.get<double>("penaltyFactor");
-    const int patchDepth = problemParameters.get<int>("patchDepth");
 
     const int maxIterations = problemParameters.get<int>("maxIterations");
     const double solverTolerance = problemParameters.get<double>("tol");
@@ -117,7 +116,7 @@ int main(int argc, char** argv) { try
 
     const int fineGridN = std::pow(4, fineCantorLevel);
 
-    std::ofstream out(resultPath + oscDataFile + "_" + std::to_string(minCantorLevel) + "_" + std::to_string(fineCantorLevel) + "_" + std::to_string(maxCantorLevel) + "_mult.log");
+    std::ofstream out(resultPath + oscDataFile + "_" + std::to_string(minCantorLevel) + "_" + std::to_string(fineCantorLevel) + "_" + std::to_string(maxCantorLevel) + ".log");
     std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf
     std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt
 
diff --git a/src/cantorfaultnetworks/sparsecantorfaultnetwork.parset b/src/cantorfaultnetworks/sparsecantorfaultnetwork.parset
index 354f92a..1f8e671 100644
--- a/src/cantorfaultnetworks/sparsecantorfaultnetwork.parset
+++ b/src/cantorfaultnetworks/sparsecantorfaultnetwork.parset
@@ -2,9 +2,9 @@ path        = ../data/
 resultPath  = ../cantorfaultnetworks/results/sparse/
 
 [preconditioner]
-patch = CELL            # CELL , SUPPORT
+patch = SUPPORT            # CELL , SUPPORT
 mode = ADDITIVE         # ADDITIVE , MULTIPLICATIVE
-multMode = SYMMETRIC    # SYMMETRIC , FORWARD , BACKWARD
+multDirection = SYMMETRIC    # SYMMETRIC , FORWARD , BACKWARD
 patchDepth = 1
 
 ###########################################
diff --git a/src/geofaultnetworks/geofaultnetwork.cc b/src/geofaultnetworks/geofaultnetwork.cc
index 1cd45f9..ddad719 100644
--- a/src/geofaultnetworks/geofaultnetwork.cc
+++ b/src/geofaultnetworks/geofaultnetwork.cc
@@ -340,17 +340,16 @@ int main(int argc, char** argv) { try
         }
     }
 
-    typedef MultilevelPatchPreconditioner<DGBasis, LocalOscAssembler, LocalInterfaceAssembler, MatrixType, VectorType> MultilevelPatchPreconditioner;
-    typedef typename MultilevelPatchPreconditioner::LevelPatchPreconditionerType LevelPatchPreconditioner;
-    MultilevelPatchPreconditioner::Mode preconditionerMode = MultilevelPatchPreconditioner::Mode::additive;
+    const auto& preconditionerParset = parameterSet.sub("preconditioner");
+    using MultilevelPatchPreconditioner = MultilevelPatchPreconditioner<DGBasis, LocalOscAssembler, LocalInterfaceAssembler, MatrixType, VectorType>;
 
-    MultilevelPatchPreconditioner preconditioner(interfaceNetwork, activeLevels, localAssemblers, localIntersectionAssemblers, preconditionerMode);
-    for (size_t i=0; i<preconditioner.size()-1; i++) {
+    MultilevelPatchPreconditioner preconditioner(interfaceNetwork, activeLevels, localAssemblers, localIntersectionAssemblers, preconditionerParset);
+    /*for (size_t i=0; i<preconditioner.size()-1; i++) {
         LevelPatchPreconditioner& levelFaultPreconditioner = *preconditioner.levelPatchPreconditioner(i);
 
         levelFaultPreconditioner.setPatchDepth(patchDepth);
         levelFaultPreconditioner.setBoundaryMode(LevelPatchPreconditioner::BoundaryMode::homogeneous);
-    }
+    }*/
     preconditioner.build();
 
     std::cout << "Setup complete, starting preconditioned cg iteration!" << std::endl;
-- 
GitLab