From a05b81c77151ace347ea3c62e456adf08487bbe3 Mon Sep 17 00:00:00 2001
From: Ansgar Burchardt <Ansgar.Burchardt@tu-dresden.de>
Date: Mon, 19 Oct 2015 19:29:44 +0200
Subject: [PATCH] Restore short-circuit for known elements

With these changes the short-circuit that was removed in
f77e27a4c4289409ef50bd4132084cb1a250c9bd is restored, but with
a check for "duplicated" elements over different levels as one
can get from UGGrid with setRefinementType(UGGrid::COPY).
---
 dune/fufem/functiontools/basisidmapper.hh | 61 +++++++++++++----------
 1 file changed, 36 insertions(+), 25 deletions(-)

diff --git a/dune/fufem/functiontools/basisidmapper.hh b/dune/fufem/functiontools/basisidmapper.hh
index 6958939f..590229b9 100644
--- a/dune/fufem/functiontools/basisidmapper.hh
+++ b/dune/fufem/functiontools/basisidmapper.hh
@@ -72,6 +72,7 @@ class BasisIdMapper
             typedef typename B::LocalFiniteElement LocalFiniteElement;
 
             const GridView& gridview = basis_.getGridView();
+            const auto& idSet = gridview_.grid().globalIdSet();
 
             storedFEs_.clear();
             elementToFE_.clear();
@@ -79,18 +80,8 @@ class BasisIdMapper
                 indices_[i].clear();
 
             for (auto&& e : elements(gridview)) {
-
-                const LocalFiniteElement& fe = basis_.getLocalFiniteElement(e);
-
-                // store local finite element if not already done
-                // If we have a base class with virtual functions
-                // we must use the 'virtual copy constructor' hack
-                // using virtual clone() methods for ALL local FEs
-                typename StoredFEMap::const_iterator storedFEIt = storedFEs_.find(&fe);
-                if (storedFEIt == storedFEs_.end())
-                    storedFEs_[&fe] = SmartFEPointer(fe.clone());
-
-                elementToFE_[gridview_.grid().globalIdSet().id(e)] = &fe;
+                const IdType id = idSet.id(e);
+                const LocalFiniteElement& fe = storeElement(id, e);
 
                 // if elements might vanish we need to store all elements up to level 0
                 if (allowVanishingElements_)
@@ -138,27 +129,47 @@ class BasisIdMapper
 
 
     private:
+        void storeFiniteElement(const LocalFiniteElement& fe)
+        {
+            // store local finite element if not already done
+            // If we have a base class with virtual functions
+            // we must use the 'virtual copy constructor' hack
+            // using virtual clone() methods for ALL local FEs
+            if (storedFEs_.count(&fe) == 0)
+                storedFEs_.emplace(&fe, SmartFEPointer(fe.clone()));
+        }
 
-        void storeParents(Element e)
+        const LocalFiniteElement& storeElement(const IdType& elementId, const Element& element)
         {
+            const LocalFiniteElement& fe = basis_.getLocalFiniteElement(element);
+            storeFiniteElement(fe);
+            elementToFE_[elementId] = &fe;
+            return fe;
+        }
 
-            while(e.level() > 0)
-            {
+        void storeParents(const Element& element)
+        {
+            const auto& idSet = gridview_.grid().globalIdSet();
+
+            Element e = element;
+            IdType prevId = idSet.id(element);
+            while (e.level() > 0) {
                 e = e.father();
-                const IdType id = gridview_.grid().globalIdSet().id(e);
+                const IdType id = idSet.id(e);
 
-                // if father was already added we can stop
-                if (elementToFE_.find(id) != elementToFE_.end())
+                // Element is its own father. This can happen when UGGrid is used
+                // with the setRefinementType(UGGrid::COPY) option.
+                // We can skip this element, but still might have to visit "real"
+                // father elements.
+                if (id == prevId)
                     continue;
 
-                const LocalFiniteElement& fe = basis_.getLocalFiniteElement(e);
-
-                // store local finite element if not already done
-                typename StoredFEMap::const_iterator storedFEIt = storedFEs_.find(&fe);
-                if (storedFEIt == storedFEs_.end())
-                    storedFEs_[&fe] = SmartFEPointer(fe.clone());
+                // Father was already added. No need to visit rest of the hierarchy.
+                if (elementToFE_.count(id) != 0)
+                    break;
 
-                elementToFE_[id] = &fe;
+                prevId = id;
+                storeElement(id, element);
             }
         }
 
-- 
GitLab