From 1428d2d33f03b26704f2c28f360af7653d12843f Mon Sep 17 00:00:00 2001
From: Oliver Sander <oliver.sander@tu-dresden.de>
Date: Sun, 24 Mar 2024 08:53:03 +0100
Subject: [PATCH] Implement GlobalP2Mapper for cube grids without dune-parmg

Unfortunately, this code is used even in sequential situations,
but previously the code only supported 1d- and 2d grids.
And as we still support installations without dune-parmg,
this commit adds an implementation for hypercube grids
of all dimensions.
---
 dune/gfe/parallel/globalp2mapper.hh | 108 ++++++++--------------------
 1 file changed, 29 insertions(+), 79 deletions(-)

diff --git a/dune/gfe/parallel/globalp2mapper.hh b/dune/gfe/parallel/globalp2mapper.hh
index fbecb00b..3bc1fd99 100644
--- a/dune/gfe/parallel/globalp2mapper.hh
+++ b/dune/gfe/parallel/globalp2mapper.hh
@@ -1,6 +1,8 @@
 #ifndef DUNE_GFE_PARALLEL_GLOBALP2MAPPER_HH
 #define DUNE_GFE_PARALLEL_GLOBALP2MAPPER_HH
 
+#include <memory>
+
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
 
 #include <dune/gfe/parallel/globalmapper.hh>
@@ -22,96 +24,44 @@ namespace Dune {
       p2Mapper_(gridView)
     {
 #if !HAVE_DUNE_PARMG
-      static_assert(GridView::dimension<=2, "Only implemented for one- and two-dimensional grids");
+      if (gridView.size(GeometryTypes::simplex(GridView::dimension))>=1)
+        DUNE_THROW(NotImplemented, "GlobalP2Mapper only works for grids without simplex elements!");
+
+      // Indexed by *co*dimension!
+      std::array<std::unique_ptr<GlobalIndexSet<GridView> >, GridView::dimension+1> globalIndexSets;
 
-      if (gridView.size(GeometryTypes::triangle)>1)
-        DUNE_THROW(NotImplemented, "GlobalP2Mapper only works for quad grids!");
+      for (int i=0; i<=GridView::dimension; ++i)
+        globalIndexSets[i] = std::make_unique<GlobalIndexSet<GridView> >(gridView, i);
 
-      GlobalIndexSet<GridView> globalVertexIndex(gridView,GridView::dimension);
-      GlobalIndexSet<GridView> globalElementIndex(gridView,0);
+      // total number of degrees of freedom
+      this->size_ = 0;
+      for (int i=0; i<=GridView::dimension; ++i)
+        this->size_ += globalIndexSets[i]->size(i);
 
       auto localView = p2Mapper_.localView();
 
-      if (GridView::dimension==1)
+      // Loop over all elements, as a means to loop over all degrees of freedom
+      for (const auto& element : elements(gridView))
       {
-        // total number of degrees of freedom
-        this->size_ = globalVertexIndex.size(GridView::dimension) + globalElementIndex.size(0);
+        localView.bind(element);
 
-        // Determine
-        for (const auto& element : elements(gridView))
+        // Loop over all local degrees of freedom
+        for (size_t i=0; i<localView.size(); i++)
         {
-          localView.bind(element);
-
-          // Loop over all local degrees of freedom
-          for (size_t i=0; i<localView.size(); i++)
-          {
-            int codim = localView.tree().finiteElement().localCoefficients().localKey(i).codim();
-            int entity   = localView.tree().finiteElement().localCoefficients().localKey(i).subEntity();
-
-            auto localIndex  = localView.index(i);
-            int globalIndex;
-            switch (codim)
-            {
-            case 1 :   // vertex dofs
-              globalIndex = globalVertexIndex.index(element.template subEntity<1>(entity));
-              break;
-
-            case 0 :   // element dofs
-              globalIndex = globalElementIndex.index(element.template subEntity<0>(entity))
-                            + globalVertexIndex.size(1);
-              break;
-
-            default :
-              DUNE_THROW(Dune::Exception, "Impossible codimension!");
-            }
-
-            localGlobalMap_[localIndex]  = globalIndex;
-          }
-        }
+          auto codim = localView.tree().finiteElement().localCoefficients().localKey(i).codim();
+          auto entity = localView.tree().finiteElement().localCoefficients().localKey(i).subEntity();
 
-      }
-      else
-      {
-        GlobalIndexSet<GridView> globalEdgeIndex(gridView,1);
+          auto localIndex  = localView.index(i);
 
-        // total number of degrees of freedom
-        this->size_ = globalVertexIndex.size(2) + globalEdgeIndex.size(1) + globalElementIndex.size(0);
+          // Compute a global index for this degree of freedom
+          int globalIndex = 0;
 
-        // Determine
-        for (const auto& element : elements(gridView))
-        {
-          localView.bind(element);
-
-          // Loop over all local degrees of freedom
-          for (size_t i=0; i<localView.size(); i++)
-          {
-            int codim = localView.tree().finiteElement().localCoefficients().localKey(i).codim();
-            int entity   = localView.tree().finiteElement().localCoefficients().localKey(i).subEntity();
-
-            auto localIndex  = localView.index(i);
-            int globalIndex;
-            switch (codim)
-            {
-            case 2 :   // vertex dofs
-              globalIndex = globalVertexIndex.index(element.template subEntity<GridView::dimension>(entity));
-              break;
-
-            case 1 :   // edge dofs
-              globalIndex = globalEdgeIndex.index(element.template subEntity<1>(entity)) + globalVertexIndex.size(2);
-              break;
-
-            case 0 :   // element dofs
-              globalIndex = globalElementIndex.index(element.template subEntity<0>(entity))
-                            + globalEdgeIndex.size(1)
-                            + globalVertexIndex.size(2);
-              break;
-
-            default :
-              DUNE_THROW(Dune::Exception, "Impossible codimension!");
-            }
-
-            localGlobalMap_[localIndex]  = globalIndex;
-          }
+          for (int j=codim+1; j<=GridView::dimension; ++j)
+            globalIndex += globalIndexSets[j]->size(j);
+
+          globalIndex += globalIndexSets[codim]->subIndex(element, entity, codim);
+
+          localGlobalMap_[localIndex] = globalIndex;
         }
       }
 #endif
-- 
GitLab