From e3282300e4ce4ce8bb3249f67f88c59c55a6b872 Mon Sep 17 00:00:00 2001
From: Timo Koch <timo.koch@iws.uni-stuttgart.de>
Date: Thu, 14 Dec 2017 15:49:34 +0100
Subject: [PATCH] [bboxtree] Extract intersection algorithms from bounding box
 tree

* Generalize bounding box tree
* Extract intersection algorithms
* Fix some epsilon issues in interval (1d) and triangle (2d) point intersection
* Adapt point sources to new interface
* Adapt fv grid geometry to new interface -> element map moved to basefvgeometry
* Improve bounding box tree test
---
 dumux/common/boundingboxtree.hh               | 1176 +----------------
 dumux/common/elementmap.hh                    |   50 -
 dumux/common/entitymap.hh                     |   85 ++
 dumux/common/geometry/boundingboxtree.hh      |  371 ++++++
 .../geometry/boundingboxtreeintersection.hh   |   93 ++
 dumux/common/geometry/geometricentityset.hh   |  102 ++
 .../geometryintersection.hh}                  |   88 +-
 dumux/common/geometry/intersectingentities.hh |  169 +++
 .../geometry/intersectspointgeometry.hh       |  111 ++
 .../common/geometry/intersectspointsimplex.hh |  249 ++++
 dumux/common/pointsource.hh                   |   16 +-
 dumux/discretization/basefvgridgeometry.hh    |   34 +-
 .../cellcentered/mpfa/fvgridgeometry.hh       |   32 +-
 .../cellcentered/tpfa/fvgridgeometry.hh       |   29 +-
 .../staggered/fvgridgeometry.hh               |   15 +-
 test/common/boundingboxtree/CMakeLists.txt    |   14 +-
 test/common/boundingboxtree/test_bboxtree.cc  |  142 +-
 17 files changed, 1375 insertions(+), 1401 deletions(-)
 delete mode 100644 dumux/common/elementmap.hh
 create mode 100644 dumux/common/entitymap.hh
 create mode 100644 dumux/common/geometry/boundingboxtree.hh
 create mode 100644 dumux/common/geometry/boundingboxtreeintersection.hh
 create mode 100644 dumux/common/geometry/geometricentityset.hh
 rename dumux/common/{geometrycollision.hh => geometry/geometryintersection.hh} (65%)
 create mode 100644 dumux/common/geometry/intersectingentities.hh
 create mode 100644 dumux/common/geometry/intersectspointgeometry.hh
 create mode 100644 dumux/common/geometry/intersectspointsimplex.hh

diff --git a/dumux/common/boundingboxtree.hh b/dumux/common/boundingboxtree.hh
index 1b6f24f37d..9c6ed9623b 100644
--- a/dumux/common/boundingboxtree.hh
+++ b/dumux/common/boundingboxtree.hh
@@ -3,7 +3,7 @@
  *                                                                           *
  *   This program is free software: you can redistribute it and/or modify    *
  *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
+ *   the Free Software Foundation, either version 3 of the License, or       *
  *   (at your option) any later version.                                     *
  *                                                                           *
  *   This program is distributed in the hope that it will be useful,         *
@@ -14,1174 +14,8 @@
  *   You should have received a copy of the GNU General Public License       *
  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
  *****************************************************************************/
-/*!
- * \file
- * \brief An axis-aligned bounding box volume hierarchy for dune grids
- *
- * Dumux implementation of an AABB tree
- * adapted from implementation in FEniCS by Anders Logg
- */
-#ifndef DUMUX_BOUNDINGBOXTREE_HH
-#define DUMUX_BOUNDINGBOXTREE_HH
-
-#include <algorithm>
-#include <memory>
-#include <type_traits>
-#include <dune/geometry/referenceelements.hh>
-#include <dune/common/timer.hh>
-#include <dune/common/exceptions.hh>
-#include <dumux/common/math.hh>
-#include <dumux/common/exceptions.hh>
-#include <dumux/common/geometrycollision.hh>
-
-namespace Dumux {
-
-/*!
- * \brief A helper class to optimize dimension-dependent methods
- */
-template <int dimworld>
-class BoundingBoxTreeHelper {};
-
-//! Helper methods for world dimension three
-template <>
-class BoundingBoxTreeHelper<3>
-{
-    // An epsilon for floating point operations
-    static constexpr double eps_ = 1.0e-7;
-    using GlobalPosition = Dune::FieldVector<double, 3>;
-
-public:
-    //! Check whether a point is inside a given three-dimensional geometry
-    template <class Geometry>
-    static typename std::enable_if<Geometry::mydimension == 3, bool>::type
-    pointInGeometry(const Geometry& geometry, const GlobalPosition& point)
-    {
-        // get the geometry type
-        auto type = geometry.type();
-
-        // if it's a tetrahedron we can check directly
-        if (type.isTetrahedron())
-        {
-            return pointInTetrahedron(geometry.corner(0),
-                                      geometry.corner(1),
-                                      geometry.corner(2),
-                                      geometry.corner(3),
-                                      point);
-        }
-        // split hexahedrons into five tetrahedrons
-        else if (type.isHexahedron())
-        {
-            if (pointInTetrahedron(geometry.corner(0),
-                                   geometry.corner(1),
-                                   geometry.corner(3),
-                                   geometry.corner(5),
-                                   point))
-                return true;
-            if (pointInTetrahedron(geometry.corner(0),
-                                   geometry.corner(5),
-                                   geometry.corner(6),
-                                   geometry.corner(4),
-                                   point))
-                return true;
-            if (pointInTetrahedron(geometry.corner(5),
-                                   geometry.corner(3),
-                                   geometry.corner(6),
-                                   geometry.corner(7),
-                                   point))
-                return true;
-            if (pointInTetrahedron(geometry.corner(0),
-                                   geometry.corner(3),
-                                   geometry.corner(2),
-                                   geometry.corner(6),
-                                   point))
-                return true;
-            if (pointInTetrahedron(geometry.corner(5),
-                                   geometry.corner(3),
-                                   geometry.corner(0),
-                                   geometry.corner(6),
-                                   point))
-                return true;
-            return false;
-        }
-        // split pyramids into two tetrahedrons
-        else if (type.isPyramid())
-        {
-            if (pointInTetrahedron(geometry.corner(0),
-                                   geometry.corner(1),
-                                   geometry.corner(2),
-                                   geometry.corner(4),
-                                   point))
-                return true;
-            if (pointInTetrahedron(geometry.corner(1),
-                                   geometry.corner(3),
-                                   geometry.corner(2),
-                                   geometry.corner(4),
-                                   point))
-                return true;
-            return false;
-        }
-        // split prisms into three tetrahedrons
-        else if (type.isPrism())
-        {
-            if (pointInTetrahedron(geometry.corner(0),
-                                   geometry.corner(1),
-                                   geometry.corner(2),
-                                   geometry.corner(4),
-                                   point))
-                return true;
-            if (pointInTetrahedron(geometry.corner(3),
-                                   geometry.corner(0),
-                                   geometry.corner(2),
-                                   geometry.corner(4),
-                                   point))
-                return true;
-            if (pointInTetrahedron(geometry.corner(2),
-                                   geometry.corner(5),
-                                   geometry.corner(3),
-                                   geometry.corner(4),
-                                   point))
-                return true;
-            return false;
-        }
-        else
-            DUNE_THROW(Dune::NotImplemented,
-                        "Intersection for point and geometry "
-                        << type << " in three-dimensional world.");
-    }
-
-    //! Check whether a point is inside a given two-dimensional geometry
-    template <class Geometry>
-    static typename std::enable_if<Geometry::mydimension == 2, bool>::type
-    pointInGeometry(const Geometry& geometry, const GlobalPosition& point)
-    {
-        // get the geometry type
-        auto type = geometry.type();
-
-        // if it's a triangle we can check directly
-        if (type.isTriangle())
-        {
-            return pointInTriangle(geometry.corner(0),
-                                   geometry.corner(1),
-                                   geometry.corner(2),
-                                   point);
-        }
-        // split quadrilaterals into two triangles
-        else if (type.isQuadrilateral())
-        {
-            if (pointInTriangle(geometry.corner(0),
-                                geometry.corner(1),
-                                geometry.corner(3),
-                                point))
-                return true;
-            if (pointInTriangle(geometry.corner(0),
-                                geometry.corner(3),
-                                geometry.corner(2),
-                                point))
-                return true;
-            return false;
-        }
-        else
-            DUNE_THROW(Dune::NotImplemented,
-                        "Intersection for point and geometry "
-                        << type << " in three-dimensional world.");
-
-    }
-
-    //! Check whether a point is inside a given one-dimensional geometry
-    template <class Geometry>
-    static typename std::enable_if<Geometry::mydimension == 1, bool>::type
-    pointInGeometry(const Geometry& geometry, const GlobalPosition& point)
-    {
-        return pointInInterval(geometry.corner(0),
-                               geometry.corner(1),
-                               point);
-    }
-
-    //! Find out whether a point is inside a tetrahedron (p0, p1, p2, p3)
-    static bool pointInTetrahedron(const GlobalPosition& p0, const GlobalPosition& p1,
-                                   const GlobalPosition& p2, const GlobalPosition& p3,
-                                   const GlobalPosition& point)
-    {
-        // Algorithm from http://www.blackpawn.com/texts/pointinpoly/
-        // See also "Real-Time Collision Detection" by Christer Ericson.
-        // See also implementation of those algorithms by Anders Logg in FEniCS
-
-        // put the tetrahedron points in an array
-        const GlobalPosition *p[4] = {&p0, &p1, &p2, &p3};
-
-        // iterate over all faces
-        for (unsigned int i = 0; i < 4; ++i)
-        {
-            // compute all the vectors from vertex (local index 0) to the other points
-            const GlobalPosition v1 = *p[(i + 1)%4] - *p[i];
-            const GlobalPosition v2 = *p[(i + 2)%4] - *p[i];
-            const GlobalPosition v3 = *p[(i + 3)%4] - *p[i];
-            const GlobalPosition v = point - *p[i];
-            // compute the normal to the facet (cross product)
-            GlobalPosition n1 = crossProduct(v1, v2);
-            n1 /= n1.two_norm();
-            // find out on which side of the plane v and v3 are
-            const double t1 = n1.dot(v);
-            const double t2 = n1.dot(v3);
-            // If the point is not exactly on the plane the
-            // points have to be on the same side
-            const double eps = eps_ * v1.two_norm();
-            if ((t1 > eps || t1 < -eps) && std::signbit(t1) != std::signbit(t2))
-                return false;
-        }
-        return true;
-    }
-
-    //! Find out whether a point is inside a triangle (p0, p1, p2)
-    static bool pointInTriangle(const GlobalPosition& p0, const GlobalPosition& p1,
-                                const GlobalPosition& p2, const GlobalPosition& point)
-    {
-        // Algorithm from http://www.blackpawn.com/texts/pointinpoly/
-        // See also "Real-Time Collision Detection" by Christer Ericson.
-        // See also implementation of those algorithms by Anders Logg in FEniCS
-
-        // compute the vectors of the edges and the vector point-p0
-        const GlobalPosition v1 = p0 - p2;
-        const GlobalPosition v2 = p1 - p0;
-        const GlobalPosition v3 = p2 - p1;
-        const GlobalPosition v = point - p0;
-
-        // compute the normal of the triangle
-        const GlobalPosition n = crossProduct(v1, v2);
-
-        // first check if we are in the plane of the triangle
-        // if not we can return early
-        const double t = v.dot(n);
-        using std::abs;
-        if (abs(t) > v1.two_norm()*eps_) // take |v1| as scale
-            return false;
-
-        // compute the normal to the triangle made of point and first edge
-        // the dot product of this normal and the triangle normal has to
-        // be positive because we defined the edges in the right orientation
-        const GlobalPosition n1 = crossProduct(v, v1);
-        const double t1 = n.dot(n1);
-        if (t1 < 0) return false;
-
-        const GlobalPosition n2 = crossProduct(v, v2);
-        const double t2 = n.dot(n2);
-        if (t2 < 0) return false;
-
-        const GlobalPosition n3 = crossProduct(v, v3);
-        const double t3 = n.dot(n3);
-        if (t3 < 0) return false;
-
-        return true;
-    }
-
-    //! Find out whether a point is inside an interval (p0, p1)
-    static bool pointInInterval(const GlobalPosition& p0, const GlobalPosition& p1,
-                                const GlobalPosition& point)
-    {
-        // compute the vectors between p0 and the other points
-        const GlobalPosition v1 = p1 - p0;
-        const GlobalPosition v2 = point - p0;
-
-        // check if point and p0 are the same
-        const double v1norm = v1.two_norm();
-        const double v2norm = v2.two_norm();
-        if (v2norm < v1norm*eps_)
-            return true;
-
-        // if not check if p0 and p1 are the same
-        // then we know that point is not in the interval
-        if (v1norm < eps_)
-            return false;
-
-        // if the cross product is zero the points are on a line
-        const GlobalPosition n = crossProduct(v1, v2);
-
-        // early return if the vector length is larger than zero
-        if (n.two_norm() > v1norm*eps_)
-            return false;
-
-        // we know the points are aligned
-        // if the dot product is positive and the length in range
-        // the point is in the interval
-        return (v1.dot(v2) > 0.0 && v2norm < v1norm*(1 + eps_));
-    }
-
-    /*!
-     * \brief Check whether a point is in a bounding box
-     * \param point The point
-     * \param b Pointer to bounding box coordinates
-     */
-    static bool pointInBoundingBox(const Dune::FieldVector<double, 3>& point,
-                                   const double* b)
-    {
-        const double eps0 = eps_*(b[3] - b[0]);
-        const double eps1 = eps_*(b[4] - b[1]);
-        const double eps2 = eps_*(b[5] - b[2]);
-        return (b[0] - eps0 <= point[0] && point[0] <= b[3] + eps0 &&
-                b[1] - eps1 <= point[1] && point[1] <= b[4] + eps1 &&
-                b[2] - eps2 <= point[2] && point[2] <= b[5] + eps2);
-    }
-
-    /*!
-     * \brief Check whether bounding box a collides with bounding box b
-     * \param a, b Pointer to bounding box coordinates
-     */
-    static bool boundingBoxInBoundingBox(const double* a,
-                                         const double* b)
-    {
-      const double eps0 = eps_*(b[3] - b[0]);
-      const double eps1 = eps_*(b[4] - b[1]);
-      const double eps2 = eps_*(b[5] - b[2]);
-      return (b[0] - eps0 <= a[3] && a[0] <= b[3] + eps0 &&
-              b[1] - eps1 <= a[4] && a[1] <= b[4] + eps1 &&
-              b[2] - eps2 <= a[5] && a[2] <= b[5] + eps2);
-    }
-
-    //! Compute the bounding box of a vector of bounding boxes
-    static void computeBBoxOfBBoxes(double* bBox,
-                                    std::size_t& axis,
-                                    const std::vector<double>& leafBoxes,
-                                    const std::vector<unsigned int>::iterator& begin,
-                                    const std::vector<unsigned int>::iterator& end)
-    {
-        // Copy the iterator and get coordinates of first box
-        auto it = begin;
-        const double* bFirst = leafBoxes.data() + 6*(*it);
-        // Maybe write out the loop for optimization
-        for (std::size_t coordIdx = 0; coordIdx < 6; ++coordIdx)
-            bBox[coordIdx] = bFirst[coordIdx];
-
-        // Compute min and max with the remaining boxes
-        for (; it != end; ++it)
-        {
-            const double* b = leafBoxes.data() + 6*(*it);
-            if (b[0] < bBox[0]) bBox[0] = b[0];
-            if (b[1] < bBox[1]) bBox[1] = b[1];
-            if (b[2] < bBox[2]) bBox[2] = b[2];
-            if (b[3] > bBox[3]) bBox[3] = b[3];
-            if (b[4] > bBox[4]) bBox[4] = b[4];
-            if (b[5] > bBox[5]) bBox[5] = b[5];
-        }
-
-        // Compute the longest axis
-        const double x = bBox[3] - bBox[0];
-        const double y = bBox[4] - bBox[1];
-        const double z = bBox[5] - bBox[2];
-
-        if (x > y && x > z)
-            axis = 0;
-        else if (y > z)
-            axis = 1;
-        else
-            axis = 2;
-    }
-
-    //! Sort the bounding boxes along the longest axis
-    static void sortBoundingBoxes(std::size_t axis,
-                                  const std::vector<double>& leafBoxes,
-                                  const std::vector<unsigned int>::iterator& begin,
-                                  const std::vector<unsigned int>::iterator& middle,
-                                  const std::vector<unsigned int>::iterator& end)
-    {
-        switch (axis)
-        {
-            case 0:
-                std::nth_element(begin, middle, end, lessXBox(leafBoxes));
-            case 1:
-                std::nth_element(begin, middle, end, lessYBox(leafBoxes));
-            default:
-                std::nth_element(begin, middle, end, lessZBox(leafBoxes));
-        }
-    }
-
-    /*!
-     * \brief Comparison function for sorting bounding boxes on the x-axis
-     * \note This could be replaced by lambdas
-     */
-    struct lessXBox
-    {
-        const std::vector<double>& bBoxes;
-        lessXBox(const std::vector<double>& bBoxes_): bBoxes(bBoxes_) {}
-        inline bool operator()(unsigned int i, unsigned int j)
-        {
-            const double* bi = bBoxes.data() + 6*i;
-            const double* bj = bBoxes.data() + 6*j;
-            return bi[0] + bi[3] < bj[0] + bj[3];
-        }
-    };
-
-    /*!
-     * \brief Comparison function for sorting bounding boxes on the y-axis
-     * \note This could be replaced by lambdas
-     */
-    struct lessYBox
-    {
-        const std::vector<double>& bBoxes;
-        lessYBox(const std::vector<double>& bBoxes_): bBoxes(bBoxes_) {}
-        inline bool operator()(unsigned int i, unsigned int j)
-        {
-            const double* bi = bBoxes.data() + 6*i;
-            const double* bj = bBoxes.data() + 6*j;
-            return bi[1] + bi[4] < bj[1] + bj[4];
-        }
-    };
-
-    /*!
-     * \brief Comparison function for sorting bounding boxes on the z-axis
-     * \note This could be replaced by lambdas
-     */
-    struct lessZBox
-    {
-        const std::vector<double>& bBoxes;
-        lessZBox(const std::vector<double>& bBoxes_): bBoxes(bBoxes_) {}
-        inline bool operator()(unsigned int i, unsigned int j)
-        {
-            const double* bi = bBoxes.data() + 6*i;
-            const double* bj = bBoxes.data() + 6*j;
-            return bi[2] + bi[5] < bj[2] + bj[5];
-        }
-    };
-};
-
-//! Helper methods for world dimension two
-template <>
-class BoundingBoxTreeHelper<2>
-{
-    // An epsilon for floating point operations
-    static constexpr double eps_ = 1.0e-7;
-    using GlobalPosition = Dune::FieldVector<double, 2>;
-
-public:
-    // Check whether a point is inside a given geometry
-    template <class Geometry>
-    static typename std::enable_if<Geometry::mydimension == 2, bool>::type
-    pointInGeometry(const Geometry& geometry, const GlobalPosition& point)
-    {
-        // get the geometry type
-        auto type = geometry.type();
-
-        // if it's a triangle we can check directly
-        if (type.isTriangle())
-        {
-            return pointInTriangle(geometry.corner(0),
-                                   geometry.corner(1),
-                                   geometry.corner(2),
-                                   point);
-        }
-        // split quadrilaterals into two triangles
-        else if (type.isQuadrilateral())
-        {
-            if (pointInTriangle(geometry.corner(0),
-                                geometry.corner(1),
-                                geometry.corner(3),
-                                point))
-                return true;
-            if (pointInTriangle(geometry.corner(0),
-                                geometry.corner(3),
-                                geometry.corner(2),
-                                point))
-                return true;
-            return false;
-        }
-        else
-            DUNE_THROW(Dune::NotImplemented,
-                        "Intersection for point and geometry "
-                        << type << " in two-dimensional world.");
-    }
-
-    template <class Geometry>
-    static typename std::enable_if<Geometry::mydimension == 1, bool>::type
-    pointInGeometry(const Geometry& geometry, const GlobalPosition& point)
-    {
-        return pointInInterval(geometry.corner(0),
-                               geometry.corner(1),
-                               point);
-    }
-
-    //! find out if a point is inside a triangle
-    static bool pointInTriangle(const GlobalPosition& p0, const GlobalPosition& p1,
-                                const GlobalPosition& p2, const GlobalPosition& point)
-    {
-        // Use barycentric coordinates
-        const double A = 0.5*(-p1[1]*p2[0] + p0[1]*(p2[0] - p1[0])
-                                           + p0[0]*(p1[1] - p2[1]) + p1[0]*p2[1]);
-        const double sign = std::copysign(1.0, A);
-        const double s = sign*(p0[1]*p2[0] + point[0]*(p2[1]-p0[1])
-                              -p0[0]*p2[1] + point[1]*(p0[0]-p2[0]));
-        const double t = sign*(p0[0]*p1[1] + point[0]*(p0[1]-p1[1])
-                              -p0[1]*p1[0] + point[1]*(p1[0]-p0[0]));
-        const double eps = (p0 - p1).two_norm()*eps_;
-
-        return (s > -eps
-                && t > -eps
-                && (s + t) < 2*A*sign + eps);
-    }
-
-    //! find out if a point is inside an interval
-    static bool pointInInterval(const GlobalPosition& p0, const GlobalPosition& p1,
-                                const GlobalPosition& point)
-    {
-        // compute the vectors between p0 and the other points
-        const GlobalPosition v1 = p1 - p0;
-        const GlobalPosition v2 = point - p0;
-
-        // check if point and p0 are the same
-        const double v1norm = v1.two_norm();
-        const double v2norm = v2.two_norm();
-        if (v2norm < v1norm*eps_)
-            return true;
-
-        // if not check if p0 and p1 are the same
-        // then we know that point is not in the interval
-        if (v1norm < eps_)
-            return false;
-
-        // if the cross product is zero the points are on a line
-        const double n = crossProduct(v1, v2);
-
-        // early return if the cross product is larger than zero
-        using std::abs;
-        if (abs(n) > v1norm*eps_)
-            return false;
-
-        // we know the points are aligned
-        // if the dot product is positive and the length in range
-        // the point is in the interval
-        return (v1.dot(v2) > 0.0 && v2norm < v1norm*(1 + eps_));
-    }
-
-    /*!
-     * \brief Check whether a point is in a bounding box
-     * \param point The point
-     * \param b Pointer to bounding box coordinates
-     */
-    static bool pointInBoundingBox(const Dune::FieldVector<double, 2>& point,
-                                   const double* b)
-    {
-        const double eps0 = eps_*(b[2] - b[0]);
-        const double eps1 = eps_*(b[3] - b[1]);
-        return (b[0] - eps0 <= point[0] && point[0] <= b[2] + eps0 &&
-                b[1] - eps1 <= point[1] && point[1] <= b[3] + eps1);
-    }
-
-    /*!
-     * \brief Check whether bounding box a collides with bounding box b
-     * \param a, b Pointer to bounding box coordinates
-     */
-    static bool boundingBoxInBoundingBox(const double* a,
-                                         const double* b)
-    {
-      const double eps0 = eps_*(b[2] - b[0]);
-      const double eps1 = eps_*(b[3] - b[1]);
-      return (b[0] - eps0 <= a[2] && a[0] <= b[2] + eps0 &&
-              b[1] - eps1 <= a[3] && a[1] <= b[3] + eps1);
-    }
-
-    //! Compute the bounding box of a vector of bounding boxes
-    static void computeBBoxOfBBoxes(double* bBox,
-                                    std::size_t& axis,
-                                    const std::vector<double>& leafBoxes,
-                                    const std::vector<unsigned int>::iterator& begin,
-                                    const std::vector<unsigned int>::iterator& end)
-    {
-        // Copy the iterator and get coordinates of first box
-        auto it = begin;
-        const double* bFirst = leafBoxes.data() + 4*(*it);
-        // Maybe write out the loop for optimization
-        for (std::size_t coordIdx = 0; coordIdx < 4; ++coordIdx)
-            bBox[coordIdx] = bFirst[coordIdx];
-
-        // Compute min and max with the remaining boxes
-        for (; it != end; ++it)
-        {
-            const double* b = leafBoxes.data() + 4*(*it);
-            if (b[0] < bBox[0]) bBox[0] = b[0];
-            if (b[1] < bBox[1]) bBox[1] = b[1];
-            if (b[2] > bBox[2]) bBox[2] = b[2];
-            if (b[3] > bBox[3]) bBox[3] = b[3];
-        }
-
-        // Compute the longest axis
-        const double x = bBox[2] - bBox[0];
-        const double y = bBox[3] - bBox[1];
-
-        if (x > y)
-            axis = 0;
-        else
-            axis = 1;
-    }
-
-    //! Sort the bounding boxes along the longest axis
-    static void sortBoundingBoxes(std::size_t axis,
-                                  const std::vector<double>& leafBoxes,
-                                  const std::vector<unsigned int>::iterator& begin,
-                                  const std::vector<unsigned int>::iterator& middle,
-                                  const std::vector<unsigned int>::iterator& end)
-    {
-        if (axis == 0)
-            std::nth_element(begin, middle, end, lessXBox(leafBoxes));
-        else
-            std::nth_element(begin, middle, end, lessYBox(leafBoxes));
-    }
-
-    /*!
-     * \brief Comparison function for sorting bounding boxes on the x-axis
-     * \note This could be replaced by lambdas
-     */
-    struct lessXBox
-    {
-        const std::vector<double>& bBoxes;
-        lessXBox(const std::vector<double>& bBoxes_): bBoxes(bBoxes_) {}
-        inline bool operator()(unsigned int i, unsigned int j)
-        {
-            const double* bi = bBoxes.data() + 4*i;
-            const double* bj = bBoxes.data() + 4*j;
-            return bi[0] + bi[2] < bj[0] + bj[2];
-        }
-    };
-
-    /*!
-     * \brief Comparison function for sorting bounding boxes on the y-axis
-     * \note This could be replaced by lambdas
-     */
-    struct lessYBox
-    {
-        const std::vector<double>& bBoxes;
-        lessYBox(const std::vector<double>& bBoxes_): bBoxes(bBoxes_) {}
-        inline bool operator()(unsigned int i, unsigned int j)
-        {
-            const double* bi = bBoxes.data() + 4*i;
-            const double* bj = bBoxes.data() + 4*j;
-            return bi[1] + bi[3] < bj[1] + bj[3];
-        }
-    };
-};
-
-//! Helper methods for world dimension one
-template <>
-class BoundingBoxTreeHelper<1>
-{
-    // An epsilon for floating point operations
-    static constexpr double eps_ = 1.0e-7;
-    using GlobalPosition = Dune::FieldVector<double, 1>;
-
-public:
-    // Check whether a point is inside a given geometry
-    template <class Geometry>
-    static bool pointInGeometry(const Geometry& geometry,
-                                const GlobalPosition& point)
-    {
-        return pointInInterval(geometry.corner(0),
-                               geometry.corner(1),
-                               point);
-    }
-
-    //! find out if a point is inside an interval
-    static bool pointInInterval(const GlobalPosition& p0, const GlobalPosition& p1,
-                                const GlobalPosition& point)
-    {
-        const double v1 = point[0] - p0[0];
-        const double v2 = p1[0] - p0[0];
-        // the coordinates are the same
-        if (v1 < v2*eps_)
-            return true;
-        // the point doesn't coincide with p0
-        // so if p0 and p1 are equal it's not inside
-        if (v2 < eps_)
-            return false;
-
-        // the point is inside if the length is
-        // small than the interval length and the
-        // sign of v1 & v2 are the same
-        using std::abs;
-        using std::signbit;
-        return (signbit(v1) == signbit(v2)
-                && abs(v1) < abs(v2)*(1 + eps_));
-    }
-
-    /*!
-     * \brief Check whether a point is in a bounding box
-     * \param point The point
-     * \param b Pointer to bounding box coordinates
-     */
-    static bool pointInBoundingBox(const GlobalPosition& point,
-                                   const double* b)
-    {
-        const double eps0 = eps_*(b[1] - b[0]);
-        return b[0] - eps0 <= point[0] && point[0] <= b[1] + eps0;
-    }
-
-    /*!
-     * \brief Check whether bounding box a collides with bounding box b
-     * \param a, b Pointer to bounding box coordinates
-     */
-    static bool boundingBoxInBoundingBox(const double* a,
-                                         const double* b)
-    {
-      const double eps0 = eps_*(b[1] - b[0]);
-      return b[0] - eps0 <= a[1] && a[0] <= b[1] + eps0;
-    }
-
-    //! Compute the bounding box of a vector of bounding boxes
-    static void computeBBoxOfBBoxes(double* bBox,
-                                    std::size_t& axis,
-                                    const std::vector<double>& leafBoxes,
-                                    const std::vector<unsigned int>::iterator& begin,
-                                    const std::vector<unsigned int>::iterator& end)
-    {
-        // Copy the iterator and get coordinates of first box
-        auto it = begin;
-        const double* bFirst = leafBoxes.data() + 2*(*it);
-        bBox[0] = bFirst[0];
-        bBox[1] = bFirst[1];
-
-        // Compute min and max with the remaining boxes
-        for (; it != end; ++it)
-        {
-            const double* b = leafBoxes.data() + 2*(*it);
-            if (b[0] < bBox[0]) bBox[0] = b[0];
-            if (b[1] > bBox[1]) bBox[1] = b[1];
-        }
-
-        // Compute the longest axis
-        axis = 0;
-    }
-
-    //! Sort the bounding boxes along the longest axis
-    static void sortBoundingBoxes(std::size_t axis,
-                                  const std::vector<double>& leafBoxes,
-                                  const std::vector<unsigned int>::iterator& begin,
-                                  const std::vector<unsigned int>::iterator& middle,
-                                  const std::vector<unsigned int>::iterator& end)
-    { std::nth_element(begin, middle, end, lessXBox(leafBoxes)); }
-
-    /*!
-     * \brief Comparison function for sorting bounding boxes on the x-axis
-     * \note This could be replaced by lambdas
-     */
-    struct lessXBox
-    {
-        const std::vector<double>& bBoxes;
-        lessXBox(const std::vector<double>& bBoxes_): bBoxes(bBoxes_) {}
-        inline bool operator()(unsigned int i, unsigned int j)
-        {
-            const double* bi = bBoxes.data() + 2*i;
-            const double* bj = bBoxes.data() + 2*j;
-            return bi[0] + bi[1] < bj[0] + bj[1];
-        }
-    };
-};
-
-/*!
- * \brief An intersection object resulting from the collision of two bounding box tree primitives
- *
- * After is has been found that two leaf bounding boxes intersect a primitive test has to be
- * performed to see if the actual entities inside the bounding box intersect too. The result
- * if such an intersection is found as an object of this class containing the indices of the
- * intersecting entities and the corners of the intersection object.
- */
-template<class GridView1, class GridView2>
-class BoundingBoxTreeIntersection
-{
-    const static int dimworld = GridView1::dimensionworld;
-    using Scalar = typename GridView1::ctype;
-    using GlobalPosition = Dune::FieldVector<Scalar, dimworld>;
-
-public:
-    BoundingBoxTreeIntersection(unsigned int a, unsigned int b, std::vector<GlobalPosition>&& c)
-    : a_(a), b_(b), corners_(c) {}
-
-    //! Get the index of the intersecting entity belonging to this grid
-    inline unsigned int first() const
-    { return a_; }
-
-    //! Get the index of the intersecting entity belonging to the other grid
-    inline unsigned int second() const
-    { return b_; }
-
-    //! Get the corners of the intersection geometry
-    inline std::vector<GlobalPosition> corners() const
-    { return corners_; }
-
-    /*!
-     * \brief Check if the corners of this intersection match with the given corners
-     * \note This is useful to check if the intersection geometry of two intersections coincide.
-     */
-    bool cornersMatch(const std::vector<GlobalPosition>& corners) const
-    {
-        if (corners.size() != corners_.size())
-            return false;
-
-        const auto eps = 1.5e-7*(corners_[1] - corners_[0]).two_norm();
-        for (int i = 0; i < corners_.size(); ++i)
-            if ((corners[0] - corners[1]).two_norm() > eps)
-                return false;
-
-        return true;
-    }
-
-private:
-    unsigned int a_, b_; //!< Indices of the intersection elements
-    std::vector<GlobalPosition> corners_; //!< the corner points of the intersection geometry
-};
-
-/*!
- * \brief A class mapping from an element index to elements using element seeds
- */
-template <class GridView>
-class IndexToElementMap
-  : public std::vector<typename GridView::Traits::Grid::template Codim<0>::EntitySeed>
-{
-    using Grid = typename GridView::Traits::Grid;
-    using Element = typename GridView::template Codim<0>::Entity;
-public:
-    IndexToElementMap(const GridView& gridView)
-      : grid_(gridView.grid()) {}
-
-    //! get an element from an index t
-    template<class T>
-    Element entity(T&& t)
-    { return grid_.entity((*this)[std::forward<T>(t)]); }
-
-private:
-    const Grid& grid_;
-};
-
-/*!
- * \brief An axis-aligned bounding box volume tree implementation
- *
- * The class constructs a hierarchical structure of bounding box volumes around
- * grid entities. This class can be used to efficiently compute intersections
- * between a grid and other geometrical object. It only implements the intersection
- * of two of such bounding box trees, so that two independent grids can be intersected.
- */
-template <class GridView>
-class BoundingBoxTree
-{
-    //! be friends with all other kinds bounding box trees so that
-    //! they can call each others private methods
-    template <class OtherGridView> friend class BoundingBoxTree;
-
-    static const int dim = GridView::dimension;
-    static const int dimworld = GridView::dimensionworld;
-    using Element = typename GridView::template Codim<0>::Entity;
-    using Scalar = typename GridView::ctype;
-    using GlobalPosition = typename Dune::FieldVector<Scalar, dimworld>;
-
-public:
-    //! Default Constructor
-    BoundingBoxTree() {}
-
-    //! Constructor with gridView
-    BoundingBoxTree(const GridView& leafGridView)
-    { build(leafGridView); }
-
-    //! Build up bounding box tree for a grid with leafGridView
-    void build(const GridView& leafGridView)
-    {
-        // clear data if any
-        clear_();
-
-        // Create bounding boxes for all elements
-        const unsigned int numLeaves = leafGridView.size(0);
-
-        // start the timer
-        Dune::Timer timer;
-
-        // create a vector for leaf boxes (min and max for all dims)
-        std::vector<double> leafBoxes(2*dimworld*numLeaves);
-
-        // Create index to element map
-        indexToElementMap_ = std::make_shared<IndexToElementMap<GridView> >(leafGridView);
-        indexToElementMap_->resize(numLeaves);
-
-        for (auto&& element : elements(leafGridView))
-        {
-            unsigned int eIdx = leafGridView.indexSet().index(element);
-            computeEntityBoundingBox_(leafBoxes.data() + 2*dimworld*eIdx, element);
-            (*indexToElementMap_)[eIdx] = element.seed();
-        }
-
-        // Create the leaf partition, the set of available indices (to be sorted)
-        std::vector<unsigned int> leafPartition(numLeaves);
-        for (unsigned int i = 0; i < numLeaves; ++i)
-            leafPartition[i] = i;
-
-        // Recursively build the bounding box tree
-        build_(leafBoxes, leafPartition.begin(), leafPartition.end());
-
-        // We are done, log output
-        std::cout << "Computed bounding box tree with " << numBoundingBoxes_()
-                  << " nodes for " << numLeaves << " grid entites in "
-                  << timer.stop() << " seconds." << std::endl;
-    }
-
-    //! Compute all intersections between entities and a point
-    std::vector<unsigned int> computeEntityCollisions(const Dune::FieldVector<double, dimworld>& point) const
-    {
-        // Call the recursive find function to find candidates
-        std::vector<unsigned int> entities;
-        computeCollisions_(point, numBoundingBoxes_() - 1, entities);
-        return entities;
-    }
-
-    //! Compute all intersections between entities and another bounding box tree
-    template<class OtherGridView>
-    std::vector<BoundingBoxTreeIntersection<GridView, OtherGridView>>
-    computeEntityCollisions(const BoundingBoxTree<OtherGridView>& otherTree) const
-    {
-        // check if the world dimensions match
-        static_assert(dimworld == OtherGridView::dimensionworld, "Can only collide bounding box trees of same world dimension");
-
-        // Create data structure for return type
-        std::vector<BoundingBoxTreeIntersection<GridView, OtherGridView>> intersections;
-
-        // Call the recursive find function to find candidates
-        computeCollisions_(otherTree,
-                           this->numBoundingBoxes_() - 1,
-                           otherTree.numBoundingBoxes_() -1,
-                           intersections);
-
-        return intersections;
-    }
-
-    //! Get an element from a global element index
-    Element entity(unsigned int eIdx) const
-    { return indexToElementMap_->entity(eIdx); }
-
-private:
-    /*!
-     * \brief Bounding box data structure
-     * Leaf nodes are indicated by setting child_0 to
-     * the node itself and child_1 is the index of the entity in the bounding box.
-     */
-    struct BoundingBox
-    {
-        unsigned int child_0;
-        unsigned int child_1;
-    };
-
-    //! Vector of bounding boxes
-    std::vector<BoundingBox> boundingBoxes_;
-
-    //! Vector of bounding box coordinates
-    std::vector<double> boundingBoxCoordinates_;
-
-    //! Shared pointer to the index to element map
-    std::shared_ptr<IndexToElementMap<GridView> > indexToElementMap_;
-
-    //! Clear all data
-    void clear_()
-    {
-        boundingBoxes_.clear();
-        boundingBoxCoordinates_.clear();
-        if(indexToElementMap_) indexToElementMap_->clear();
-    }
-
-    //! Build bounding box tree for all entities recursively
-    unsigned int build_(const std::vector<double>& leafBoxes,
-                        const std::vector<unsigned int>::iterator& begin,
-                        const std::vector<unsigned int>::iterator& end)
-    {
-        assert(begin < end);
-
-        // Create empty bounding box
-        BoundingBox bBox;
-
-        // If we reached the leaf
-        if (end - begin == 1)
-        {
-            // Get the bounding box coordinates for the leaf
-            const unsigned int eIdx = *begin;
-            const double* b = leafBoxes.data() + 2*dimworld*eIdx;
-
-            // Store the data in the bounding box
-            bBox.child_0 = numBoundingBoxes_();
-            bBox.child_1 = eIdx;
-            return addBoundingBox_(bBox, b);
-        }
-
-        // Compute the bounding box of all bounding boxes in the range [begin, end]
-        double b[dimworld*2];
-        std::size_t axis;
-        BoundingBoxTreeHelper<dimworld>::computeBBoxOfBBoxes(b, axis, leafBoxes, begin, end);
-
-        // Sort bounding boxes along the longest axis
-        std::vector<unsigned int>::iterator middle = begin + (end - begin)/2;
-        BoundingBoxTreeHelper<dimworld>::sortBoundingBoxes(axis, leafBoxes, begin, middle, end);
-
-        // Split the bounding boxes into two branches and call build recursively
-        bBox.child_0 = build_(leafBoxes, begin, middle);
-        bBox.child_1 = build_(leafBoxes, middle, end);
-
-        // Store the bounding box data. The root will be added at the end.
-        return addBoundingBox_(bBox, b);
-    }
-
-    //! Compute collisions with point recursively
-    void computeCollisions_(const Dune::FieldVector<double, dimworld>& point,
-                            unsigned int node,
-                            std::vector<unsigned int>& entities) const
-    {
-        // Get the bounding box for the current node
-        const BoundingBox& bBox = getBoundingBox_(node);
-
-        // if the point is not in the bounding box we can stop
-        if (!BoundingBoxTreeHelper<dimworld>::pointInBoundingBox(point, getBoundingBoxCoordinates_(node)))
-            return;
-
-        // We know now it's inside. If the box is a leaf add it.
-        else if (isLeaf_(bBox, node))
-        {
-            // but add it only if the point is also inside the entity
-            const unsigned int eIdx = bBox.child_1;
-            auto geometry = (indexToElementMap_->entity(eIdx)).geometry();
-            if (BoundingBoxTreeHelper<dimworld>::pointInGeometry(geometry, point))
-                entities.push_back(eIdx);
-
-            // const ReferenceElement &refElement = ReferenceElements::general(geometry.type());
-            // if (refElement.checkInside(geometry.local(point)))
-            //     entities.push_back(eIdx);
-        }
-
-        // No leaf. Check both children.
-        else
-        {
-            computeCollisions_(point, bBox.child_0, entities);
-            computeCollisions_(point, bBox.child_1, entities);
-        }
-    }
-
-    //! Compute collisions with other bounding box tree recursively
-    template <class OtherGridView>
-    void computeCollisions_(const BoundingBoxTree<OtherGridView>& treeB,
-                            unsigned int nodeA,
-                            unsigned int nodeB,
-                            std::vector<BoundingBoxTreeIntersection<GridView, OtherGridView>>& intersections) const
-    {
-        // get alias
-        const auto& treeA = *this;
-
-        // Get the bounding box for the current node
-        const auto& bBoxA = treeA.getBoundingBox_(nodeA);
-        const auto& bBoxB = treeB.getBoundingBox_(nodeB);
-
-        // if the two bounding boxes don't collide we can stop searching
-        if (!BoundingBoxTreeHelper<dimworld>::
-             boundingBoxInBoundingBox(treeA.getBoundingBoxCoordinates_(nodeA),
-                                      treeB.getBoundingBoxCoordinates_(nodeB)))
-            return;
-
-        // Check if we have a leaf in treeA or treeB
-        const bool isLeafA = treeA.isLeaf_(bBoxA, nodeA);
-        const bool isLeafB = treeB.isLeaf_(bBoxB, nodeB);
-
-        // If both boxes are leaves and collide add them
-        if (isLeafA && isLeafB)
-        {
-            const unsigned int eIdxA = bBoxA.child_1;
-            const unsigned int eIdxB = bBoxB.child_1;
-
-            auto geometryA = treeA.entity(eIdxA).geometry();
-            auto geometryB = treeB.entity(eIdxB).geometry();
-
-            using CollisionType = GeometryCollision<decltype(geometryA), decltype(geometryB)>;
-            std::vector<GlobalPosition> intersection;
-            if (CollisionType::collide(geometryA, geometryB, intersection))
-                intersections.emplace_back(eIdxA, eIdxB, std::move(intersection));
-        }
-
-        // if we reached the leaf in treeA, just continue in treeB
-        else if (isLeafA)
-        {
-            computeCollisions_(treeB, nodeA, bBoxB.child_0, intersections);
-            computeCollisions_(treeB, nodeA, bBoxB.child_1, intersections);
-        }
-
-        // if we reached the leaf in treeB, just continue in treeA
-        else if (isLeafB)
-        {
-            computeCollisions_(treeB, bBoxA.child_0, nodeB, intersections);
-            computeCollisions_(treeB, bBoxA.child_1, nodeB, intersections);
-        }
-
-        // we know now that both trees didn't reach the leaf yet so
-        // we continue with the larger tree first (bigger node number)
-        else if (nodeA > nodeB)
-        {
-            computeCollisions_(treeB, bBoxA.child_0, nodeB, intersections);
-            computeCollisions_(treeB, bBoxA.child_1, nodeB, intersections);
-        }
-        else
-        {
-            computeCollisions_(treeB, nodeA, bBoxB.child_0, intersections);
-            computeCollisions_(treeB, nodeA, bBoxB.child_1, intersections);
-        }
-    }
-
-    //! Add a new bounding box to the tree
-    inline unsigned int addBoundingBox_(const BoundingBox& bBox,
-                                        const double* b)
-    {
-        // Add the bounding box
-        boundingBoxes_.push_back(bBox);
-
-        // Add the bounding box's coordinates
-        for (std::size_t i = 0; i < 2*dimworld; ++i)
-            boundingBoxCoordinates_.push_back(b[i]);
-
-        // return the index of the new node
-        return boundingBoxes_.size() - 1;
-    }
-
-    //! Get an existing bounding box for a given node
-    inline const BoundingBox& getBoundingBox_(unsigned int node) const
-    { return boundingBoxes_[node]; }
-
-    //! Get an existing bounding box for a given node
-    const double* getBoundingBoxCoordinates_(unsigned int node) const
-    { return boundingBoxCoordinates_.data() + 2*dimworld*node; }
-
-    //! Get the number of bounding boxes currently in the tree
-    inline std::size_t numBoundingBoxes_() const
-    { return boundingBoxes_.size(); }
-
-    //! Check whether a bounding box is a leaf node
-    //! Leaf nodes have itself as child_0
-    inline bool isLeaf_(const BoundingBox& bBox, unsigned int node) const
-    { return bBox.child_0 == node; }
-
-    //! Compute the bounding box of a grid entity
-    template <class Entity>
-    void computeEntityBoundingBox_(double* b, const Entity& entity) const
-    {
-        // get the bounding box coordinates
-        double* xMin = b;
-        double* xMax = b + dimworld;
-
-        // get mesh entity data
-        auto geometry = entity.geometry();
-
-        // Get coordinates of first vertex
-        auto corner = geometry.corner(0);
-        for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx)
-            xMin[dimIdx] = xMax[dimIdx] = corner[dimIdx];
-
-        // Compute the min and max over the remaining vertices
-        for (std::size_t vLocalIdx = 1; vLocalIdx < entity.subEntities(dim); ++vLocalIdx)
-        {
-            corner = geometry.corner(vLocalIdx);
-            for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx)
-            {
-                using std::max;
-                using std::min;
-                xMin[dimIdx] = min(xMin[dimIdx], corner[dimIdx]);
-                xMax[dimIdx] = max(xMax[dimIdx], corner[dimIdx]);
-            }
-        }
-    }
-};
-
-} // end namespace Dumux
-
+#ifndef DUMUX_OLD_BOUNDINGBOXTREE_HH
+#define DUMUX_OLD_BOUNDINGBOXTREE_HH
+#warning "This header is deprecated. Include dumux/common/geometry/boundingboxtree.hh"
+#include <dumux/common/geometry/boundingboxtree.hh>
 #endif
diff --git a/dumux/common/elementmap.hh b/dumux/common/elementmap.hh
deleted file mode 100644
index 5ffb0c26b6..0000000000
--- a/dumux/common/elementmap.hh
+++ /dev/null
@@ -1,50 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \brief Base class for the finite volume geometry vector for cell-centered TPFA models
- *        This builds up the sub control volumes and sub control volume faces
- *        for each element.
- */
-#ifndef DUMUX_ELEMENT_MAP_HH
-#define DUMUX_ELEMENT_MAP_HH
-
-namespace Dumux {
-
-//! An index to element map
-template <class GridView>
-class ElementMap
-  : public std::vector<typename GridView::Traits::Grid::template Codim<0>::EntitySeed>
-{
-    using Grid = typename GridView::Traits::Grid;
-    using Element = typename GridView::template Codim<0>::Entity;
-    using IndexType = typename GridView::IndexSet::IndexType;
-public:
-    ElementMap(const GridView& gridView_) : grid_(gridView_.grid()) {}
-
-    Element element(IndexType eIdx) const
-    { return grid_.entity((*this)[eIdx]); }
-
-private:
-    const Grid& grid_;
-};
-
-} // end namespace Dumux
-
-#endif
\ No newline at end of file
diff --git a/dumux/common/entitymap.hh b/dumux/common/entitymap.hh
new file mode 100644
index 0000000000..de4a42b773
--- /dev/null
+++ b/dumux/common/entitymap.hh
@@ -0,0 +1,85 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief A map from indices to entities using grid entity seeds
+ */
+#ifndef DUMUX_ENTITY_INDEX_MAP_HH
+#define DUMUX_ENTITY_INDEX_MAP_HH
+
+namespace Dumux {
+
+/*!
+ * \brief A map from indices to entities using grid entity seeds
+ */
+template <class GridView, int codim = 0>
+class EntityMap
+{
+public:
+    using Grid = typename GridView::Traits::Grid;
+    using Entity = typename Grid::template Codim<codim>::Entity;
+    using EntitySeed = typename Grid::template Codim<codim>::EntitySeed;
+
+    //! constructor moving a ready seed list in here
+    EntityMap(const Grid& grid, std::vector<EntitySeed>&& seeds)
+    : grid_(grid)
+    , seeds_(std::move(seeds))
+    {}
+
+    //! constructor with all entites of codim
+    template<class Mapper>
+    EntityMap(const Grid& grid, const Mapper& mapper)
+    : grid_(grid)
+    {
+        update(mapper);
+    }
+
+    //! update the map after the grid changed
+    void update(std::vector<EntitySeed>&& seeds)
+    { seeds_.swap(std::move(seeds)); }
+
+    //! update the map after the grid changed
+    template<class Mapper>
+    void update(const Mapper& mapper)
+    {
+        const auto& gv = grid_.leafGridView();
+        seeds_.resize(gv.size(codim));
+        for (const auto& entity : entities(gv, Dune::Codim<codim>()))
+            seeds_[mapper.index(entity)] = entity.seed();
+    }
+
+    //! get an element from an index i
+    Entity operator[](std::size_t i) const
+    { return grid_.entity(seeds_[i]); }
+
+    //! get the size of the map
+    std::size_t size() const
+    { return seeds_.size(); }
+
+private:
+    const Grid& grid_;
+    std::vector<EntitySeed> seeds_;
+};
+
+template<class GridView>
+using ElementMap = EntityMap<GridView, 0>;
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/common/geometry/boundingboxtree.hh b/dumux/common/geometry/boundingboxtree.hh
new file mode 100644
index 0000000000..e3aec399d1
--- /dev/null
+++ b/dumux/common/geometry/boundingboxtree.hh
@@ -0,0 +1,371 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 3 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief An axis-aligned bounding box volume hierarchy for dune grids
+ *
+ * Dumux implementation of an AABB tree
+ * Inspired by the AABB tree implementation in DOLFIN by Anders Logg which has the
+ * following license info: DOLFIN is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef DUMUX_BOUNDINGBOXTREE_HH
+#define DUMUX_BOUNDINGBOXTREE_HH
+
+#include <vector>
+#include <array>
+#include <algorithm>
+#include <numeric>
+#include <type_traits>
+
+#include <dune/common/promotiontraits.hh>
+#include <dune/common/timer.hh>
+#include <dune/common/fvector.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \brief An axis-aligned bounding box volume tree implementation
+ *
+ * The class constructs a hierarchical structure of bounding box volumes around
+ * grid entities. This class can be used to efficiently compute intersections
+ * between a grid and other geometrical object. It only implements the intersection
+ * of two of such bounding box trees, so that two independent grids can be intersected.
+ * \tparam GeometricEntitySet has the following requirements
+ *         * export dimensionworld, ctype
+ *         * a size() member function returning the number of entities
+ *         * begin() and end() member function returning at least forward iterators to entities
+ *         * an index() method returning a consecutive index given an entity
+ *         * an entity() method returning an entity given the consecutive index
+ *         * entities have the following requirements:
+ *             * a member function geometry() returning a geometry with the member functions
+ *                 * corner() and corners() returning global coordinates and number of corners
+ */
+template <class GeometricEntitySet>
+class BoundingBoxTree
+{
+    enum { dimworld = GeometricEntitySet::dimensionworld };
+    using ctype = typename GeometricEntitySet::ctype;
+
+    /*!
+     * \brief Bounding box node data structure
+     * leaf nodes are indicated by setting child0 to
+     * the node itself and child1 to the index of the entity in the bounding box.
+     */
+    struct BoundingBoxNode
+    {
+        std::size_t child0;
+        std::size_t child1;
+    };
+
+public:
+    //! the type of entity set this tree was built with
+    using EntitySet = GeometricEntitySet;
+
+    //! Default Constructor
+    BoundingBoxTree() = default;
+
+    //! Constructor with gridView
+    BoundingBoxTree(std::shared_ptr<const GeometricEntitySet> set)
+    { build(set); }
+
+    //! Build up bounding box tree for a grid with leafGridView
+    void build(std::shared_ptr<const GeometricEntitySet> set)
+    {
+        // set the pointer to the entity set
+        entitySet_ = set;
+
+        // clear all internal data
+        boundingBoxNodes_.clear();
+        boundingBoxCoordinates_.clear();
+
+        // start the timer
+        Dune::Timer timer;
+
+        // Create bounding boxes for all elements
+        const auto numLeaves = set->size();
+
+        // reserve enough space for the nodes and the coordinates
+        const auto numNodes = 2*numLeaves - 1;
+        boundingBoxNodes_.reserve(numNodes);
+        boundingBoxCoordinates_.reserve(numNodes*2*dimworld);
+
+        // create a vector for leaf boxes (min and max for all dims)
+        std::vector<ctype> leafBoxes(2*dimworld*numLeaves);
+
+        for (const auto& geometricEntity : *set)
+            computeEntityBoundingBox_(leafBoxes.data() + 2*dimworld*set->index(geometricEntity), geometricEntity);
+
+        // create the leaf partition, the set of available indices (to be sorted)
+        std::vector<std::size_t> leafPartition(numLeaves);
+        std::iota(leafPartition.begin(), leafPartition.end(), 0);
+
+        // Recursively build the bounding box tree
+        build_(leafBoxes, leafPartition.begin(), leafPartition.end());
+
+        // We are done, log output
+        std::cout << "Computed bounding box tree with " << numBoundingBoxes()
+                  << " nodes for " << numLeaves << " grid entites in "
+                  << timer.stop() << " seconds." << std::endl;
+    }
+
+    //! the entity set this tree was built with
+    const EntitySet& entitySet() const
+    { return *entitySet_; }
+
+    /////////////////////////////////////////////////////
+    //! Interface to be used by other bounding box trees
+    /////////////////////////////////////////////////////
+
+    //! Get an existing bounding box for a given node
+    const BoundingBoxNode& getBoundingBoxNode(std::size_t nodeIdx) const
+    { return boundingBoxNodes_[nodeIdx]; }
+
+    //! Get an existing bounding box for a given node
+    const ctype* getBoundingBoxCoordinates(std::size_t nodeIdx) const
+    { return boundingBoxCoordinates_.data() + 2*dimworld*nodeIdx; }
+
+    //! Get the number of bounding boxes currently in the tree
+    std::size_t numBoundingBoxes() const
+    { return boundingBoxNodes_.size(); }
+
+    //! Check whether a bounding box node is a leaf node
+    //! Leaf nodes have itself as child0
+    bool isLeaf(const BoundingBoxNode& node, std::size_t nodeIdx) const
+    { return node.child0 == nodeIdx; }
+
+private:
+
+    //! vector of bounding box nodes
+    std::vector<BoundingBoxNode> boundingBoxNodes_;
+
+    //! vector of bounding box coordinates
+    std::vector<ctype> boundingBoxCoordinates_;
+
+    //! a pointer to the entity set
+    std::shared_ptr<const EntitySet> entitySet_;
+
+    //! Compute the bounding box of a grid entity
+    template <class Entity>
+    void computeEntityBoundingBox_(ctype* b, const Entity& entity) const
+    {
+        // get the bounding box coordinates
+        ctype* xMin = b;
+        ctype* xMax = b + dimworld;
+
+        // get mesh entity data
+        auto geometry = entity.geometry();
+
+        // Get coordinates of first vertex
+        auto corner = geometry.corner(0);
+        for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx)
+            xMin[dimIdx] = xMax[dimIdx] = corner[dimIdx];
+
+        // Compute the min and max over the remaining vertices
+        for (std::size_t cornerIdx = 1; cornerIdx < geometry.corners(); ++cornerIdx)
+        {
+            corner = geometry.corner(cornerIdx);
+            for (std::size_t dimIdx = 0; dimIdx < dimworld; ++dimIdx)
+            {
+                using std::max;
+                using std::min;
+                xMin[dimIdx] = min(xMin[dimIdx], corner[dimIdx]);
+                xMax[dimIdx] = max(xMax[dimIdx], corner[dimIdx]);
+            }
+        }
+    }
+
+    //! Build bounding box tree for all entities recursively
+    std::size_t build_(const std::vector<ctype>& leafBoxes,
+                       const std::vector<std::size_t>::iterator& begin,
+                       const std::vector<std::size_t>::iterator& end)
+    {
+        assert(begin < end);
+
+        // If we reached the end of the recursion, i.e. only a leaf box is left
+        if (end - begin == 1)
+        {
+            // Get the bounding box coordinates for the leaf
+            const std::size_t leafNodeIdx = *begin;
+            const auto beginCoords = leafBoxes.begin() + 2*dimworld*leafNodeIdx;
+            const auto endCoords = beginCoords + 2*dimworld;
+
+            // Store the data in the bounding box
+            // leaf nodes are indicated by setting child0 to
+            // the node itself and child1 to the index of the entity in the bounding box.
+            return addBoundingBox_(BoundingBoxNode{numBoundingBoxes(), leafNodeIdx}, beginCoords, endCoords);
+        }
+
+        // Compute the bounding box of all bounding boxes in the range [begin, end]
+        const auto bCoords = computeBBoxOfBBoxes_(leafBoxes, begin, end);
+
+        // sort bounding boxes along the longest axis
+        const auto axis = computeLongestAxis_(bCoords);
+
+        // nth_element sorts the range to make sure that middle points to the coordinate median in axis direction
+        // this is the most expensive part of the algorithm
+        auto middle = begin + (end - begin)/2;
+        std::nth_element(begin, middle, end, [&leafBoxes, axis](std::size_t i, std::size_t j)
+                         {
+                             const ctype* bi = leafBoxes.data() + 2*dimworld*i;
+                             const ctype* bj = leafBoxes.data() + 2*dimworld*j;
+                             return bi[axis] + bi[axis + dimworld] < bj[axis] + bj[axis + dimworld];
+                         });
+
+        // split the bounding boxes into two at the middle iterator and call build recursively, each
+        // call resulting in a new node of this bounding box, i.e. the root will be added at the end of the process.
+        return addBoundingBox_(BoundingBoxNode{build_(leafBoxes, begin, middle), build_(leafBoxes, middle, end)},
+                               bCoords.begin(), bCoords.end());
+    }
+
+    //! Add a new bounding box to the tree
+    template <class Iterator>
+    std::size_t addBoundingBox_(BoundingBoxNode&& node,
+                                const Iterator& coordBegin,
+                                const Iterator& coordEnd)
+    {
+        // Add the bounding box
+        boundingBoxNodes_.emplace_back(node);
+
+        // Add the bounding box's coordinates
+        boundingBoxCoordinates_.insert(boundingBoxCoordinates_.end(), coordBegin, coordEnd);
+
+        // return the index of the new node
+        return boundingBoxNodes_.size() - 1;
+    }
+
+    //! Compute the bounding box of a vector of bounding boxes
+    std::array<ctype, 2*dimworld>
+    computeBBoxOfBBoxes_(const std::vector<ctype>& leafBoxes,
+                         const std::vector<std::size_t>::iterator& begin,
+                         const std::vector<std::size_t>::iterator& end)
+    {
+        std::array<ctype, 2*dimworld> bBoxCoords;
+
+        // copy the iterator and get coordinates of first box
+        auto it = begin;
+        const auto* bFirst = leafBoxes.data() + 2*dimworld*(*it);
+
+        for (int coordIdx = 0; coordIdx < 2*dimworld; ++coordIdx)
+            bBoxCoords[coordIdx] = bFirst[coordIdx];
+
+        // Compute min and max with the remaining boxes
+        for (; it != end; ++it)
+        {
+            const auto* b = leafBoxes.data() + 2*dimworld*(*it);
+            for (int coordIdx = 0; coordIdx < dimworld; ++coordIdx)
+                if (b[coordIdx] < bBoxCoords[coordIdx])
+                    bBoxCoords[coordIdx] = b[coordIdx];
+            for (int coordIdx = dimworld; coordIdx < 2*dimworld; ++coordIdx)
+                if (b[coordIdx] > bBoxCoords[coordIdx])
+                    bBoxCoords[coordIdx] = b[coordIdx];
+        }
+
+        return bBoxCoords;
+    }
+
+    //! Compute the bounding box of a vector of bounding boxes
+    std::size_t computeLongestAxis_(const std::array<ctype, 2*dimworld>& bCoords)
+    {
+        std::array<ctype, dimworld> axisLength;
+        for (int coordIdx = 0; coordIdx < dimworld; ++coordIdx)
+            axisLength[coordIdx] = bCoords[dimworld + coordIdx] - bCoords[coordIdx];
+
+        return std::distance(axisLength.begin(), std::max_element(axisLength.begin(), axisLength.end()));
+    }
+};
+
+/*!
+ * \brief Check whether a point is intersectin a bounding box
+ * \param point The point
+ * \param b Pointer to bounding box coordinates
+ */
+template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 3, int> = 0>
+inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b)
+{
+    static constexpr ctype eps_ = 1.0e-7;
+    const ctype eps0 = eps_*(b[3] - b[0]);
+    const ctype eps1 = eps_*(b[4] - b[1]);
+    const ctype eps2 = eps_*(b[5] - b[2]);
+    return (b[0] - eps0 <= point[0] && point[0] <= b[3] + eps0 &&
+            b[1] - eps1 <= point[1] && point[1] <= b[4] + eps1 &&
+            b[2] - eps2 <= point[2] && point[2] <= b[5] + eps2);
+}
+
+template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 2, int> = 0>
+inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b)
+{
+    static constexpr ctype eps_ = 1.0e-7;
+    const ctype eps0 = eps_*(b[2] - b[0]);
+    const ctype eps1 = eps_*(b[3] - b[1]);
+    return (b[0] - eps0 <= point[0] && point[0] <= b[2] + eps0 &&
+            b[1] - eps1 <= point[1] && point[1] <= b[3] + eps1);
+}
+
+template<class ctype, int dimworld, typename std::enable_if_t<dimworld == 1, int> = 0>
+inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b)
+{
+    static constexpr ctype eps_ = 1.0e-7;
+    const ctype eps0 = eps_*(b[1] - b[0]);
+    return b[0] - eps0 <= point[0] && point[0] <= b[1] + eps0;
+}
+
+/*!
+ * \brief Check whether a bounding box is intersecting another bounding box
+ * \param a Pointer to first bounding box coordinates
+ * \param b Pointer to second bounding box coordinates
+ */
+template<int dimworld, class ctypea, class ctypeb, typename std::enable_if_t<dimworld == 3, int> = 0>
+inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b)
+{
+    using ctype = typename Dune::PromotionTraits<ctypea, ctypeb>::PromotedType;
+    static constexpr ctype eps_ = 1.0e-7;
+    const ctype eps0 = eps_*(b[3] - b[0]);
+    const ctype eps1 = eps_*(b[4] - b[1]);
+    const ctype eps2 = eps_*(b[5] - b[2]);
+    return (b[0] - eps0 <= a[3] && a[0] <= b[3] + eps0 &&
+            b[1] - eps1 <= a[4] && a[1] <= b[4] + eps1 &&
+            b[2] - eps2 <= a[5] && a[2] <= b[5] + eps2);
+
+}
+
+template<int dimworld, class ctypea, class ctypeb, typename std::enable_if_t<dimworld == 2, int> = 0>
+inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b)
+{
+    using ctype = typename Dune::PromotionTraits<ctypea, ctypeb>::PromotedType;
+    static constexpr ctype eps_ = 1.0e-7;
+    const ctype eps0 = eps_*(b[2] - b[0]);
+    const ctype eps1 = eps_*(b[3] - b[1]);
+    return (b[0] - eps0 <= a[2] && a[0] <= b[2] + eps0 &&
+            b[1] - eps1 <= a[3] && a[1] <= b[3] + eps1);
+}
+
+template<int dimworld, class ctypea, class ctypeb, typename std::enable_if_t<dimworld == 1, int> = 0>
+inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b)
+{
+    using ctype = typename Dune::PromotionTraits<ctypea, ctypeb>::PromotedType;
+    static constexpr ctype eps_ = 1.0e-1;
+    const ctype eps0 = eps_*(b[1] - b[0]);
+    return b[0] - eps0 <= a[1] && a[0] <= b[1] + eps0;
+}
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/common/geometry/boundingboxtreeintersection.hh b/dumux/common/geometry/boundingboxtreeintersection.hh
new file mode 100644
index 0000000000..d80b906c45
--- /dev/null
+++ b/dumux/common/geometry/boundingboxtreeintersection.hh
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 3 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief A class storing intersections from intersecting two bounding box trees
+ */
+#ifndef DUMUX_BOUNDING_BOX_TREE_INTERSECTION_HH
+#define DUMUX_BOUNDING_BOX_TREE_INTERSECTION_HH
+
+#include <dune/common/fvector.hh>
+#include <dune/common/promotiontraits.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \brief An intersection object resulting from the intersection of two bounding box tree primitives
+ *
+ * After is has been found that two leaf bounding boxes intersect a primitive test has to be
+ * performed to see if the actual entities inside the bounding box intersect too. The result
+ * if such an intersection is found as an object of this class containing the indices of the
+ * intersecting entities and the corners of the intersection object.
+ */
+template<class EntitySet0, class EntitySet1>
+class BoundingBoxTreeIntersection
+{
+    enum { dimworld = EntitySet0::dimensionworld };
+    using ctype = typename Dune::PromotionTraits<typename EntitySet0::ctype, typename EntitySet1::ctype>::PromotedType;
+    using GlobalPosition = Dune::FieldVector<ctype, dimworld>;
+
+public:
+    explicit BoundingBoxTreeIntersection(std::size_t a,
+                                         std::size_t b,
+                                         std::vector<GlobalPosition>&& c)
+    : a_(a)
+    , b_(b)
+    , corners_(std::move(c))
+    {
+        static_assert(int(EntitySet0::dimensionworld) == int(EntitySet1::dimensionworld),
+          "Can only store intersections of entity sets with the same world dimension");
+    }
+
+    //! Get the index of the intersecting entity belonging to this grid
+    std::size_t first() const
+    { return a_; }
+
+    //! Get the index of the intersecting entity belonging to the other grid
+    std::size_t second() const
+    { return b_; }
+
+    //! Get the corners of the intersection geometry
+    std::vector<GlobalPosition> corners() const
+    { return corners_; }
+
+    /*!
+     * \brief Check if the corners of this intersection match with the given corners
+     * \note This is useful to check if the intersection geometry of two intersections coincide.
+     */
+    bool cornersMatch(const std::vector<GlobalPosition>& otherCorners) const
+    {
+        if (otherCorners.size() != corners_.size())
+            return false;
+
+        const auto eps = 1.5e-7*(corners_[1] - corners_[0]).two_norm();
+        for (int i = 0; i < corners_.size(); ++i)
+            if ((corners_[i] - otherCorners[i]).two_norm() > eps)
+                return false;
+
+        return true;
+    }
+
+private:
+    std::size_t a_, b_; //!< Indices of the intersection elements
+    std::vector<GlobalPosition> corners_; //!< the corner points of the intersection geometry
+};
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/common/geometry/geometricentityset.hh b/dumux/common/geometry/geometricentityset.hh
new file mode 100644
index 0000000000..e298cb14d0
--- /dev/null
+++ b/dumux/common/geometry/geometricentityset.hh
@@ -0,0 +1,102 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief An interface for a set of geometric entities
+ * \note This can be used e.g. to contruct a bounding box volume hierarchy of a grid
+ * It defines the minimum requirement for such a set
+ */
+#ifndef DUMUX_GRIDVIEW_GEOMETRIC_ENTITY_SET_HH
+#define DUMUX_GRIDVIEW_GEOMETRIC_ENTITY_SET_HH
+
+#include <memory>
+#include <dune/grid/common/mcmgmapper.hh>
+#include <dumux/common/entitymap.hh>
+
+namespace Dumux {
+
+template <class GridView, int codim = 0>
+class GridViewGeometricEntitySet
+{
+    using Mapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>;
+    using Entity = typename GridView::template Codim<codim>::Entity;
+
+public:
+    GridViewGeometricEntitySet(const GridView& gridView)
+    : gridView_(gridView)
+    , mapper_(gridView, Dune::mcmgLayout(Dune::Codim<codim>()))
+    , entityMap_(std::make_shared<EntityMap<GridView, codim>>(gridView.grid(), mapper_))
+    {}
+
+    GridViewGeometricEntitySet(const GridView& gridView,
+                               const Mapper& mapper,
+                               std::shared_ptr<const EntityMap<GridView, codim>> entityMap)
+    : gridView_(gridView)
+    , mapper_(mapper)
+    , entityMap_(entityMap)
+    {}
+
+    /*!
+     * \brief The world dimension of the entity set
+     */
+    enum { dimensionworld = GridView::dimensionworld };
+
+    /*!
+     * \brief the coordinate type
+     */
+    using ctype = typename GridView::ctype;
+
+    /*!
+     * \brief the number of entities in this set
+     */
+    decltype(auto) size() const
+    { return gridView_.size(codim); }
+
+    /*!
+     * \brief begin iterator to enable range-based for iteration
+     */
+    decltype(auto) begin() const
+    { return entities(gridView_, Dune::Codim<codim>()).begin(); }
+
+    /*!
+     * \brief end iterator to enable range-based for iteration
+     */
+    decltype(auto) end() const
+    { return entities(gridView_, Dune::Codim<codim>()).end(); }
+
+    /*!
+     * \brief get an entities index
+     */
+    std::size_t index(const Entity& e) const
+    { return mapper_.index(e); }
+
+    /*!
+     * \brief get an entity from an index
+     */
+    Entity entity(std::size_t index) const
+    { return (*entityMap_)[index]; }
+
+private:
+    GridView gridView_;
+    Mapper mapper_;
+    std::shared_ptr<const EntityMap<GridView, codim>> entityMap_;
+
+};
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/common/geometrycollision.hh b/dumux/common/geometry/geometryintersection.hh
similarity index 65%
rename from dumux/common/geometrycollision.hh
rename to dumux/common/geometry/geometryintersection.hh
index d148a578a3..8095a07bb3 100644
--- a/dumux/common/geometrycollision.hh
+++ b/dumux/common/geometry/geometryintersection.hh
@@ -19,8 +19,8 @@
  * \brief A class for collision detection of two geometries
  *        and computation of intersection corners
  */
-#ifndef DUMUX_GEOMETRY_COLLISION_HH
-#define DUMUX_GEOMETRY_COLLISION_HH
+#ifndef DUMUX_GEOMETRY_INTERSECTION_HH
+#define DUMUX_GEOMETRY_INTERSECTION_HH
 
 #include <dune/common/exceptions.hh>
 #include <dune/common/promotiontraits.hh>
@@ -41,34 +41,39 @@ template
   int dimworld = Geometry1::coorddimension,
   int dim1 = Geometry1::mydimension,
   int dim2 = Geometry2::mydimension>
-class GeometryCollision
+class GeometryIntersection
 {
-    using Scalar = typename Dune::PromotionTraits<typename Geometry1::ctype, typename Geometry2::ctype>::PromotedType;
-    using GlobalPosition = Dune::FieldVector<Scalar, dimworld>;
-
 public:
+    using ctype = typename Dune::PromotionTraits<typename Geometry1::ctype, typename Geometry2::ctype>::PromotedType;
+    using GlobalPosition = Dune::FieldVector<ctype, dimworld>;
+    using IntersectionType = std::vector<GlobalPosition>;
+
     //! Determine if the two geometries intersect and compute the intersection corners
-    static bool collide(const Geometry1& geo1, const Geometry2& geo2, std::vector<GlobalPosition>& intersection)
+    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, IntersectionType& intersection)
     {
-        static_assert(dimworld == Geometry2::coorddimension, "Can only collide geometries of same coordinate dimension");
-        DUNE_THROW(Dune::NotImplemented, "Geometry collision detection with intersection computation not implemented for dimworld = "
+        static_assert(dimworld == Geometry2::coorddimension, "Can only intersect geometries of same coordinate dimension");
+        DUNE_THROW(Dune::NotImplemented, "Geometry intersection detection with intersection computation not implemented for dimworld = "
                                           << dimworld << ", dim1 = " << dim1 << ", dim2 = " << dim2);
     }
 };
 
 //! Geometry collision detection with 3d and 1d geometry in 3d space
 template <class Geometry1, class Geometry2>
-class GeometryCollision<Geometry1, Geometry2, 3, 3, 1>
+class GeometryIntersection<Geometry1, Geometry2, 3, 3, 1>
 {
-    static const int dimworld = 3;
-    static const int dim1 = 3;
-    static const int dim2 = 1;
-    static const int dimis = dim2; // the intersection dimension
-    using Scalar = typename Dune::PromotionTraits<typename Geometry1::ctype, typename Geometry2::ctype>::PromotedType;
-    using ReferenceElements = typename Dune::ReferenceElements<Scalar, dim1>;
-    using GlobalPosition = Dune::FieldVector<Scalar, dimworld>;
+    enum { dimworld = 3 };
+    enum { dim1 = 3 };
+    enum { dim2 = 1 };
+    enum { dimis = dim2 }; // the intersection dimension
+
+public:
+    using ctype = typename Dune::PromotionTraits<typename Geometry1::ctype, typename Geometry2::ctype>::PromotedType;
+    using GlobalPosition = Dune::FieldVector<ctype, dimworld>;
+    using IntersectionType = std::vector<GlobalPosition>;
 
-    static constexpr Scalar eps_ = 1.5e-7; // base epsilon for floating point comparisons
+private:
+    static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons
+    using ReferenceElements = typename Dune::ReferenceElements<ctype, dim1>;
 
 public:
     /*!
@@ -80,9 +85,9 @@ public:
      * \param intersection If the geometries collide intersection holds the corner points of
      *        the intersection object in global coordinates.
      */
-    static bool collide(const Geometry1& geo1, const Geometry2& geo2, std::vector<GlobalPosition>& intersection)
+    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, IntersectionType& intersection)
     {
-        static_assert(dimworld == Geometry2::coorddimension, "Can only collide geometries of same coordinate dimension");
+        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
 
         const auto a = geo2.corner(0);
         const auto b = geo2.corner(1);
@@ -91,24 +96,29 @@ public:
         // The initial interval is the whole segment
         // afterward we start clipping the interval
         // by the planes decribed by the facet
-        Scalar tfirst = 0;
-        Scalar tlast = 1;
+        ctype tfirst = 0.0;
+        ctype tlast = 1.0;
 
-        std::vector<std::vector<int>> facets;
-        // sort facet corner so that normal n = (p1-p0)x(p2-p0) always points outwards
-        switch (geo1.corners())
+        const std::vector<std::vector<int>> facets = [&]()
         {
-            // todo compute intersection geometries
-            case 8: // hexahedron
-                facets = {{2, 0, 6, 4}, {1, 3, 5, 7}, {0, 1, 4, 5},
-                          {3, 2, 7, 6}, {1, 0, 3, 2}, {4, 5, 6, 7}};
-                break;
-            case 4: // tetrahedron
-                facets = {{1, 2, 0}, {0, 1, 3}, {0, 3, 2}, {1, 2, 3}};
-                break;
-            default:
-                DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type " << geo1.type() << ", "<< geo1.corners() << " corners.");
-        }
+            std::vector<std::vector<int>> facets;
+            // sort facet corner so that normal n = (p1-p0)x(p2-p0) always points outwards
+            switch (geo1.corners())
+            {
+                // todo compute intersection geometries
+                case 8: // hexahedron
+                    facets = {{2, 0, 6, 4}, {1, 3, 5, 7}, {0, 1, 4, 5},
+                              {3, 2, 7, 6}, {1, 0, 3, 2}, {4, 5, 6, 7}};
+                    break;
+                case 4: // tetrahedron
+                    facets = {{1, 2, 0}, {0, 1, 3}, {0, 3, 2}, {1, 2, 3}};
+                    break;
+                default:
+                    DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type " << geo1.type() << ", "<< geo1.corners() << " corners.");
+            }
+
+            return facets;
+        }();
 
         for (const auto& f : facets)
         {
@@ -120,8 +130,8 @@ public:
             auto n = crossProduct(v0, v1);
             n /= n.two_norm();
 
-            const Scalar denom = n*d;
-            const Scalar dist = n*(a-geo1.corner(f[0]));
+            const ctype denom = n*d;
+            const ctype dist = n*(a-geo1.corner(f[0]));
 
             // if denominator is zero the segment in parallel to
             // the plane. If the distance is positive there is no intersection
@@ -133,7 +143,7 @@ public:
             }
             else // not parallel: compute line-plane intersection
             {
-                const Scalar t = -dist / denom;
+                const ctype t = -dist / denom;
                 // if entering half space cut tfirst if t is larger
                 using std::signbit;
                 if (signbit(denom))
diff --git a/dumux/common/geometry/intersectingentities.hh b/dumux/common/geometry/intersectingentities.hh
new file mode 100644
index 0000000000..0673c61ea5
--- /dev/null
+++ b/dumux/common/geometry/intersectingentities.hh
@@ -0,0 +1,169 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 3 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Algorithms that finds which geometric entites intersect
+ */
+#ifndef DUMUX_INTERSECTING_ENTITIES_HH
+#define DUMUX_INTERSECTING_ENTITIES_HH
+
+#include <cmath>
+#include <type_traits>
+#include <dune/common/fvector.hh>
+#include <dumux/common/math.hh>
+#include <dumux/common/geometry/boundingboxtree.hh>
+#include <dumux/common/geometry/intersectspointgeometry.hh>
+#include <dumux/common/geometry/geometryintersection.hh>
+#include <dumux/common/geometry/boundingboxtreeintersection.hh>
+
+namespace Dumux
+{
+
+//! Compute all intersections between entities and a point
+template<class EntitySet, class ctype, int dimworld>
+inline std::vector<std::size_t>
+intersectingEntities(const Dune::FieldVector<ctype, dimworld>& point,
+                     const BoundingBoxTree<EntitySet>& tree)
+{
+    // Call the recursive find function to find candidates
+    std::vector<std::size_t> entities;
+    intersectingEntities(point, tree, tree.numBoundingBoxes() - 1, entities);
+    return entities;
+}
+
+//! Compute collisions with point for a node of the bounding box tree
+template<class EntitySet, class ctype, int dimworld>
+void intersectingEntities(const Dune::FieldVector<ctype, dimworld>& point,
+                          const BoundingBoxTree<EntitySet>& tree,
+                          std::size_t node,
+                          std::vector<std::size_t>& entities)
+{
+    // Get the bounding box for the current node
+    const auto& bBox = tree.getBoundingBoxNode(node);
+
+    // if the point is not in the bounding box we can stop
+    if (!intersectsPointBoundingBox(point, tree.getBoundingBoxCoordinates(node))) return;
+
+    // now we know it's inside
+    // if the box is a leaf do the primitive test.
+    else if (tree.isLeaf(bBox, node))
+    {
+        const std::size_t entityIdx = bBox.child1;
+        const auto geometry = tree.entitySet().entity(entityIdx).geometry();
+        // if the primitive is positive it intersects the actual geometry, add the entity to the list
+        if (intersectsPointGeometry(point, geometry))
+            entities.push_back(entityIdx);
+    }
+
+    // No leaf. Check both children nodes.
+    else
+    {
+        intersectingEntities(point, tree, bBox.child0, entities);
+        intersectingEntities(point, tree, bBox.child1, entities);
+    }
+}
+
+//! Compute all intersections between two bounding box trees
+template<class EntitySet0, class EntitySet1>
+inline std::vector<BoundingBoxTreeIntersection<EntitySet0, EntitySet1>>
+intersectingEntities(const BoundingBoxTree<EntitySet0>& treeA,
+                     const BoundingBoxTree<EntitySet1>& treeB)
+{
+    // check if the world dimensions match
+    static_assert(int(EntitySet0::dimensionworld) == int(EntitySet1::dimensionworld),
+        "Can only intersect bounding box trees of same world dimension");
+
+    // Create data structure for return type
+    std::vector<BoundingBoxTreeIntersection<EntitySet0, EntitySet1>> intersections;
+
+    // Call the recursive find function to find candidates
+    intersectingEntities(treeA, treeB,
+                         treeA.numBoundingBoxes() - 1,
+                         treeB.numBoundingBoxes() - 1,
+                         intersections);
+
+    return intersections;
+}
+
+//! Compute all intersections between two bounding box tree nodes recursively
+template<class EntitySet0, class EntitySet1>
+void intersectingEntities(const BoundingBoxTree<EntitySet0>& treeA,
+                          const BoundingBoxTree<EntitySet1>& treeB,
+                          std::size_t nodeA, std::size_t nodeB,
+                          std::vector<BoundingBoxTreeIntersection<EntitySet0, EntitySet1>>& intersections)
+{
+    // Get the bounding box for the current node
+    const auto& bBoxA = treeA.getBoundingBoxNode(nodeA);
+    const auto& bBoxB = treeB.getBoundingBoxNode(nodeB);
+
+    // if the two bounding boxes of the current nodes don't intersect we can stop searching
+    static constexpr int dimworld = EntitySet0::dimensionworld;
+    if (!intersectsBoundingBoxBoundingBox<dimworld>(treeA.getBoundingBoxCoordinates(nodeA),
+                                                    treeB.getBoundingBoxCoordinates(nodeB)))
+        return;
+
+    // Check if we have a leaf in treeA or treeB
+    const bool isLeafA = treeA.isLeaf(bBoxA, nodeA);
+    const bool isLeafB = treeB.isLeaf(bBoxB, nodeB);
+
+    // If both boxes are leaves do the primitive test
+    if (isLeafA && isLeafB)
+    {
+        const auto eIdxA = bBoxA.child1;
+        const auto eIdxB = bBoxB.child1;
+
+        const auto geometryA = treeA.entitySet().entity(eIdxA).geometry();
+        const auto geometryB = treeB.entitySet().entity(eIdxB).geometry();
+
+        using IntersectionAlgorithm = GeometryIntersection< std::decay_t<decltype(geometryA)>,
+                                                            std::decay_t<decltype(geometryB)> >;
+        typename IntersectionAlgorithm::IntersectionType intersection;
+        if (IntersectionAlgorithm::intersection(geometryA, geometryB, intersection))
+            intersections.emplace_back(eIdxA, eIdxB, std::move(intersection));
+    }
+
+    // if we reached the leaf in treeA, just continue in treeB
+    else if (isLeafA)
+    {
+        intersectingEntities(treeA, treeB, nodeA, bBoxB.child0, intersections);
+        intersectingEntities(treeA, treeB, nodeA, bBoxB.child1, intersections);
+    }
+
+    // if we reached the leaf in treeB, just continue in treeA
+    else if (isLeafB)
+    {
+        intersectingEntities(treeA, treeB, bBoxA.child0, nodeB, intersections);
+        intersectingEntities(treeA, treeB, bBoxA.child1, nodeB, intersections);
+    }
+
+    // we know now that both trees didn't reach the leaf yet so
+    // we continue with the larger tree first (bigger node number)
+    else if (nodeA > nodeB)
+    {
+        intersectingEntities(treeA, treeB, bBoxA.child0, nodeB, intersections);
+        intersectingEntities(treeA, treeB, bBoxA.child1, nodeB, intersections);
+    }
+    else
+    {
+        intersectingEntities(treeA, treeB, nodeA, bBoxB.child0, intersections);
+        intersectingEntities(treeA, treeB, nodeA, bBoxB.child1, intersections);
+    }
+}
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/common/geometry/intersectspointgeometry.hh b/dumux/common/geometry/intersectspointgeometry.hh
new file mode 100644
index 0000000000..4b13fd0359
--- /dev/null
+++ b/dumux/common/geometry/intersectspointgeometry.hh
@@ -0,0 +1,111 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 3 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Detect if a point intersects a geometry
+ */
+#ifndef DUMUX_INTERSECTS_POINT_GEOMETRY_HH
+#define DUMUX_INTERSECTS_POINT_GEOMETRY_HH
+
+#include <cmath>
+#include <dune/common/exceptions.hh>
+#include <dune/common/fvector.hh>
+
+#include "intersectspointsimplex.hh"
+
+namespace Dumux {
+
+//! Find out whether a point is inside a three-dimensional geometry
+template <class ctype, int dimworld, class Geometry, typename std::enable_if_t<(Geometry::mydimension == 3), int> = 0>
+bool intersectsPointGeometry(const Dune::FieldVector<ctype, dimworld>& point, const Geometry& g)
+{
+    // get the g type
+    const auto type = g.type();
+
+    // if it's a tetrahedron we can check directly
+    if (type.isTetrahedron())
+        return intersectsPointSimplex(point, g.corner(0), g.corner(1), g.corner(2), g.corner(3));
+
+    // split hexahedrons into five tetrahedrons
+    else if (type.isHexahedron())
+    {
+        if (intersectsPointSimplex(point, g.corner(0), g.corner(1), g.corner(3), g.corner(5))) return true;
+        if (intersectsPointSimplex(point, g.corner(0), g.corner(5), g.corner(6), g.corner(4))) return true;
+        if (intersectsPointSimplex(point, g.corner(5), g.corner(3), g.corner(6), g.corner(7))) return true;
+        if (intersectsPointSimplex(point, g.corner(0), g.corner(3), g.corner(2), g.corner(6))) return true;
+        if (intersectsPointSimplex(point, g.corner(5), g.corner(3), g.corner(0), g.corner(6))) return true;
+        return false;
+    }
+
+    // split pyramids into two tetrahedrons
+    else if (type.isPyramid())
+    {
+        if (intersectsPointSimplex(point, g.corner(0), g.corner(1), g.corner(2), g.corner(4))) return true;
+        if (intersectsPointSimplex(point, g.corner(1), g.corner(3), g.corner(2), g.corner(4))) return true;
+        return false;
+    }
+
+    // split prisms into three tetrahedrons
+    else if (type.isPrism())
+    {
+        if (intersectsPointSimplex(point, g.corner(0), g.corner(1), g.corner(2), g.corner(4))) return true;
+        if (intersectsPointSimplex(point, g.corner(3), g.corner(0), g.corner(2), g.corner(4))) return true;
+        if (intersectsPointSimplex(point, g.corner(2), g.corner(5), g.corner(3), g.corner(4))) return true;
+        return false;
+    }
+
+    else
+        DUNE_THROW(Dune::NotImplemented,
+                   "Intersection for point and geometry type "
+                   << type << " in " << dimworld << "-dimensional world.");
+}
+
+//! Find out whether a point is inside a two-dimensional geometry
+template <class ctype, int dimworld, class Geometry, typename std::enable_if_t<(Geometry::mydimension == 2), int> = 0>
+bool intersectsPointGeometry(const Dune::FieldVector<ctype, dimworld>& point, const Geometry& g)
+{
+    // get the g type
+    const auto type = g.type();
+
+    // if it's a triangle we can check directly
+    if (type.isTriangle())
+        return intersectsPointSimplex(point, g.corner(0), g.corner(1), g.corner(2));
+
+    // split quadrilaterals into two triangles
+    else if (type.isQuadrilateral())
+    {
+        if (intersectsPointSimplex(point, g.corner(0), g.corner(1), g.corner(3))) return true;
+        if (intersectsPointSimplex(point, g.corner(0), g.corner(3), g.corner(2))) return true;
+        return false;
+    }
+
+    else
+        DUNE_THROW(Dune::NotImplemented,
+                   "Intersection for point and geometry type "
+                   << type << " in " << dimworld << "-dimensional world.");
+}
+
+//! Find out whether a point is inside a one-dimensional geometry
+template <class ctype, int dimworld, class Geometry, typename std::enable_if_t<(Geometry::mydimension == 1), int> = 0>
+bool intersectsPointGeometry(const Dune::FieldVector<ctype, dimworld>& point, const Geometry& g)
+{
+    return intersectsPointSimplex(point, g.corner(0), g.corner(1));
+}
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/common/geometry/intersectspointsimplex.hh b/dumux/common/geometry/intersectspointsimplex.hh
new file mode 100644
index 0000000000..601f189057
--- /dev/null
+++ b/dumux/common/geometry/intersectspointsimplex.hh
@@ -0,0 +1,249 @@
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 3 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Detect if a point intersects a simplex (including boundary)
+ */
+#ifndef DUMUX_INTERSECTS_POINT_SIMPLEX_HH
+#define DUMUX_INTERSECTS_POINT_SIMPLEX_HH
+
+#include <cmath>
+#include <dune/common/fvector.hh>
+#include <dumux/common/math.hh>
+
+namespace Dumux {
+
+//! Find out whether a point is inside a tetrahedron (p0, p1, p2, p3) (dimworld is 3)
+template<class ctype, int dimworld, typename std::enable_if_t<(dimworld == 3), int> = 0>
+bool intersectsPointSimplex(const Dune::FieldVector<ctype, dimworld>& point,
+                            const Dune::FieldVector<ctype, dimworld>& p0,
+                            const Dune::FieldVector<ctype, dimworld>& p1,
+                            const Dune::FieldVector<ctype, dimworld>& p2,
+                            const Dune::FieldVector<ctype, dimworld>& p3)
+{
+    // Algorithm from http://www.blackpawn.com/texts/pointinpoly/
+    // See also "Real-Time Collision Detection" by Christer Ericson.
+    using GlobalPosition = Dune::FieldVector<ctype, dimworld>;
+    static constexpr ctype eps_ = 1.0e-7;
+
+    // put the tetrahedron points in an array
+    const GlobalPosition *p[4] = {&p0, &p1, &p2, &p3};
+
+    // iterate over all faces
+    for (int i = 0; i < 4; ++i)
+    {
+        // compute all the vectors from vertex (local index 0) to the other points
+        const GlobalPosition v1 = *p[(i + 1)%4] - *p[i];
+        const GlobalPosition v2 = *p[(i + 2)%4] - *p[i];
+        const GlobalPosition v3 = *p[(i + 3)%4] - *p[i];
+        const GlobalPosition v = point - *p[i];
+        // compute the normal to the facet (cross product)
+        GlobalPosition n1 = crossProduct(v1, v2);
+        n1 /= n1.two_norm();
+        // find out on which side of the plane v and v3 are
+        const auto t1 = n1.dot(v);
+        const auto t2 = n1.dot(v3);
+        // If the point is not exactly on the plane the
+        // points have to be on the same side
+        const auto eps = eps_ * v1.two_norm();
+        if ((t1 > eps || t1 < -eps) && std::signbit(t1) != std::signbit(t2))
+            return false;
+    }
+    return true;
+}
+
+//! Find out whether a point is inside a triangle (p0, p1, p2) (dimworld is 3)
+template<class ctype, int dimworld, typename std::enable_if_t<(dimworld == 3), int> = 0>
+bool intersectsPointSimplex(const Dune::FieldVector<ctype, dimworld>& point,
+                            const Dune::FieldVector<ctype, dimworld>& p0,
+                            const Dune::FieldVector<ctype, dimworld>& p1,
+                            const Dune::FieldVector<ctype, dimworld>& p2)
+{
+    // Algorithm from http://www.blackpawn.com/texts/pointinpoly/
+    // See also "Real-Time Collision Detection" by Christer Ericson.
+    using GlobalPosition = Dune::FieldVector<ctype, dimworld>;
+    static constexpr ctype eps_ = 1.0e-7;
+
+    // compute the vectors of the edges and the vector point-p0
+    const GlobalPosition v1 = p0 - p2;
+    const GlobalPosition v2 = p1 - p0;
+    const GlobalPosition v3 = p2 - p1;
+    const GlobalPosition v = point - p0;
+
+    // compute the normal of the triangle
+    const GlobalPosition n = crossProduct(v1, v2);
+
+    // first check if we are in the plane of the triangle
+    // if not we can return early
+    const double t = v.dot(n);
+    using std::abs;
+    if (abs(t) > v1.two_norm()*eps_) // take |v1| as scale
+        return false;
+
+    // compute the normal to the triangle made of point and first edge
+    // the dot product of this normal and the triangle normal has to
+    // be positive because we defined the edges in the right orientation
+    const GlobalPosition n1 = crossProduct(v, v1);
+    const double t1 = n.dot(n1);
+    if (t1 < 0) return false;
+
+    const GlobalPosition n2 = crossProduct(v, v2);
+    const double t2 = n.dot(n2);
+    if (t2 < 0) return false;
+
+    const GlobalPosition n3 = crossProduct(v, v3);
+    const double t3 = n.dot(n3);
+    if (t3 < 0) return false;
+
+    return true;
+}
+
+//! Find out whether a point is inside a triangle (p0, p1, p2) (dimworld is 2)
+template<class ctype, int dimworld, typename std::enable_if_t<(dimworld == 2), int> = 0>
+bool intersectsPointSimplex(const Dune::FieldVector<ctype, dimworld>& point,
+                            const Dune::FieldVector<ctype, dimworld>& p0,
+                            const Dune::FieldVector<ctype, dimworld>& p1,
+                            const Dune::FieldVector<ctype, dimworld>& p2)
+{
+    static constexpr ctype eps_ = 1.0e-7;
+
+    // Use barycentric coordinates
+    const ctype A = 0.5*(-p1[1]*p2[0] + p0[1]*(p2[0] - p1[0])
+                         +p1[0]*p2[1] + p0[0]*(p1[1] - p2[1]));
+    const ctype sign = std::copysign(1.0, A);
+    const ctype s = sign*(p0[1]*p2[0] + point[0]*(p2[1]-p0[1])
+                         -p0[0]*p2[1] + point[1]*(p0[0]-p2[0]));
+    const ctype t = sign*(p0[0]*p1[1] + point[0]*(p0[1]-p1[1])
+                         -p0[1]*p1[0] + point[1]*(p1[0]-p0[0]));
+    const ctype eps = sign*A*eps_;
+
+    return (s > -eps
+            && t > -eps
+            && (s + t) < 2*A*sign + eps);
+}
+
+//! Find out whether a point is inside an interval (p0, p1) (dimworld is 3)
+template<class ctype, int dimworld, typename std::enable_if_t<(dimworld == 3), int> = 0>
+bool intersectsPointSimplex(const Dune::FieldVector<ctype, dimworld>& point,
+                            const Dune::FieldVector<ctype, dimworld>& p0,
+                            const Dune::FieldVector<ctype, dimworld>& p1)
+{
+    using GlobalPosition = Dune::FieldVector<ctype, dimworld>;
+    static constexpr ctype eps_ = 1.0e-7;
+
+    // compute the vectors between p0 and the other points
+    const GlobalPosition v1 = p1 - p0;
+    const GlobalPosition v2 = point - p0;
+
+    // check if point and p0 are the same
+    const ctype v1norm = v1.two_norm();
+    const ctype v2norm = v2.two_norm();
+    if (v2norm < v1norm*eps_)
+        return true;
+
+    // if not check if p0 and p1 are the same
+    // then we know that point is not in the interval
+    if (v1norm < eps_)
+        return false;
+
+    // if the cross product is zero the points are on a line
+    const GlobalPosition n = crossProduct(v1, v2);
+
+    // early return if the vector length is larger than zero
+    if (n.two_norm() > v1norm*eps_)
+        return false;
+
+    // we know the points are aligned
+    // if the dot product is positive and the length in range
+    // the point is in the interval
+    return (v1.dot(v2) > 0.0 && v2norm < v1norm*(1 + eps_));
+}
+
+//! Find out whether a point is inside an interval (p0, p1) (dimworld is 2)
+template<class ctype, int dimworld, typename std::enable_if_t<(dimworld == 2), int> = 0>
+bool intersectsPointSimplex(const Dune::FieldVector<ctype, dimworld>& point,
+                            const Dune::FieldVector<ctype, dimworld>& p0,
+                            const Dune::FieldVector<ctype, dimworld>& p1)
+{
+    using GlobalPosition = Dune::FieldVector<ctype, dimworld>;
+    static constexpr ctype eps_ = 1.0e-7;
+
+    // compute the vectors between p0 and the other points
+    const GlobalPosition v1 = p1 - p0;
+    const GlobalPosition v2 = point - p0;
+
+    // check if point and p0 are the same
+    const ctype v1norm = v1.two_norm();
+    const ctype v2norm = v2.two_norm();
+    if (v2norm < v1norm*eps_)
+        return true;
+
+    // if not check if p0 and p1 are the same
+    // then we know that point is not in the interval
+    if (v1norm < eps_)
+        return false;
+
+    // if the cross product is zero the points are on a line
+    const ctype n = crossProduct(v1, v2);
+
+    // early return if the cross product is larger than zero
+    using std::abs;
+    if (abs(n) > v1norm*eps_)
+        return false;
+
+    // we know the points are aligned
+    // if the dot product is positive and the length in range
+    // the point is in the interval
+    return (v1.dot(v2) > 0.0 && v2norm < v1norm*(1 + eps_));
+}
+
+//! Find out whether a point is inside an interval (p0, p1) (dimworld is 1)
+template<class ctype, int dimworld, typename std::enable_if_t<(dimworld == 1), int> = 0>
+bool intersectsPointSimplex(const Dune::FieldVector<ctype, dimworld>& point,
+                            const Dune::FieldVector<ctype, dimworld>& p0,
+                            const Dune::FieldVector<ctype, dimworld>& p1)
+{
+    static constexpr ctype eps_ = 1.0e-7;
+
+    // sort the interval so interval[1] is the end and interval[0] the start
+    const ctype *interval[2] = {&p0[0], &p1[0]};
+    if (*interval[0] > *interval[1])
+        std::swap(interval[0], interval[1]);
+
+    const ctype v1 = point[0] - *interval[0];
+    const ctype v2 = *interval[1] - *interval[0]; // always positive
+
+    // the coordinates are the same
+    using std::abs;
+    if (abs(v1) < v2*eps_)
+        return true;
+
+    // the point doesn't coincide with p0
+    // so if p0 and p1 are equal it's not inside
+    if (v2 < 1.0e-30)
+        return false;
+
+    // the point is inside if the length is
+    // smaller than the interval length and the
+    // sign of v1 & v2 are the same
+    using std::signbit;
+    return (!signbit(v1) && abs(v1) < v2*(1.0 + eps_));
+}
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/common/pointsource.hh b/dumux/common/pointsource.hh
index 2b429d5df2..bcda706a4d 100644
--- a/dumux/common/pointsource.hh
+++ b/dumux/common/pointsource.hh
@@ -29,7 +29,9 @@
 
 #include <dumux/common/properties.hh>
 #include <dumux/common/parameters.hh>
-#include <dumux/common/boundingboxtree.hh>
+#include <dumux/common/geometry/boundingboxtree.hh>
+#include <dumux/common/geometry/intersectspointgeometry.hh>
+#include <dumux/common/geometry/intersectingentities.hh>
 
 #include <dumux/discretization/methods.hh>
 
@@ -67,7 +69,7 @@ public:
     //! Constructor for sol dependent point sources, when there is no
     // value known at the time of initialization
     PointSource(GlobalPosition pos)
-      : values_(0), pos_(pos), embeddings_(1) {}
+      : values_(0.0), pos_(pos), embeddings_(1) {}
 
     //! Convenience += operator overload modifying only the values
     PointSource& operator+= (Scalar s)
@@ -177,7 +179,7 @@ public:
     //! Constructor for sol dependent point sources, when there is no
     // value known at the time of initialization
     IdPointSource(GlobalPosition pos, IdType id)
-      : ParentType(pos, PrimaryVariables(0)), id_(id) {}
+      : ParentType(pos, PrimaryVariables(0.0)), id_(id) {}
 
     //! return the sources identifier
     IdType id() const
@@ -232,7 +234,7 @@ public:
     // value known at the time of initialization
     SolDependentPointSource(GlobalPosition pos,
                             ValueFunction valueFunction)
-      : ParentType(pos, PrimaryVariables(0)), valueFunction_(valueFunction) {}
+      : ParentType(pos, PrimaryVariables(0.0)), valueFunction_(valueFunction) {}
 
     //! an update function called before adding the value
     // to the local residual in the problem in scvPointSources
@@ -293,7 +295,7 @@ public:
         for (auto&& source : sources)
         {
             // compute in which elements the point source falls
-            std::vector<unsigned int> entities = boundingBoxTree.computeEntityCollisions(source.position());
+            const auto entities = intersectingEntities(source.position(), boundingBoxTree);
             // split the source values equally among all concerned entities
             source.setEmbeddings(entities.size()*source.embeddings());
             // loop over all concernes elements
@@ -302,7 +304,7 @@ public:
                 if(isBox)
                 {
                     // check in which subcontrolvolume(s) we are
-                    const auto element = boundingBoxTree.entity(eIdx);
+                    const auto element = boundingBoxTree.entitySet().entity(eIdx);
                     auto fvGeometry = localView(fvGridGeometry);
                     fvGeometry.bindElement(element);
 
@@ -311,7 +313,7 @@ public:
                     std::vector<unsigned int> scvIndices;
                     for (auto&& scv : scvs(fvGeometry))
                     {
-                        if (BoundingBoxTreeHelper<dimworld>::pointInGeometry(scv.geometry(), globalPos))
+                        if (intersectsPointGeometry(globalPos, scv.geometry()))
                             scvIndices.push_back(scv.indexInElement());
                     }
                     // for all scvs that where tested positiv add the point sources
diff --git a/dumux/discretization/basefvgridgeometry.hh b/dumux/discretization/basefvgridgeometry.hh
index 3787db93d6..8a674d4412 100644
--- a/dumux/discretization/basefvgridgeometry.hh
+++ b/dumux/discretization/basefvgridgeometry.hh
@@ -27,7 +27,9 @@
 #include <dune/grid/common/mcmgmapper.hh>
 
 #include <dumux/common/properties.hh>
-#include <dumux/common/boundingboxtree.hh>
+#include <dumux/common/entitymap.hh>
+#include <dumux/common/geometry/boundingboxtree.hh>
+#include <dumux/common/geometry/geometricentityset.hh>
 
 namespace Dumux
 {
@@ -44,7 +46,9 @@ class BaseFVGridGeometry
     using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
     using ElementMapper = typename GET_PROP_TYPE(TypeTag, ElementMapper);
     using VertexMapper = typename GET_PROP_TYPE(TypeTag, VertexMapper);
-    using BoundingBoxTree = Dumux::BoundingBoxTree<GridView>;
+    using ElementMap = EntityMap<GridView, 0>;
+    using ElementSet = GridViewGeometricEntitySet<GridView, 0>;
+    using BoundingBoxTree = Dumux::BoundingBoxTree<ElementSet>;
 
     static const int dim = GridView::dimension;
     static const int dimWorld = GridView::dimensionworld;
@@ -89,8 +93,9 @@ public:
         //! Compute the bouding box of the entire domain, for e.g. setting boundary conditions
         computeGlobalBoundingBox_();
 
-        //! reset bounding box tree until requested the next time
-        boundingBoxTree_.reset(nullptr);
+        //! reset bounding box tree and the element map until requested the next time
+        boundingBoxTree_.release();
+        elementMap_.reset();
     }
 
     /*!
@@ -126,23 +131,27 @@ public:
     /*!
      * \brief Returns the bounding box tree of the grid
      */
-    BoundingBoxTree& boundingBoxTree()
+    const BoundingBoxTree& boundingBoxTree() const
     {
         if(!boundingBoxTree_)
-            boundingBoxTree_ = std::make_unique<BoundingBoxTree>(gridView_);
+        {
+            elementMap(); // make sure the element map is built
+            boundingBoxTree_ = std::make_unique<BoundingBoxTree>
+                                    ( std::make_shared<ElementSet>(gridView_, elementMapper(), elementMap_) );
+        }
 
         return *boundingBoxTree_;
     }
 
     /*!
-     * \brief Returns the bounding box tree of the grid
+     * \brief Returns the element index to element map
      */
-    const BoundingBoxTree& boundingBoxTree() const
+    const ElementMap& elementMap() const
     {
-        if(!boundingBoxTree_)
-            boundingBoxTree_ = std::make_unique<BoundingBoxTree>(gridView_);
+        if(!elementMap_)
+            elementMap_ = std::make_shared<ElementMap>(gridView_.grid(), elementMapper_);
 
-        return *boundingBoxTree_;
+        return *elementMap_;
     }
 
     /*!
@@ -197,6 +206,9 @@ private:
     // the bounding box tree of the grid view for effecient element intersections
     mutable std::unique_ptr<BoundingBoxTree> boundingBoxTree_;
 
+    // a map from element index to elements (needed in the bounding box tree and for assembling cell-centered discretization)
+    mutable std::shared_ptr<ElementMap> elementMap_;
+
     // the bounding box of the whole domain
     GlobalPosition bBoxMin_;
     GlobalPosition bBoxMax_;
diff --git a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh
index 90f1fa01aa..858b4fec5b 100644
--- a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh
+++ b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh
@@ -22,14 +22,12 @@
  *        This builds up the sub control volumes and sub control volume faces
  *        for each element.
  */
-#ifndef DUMUX_DISCRETIZATION_CC_MPFA_FV_GRID_GEOMETRY_BASE_HH
-#define DUMUX_DISCRETIZATION_CC_MPFA_FV_GRID_GEOMETRY_BASE_HH
+#ifndef DUMUX_DISCRETIZATION_CC_MPFA_FV_GRID_GEOMETRY_HH
+#define DUMUX_DISCRETIZATION_CC_MPFA_FV_GRID_GEOMETRY_HH
 
 #include <dune/geometry/multilineargeometry.hh>
 #include <dune/geometry/referenceelements.hh>
 
-#include <dumux/common/elementmap.hh>
-
 #include <dumux/discretization/basefvgridgeometry.hh>
 #include <dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh>
 #include <dumux/discretization/cellcentered/mpfa/connectivitymap.hh>
@@ -81,7 +79,6 @@ public:
     //! Per default, we use the secondary IVs at branching points & boundaries
     explicit CCMpfaFVGridGeometry(const GridView& gridView)
              : ParentType(gridView)
-             , elementMap_(gridView)
              , secondaryIvIndicator_([] (const Element& e, const Intersection& is, bool isBranching)
                                         { return is.boundary() || isBranching; } )
              {}
@@ -89,7 +86,6 @@ public:
      //! Constructor with user-defined indicator function for secondary interaction volumes
      explicit CCMpfaFVGridGeometry(const GridView& gridView, const SecondaryIvIndicator& indicator)
               : ParentType(gridView)
-              , elementMap_(gridView)
               , secondaryIvIndicator_(indicator)
               {}
 
@@ -126,13 +122,13 @@ public:
      * \brief Gets an element from a global element index.
      */
     Element element(IndexType eIdx) const
-    { return elementMap_.element(eIdx); }
+    { return this->elementMap()[eIdx]; }
 
     /*!
      * \brief Gets an element from a sub control volume contained in it.
      */
     Element element(const SubControlVolume& scv) const
-    { return elementMap_.element(scv.elementIndex()); }
+    { return this->elementMap()[scv.elementIndex()]; }
 
     /*!
      * \brief Returns true if primary interaction volumes are used around a given vertex,
@@ -183,7 +179,6 @@ public:
         scvs_.resize(numScvs);
         scvfs_.reserve(numScvf);
         scvfIndicesOfScv_.resize(numScvs);
-        elementMap_.resize(numScvs);
 
         // Some methods require to use a second type of interaction volume, e.g.
         // around vertices on the boundary or branching points (surface grids)
@@ -206,9 +201,6 @@ public:
             // the element geometry
             auto elementGeometry = element.geometry();
 
-            // fill the element map with seeds
-            elementMap_[eIdx] = element.seed();
-
             // The local scvf index set
             std::vector<IndexType> scvfIndexSet;
             scvfIndexSet.reserve(MpfaHelper::getNumLocalScvfs(elementGeometry.type()));
@@ -415,8 +407,7 @@ public:
     { return ivIndexSets_; }
 
 private:
-    // mappers
-    Dumux::ElementMap<GridView> elementMap_;
+    // connectivity map for efficient assembly
     ConnectivityMap connectivityMap_;
 
     // the finite volume grid geometries
@@ -472,7 +463,6 @@ public:
     //! Per default, we use the secondary IVs at branching points & boundaries
     explicit CCMpfaFVGridGeometry(const GridView& gridView)
              : ParentType(gridView)
-             , elementMap_(gridView)
              , secondaryIvIndicator_([] (const Element& e, const Intersection& is, bool isBranching)
                                         { return is.boundary() || isBranching; } )
              {}
@@ -480,7 +470,6 @@ public:
      //! Constructor with user-defined indicator function for secondary interaction volumes
      explicit CCMpfaFVGridGeometry(const GridView& gridView, const SecondaryIvIndicator& indicator)
               : ParentType(gridView)
-              , elementMap_(gridView)
               , secondaryIvIndicator_(indicator)
               {}
 
@@ -517,13 +506,13 @@ public:
      * \brief Gets an element from a global element index.
      */
     Element element(IndexType eIdx) const
-    { return elementMap_.element(eIdx); }
+    { return this->elementMap()[eIdx]; }
 
     /*!
      * \brief Gets an element from a sub control volume contained in it.
      */
     Element element(const SubControlVolume& scv) const
-    { return elementMap_.element(scv.elementIndex()); }
+    { return this->elementMap()[scv.elementIndex()]; }
 
     /*!
      * \brief Returns true if primary interaction volumes are used around a given vertex,
@@ -579,7 +568,6 @@ public:
         numScvs_ = numDofs();
         scvfIndicesOfScv_.resize(numScvs_);
         neighborVolVarIndices_.resize(numScvs_);
-        elementMap_.resize(numScvs_);
 
         // Some methods require to use a second type of interaction volume, e.g.
         // around vertices on the boundary or branching points (surface grids)
@@ -603,9 +591,6 @@ public:
             // the element geometry
             auto elementGeometry = element.geometry();
 
-            // fill the element map with seeds
-            elementMap_[eIdx] = element.seed();
-
             // the element-wise index sets for finite volume geometry
             const auto numLocalFaces = MpfaHelper::getNumLocalScvfs(elementGeometry.type());
             std::vector<IndexType> scvfsIndexSet;
@@ -746,8 +731,7 @@ public:
     { return ivIndexSets_; }
 
 private:
-    // mappers
-    Dumux::ElementMap<GridView> elementMap_;
+    // connectivity map for efficient assembly
     ConnectivityMap connectivityMap_;
 
     // containers storing the global data
diff --git a/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh
index 8add925436..3373a48799 100644
--- a/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh
+++ b/dumux/discretization/cellcentered/tpfa/fvgridgeometry.hh
@@ -27,9 +27,6 @@
 
 #include <dune/common/version.hh>
 
-#include <dumux/common/elementmap.hh>
-#include <dumux/common/boundingboxtree.hh>
-
 #include <dumux/discretization/basefvgridgeometry.hh>
 #include <dumux/discretization/cellcentered/tpfa/fvelementgeometry.hh>
 #include <dumux/discretization/cellcentered/connectivitymap.hh>
@@ -74,7 +71,6 @@ public:
     //! Constructor
     CCTpfaFVGridGeometry(const GridView& gridView)
     : ParentType(gridView)
-    , elementMap_(gridView)
     {}
 
     //! the element mapper is the dofMapper
@@ -106,11 +102,11 @@ public:
 
     // Get an element from a sub control volume contained in it
     Element element(const SubControlVolume& scv) const
-    { return elementMap_.element(scv.elementIndex()); }
+    { return this->elementMap()[scv.elementIndex()]; }
 
     // Get an element from a global element index
     Element element(IndexType eIdx) const
-    { return elementMap_.element(eIdx); }
+    { return this->elementMap()[eIdx]; }
 
     //! update all fvElementGeometries (do this again after grid adaption)
     void update()
@@ -122,7 +118,6 @@ public:
         scvfs_.clear();
         scvfIndicesOfScv_.clear();
         flipScvfIndices_.clear();
-        elementMap_.clear();
 
         // determine size of containers
         IndexType numScvs = numDofs();
@@ -131,7 +126,6 @@ public:
             numScvf += element.subEntities(1);
 
         // reserve memory
-        elementMap_.resize(numScvs);
         scvs_.resize(numScvs);
         scvfs_.reserve(numScvf);
         scvfIndicesOfScv_.resize(numScvs);
@@ -144,9 +138,6 @@ public:
             const auto eIdx = this->elementMapper().index(element);
             scvs_[eIdx] = SubControlVolume(element.geometry(), eIdx);
 
-            // fill the element map with seeds
-            elementMap_[eIdx] = element.seed();
-
             // the element-wise index sets for finite volume geometry
             std::vector<IndexType> scvfsIndexSet;
             scvfsIndexSet.reserve(element.subEntities(1));
@@ -294,9 +285,8 @@ private:
         DUNE_THROW(Dune::InvalidStateException, "No flipped version of this scvf found!");
     }
 
-    // mappers
+    // connectivity map for efficient assembly
     ConnectivityMap connectivityMap_;
-    Dumux::ElementMap<GridView> elementMap_;
 
     // containers storing the global data
     std::vector<SubControlVolume> scvs_;
@@ -332,7 +322,6 @@ public:
     //! Constructor
     CCTpfaFVGridGeometry(const GridView& gridView)
     : ParentType(gridView)
-    , elementMap_(gridView)
     {}
 
     //! the element mapper is the dofMapper
@@ -364,11 +353,11 @@ public:
 
     // Get an element from a sub control volume contained in it
     Element element(const SubControlVolume& scv) const
-    { return elementMap_.element(scv.elementIndex()); }
+    { return this->elementMap()[scv.elementIndex()]; }
 
     // Get an element from a global element index
     Element element(IndexType eIdx) const
-    { return elementMap_.element(eIdx); }
+    { return this->elementMap()[eIdx]; }
 
     //! update all fvElementGeometries (do this again after grid adaption)
     void update()
@@ -376,7 +365,6 @@ public:
         ParentType::update();
 
         // clear local data
-        elementMap_.clear();
         scvfIndicesOfScv_.clear();
         neighborVolVarIndices_.clear();
 
@@ -384,7 +372,6 @@ public:
         numScvs_ = numDofs();
         numScvf_ = 0;
         numBoundaryScvf_ = 0;
-        elementMap_.resize(numScvs_);
         scvfIndicesOfScv_.resize(numScvs_);
         neighborVolVarIndices_.resize(numScvs_);
 
@@ -393,9 +380,6 @@ public:
         {
             const auto eIdx = this->elementMapper().index(element);
 
-            // fill the element map with seeds
-            elementMap_[eIdx] = element.seed();
-
             // the element-wise index sets for finite volume geometry
             auto numLocalFaces = element.subEntities(1);
             std::vector<IndexType> scvfsIndexSet;
@@ -489,8 +473,7 @@ private:
     IndexType numScvf_;
     IndexType numBoundaryScvf_;
 
-    // mappers
-    Dumux::ElementMap<GridView> elementMap_;
+    // connectivity map for efficient assembly
     ConnectivityMap connectivityMap_;
 
     // vectors that store the global data
diff --git a/dumux/discretization/staggered/fvgridgeometry.hh b/dumux/discretization/staggered/fvgridgeometry.hh
index d18c28c6bd..e1df6246c7 100644
--- a/dumux/discretization/staggered/fvgridgeometry.hh
+++ b/dumux/discretization/staggered/fvgridgeometry.hh
@@ -26,9 +26,7 @@
 #define DUMUX_DISCRETIZATION_STAGGERED_GLOBAL_FVGEOMETRY_HH
 
 #include <dumux/common/properties.hh>
-#include <dumux/common/elementmap.hh>
 #include <dumux/discretization/basefvgridgeometry.hh>
-#include <dumux/common/boundingboxtree.hh>
 #include <dumux/discretization/staggered/connectivitymap.hh>
 
 namespace Dumux
@@ -72,7 +70,8 @@ class StaggeredFVGridGeometry<TypeTag, true> : public BaseFVGridGeometry<TypeTag
 public:
     //! Constructor
     StaggeredFVGridGeometry(const GridView& gridView)
-    : ParentType(gridView), elementMap_(gridView), intersectionMapper_(gridView) {}
+    : ParentType(gridView)
+    , intersectionMapper_(gridView) {}
 
     //! The total number of sub control volumes
     std::size_t numScv() const
@@ -110,11 +109,11 @@ public:
 
     // Get an element from a sub control volume contained in it
     Element element(const SubControlVolume& scv) const
-    { return elementMap_.element(scv.elementIndex()); }
+    { return this->elementMap()[scv.elementIndex()]; }
 
     // Get an element from a global element index
     Element element(IndexType eIdx) const
-    { return elementMap_.element(eIdx); }
+    { return this->elementMap()[eIdx]; }
 
     //! update all fvElementGeometries (do this again after grid adaption)
     void update()
@@ -123,7 +122,6 @@ public:
         scvs_.clear();
         scvfs_.clear();
         scvfIndicesOfScv_.clear();
-        elementMap_.clear();
         intersectionMapper_.update();
 
         // determine size of containers
@@ -133,7 +131,6 @@ public:
             numScvf += element.subEntities(1);
 
         // reserve memory
-        elementMap_.resize(numScvs);
         scvs_.resize(numScvs);
         scvfs_.reserve(numScvf);
         scvfIndicesOfScv_.resize(numScvs);
@@ -152,9 +149,6 @@ public:
 
             scvs_[eIdx] = SubControlVolume(element.geometry(), eIdx);
 
-            // fill the element map with seeds
-            elementMap_[eIdx] = element.seed();
-
             // the element-wise index sets for finite volume geometry
             std::vector<IndexType> scvfsIndexSet;
             scvfsIndexSet.reserve(numLocalFaces);
@@ -243,7 +237,6 @@ private:
 
     // mappers
     ConnectivityMap connectivityMap_;
-    Dumux::ElementMap<GridView> elementMap_;
     IntersectionMapper intersectionMapper_;
 
     std::vector<SubControlVolume> scvs_;
diff --git a/test/common/boundingboxtree/CMakeLists.txt b/test/common/boundingboxtree/CMakeLists.txt
index 3ccdfee921..13754bafd4 100644
--- a/test/common/boundingboxtree/CMakeLists.txt
+++ b/test/common/boundingboxtree/CMakeLists.txt
@@ -1,5 +1,15 @@
 # build the tests for the bounding box tree
-dune_add_test(SOURCES test_bboxtree.cc)
+dune_add_test(NAME test_bboxtree_dim1
+              SOURCES test_bboxtree.cc
+              COMPILE_DEFINITIONS WORLD_DIMENSION=1)
+
+dune_add_test(NAME test_bboxtree_dim2
+              SOURCES test_bboxtree.cc
+              COMPILE_DEFINITIONS WORLD_DIMENSION=2)
+
+dune_add_test(NAME test_bboxtree_dim3
+              SOURCES test_bboxtree.cc
+              COMPILE_DEFINITIONS WORLD_DIMENSION=3)
 
 # symlink the input file in the build directory
 dune_symlink_to_source_files(FILES "network1d.msh")
@@ -8,3 +18,5 @@ dune_symlink_to_source_files(FILES "network1d.msh")
 install(FILES
 test_bboxtree.cc
 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dumux/test/common/boundingboxtree)
+
+set(CMAKE_BUILD_TYPE Release)
diff --git a/test/common/boundingboxtree/test_bboxtree.cc b/test/common/boundingboxtree/test_bboxtree.cc
index 0cdccae1a3..9da087f549 100644
--- a/test/common/boundingboxtree/test_bboxtree.cc
+++ b/test/common/boundingboxtree/test_bboxtree.cc
@@ -1,11 +1,13 @@
 #include <config.h>
 #include <iostream>
+#include <algorithm>
 
 #include <dune/grid/utility/structuredgridfactory.hh>
 #include <dune/common/parallel/mpihelper.hh>
 #include <dune/grid/io/file/vtk.hh>
 #include <dune/grid/io/file/gmshreader.hh>
 #include <dune/grid/yaspgrid.hh>
+#include <dune/common/timer.hh>
 
 #if HAVE_DUNE_FOAMGRID
 #include <dune/foamgrid/foamgrid.hh>
@@ -18,7 +20,9 @@
 #endif
 
 #include <dumux/common/exceptions.hh>
-#include <dumux/common/boundingboxtree.hh>
+#include <dumux/common/geometry/boundingboxtree.hh>
+#include <dumux/common/geometry/geometricentityset.hh>
+#include <dumux/common/geometry/intersectingentities.hh>
 
 namespace Dumux {
 
@@ -29,50 +33,45 @@ class BBoxTreeTests
     using Scalar = typename Grid::ctype;
     enum { dimWorld = Grid::dimensionworld };
     using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
+    using EntitySet = GridViewGeometricEntitySet<GridView, 0>;
+    using BoundingBoxTree = Dumux::BoundingBoxTree<EntitySet>;
 
 public:
-    int construct(const GridView& gv)
+    int build(const GridView& gv)
     {
-        std::cout << std::endl
-                  << "Construct bounding box tree from grid view:" << std::endl
-                  << "*******************************************"
-                  << std::endl;
-
-        // construct a bounding box tree
-        tree_ = std::make_shared<Dumux::BoundingBoxTree<GridView>>();
-        tree_->build(gv);
-
+        // build a bounding box tree
+        tree_ = std::make_shared<BoundingBoxTree>();
+        tree_->build(std::make_shared<EntitySet>(gv));
         return 0;
     }
 
     int intersectPoint(const GlobalPosition& p, std::size_t expectedCollisions)
     {
-        std::cout << std::endl
-                  << "Intersect with point ("<< p <<"):" << std::endl
-                  << "************************************************"
-                  << std::endl;
+        std::cout << "Intersect with point ("<< p <<") ";
+
+        Dune::Timer timer;
+        const auto entities = intersectingEntities(p, *tree_);
 
-        auto entities = tree_->computeEntityCollisions(p);
+        std::cout << " --> " << entities.size() << " intersection(s) found ("
+                  << expectedCollisions << " expected) in " << timer.elapsed() << " seconds.\n";
 
-        std::cout << entities.size() << " intersection(s) found ("
-                  << expectedCollisions << " expected)." << std::endl;
         if (entities.size() != expectedCollisions)
         {
             std::cerr << "Point intersection failed: Expected "
                       << expectedCollisions << " and got "
-                      << entities.size() << "!" <<std::endl;
+                      << entities.size() << "!\n";
             return 1;
         }
         return 0;
     }
 
-    template <class OtherGridView>
-    int intersectTree(const Dumux::BoundingBoxTree<OtherGridView>& otherTree,
+    template <class OtherEntitySet, class OtherGridView>
+    int intersectTree(const Dumux::BoundingBoxTree<OtherEntitySet>& otherTree,
                       const OtherGridView& otherGridView,
                       std::size_t expectedIntersections)
     {
         Dune::Timer timer;
-        auto intersections = tree_->computeEntityCollisions(otherTree);
+        const auto intersections = intersectingEntities(*tree_, otherTree);
         std::cout << "Computed tree intersections in " << timer.elapsed() << std::endl;
         timer.reset();
 
@@ -108,14 +107,7 @@ public:
     }
 
 private:
-    template<class Intersection>
-    bool intersectionsEqual(const Intersection& is1, const Intersection& is2)
-    {
-        using std::max;
-        auto eps = 1e-7*max((is1[0] - is1[1]).two_norm(), (is2[0] - is2[1]).two_norm());
-        return (is1[0] - is2[0]).two_norm() < eps && (is1[1] - is2[1]).two_norm() < eps;
-    }
-    std::shared_ptr<Dumux::BoundingBoxTree<GridView>> tree_;
+    std::shared_ptr<BoundingBoxTree> tree_;
 };
 
 } // end namespace Dumux
@@ -126,7 +118,8 @@ int main (int argc, char *argv[]) try
     Dune::MPIHelper::instance(argc, argv);
 
     // Some aliases two type tags for tests using two grids
-    using Grid = Dune::YaspGrid<3>;
+    constexpr int dimworld = WORLD_DIMENSION;
+    using Grid = Dune::YaspGrid<dimworld>;
     using Scalar = Grid::ctype;
     enum { dimWorld = Grid::dimensionworld };
     enum { dim = Grid::dimension };
@@ -144,48 +137,69 @@ int main (int argc, char *argv[]) try
                       << std::endl;
 
         // create a cube grid
-        const GlobalPosition lowerLeft(0.0);
-        const GlobalPosition upperRight(1.0*scaling);
-        std::array<unsigned int, dim> elems; elems.fill(3);
-        auto grid = Dune::StructuredGridFactory<Grid>::createCubeGrid(lowerLeft, upperRight, elems);
+        {
+            const GlobalPosition lowerLeft(0.0);
+            const GlobalPosition upperRight(1.0*scaling);
+            constexpr int numCellsX = 33;
+            std::array<unsigned int, dim> elems; elems.fill(numCellsX);
+            auto grid = Dune::StructuredGridFactory<Grid>::createCubeGrid(lowerLeft, upperRight, elems);
+
+            // Dune::VTKWriter<Grid::LeafGridView> vtkWriter(grid->leafGridView());
+            // vtkWriter.write("grid_dim" + std::to_string(dimworld), Dune::VTK::ascii);
+
+            // bboxtree tests using one bboxtree
+            returns.push_back(test.build(grid->leafGridView()));
+            returns.push_back(test.intersectPoint(GlobalPosition(0.0*scaling), 1));
+            returns.push_back(test.intersectPoint(GlobalPosition(1e-3*scaling), 1));
+            returns.push_back(test.intersectPoint(GlobalPosition(1.0*scaling/numCellsX), 1<<dimworld));
+            returns.push_back(test.intersectPoint(GlobalPosition(1.0*scaling), 1));
+        }
+
+#if HAVE_DUNE_FOAMGRID && WORLD_DIMENSION == 3
+        {
+            const GlobalPosition lowerLeft(0.0);
+            const GlobalPosition upperRight(1.0*scaling);
+            constexpr int numCellsX = 10;
+            std::array<unsigned int, dim> elems; elems.fill(numCellsX);
+            auto grid = Dune::StructuredGridFactory<Grid>::createCubeGrid(lowerLeft, upperRight, elems);
 
-        Dune::VTKWriter<Grid::LeafGridView> vtkWriter(grid->leafGridView());
-        vtkWriter.write("grid", Dune::VTK::ascii);
+            // Dune::VTKWriter<Grid::LeafGridView> vtkWriter(grid->leafGridView());
+            // vtkWriter.write("grid_dim" + std::to_string(dimworld), Dune::VTK::ascii);
 
-        // bboxtree tests using one bboxtree
-        returns.push_back(test.construct(grid->leafGridView()));
-        returns.push_back(test.intersectPoint(GlobalPosition(0.0), 1));
-        returns.push_back(test.intersectPoint(GlobalPosition(1e-3*scaling), 1));
-        returns.push_back(test.intersectPoint(GlobalPosition(1.0/3.0*scaling), 8));
+            using NetworkGrid = Dune::FoamGrid<1, dimworld>;
+            using NetworkGridView = NetworkGrid::LeafGridView;
 
-#if HAVE_DUNE_FOAMGRID
-        using NetworkGrid = Dune::FoamGrid<1, 3>;
-        using NetworkGridView = NetworkGrid::LeafGridView;
+            std::cout << std::endl
+                          << "Intersect with other bounding box tree:" << std::endl
+                          << "***************************************"
+                          << std::endl;
 
-        std::cout << std::endl
-                      << "Intersect with other bounding box tree:" << std::endl
-                      << "***************************************"
-                      << std::endl;
+            auto networkGrid = std::shared_ptr<NetworkGrid>(Dune::GmshReader<NetworkGrid>::read("network1d.msh", false, false));
 
-        auto networkGrid = std::shared_ptr<NetworkGrid>(Dune::GmshReader<NetworkGrid>::read("network1d.msh", false, false));
+            // scaling
+            for (const auto& vertex : vertices(networkGrid->leafGridView()))
+            {
+                auto newPos = vertex.geometry().corner(0);
+                newPos *= scaling;
+                networkGrid->setPosition(vertex, newPos);
+            }
 
-        // scaling
-        for (const auto& vertex : vertices(networkGrid->leafGridView()))
-        {
-            auto newPos = vertex.geometry().corner(0);
-            newPos *= scaling;
-            networkGrid->setPosition(vertex, newPos);
-        }
+            // Dune::VTKWriter<NetworkGridView> lowDimVtkWriter(networkGrid->leafGridView());
+            // lowDimVtkWriter.write("network", Dune::VTK::ascii);
 
-        Dune::VTKWriter<NetworkGridView> lowDimVtkWriter(networkGrid->leafGridView());
-        lowDimVtkWriter.write("network", Dune::VTK::ascii);
+            std::cout << "Constructed 1d network grid with " << networkGrid->leafGridView().size(0) << " elements." << std::endl;
 
-        std::cout << "Constructed " << networkGrid->leafGridView().size(0) <<
-                                  " element 1d network grid." << std::endl;
+            // build the bulk grid bounding box tree
+            returns.push_back(test.build(grid->leafGridView()));
 
-        Dumux::BoundingBoxTree<NetworkGridView> networkTree;
-        networkTree.build(networkGrid->leafGridView());
-        returns.push_back(test.intersectTree(networkTree, networkGrid->leafGridView(), 9));
+            // build the network grid bounding box tree
+            using EntitySet = Dumux::GridViewGeometricEntitySet<NetworkGridView, 0>;
+            Dumux::BoundingBoxTree<EntitySet> networkTree;
+            networkTree.build(std::make_shared<EntitySet>(networkGrid->leafGridView()));
+
+            // intersect the two bounding box trees
+            returns.push_back(test.intersectTree(networkTree, networkGrid->leafGridView(), 20));
+        }
 #endif
     }
 
-- 
GitLab