From 40ffdda763c266277d0354b0e7cc8329f0c0c4df Mon Sep 17 00:00:00 2001
From: Jonathan Youett <youett@math.fu-berlin.de>
Date: Mon, 18 Sep 2017 11:43:18 +0200
Subject: [PATCH] Make obstacle data protected and add setters taking
 l-,r-values or shared_ptr

Internally this data is now stored within shared pointer
---
 dune/solvers/iterationsteps/mmgstep.cc | 26 ++++++++-------------
 dune/solvers/iterationsteps/mmgstep.hh | 32 ++++++++++++++++++++------
 dune/solvers/test/mmgtest.cc           |  5 ++--
 3 files changed, 36 insertions(+), 27 deletions(-)

diff --git a/dune/solvers/iterationsteps/mmgstep.cc b/dune/solvers/iterationsteps/mmgstep.cc
index 87f4f0b6..a9395e9f 100644
--- a/dune/solvers/iterationsteps/mmgstep.cc
+++ b/dune/solvers/iterationsteps/mmgstep.cc
@@ -24,15 +24,11 @@ preprocess()
     MultigridStep<MatrixType,VectorType>::preprocess();
 
     // Then setup the obstacle flags which specify the subset of entries to be reassembled at each iteration
-     for (int i=0; i<(int) hasObstacleHierarchy_.size()-1; i++)
-        if (hasObstacleHierarchy_[i] != nullptr)
-            delete(hasObstacleHierarchy_[i]);
-
     hasObstacleHierarchy_.resize(this->numLevels());
     hasObstacleHierarchy_.back() = hasObstacle_;
 
     for (int i=this->mgTransfer_.size()-1; i>=0; i--) {
-        hasObstacleHierarchy_[i] = new Dune::BitSetVector<dim>();
+        hasObstacleHierarchy_[i] = std::make_shared<Dune::BitSetVector<dim> >();
         this->mgTransfer_[i]->restrict(*hasObstacleHierarchy_[i+1], *hasObstacleHierarchy_[i]);
         for (size_t j=0; j<hasObstacleHierarchy_[i]->size(); j++)
             if ((*this->ignoreNodesHierarchy_[i])[j].any())
@@ -58,15 +54,11 @@ preprocess()
     //   Set up base solver
     // /////////////////////////////////////////////
 
-    for (int i=0; i<(int) obstacleHierarchy_.size()-1; i++)
-        if (obstacleHierarchy_[i] != nullptr)
-            delete(obstacleHierarchy_[i]);
-
     obstacleHierarchy_.resize(this->numLevels());
     obstacleHierarchy_.back() = obstacles_;
 
     for (size_t i=0; i<obstacleHierarchy_.size()-1; i++)
-        obstacleHierarchy_[i] = new ObstacleVectorType();
+        obstacleHierarchy_[i] = std::make_shared<ObstacleVectorType>();
 
     if (typeid(*this->basesolver_) == typeid(::LoopSolver<VectorType>)) {
 
@@ -74,8 +66,8 @@ preprocess()
 
         typedef ProjectedBlockGSStep<MatrixType, VectorType> SmootherType;
 
-        dynamic_cast<SmootherType*>(&loopBaseSolver->getIterationStep())->hasObstacle_ = hasObstacleHierarchy_[0];
-        dynamic_cast<SmootherType*>(&loopBaseSolver->getIterationStep())->obstacles_   = obstacleHierarchy_[0];
+        dynamic_cast<SmootherType*>(&loopBaseSolver->getIterationStep())->hasObstacle_ = hasObstacleHierarchy_[0].get();
+        dynamic_cast<SmootherType*>(&loopBaseSolver->getIterationStep())->obstacles_   = obstacleHierarchy_[0].get();
 
 #if HAVE_IPOPT
     } else if (typeid(*this->basesolver_) == typeid(QuadraticIPOptSolver<MatrixType,VectorType>)) {
@@ -142,7 +134,7 @@ void MonotoneMGStep<MatrixType, VectorType>::iterate()
     std::vector<std::shared_ptr<const MatrixType> >& mat = this->matrixHierarchy_;
     std::vector<std::shared_ptr<VectorType> >& x   = this->xHierarchy_;
     std::vector<VectorType>& rhs = this->rhsHierarchy_;
-    std::vector<ObstacleVectorType* >& obstacles = obstacleHierarchy_;
+    auto& obstacles = obstacleHierarchy_;
 
     Dune::BitSetVector<dim> critical(x[level]->size(), false);
 
@@ -171,8 +163,8 @@ void MonotoneMGStep<MatrixType, VectorType>::iterate()
         ProjectedBlockGSStep<MatrixType,VectorType>* presmoother = dynamic_cast<ProjectedBlockGSStep<MatrixType, VectorType>*>(this->presmoother_[level].get());
         assert(presmoother);
         presmoother->setProblem(*(mat[level]), *x[level], rhs[level]);
-        presmoother->obstacles_ = obstacles[level];
-        presmoother->hasObstacle_ = hasObstacleHierarchy_[level];
+        presmoother->obstacles_ = obstacles[level].get();
+        presmoother->hasObstacle_ = hasObstacleHierarchy_[level].get();
         presmoother->ignoreNodes_ = this->ignoreNodesHierarchy_[level];
 
         for (int i=0; i<this->nu1_; i++)
@@ -291,8 +283,8 @@ void MonotoneMGStep<MatrixType, VectorType>::iterate()
         ProjectedBlockGSStep<MatrixType,VectorType>* postsmoother = dynamic_cast<ProjectedBlockGSStep<MatrixType, VectorType>*>(this->postsmoother_[level].get());
         assert(postsmoother);
         postsmoother->setProblem(*(mat[level]), *x[level], rhs[level]);
-        postsmoother->obstacles_ = obstacles[level];
-        postsmoother->hasObstacle_ = hasObstacleHierarchy_[level];
+        postsmoother->obstacles_ = obstacles[level].get();
+        postsmoother->hasObstacle_ = hasObstacleHierarchy_[level].get();
         postsmoother->ignoreNodes_ = this->ignoreNodesHierarchy_[level];
 
         for (int i=0; i<this->nu2_; i++)
diff --git a/dune/solvers/iterationsteps/mmgstep.hh b/dune/solvers/iterationsteps/mmgstep.hh
index 95a71526..d8c7ddfc 100644
--- a/dune/solvers/iterationsteps/mmgstep.hh
+++ b/dune/solvers/iterationsteps/mmgstep.hh
@@ -54,10 +54,28 @@ public:
     virtual void nestedIteration();
 
     //! Set the hasObstacle bitfield
-    void setHasObstacles(Dune::BitSetVector<dim>* hasObstacle) {hasObstacle_ = hasObstacle;}
+    DUNE_DEPRECATED_MSG("Setting by raw pointer is deprecated. Use l-value or r-value or a shared_ptr")
+    void setHasObstacles(Dune::BitSetVector<dim>* hasObstacle) {
+      hasObstacle_ = Dune::stackobject_to_shared_ptr(hasObstacle);
+    }
+
+    //! Set the hasObstacle bitfield
+    template <class BitVector, class Enable = std::enable_if_t<not std::is_pointer<BitVector>::value> >
+    void setHasObstacles(BitVector&& hasObstacles) {
+      hasObstacle_ = Dune::Solvers::wrap_own_share<Dune::BitSetVector<dim> >(std::forward<BitVector>(hasObstacles));
+    }
+
+    //! Set the obstacle field
+    DUNE_DEPRECATED_MSG("Setting by raw pointer is deprecated. Use l-value or r-value or a shared_ptr")
+    void setObstacles(ObstacleVectorType* obstacles) {
+      obstacles_ = Dune::stackobject_to_shared_ptr(obstacles);
+    }
 
     //! Set the obstacle field
-    void setObstacles(ObstacleVectorType* obstacles) {obstacles_ = obstacles;}
+    template <class ObstacleVector, class Enable = std::enable_if_t<not std::is_pointer<ObstacleVector>::value> >
+    void setObstacles(ObstacleVector&& obstacles) {
+      obstacles_ = Dune::Solvers::wrap_own_share<ObstacleVectorType>(std::forward<ObstacleVector>(obstacles));
+    }
 
     //! Set the obstacle restrictor
     template <class Restrictor>
@@ -65,22 +83,22 @@ public:
         obstacleRestrictor_ = Dune::Solvers::wrap_own_share<ObstacleRestrictor<VectorType> >(std::forward<Restrictor>(restrictor));
     }
 
+protected:
     //! Bitfield determining which fine grid nodes have an obstacle
-    Dune::BitSetVector<dim>* hasObstacle_;
+    std::shared_ptr<Dune::BitSetVector<dim> > hasObstacle_;
 
     //! Vector containing the obstacle values of the fine grid nodes
-    ObstacleVectorType * obstacles_;
+    std::shared_ptr<ObstacleVectorType> obstacles_;
 
     // Needed to track changes in the set of critical bits, and allows
     // to check which dofs where critical after the last iteration
     Dune::BitSetVector<dim> oldCritical;
 
-protected:
     //! The restrictor used to construct the coarse obstacles
     std::shared_ptr<ObstacleRestrictor<VectorType> > obstacleRestrictor_;
 
     //! Bitfield hierarchy containing the coarse obstacle nodes
-    std::vector<Dune::BitSetVector<dim>* > hasObstacleHierarchy_;
+    std::vector<std::shared_ptr<Dune::BitSetVector<dim>> > hasObstacleHierarchy_;
 
     //! For each level specify the matrix lines that need reassembly
     std::vector<Dune::BitSetVector<dim> > recompute_;
@@ -89,7 +107,7 @@ protected:
     std::vector<Dune::BitSetVector<dim> > oldCritical_;
 
     //! Hierarchy containing the obstacle values of the coarse obstacles
-    std::vector<ObstacleVectorType*>  obstacleHierarchy_;
+    std::vector<std::shared_ptr<ObstacleVectorType> >  obstacleHierarchy_;
 private:
     using Base::setProblem;
 
diff --git a/dune/solvers/test/mmgtest.cc b/dune/solvers/test/mmgtest.cc
index 43d6098e..cc005693 100644
--- a/dune/solvers/test/mmgtest.cc
+++ b/dune/solvers/test/mmgtest.cc
@@ -60,14 +60,13 @@ void solveObstacleProblemByMMGSolver(const GridType& grid, const MatrixType& mat
     mmgStep.setSmoother(&smoother);
     mmgStep.setObstacleRestrictor(MandelObstacleRestrictor<VectorType>());
 
-    Dune::BitSetVector<blockSize> hasObstacle(x.size(),true);
-    mmgStep.hasObstacle_       = &hasObstacle;
+    mmgStep.setHasObstacles(Dune::BitSetVector<blockSize>(x.size(),true));
 
     std::vector<BoxConstraint<typename VectorType::field_type,blockSize> > boxConstraints(rhs.size());
     for (size_t i = 0; i < boxConstraints.size(); ++i)
         for (int j = 0; j < blockSize; ++j)
             boxConstraints[i][j] = { -1, +1 };
-    mmgStep.obstacles_         = &boxConstraints;
+    mmgStep.setObstacles(boxConstraints);
 
     // we need a vector of pointers to the transfer operator base class
     using Transfer = TruncatedCompressedMGTransfer<VectorType>;
-- 
GitLab