From 3da29f78907af49941719fb62a2a74cde37186ef Mon Sep 17 00:00:00 2001
From: Markus Blatt <markus@dr-blatt.de>
Date: Wed, 19 Jun 2013 12:38:00 +0200
Subject: [PATCH] Support copying of FastAMG and usage in different threads.

---
 dune/istl/paamg/amg.hh                 |   2 +-
 dune/istl/paamg/fastamg.hh             | 210 +++++++++++++++----------
 dune/istl/paamg/test/CMakeLists.txt    |  12 +-
 dune/istl/paamg/test/pthreadamgtest.cc |  16 +-
 4 files changed, 148 insertions(+), 92 deletions(-)

diff --git a/dune/istl/paamg/amg.hh b/dune/istl/paamg/amg.hh
index 5b347d798..4dc797628 100644
--- a/dune/istl/paamg/amg.hh
+++ b/dune/istl/paamg/amg.hh
@@ -169,7 +169,7 @@ namespace Dune
        */
       template<class C>
       AMG(const Operator& fineOperator, const C& criterion,
-          const SmootherArgs& smootherArgs,
+          const SmootherArgs& smootherArgs=SmootherArgs(),
           const ParallelInformation& pinfo=ParallelInformation());
 
       /**
diff --git a/dune/istl/paamg/fastamg.hh b/dune/istl/paamg/fastamg.hh
index ea1f93be2..bd6309fb2 100644
--- a/dune/istl/paamg/fastamg.hh
+++ b/dune/istl/paamg/fastamg.hh
@@ -55,7 +55,7 @@ namespace Dune
      * \tparam A An allocator for X
      */
     template<class M, class X, class PI=SequentialInformation, class A=std::allocator<X> >
-    class FastAMG : public Dune::Preconditioner<X,X>
+    class FastAMG : public Preconditioner<X,X>
     {
     public:
       /** @brief The matrix operator type. */
@@ -68,7 +68,7 @@ namespace Dune
        */
       typedef PI ParallelInformation;
       /** @brief The operator hierarchy type. */
-      typedef Dune::Amg::MatrixHierarchy<M, ParallelInformation, A> OperatorHierarchy;
+      typedef MatrixHierarchy<M, ParallelInformation, A> OperatorHierarchy;
       /** @brief The parallal data distribution hierarchy type. */
       typedef typename OperatorHierarchy::ParallelInformationHierarchy ParallelInformationHierarchy;
 
@@ -77,7 +77,7 @@ namespace Dune
       /** @brief The range type. */
       typedef X Range;
       /** @brief the type of the coarse solver. */
-      typedef Dune::InverseOperator<X,X> CoarseSolver;
+      typedef InverseOperator<X,X> CoarseSolver;
 
       enum {
         /** @brief The solver category. */
@@ -92,7 +92,7 @@ namespace Dune
        * @param parms The parameters for the AMG.
        */
       FastAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver,
-              const Dune::Amg::Parameters& parms,
+              const Parameters& parms,
               bool symmetric=true);
 
       /**
@@ -108,10 +108,15 @@ namespace Dune
        */
       template<class C>
       FastAMG(const Operator& fineOperator, const C& criterion,
-              const Parameters& parms,
+              const Parameters& parms=Parameters(),
               bool symmetric=true,
               const ParallelInformation& pinfo=ParallelInformation());
 
+      /**
+       * @brief Copy constructor.
+       */
+      FastAMG(const FastAMG& amg),
+
       ~FastAMG();
 
       /** \copydoc Preconditioner::pre */
@@ -144,7 +149,7 @@ namespace Dune
        */
       void recalculateHierarchy()
       {
-        matrices_->recalculateGalerkin(Dune::NegateSet<typename PI::OwnerSet>());
+        matrices_->recalculateGalerkin(NegateSet<typename PI::OwnerSet>());
       }
 
       /**
@@ -154,6 +159,16 @@ namespace Dune
       bool usesDirectCoarseLevelSolver() const;
 
     private:
+      /**
+       * @brief Create matrix and smoother hierarchies.
+       * @param criterion The coarsening criterion.
+       * @param matrix The fine level matrix operator.
+       * @param pinfo The fine level parallel information.
+       */
+      template<class C>
+      void createHierarchies(C& criterion, Operator& matrix,
+                             const PI& pinfo);
+
       /** @brief Multigrid cycle on a level. */
       void mgc(Domain& x, const Range& b);
 
@@ -161,10 +176,9 @@ namespace Dune
       typename ParallelInformationHierarchy::Iterator pinfo;
       typename OperatorHierarchy::RedistributeInfoList::const_iterator redist;
       typename OperatorHierarchy::AggregatesMapList::const_iterator aggregates;
-      typename Dune::Amg::Hierarchy<Domain,A>::Iterator lhs;
-      typename Dune::Amg::Hierarchy<Domain,A>::Iterator residual;
-      typename Dune::Amg::Hierarchy<Domain,A>::Iterator tmp;
-      typename Dune::Amg::Hierarchy<Range,A>::Iterator rhs;
+      typename Hierarchy<Domain,A>::Iterator lhs;
+      typename Hierarchy<Domain,A>::Iterator residual;
+      typename Hierarchy<Range,A>::Iterator rhs;
 
 
       /** @brief Apply pre smoothing on the current level. */
@@ -189,17 +203,16 @@ namespace Dune
       /** @brief The solver of the coarsest level. */
       Dune::shared_ptr<CoarseSolver> solver_;
       /** @brief The right hand side of our problem. */
-      Dune::Amg::Hierarchy<Range,A>* rhs_;
+      Hierarchy<Range,A>* rhs_;
       /** @brief The left approximate solution of our problem. */
-      Dune::Amg::Hierarchy<Domain,A>* lhs_;
+      Hierarchy<Domain,A>* lhs_;
       /** @brief The current residual. */
-      Dune::Amg::Hierarchy<Domain,A>* residual_;
+      Hierarchy<Domain,A>* residual_;
 
       /** @brief The type of the chooser of the scalar product. */
-      typedef Dune::ScalarProductChooser<X,PI,M::category> ScalarProductChooser;
+      typedef ScalarProductChooser<X,PI,M::category> ScalarProductChooserType;
       /** @brief The type of the scalar product for the coarse solver. */
-      typedef typename ScalarProductChooser::ScalarProduct ScalarProduct;
-
+      typedef typename ScalarProductChooserType::ScalarProduct ScalarProduct;
       typedef Dune::shared_ptr<ScalarProduct> ScalarProductPointer;
       /** @brief Scalar product on the coarse level. */
       ScalarProductPointer scalarProduct_;
@@ -213,17 +226,34 @@ namespace Dune
       bool buildHierarchy_;
       bool symmetric;
       bool coarsesolverconverged;
-      typedef Dune::SeqSSOR<typename M::matrix_type,X,X> Smoother;
+      typedef SeqSSOR<typename M::matrix_type,X,X> Smoother;
       typedef Dune::shared_ptr<Smoother> SmootherPointer;
       SmootherPointer coarseSmoother_;
       /** @brief The verbosity level. */
       std::size_t verbosity_;
     };
 
+    template<class M, class X, class PI, class A>
+    FastAMG<M,X,PI,A>::FastAMG(const FastAMG& amg)
+    : matrices_(amg.matrices_), solver_(amg.solver_),
+      rhs_(), lhs_(), residual_(), scalarProduct_(amg.scalarProduct_),
+      gamma_(amg.gamma_), preSteps_(amg.preSteps_), postSteps_(amg.postSteps_),
+      symmetric(amg.symmetric), coarsesolverconverged(amg.coarsesolverconverged),
+      coarseSmoother_(amg.coarseSmoother_), verbosity_(amg.verbosity_)
+    {
+      if(amg.rhs_)
+        rhs_=new Hierarchy<Range,A>(*amg.rhs_);
+      if(amg.lhs_)
+        lhs_=new Hierarchy<Domain,A>(*amg.lhs_);
+      if(amg.residual_)
+        residual_=new Hierarchy<Domain,A>(*amg.residual_);
+    }
+
     template<class M, class X, class PI, class A>
     FastAMG<M,X,PI,A>::FastAMG(const OperatorHierarchy& matrices, CoarseSolver& coarseSolver,
-                               const Dune::Amg::Parameters& parms, bool symmetric_)
-      : matrices_(&matrices), solver_(&coarseSolver), scalarProduct_(),
+                               const Parameters& parms, bool symmetric_)
+      : matrices_(&matrices), solver_(&coarseSolver),
+        rhs_(), lhs_(), residual_(), scalarProduct_(),
         gamma_(parms.getGamma()), preSteps_(parms.getNoPreSmoothSteps()),
         postSteps_(parms.getNoPostSmoothSteps()), buildHierarchy_(false),
         symmetric(symmetric_), coarsesolverconverged(true),
@@ -235,16 +265,16 @@ namespace Dune
         preSteps_=postSteps_=0;
       }
       assert(matrices_->isBuilt());
-      dune_static_assert((Dune::is_same<PI,Dune::Amg::SequentialInformation>::value), "Currently only sequential runs are supported");
+      dune_static_assert((is_same<PI,SequentialInformation>::value), "Currently only sequential runs are supported");
     }
     template<class M, class X, class PI, class A>
     template<class C>
     FastAMG<M,X,PI,A>::FastAMG(const Operator& matrix,
                                const C& criterion,
-                               const Dune::Amg::Parameters& parms,
+                               const Parameters& parms,
                                bool symmetric_,
                                const PI& pinfo)
-      : solver_(), scalarProduct_(), gamma_(parms.getGamma()),
+      : solver_(), rhs_(), lhs_(), residual_(), scalarProduct_(), gamma_(parms.getGamma()),
         preSteps_(parms.getNoPreSmoothSteps()), postSteps_(parms.getNoPostSmoothSteps()),
         buildHierarchy_(true),
         symmetric(symmetric_), coarsesolverconverged(true),
@@ -255,42 +285,69 @@ namespace Dune
         std::cerr<<"WARNING only one step of smoothing is supported!"<<std::endl;
         preSteps_=postSteps_=1;
       }
-      dune_static_assert((Dune::is_same<PI,Dune::Amg::SequentialInformation>::value), "Currently only sequential runs are supported");
+      dune_static_assert((is_same<PI,SequentialInformation>::value), "Currently only sequential runs are supported");
       // TODO: reestablish compile time checks.
       //dune_static_assert(static_cast<int>(PI::category)==static_cast<int>(S::category),
       //			 "Matrix and Solver must match in terms of category!");
-      Dune::Timer watch;
-      matrices_.reset(new OperatorHierarchy(const_cast<Operator&>(matrix), pinfo));
+      createHierarchies(criterion, const_cast<Operator&>(matrix), pinfo);
+    }
+
+    template<class M, class X, class PI, class A>
+    FastAMG<M,X,PI,A>::~FastAMG()
+    {
+      if(buildHierarchy_) {
+        if(solver_)
+          solver_.reset();
+        if(coarseSmoother_)
+          coarseSmoother_.reset();
+      }
+      if(lhs_)
+        delete lhs_;
+      lhs_=nullptr;
+      if(residual_)
+        delete residual_;
+      residual_=nullptr;
+      if(rhs_)
+        delete rhs_;
+      rhs_=nullptr;
+    }
 
-      matrices_->template build<Dune::NegateSet<typename PI::OwnerSet> >(criterion);
+    template<class M, class X, class PI, class A>
+    template<class C>
+    void FastAMG<M,X,PI,A>::createHierarchies(C& criterion, Operator& matrix,
+                                            const PI& pinfo)
+    {
+      Timer watch;
+      matrices_.reset(new OperatorHierarchy(matrix, pinfo));
+
+      matrices_->template build<NegateSet<typename PI::OwnerSet> >(criterion);
+
+      if(verbosity_>0 && matrices_->parallelInformation().finest()->communicator().rank()==0)
+        std::cout<<"Building Hierarchy of "<<matrices_->maxlevels()<<" levels took "<<watch.elapsed()<<" seconds."<<std::endl;
 
       if(buildHierarchy_ && matrices_->levels()==matrices_->maxlevels()) {
         // We have the carsest level. Create the coarse Solver
-        typedef typename Dune::Amg::SmootherTraits<Smoother>::Arguments SmootherArgs;
+        typedef typename SmootherTraits<Smoother>::Arguments SmootherArgs;
         SmootherArgs sargs;
         sargs.iterations = 1;
 
-        typename Dune::Amg::ConstructionTraits<Smoother>::Arguments cargs;
+        typename ConstructionTraits<Smoother>::Arguments cargs;
         cargs.setArgs(sargs);
         if(matrices_->redistributeInformation().back().isSetup()) {
           // Solve on the redistributed partitioning
           cargs.setMatrix(matrices_->matrices().coarsest().getRedistributed().getmat());
           cargs.setComm(matrices_->parallelInformation().coarsest().getRedistributed());
-
-          coarseSmoother_ = SmootherPointer(Dune::Amg::ConstructionTraits<Smoother>::construct(cargs),
-                                            Dune::Amg::ConstructionTraits<Smoother>::deconstruct);
-          scalarProduct_ = ScalarProductPointer(ScalarProductChooser::construct(matrices_->parallelInformation().coarsest().getRedistributed()));
         }else{
           cargs.setMatrix(matrices_->matrices().coarsest()->getmat());
           cargs.setComm(*matrices_->parallelInformation().coarsest());
-
-          coarseSmoother_ = SmootherPointer(Dune::Amg::ConstructionTraits<Smoother>::construct(cargs),
-                                            Dune::Amg::ConstructionTraits<Smoother>::deconstruct);
-          scalarProduct_ = ScalarProductPointer(ScalarProductChooser::construct(*matrices_->parallelInformation().coarsest()));
         }
+
+        coarseSmoother_.reset(ConstructionTraits<Smoother>::construct(cargs));
+        scalarProduct_.reset(ScalarProductChooserType::construct(cargs.getComm()));
+
 #if HAVE_SUPERLU
         // Use superlu if we are purely sequential or with only one processor on the coarsest level.
-        if(Dune::is_same<ParallelInformation,Dune::Amg::SequentialInformation>::value // sequential mode
+        if(is_same<ParallelInformation,SequentialInformation>::value // sequential mode
            || matrices_->parallelInformation().coarsest()->communicator().size()==1 //parallel mode and only one processor
            || (matrices_->parallelInformation().coarsest().isRedistributed()
                && matrices_->parallelInformation().coarsest().getRedistributed().communicator().size()==1
@@ -301,9 +358,11 @@ namespace Dune
           {
             if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0)
               // We are still participating on this level
-              solver_  = Dune::shared_ptr<Dune::SuperLU<typename M::matrix_type> >( new Dune::SuperLU<typename M::matrix_type>(matrices_->matrices().coarsest().getRedistributed().getmat()));
+              solver_.reset(new SuperLU<typename M::matrix_type>(matrices_->matrices().coarsest().getRedistributed().getmat(), false, false));
+            else
+              solver_.reset();
           }else
-            solver_  = Dune::shared_ptr<Dune::SuperLU<typename M::matrix_type> >( new Dune::SuperLU<typename M::matrix_type>(matrices_->matrices().coarsest()->getmat()));
+            solver_.reset(new SuperLU<typename M::matrix_type>(matrices_->matrices().coarsest()->getmat(), false, false));
         }else
 #endif
         {
@@ -311,13 +370,15 @@ namespace Dune
           {
             if(matrices_->matrices().coarsest().getRedistributed().getmat().N()>0)
               // We are still participating on this level
-              solver_ = Dune::shared_ptr<Dune::BiCGSTABSolver<X> >(new Dune::BiCGSTABSolver<X>(const_cast<M&>(matrices_->matrices().coarsest().getRedistributed()),
-                                                                                               *scalarProduct_,
-                                                                                               *coarseSmoother_, 1E-2, 10000, 0));
+              solver_.reset(new BiCGSTABSolver<X>(const_cast<M&>(matrices_->matrices().coarsest().getRedistributed()),
+                                                  *scalarProduct_,
+                                                  *coarseSmoother_, 1E-2, 1000, 0));
+            else
+              solver_.reset();
           }else
-            solver_ = Dune::shared_ptr<Dune::BiCGSTABSolver<X> >(new Dune::BiCGSTABSolver<X>(const_cast<M&>(*matrices_->matrices().coarsest()),
-                                                                                             *scalarProduct_,
-                                                                                             *coarseSmoother_, 1E-2, 1000, 0));
+            solver_.reset(new BiCGSTABSolver<X>(const_cast<M&>(*matrices_->matrices().coarsest()),
+                                                *scalarProduct_,
+                                                *coarseSmoother_, 1E-2, 1000, 0));
         }
       }
 
@@ -325,15 +386,11 @@ namespace Dune
         std::cout<<"Building Hierarchy of "<<matrices_->maxlevels()<<" levels took "<<watch.elapsed()<<" seconds."<<std::endl;
     }
 
-    template<class M, class X, class PI, class A>
-    FastAMG<M,X,PI,A>::~FastAMG()
-    {}
-
 
     template<class M, class X, class PI, class A>
     void FastAMG<M,X,PI,A>::pre(Domain& x, Range& b)
     {
-      Dune::Timer watch, watch1;
+      Timer watch, watch1;
       // Detect Matrix rows where all offdiagonal entries are
       // zero and set x such that  A_dd*x_d=b_d
       // Thus users can be more careless when setting up their linear
@@ -367,11 +424,15 @@ namespace Dune
       // No smoother to make x consistent! Do it by hand
       matrices_->parallelInformation().coarsest()->copyOwnerToAll(x,x);
       Range* copy = new Range(b);
-      rhs_ = new Dune::Amg::Hierarchy<Range,A>(*copy);
+      if(rhs_)
+        delete rhs_;
+      rhs_ = new Hierarchy<Range,A>(copy);
       Domain* dcopy = new Domain(x);
-      lhs_ = new Dune::Amg::Hierarchy<Domain,A>(*dcopy);
+      if(lhs_)
+        delete lhs_;
+      lhs_ = new Hierarchy<Domain,A>(dcopy);
       dcopy = new Domain(x);
-      residual_ = new Dune::Amg::Hierarchy<Domain,A>(*dcopy);
+      residual_ = new Hierarchy<Domain,A>(dcopy);
       matrices_->coarsenVector(*rhs_);
       matrices_->coarsenVector(*lhs_);
       matrices_->coarsenVector(*residual_);
@@ -380,10 +441,6 @@ namespace Dune
       // copy the changes to the original vectors.
       x = *lhs_->finest();
       b = *rhs_->finest();
-
-      std::cout<<" Preprocessing smoothers took "<<watch1.elapsed()<<std::endl;
-      watch1.reset();
-      std::cout<<"AMG::pre took "<<watch.elapsed()<<std::endl;
     }
     template<class M, class X, class PI, class A>
     std::size_t FastAMG<M,X,PI,A>::levels()
@@ -406,20 +463,10 @@ namespace Dune
       assert(v.two_norm()==0);
 
       level=0;
-      /*if(redist->isSetup())
-         {
-         *lhs=v;
-         *rhs = d;
-         mgc(*lhs, *rhs);
-         if(postSteps_==0||matrices_->maxlevels()==1)
-         pinfo->copyOwnerToAll(*lhs, *lhs);
-         v=*lhs;
-         }else{*/
+
       mgc(v, d);
       if(postSteps_==0||matrices_->maxlevels()==1)
         pinfo->copyOwnerToAll(v, v);
-      //}
-
     }
 
     template<class M, class X, class PI, class A>
@@ -448,14 +495,14 @@ namespace Dune
         if(processNextLevel) {
           //restrict defect to coarse level right hand side.
           ++pinfo;
-          Dune::Amg::Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
+          Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
           ::restrictVector(*(*aggregates), *rhs, static_cast<const Range&>(residual.getRedistributed()), *pinfo);
         }
       }else{
         //restrict defect to coarse level right hand side.
-        typename Dune::Amg::Hierarchy<Range,A>::Iterator fineRhs = rhs++;
+        typename Hierarchy<Range,A>::Iterator fineRhs = rhs++;
         ++pinfo;
-        Dune::Amg::Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
+        Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
         ::restrictVector(*(*aggregates), *rhs, static_cast<const Range&>(*residual), *pinfo);
       }
 
@@ -495,15 +542,15 @@ namespace Dune
 
       }
 
-      typename Dune::Amg::Hierarchy<Domain,A>::Iterator coarseLhs = lhs--;
+      typename Hierarchy<Domain,A>::Iterator coarseLhs = lhs--;
       if(redist->isSetup()) {
 
         // Need to redistribute during prolongate
-        Dune::Amg::Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
+        Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
         ::prolongateVector(*(*aggregates), *coarseLhs, x, lhs.getRedistributed(), matrices_->getProlongationDampingFactor(),
                            *pinfo, *redist);
       }else{
-        Dune::Amg::Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
+        Transfer<typename OperatorHierarchy::AggregatesMap::AggregateDescriptor,Range,ParallelInformation>
         ::prolongateVector(*(*aggregates), *coarseLhs, x,
                            matrices_->getProlongationDampingFactor(), *pinfo);
 
@@ -540,7 +587,7 @@ namespace Dune
     template<class M, class X, class PI, class A>
     bool FastAMG<M,X,PI,A>::usesDirectCoarseLevelSolver() const
     {
-      return Dune::IsDirectSolver< CoarseSolver>::value;
+      return IsDirectSolver< CoarseSolver>::value;
     }
 
     template<class M, class X, class PI, class A>
@@ -548,7 +595,7 @@ namespace Dune
 
       if(matrix == matrices_->matrices().coarsest() && levels()==maxlevels()) {
         // Solve directly
-        Dune::InverseOperatorResult res;
+        InverseOperatorResult res;
         res.converged=true; // If we do not compute this flag will not get updated
         if(redist->isSetup()) {
           redist->redistribute(b, rhs.getRedistributed());
@@ -590,7 +637,7 @@ namespace Dune
         if(matrix == matrices_->matrices().finest()) {
           coarsesolverconverged = matrices_->parallelInformation().finest()->communicator().prod(coarsesolverconverged);
           if(!coarsesolverconverged)
-            DUNE_THROW(Dune::MathError, "Coarse solver did not converge");
+            DUNE_THROW(MathError, "Coarse solver did not converge");
         }
 
         // printvector(std::cout, *lhs, "update corrected", "u", 10, 10, 10);
@@ -606,13 +653,12 @@ namespace Dune
     template<class M, class X, class PI, class A>
     void FastAMG<M,X,PI,A>::post(Domain& x)
     {
-      delete &(*lhs_->finest());
       delete lhs_;
-      delete &(*residual_->finest());
-      delete residual_;
-
-      delete &(*rhs_->finest());
+      lhs_=nullptr;
       delete rhs_;
+      rhs_=nullptr;
+      delete residual_;
+      residual_=nullptr;
     }
 
     template<class M, class X, class PI, class A>
diff --git a/dune/istl/paamg/test/CMakeLists.txt b/dune/istl/paamg/test/CMakeLists.txt
index b9dad7060..247301c0f 100644
--- a/dune/istl/paamg/test/CMakeLists.txt
+++ b/dune/istl/paamg/test/CMakeLists.txt
@@ -5,8 +5,10 @@ endif(MPI_FOUND)
 if(PARMETIS_FOUND)
   set(PARMETISTESTS pamgtest pamg_comm_repart_test)
 endif(PARMETIS_FOUND)
-
-set(NORMALTESTS amgtest fastamg graphtest kamgtest pthreadamgtest)
+if(CMAKE_USE_PTHREADS_INIT)
+  set(PTHREADTESTS pthreadamgtest pthreadfastamgtest)
+endif(CMAKE_USE_PTHREADS_INIT)
+set(NORMALTESTS amgtest fastamg graphtest kamgtest ${PTHREADTESTS})
 set(ALLTESTS ${MPITESTS} ${PARMETISTESTS} ${NORMALTESTS})
 
 # We do not want want to build the tests during make all,
@@ -17,6 +19,12 @@ add_dependencies(${_test_target} ${ALLTESTS})
 find_package(Threads)
 if(CMAKE_USE_PTHREADS_INIT)
   add_executable(pthreadamgtest pthreadamgtest.cc)
+  set_property(TARGET pthreadamgtest APPEND PROPERTY
+    COMPILE_DEFINITIONS "MYAMG=Dune::Amg::AMG<Operator,Vector,Smoother>")
+  target_link_libraries(pthreadamgtest "${CMAKE_THREAD_LIBS_INIT}")
+  add_executable(pthreadfastamgtest pthreadamgtest.cc)
+  set_property(TARGET pthreadfastamgtest APPEND PROPERTY
+    COMPILE_DEFINITIONS "MYAMG=Dune::Amg::FastAMG<Operator,Vector>")
   target_link_libraries(pthreadamgtest "${CMAKE_THREAD_LIBS_INIT}")
 endif(CMAKE_USE_PTHREADS_INIT)
 
diff --git a/dune/istl/paamg/test/pthreadamgtest.cc b/dune/istl/paamg/test/pthreadamgtest.cc
index be81e7cef..a4d3c1c20 100644
--- a/dune/istl/paamg/test/pthreadamgtest.cc
+++ b/dune/istl/paamg/test/pthreadamgtest.cc
@@ -20,12 +20,13 @@
 #include <dune/common/parallel/indexset.hh>
 #include <dune/common/parallel/collectivecommunication.hh>
 #include <dune/istl/paamg/amg.hh>
+#include <dune/istl/paamg/fastamg.hh>
 #include <dune/istl/paamg/pinfo.hh>
 #include <dune/istl/solvers.hh>
 #include <cstdlib>
 #include <ctime>
 #include <pthread.h>
-#define NUM_THREADS 1
+#define NUM_THREADS 3
 
 typedef double XREAL;
 
@@ -68,11 +69,10 @@ typedef Dune::MatrixAdapter<BCRSMat,Vector,Vector> Operator;
 typedef Dune::CollectiveCommunication<void*> Comm;
 typedef Dune::SeqSSOR<BCRSMat,Vector,Vector> Smoother;
 typedef typename Dune::Amg::SmootherTraits<Smoother>::Arguments SmootherArgs;
-typedef Dune::Amg::AMG<Operator,Vector,Smoother> AMG;
 
 struct thread_arg
 {
-  AMG *amg;
+  MYAMG *amg;
   Vector *b;
   Vector *x;
   Operator *fop;
@@ -99,6 +99,7 @@ void *solve(void* arg)
 void *solve1(void* arg)
 {
   thread_arg *amgarg=(thread_arg*) arg;
+  *amgarg->x=0;
   (*amgarg->amg).apply(*amgarg->x,*amgarg->b);
   (*amgarg->amg).post(*amgarg->x);
 
@@ -107,12 +108,13 @@ void *solve1(void* arg)
 void *solve2(void* arg)
 {
   thread_arg *amgarg=(thread_arg*) arg;
+  *amgarg->x=0;
   (*amgarg->amg).pre(*amgarg->x,*amgarg->b);
   (*amgarg->amg).apply(*amgarg->x,*amgarg->b);
   (*amgarg->amg).post(*amgarg->x);
 }
 
-template <int BS>
+template <int BS, typename AMG>
 void testAMG(int N, int coarsenTarget, int ml)
 {
 
@@ -177,8 +179,7 @@ void testAMG(int N, int coarsenTarget, int ml)
   Dune::SeqScalarProduct<Vector> sp;
 
   Smoother smoother(mat,1,1);
-
-  AMG amg(fop, criterion, smootherArgs, 1, 1, 1, false);
+  AMG amg(fop, criterion);
 
 
   double buildtime = watch.elapsed();
@@ -249,7 +250,8 @@ int main(int argc, char** argv)
   if(argc>3)
     ml = atoi(argv[3]);
 
-  testAMG<1>(N, coarsenTarget, ml);
+  testAMG<1,MYAMG>(N, coarsenTarget, ml);
+
   //testAMG<2>(N, coarsenTarget, ml);
 
 }
-- 
GitLab