From 9eadad5becf198fc990eab123a23e33baf738cae Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Mon, 26 May 2014 05:18:21 +0000
Subject: [PATCH] Properly implement hasObstacle and MG transfer operator for
 higher-order spaces

[[Imported from SVN: r9765]]
---
 dune/gfe/riemanniantrsolver.cc | 38 ++++++++++++++++++++++++----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/dune/gfe/riemanniantrsolver.cc b/dune/gfe/riemanniantrsolver.cc
index 592e9545..5be60a1d 100644
--- a/dune/gfe/riemanniantrsolver.cc
+++ b/dune/gfe/riemanniantrsolver.cc
@@ -167,12 +167,34 @@ setup(const GridType& grid,
 
         PKtoP1MGTransfer<CorrectionType>* topTransferOp = new PKtoP1MGTransfer<CorrectionType>;
         topTransferOp->setup(basis,p1Basis);
-        mmgStep->mgTransfer_.back() = topTransferOp;
+
+        // If we are on more than 1 processors, join all local transfer matrices on rank 0,
+        // and construct a single global transfer operator there.
+        typedef GlobalUniqueIndex<typename GridType::LeafGridView, gridDim> LeafP1GUIndex;
+        LeafP1GUIndex p1Index(grid_->leafGridView());
+
+        typedef typename TruncatedCompressedMGTransfer<CorrectionType>::TransferOperatorType TransferOperatorType;
+        MatrixCommunicator<GUIndex, TransferOperatorType, LeafP1GUIndex> matrixComm(*guIndex_, p1Index, 0);
+
+        mmgStep->mgTransfer_.back() = new PKtoP1MGTransfer<CorrectionType>
+           (Dune::make_shared<TransferOperatorType>(matrixComm.reduceCopy(topTransferOp->getMatrix())));
 
         for (int i=0; i<mmgStep->mgTransfer_.size()-1; i++){
-            TruncatedCompressedMGTransfer<CorrectionType>* newTransferOp = new TruncatedCompressedMGTransfer<CorrectionType>;
-            newTransferOp->setup(*grid_,i+1,i+2);
-            mmgStep->mgTransfer_[i] = newTransferOp;
+          // Construct the local multigrid transfer matrix
+          TruncatedCompressedMGTransfer<CorrectionType>* newTransferOp = new TruncatedCompressedMGTransfer<CorrectionType>;
+          newTransferOp->setup(*grid_,i+1,i+2);
+
+          // If we are on more than 1 processors, join all local transfer matrices on rank 0,
+          // and construct a single global transfer operator there.
+          typedef GlobalUniqueIndex<typename GridType::LevelGridView, gridDim> LevelGUIndex;
+          LevelGUIndex fineGUIndex(grid_->levelGridView(i+2));
+          LevelGUIndex coarseGUIndex(grid_->levelGridView(i+1));
+
+          typedef typename TruncatedCompressedMGTransfer<CorrectionType>::TransferOperatorType TransferOperatorType;
+          MatrixCommunicator<LevelGUIndex, TransferOperatorType> matrixComm(fineGUIndex, coarseGUIndex, 0);
+
+          mmgStep->mgTransfer_[i] = new TruncatedCompressedMGTransfer<CorrectionType>
+             (Dune::make_shared<TransferOperatorType>(matrixComm.reduceCopy(newTransferOp->getMatrix())));
         }
 
     }
@@ -206,14 +228,8 @@ setup(const GridType& grid,
     if (rank==0)
     {
         hasObstacle_.resize(numLevels);
-
-#if defined THIRD_ORDER || defined SECOND_ORDER
-        // This does not work in parallel
-        hasObstacle_.back().resize(basis.size(), true);
-#else
-        // This does not work for higher-order FE
         hasObstacle_.back().resize(guIndex_->nGlobalEntity(), true);
-#endif
+
         // If there is more than one level use the transfer operators to determine the correct coarse level system sizes
         for (int i=0; i<hasObstacle_.size()-1; i++)
             hasObstacle_[i].resize(dynamic_cast<TruncatedCompressedMGTransfer<CorrectionType>* >(mmgStep->mgTransfer_[i])->getMatrix().M(),true);
-- 
GitLab