diff --git a/dumux/common/geometry/boundingboxtree.hh b/dumux/common/geometry/boundingboxtree.hh
index 3541867287b4d2425bafdce860e2e313daf5d201..9ca148086ac58187cbb96f0f75dca404da2cc74c 100644
--- a/dumux/common/geometry/boundingboxtree.hh
+++ b/dumux/common/geometry/boundingboxtree.hh
@@ -18,399 +18,15 @@
  * \file
  * \ingroup Geometry
  * \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.
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_BOUNDINGBOXTREE_HH
-#define DUMUX_BOUNDINGBOXTREE_HH
+#ifndef DUMUX_COMMON_GEOMETRY_BOUNDINGBOXTREE_HH
+#define DUMUX_COMMON_GEOMETRY_BOUNDINGBOXTREE_HH
 
-#include <vector>
-#include <array>
-#include <algorithm>
-#include <memory>
-#include <numeric>
-#include <type_traits>
-#include <iostream>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/boundingboxtree.hh"
 
-#include <dune/common/promotiontraits.hh>
-#include <dune/common/timer.hh>
-#include <dune/common/fvector.hh>
-
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \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 (dimworld == 3)
- * \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;
-
-    using std::max;
-    const auto dx = b[3] - b[0];
-    const auto dy = b[4] - b[1];
-    const auto dz = b[5] - b[2];
-    const ctype eps = max({dx, dy, dz})*eps_;
-    return (b[0] - eps <= point[0] && point[0] <= b[3] + eps &&
-            b[1] - eps <= point[1] && point[1] <= b[4] + eps &&
-            b[2] - eps <= point[2] && point[2] <= b[5] + eps);
-}
-
-/*!
- * \brief Check whether a point is intersectin a bounding box  (dimworld == 2)
- * \param point The point
- * \param b Pointer to bounding box coordinates
- */
-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;
-
-    using std::max;
-    const auto dx = b[2] - b[0];
-    const auto dy = b[3] - b[1];
-    const ctype eps = max(dx, dy)*eps_;
-    return (b[0] - eps <= point[0] && point[0] <= b[2] + eps &&
-            b[1] - eps <= point[1] && point[1] <= b[3] + eps);
-}
-
-/*!
- * \brief Check whether a point is intersectin a bounding box  (dimworld == 1)
- * \param point The point
- * \param b Pointer to bounding box coordinates
- */
-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;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Determine if a point intersects an axis-aligned bounding box
- * The bounding box is given by the lower left corner (min) and the upper right corner (max)
- */
-template<class ctype, int dimworld>
-inline bool intersectsPointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point,
-                                       const Dune::FieldVector<ctype, dimworld>& min,
-                                       const Dune::FieldVector<ctype, dimworld>& max)
-{
-    std::array<ctype, 2*dimworld> bBox;
-    std::copy(min.begin(), min.end(), bBox.begin());
-    std::copy(max.begin(), max.end(), bBox.begin()+dimworld);
-    return intersectsPointBoundingBox(point, bBox.data());
-}
-
-/*!
- * \brief Check whether a bounding box is intersecting another bounding box (dimworld == 3)
- * \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_*std::max(b[3]-b[0], a[3]-a[0]);
-    const ctype eps1 = eps_*std::max(b[4]-b[1], a[4]-a[1]);
-    const ctype eps2 = eps_*std::max(b[5]-b[2], a[5]-a[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);
-
-}
-
-/*!
- * \brief Check whether a bounding box is intersecting another bounding box (dimworld == 2)
- * \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 == 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_*std::max(b[2]-b[0], a[2]-a[0]);
-    const ctype eps1 = eps_*std::max(b[3]-b[1], a[3]-a[1]);
-    return (b[0] - eps0 <= a[2] && a[0] <= b[2] + eps0 &&
-            b[1] - eps1 <= a[3] && a[1] <= b[3] + eps1);
-}
-
-/*!
- * \brief Check whether a bounding box is intersecting another bounding box  (dimworld == 1)
- * \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 == 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-7;
-    const ctype eps0 = eps_*std::max(b[1]-b[0], a[1]-a[0]);
-    return b[0] - eps0 <= a[1] && a[0] <= b[1] + eps0;
-}
-
-} // end namespace Dumux
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/boundingboxtree.hh>
 
 #endif
diff --git a/dumux/common/geometry/diameter.hh b/dumux/common/geometry/diameter.hh
index 8f4eed920295cb1676755fca486d511e6a3f3aaa..fe4045bec6dd0ead48fcfe6361111dae6247db1b 100644
--- a/dumux/common/geometry/diameter.hh
+++ b/dumux/common/geometry/diameter.hh
@@ -19,31 +19,15 @@
  * \ingroup Geometry
  * \brief A function to compute a geometry's diameter, i.e.
  *        the longest distance between points of a geometry
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_GEOMETRY_DIAMETER_HH
-#define DUMUX_GEOMETRY_DIAMETER_HH
+#ifndef DUMUX_COMMON_GEOMETRY_DIAMETER_HH
+#define DUMUX_COMMON_GEOMETRY_DIAMETER_HH
 
-#include <algorithm>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/diameter.hh"
 
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief Computes the longest distance between points of a geometry
- * \note Useful e.g. to compute the maximum cell diameter of a grid
- */
-template<class Geometry>
-typename Geometry::ctype diameter(const Geometry& geo)
-{
-    using std::max;
-    typename Geometry::ctype h = 0.0;
-    for (std::size_t i = 0; i < geo.corners(); ++i)
-        for (std::size_t j = i + 1; j < geo.corners(); ++j)
-            h = max(h, (geo.corner(i)-geo.corner(j)).two_norm());
-
-    return h;
-}
-
-} // end namespace Dumux
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/diameter.hh>
 
 #endif
diff --git a/dumux/common/geometry/distance.hh b/dumux/common/geometry/distance.hh
index 47fccf32ea9057aed73b1a2b5ce77c33783d20b5..e87ee09b163d88dc1b41baa9222422bdf23fdc9b 100644
--- a/dumux/common/geometry/distance.hh
+++ b/dumux/common/geometry/distance.hh
@@ -18,164 +18,15 @@
  * \file
  * \ingroup Geometry
  * \brief Helper functions for distance queries
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_GEOMETRY_DISTANCE_HH
-#define DUMUX_GEOMETRY_DISTANCE_HH
+#ifndef DUMUX_COMMON_GEOMETRY_DISTANCE_HH
+#define DUMUX_COMMON_GEOMETRY_DISTANCE_HH
 
-#include <dune/common/fvector.hh>
-#include <dune/geometry/quadraturerules.hh>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/distance.hh"
 
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief Compute the average distance from a point to a geometry by integration
- */
-template<class Geometry>
-inline typename Geometry::ctype
-averageDistancePointGeometry(const typename Geometry::GlobalCoordinate& p,
-                             const Geometry& geometry,
-                             std::size_t integrationOrder = 2)
-{
-    typename Geometry::ctype avgDist = 0.0;
-    const auto& quad = Dune::QuadratureRules<typename Geometry::ctype, Geometry::mydimension>::rule(geometry.type(), integrationOrder);
-    for (const auto& qp : quad)
-        avgDist += (geometry.global(qp.position())-p).two_norm()*qp.weight()*geometry.integrationElement(qp.position());
-    return avgDist/geometry.volume();
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the distance from a point to a line through the points a and b
- */
-template<class Point>
-inline typename Point::value_type
-distancePointLine(const Point& p, const Point& a, const Point& b)
-{
-    const auto ab = b - a;
-    const auto t = (p - a)*ab/ab.two_norm2();
-    auto proj = a;
-    proj.axpy(t, ab);
-    return (proj - p).two_norm();
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the distance from a point to a line given by a geometry with two corners
- * \note We currently lack the a representation of a line geometry. This convenience function
- *       assumes a segment geometry (with two corners) is passed which represents a line geometry.
- */
-template<class Geometry>
-inline typename Geometry::ctype
-distancePointLine(const typename Geometry::GlobalCoordinate& p, const Geometry& geometry)
-{
-    static_assert(Geometry::mydimension == 1, "Geometry has to be a line");
-    const auto& a = geometry.corner(0);
-    const auto& b = geometry.corner(1);
-    return distancePointLine(p, a, b);
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the distance from a point to the segment connecting the points a and b
- */
-template<class Point>
-inline typename Point::value_type
-distancePointSegment(const Point& p, const Point& a, const Point& b)
-{
-    const auto ab = b - a;
-    auto t = (p - a)*ab;
-
-    if (t <= 0.0)
-        return (a - p).two_norm();
-
-    const auto lengthSq = ab.two_norm2();
-    if (t >= lengthSq)
-        return (b - p).two_norm();
-
-    auto proj = a;
-    proj.axpy(t/lengthSq, ab);
-    return (proj - p).two_norm();
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the distance from a point to a given segment geometry
- */
-template<class Geometry>
-inline typename Geometry::ctype
-distancePointSegment(const typename Geometry::GlobalCoordinate& p, const Geometry& geometry)
-{
-    static_assert(Geometry::mydimension == 1, "Geometry has to be a segment");
-    const auto& a = geometry.corner(0);
-    const auto& b = geometry.corner(1);
-    return distancePointSegment(p, a, b);
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the shortest distance between two points
- */
-template<class ctype, int dimWorld>
-inline ctype distance(const Dune::FieldVector<ctype, dimWorld>& a,
-                      const Dune::FieldVector<ctype, dimWorld>& b)
-{ return (a-b).two_norm(); }
-
-
-
-namespace Detail {
-
-// helper struct to compute distance between two geometries, specialized below
-template<class Geo1, class Geo2,
-         int dimWorld = Geo1::coorddimension,
-         int dim1 = Geo1::mydimension, int dim2 = Geo2::mydimension>
-struct GeometryDistance
-{
-    static_assert(Geo1::coorddimension == Geo2::coorddimension, "Geometries have to have the same coordinate dimensions");
-    static auto distance(const Geo1& geo1, const Geo2& geo2)
-    {
-        DUNE_THROW(Dune::NotImplemented, "Geometry distance computation not implemented for dimworld = "
-                    << dimWorld << ", dim1 = " << dim1 << ", dim2 = " << dim2);
-    }
-};
-
-// distance point-point
-template<class Geo1, class Geo2, int dimWorld>
-struct GeometryDistance<Geo1, Geo2, dimWorld, 0, 0>
-{
-    static_assert(Geo1::coorddimension == Geo2::coorddimension, "Geometries have to have the same coordinate dimensions");
-    static auto distance(const Geo1& geo1, const Geo2& geo2)
-    { return Dumux::distance(geo1.corner(0), geo2.corner(0)); }
-};
-
-// distance segment-point
-template<class Geo1, class Geo2, int dimWorld>
-struct GeometryDistance<Geo1, Geo2, dimWorld, 1, 0>
-{
-    static_assert(Geo1::coorddimension == Geo2::coorddimension, "Geometries have to have the same coordinate dimensions");
-    static auto distance(const Geo1& geo1, const Geo2& geo2)
-    { return distancePointSegment(geo2.corner(0), geo1); }
-};
-
-// distance point-segment
-template<class Geo1, class Geo2, int dimWorld>
-struct GeometryDistance<Geo1, Geo2, dimWorld, 0, 1>
-{
-    static_assert(Geo1::coorddimension == Geo2::coorddimension, "Geometries have to have the same coordinate dimensions");
-    static auto distance(const Geo1& geo1, const Geo2& geo2)
-    { return distancePointSegment(geo1.corner(0), geo2); }
-};
-
-} // end namespace Detail
-
-/*!
- * \ingroup Geometry
- * \brief Compute the shortest distance between two geometries
- */
-template<class Geo1, class Geo2>
-inline auto distance(const Geo1& geo1, const Geo2& geo2)
-{ return Detail::GeometryDistance<Geo1, Geo2>::distance(geo1, geo2); }
-
-} // end namespace Dumux
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/distance.hh>
 
 #endif
diff --git a/dumux/common/geometry/geometricentityset.hh b/dumux/common/geometry/geometricentityset.hh
index 012ace5fccdaefdc3531ec55e49cb379a201a6e1..c17166fe0a99e943365e7e42d8d3a98d51f1ff10 100644
--- a/dumux/common/geometry/geometricentityset.hh
+++ b/dumux/common/geometry/geometricentityset.hh
@@ -18,222 +18,15 @@
  * \file
  * \ingroup Geometry
  * \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
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_GEOMETRIC_ENTITY_SET_HH
-#define DUMUX_GEOMETRIC_ENTITY_SET_HH
+#ifndef DUMUX_COMMON_GEOMETRY_GEOMETRIC_ENTITY_SET_HH
+#define DUMUX_COMMON_GEOMETRY_GEOMETRIC_ENTITY_SET_HH
 
-#include <memory>
-#include <dune/grid/common/mcmgmapper.hh>
-#include <dune/geometry/multilineargeometry.hh>
-#include <dumux/common/entitymap.hh>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/geometricentityset.hh"
 
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief An interface for a set of geometric entities based on a GridView
- * \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
- */
-template <class GridView, int codim = 0, class Mapper = Dune::MultipleCodimMultipleGeomTypeMapper<GridView>>
-class GridViewGeometricEntitySet
-{
-    using EntityMap = Dumux::EntityMap<GridView, codim>;
-public:
-    using Entity = typename GridView::template Codim<codim>::Entity;
-
-    GridViewGeometricEntitySet(const GridView& gridView)
-    : GridViewGeometricEntitySet(gridView, Mapper(gridView, Dune::mcmgLayout(Dune::Codim<codim>())))
-    {}
-
-    GridViewGeometricEntitySet(const GridView& gridView, const Mapper& mapper)
-    : gridView_(gridView)
-    , mapper_(mapper)
-    , entityMap_(std::make_shared<EntityMap>(gridView.grid(), mapper_))
-    {}
-
-    GridViewGeometricEntitySet(const GridView& gridView,
-                               const Mapper& mapper,
-                               std::shared_ptr<const EntityMap> 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> entityMap_;
-
-};
-
-/*!
- * \ingroup Geometry
- * \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
- */
-template<class GeoType>
-class GeometriesEntitySet
-{
-    /*!
-     * \brief Wrapper to turn a geometry into a geometric entity
-     */
-    class EntityWrapper
-    {
-    public:
-        using Geometry = GeoType;
-
-        /*!
-         * \brief Constructor
-         */
-        EntityWrapper(const Geometry& geo, const std::size_t index) : geo_(geo), index_(index) {}
-
-        /*!
-         * \brief Constructor
-         */
-        EntityWrapper(Geometry&& geo, const std::size_t index) : geo_(std::move(geo)), index_(index) {}
-
-        /*!
-         * \brief Returns the geometry
-         */
-        const Geometry& geometry() const
-        { return geo_; }
-
-        /*!
-         * \brief Returns the index of the geometry
-         */
-        std::size_t index() const
-        { return index_; }
-
-    private:
-        Geometry geo_;
-        std::size_t index_;
-    };
-
-public:
-    using Entity = EntityWrapper;
-
-    /*!
-     * \brief Constructor for initializer_list
-     */
-    GeometriesEntitySet(std::initializer_list<typename Entity::Geometry>&& geometries)
-    {
-        std::size_t index = 0;
-        // note: std::initializer_list::begin() returns const T*,
-        // thus no moving will be performed and only the copying ctor of
-        // EntityWrapper can be called
-        for (auto&& g : geometries)
-            entities_.emplace_back(g, index++);
-    }
-
-    /*!
-     * \brief Constructor for a vector of geometries
-     */
-    GeometriesEntitySet(const std::vector<typename Entity::Geometry>& geometries)
-    {
-        std::size_t index = 0;
-        for (auto&& g : geometries)
-            entities_.emplace_back(g, index++);
-    }
-
-    /*!
-     * \brief Constructor for a vector of geometries
-     */
-    GeometriesEntitySet(std::vector<typename Entity::Geometry>&& geometries)
-    {
-        std::size_t index = 0;
-        for (auto&& g : geometries)
-            entities_.emplace_back(std::move(g), index++);
-    }
-
-    /*!
-     * \brief The world dimension of the entity set
-     */
-    enum { dimensionworld = Entity::Geometry::coorddimension };
-
-    /*!
-     * \brief the coordinate type
-     */
-    using ctype = typename Entity::Geometry::ctype;
-
-    /*!
-     * \brief the number of entities in this set
-     */
-    decltype(auto) size() const
-    { return entities_.size(); }
-
-    /*!
-     * \brief begin iterator to enable range-based for iteration
-     */
-    decltype(auto) begin() const
-    { return entities_.begin(); }
-
-    /*!
-     * \brief end iterator to enable range-based for iteration
-     */
-    decltype(auto) end() const
-    { return entities_.end(); }
-
-    /*!
-     * \brief get an entities index
-     */
-    template<class Entity>
-    std::size_t index(const Entity& e) const
-    { return e.index(); }
-
-    /*!
-     * \brief get an entity from an index
-     */
-    Entity entity(std::size_t index) const
-    { return entities_[index]; }
-
-private:
-    std::vector<Entity> entities_;
-};
-
-} // end namespace Dumux
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/geometricentityset.hh>
 
 #endif
diff --git a/dumux/common/geometry/geometryintersection.hh b/dumux/common/geometry/geometryintersection.hh
index 31ce8ea999756f07a1d6c52c94d64c7ca3f377c7..97b350cd78e63dd9b24e3d4a0cb24773226c269b 100644
--- a/dumux/common/geometry/geometryintersection.hh
+++ b/dumux/common/geometry/geometryintersection.hh
@@ -19,1369 +19,15 @@
  * \ingroup Geometry
  * \brief A class for collision detection of two geometries
  *        and computation of intersection corners
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_GEOMETRY_INTERSECTION_HH
-#define DUMUX_GEOMETRY_INTERSECTION_HH
+#ifndef DUMUX_COMMON_GEOMETRY_INTERSECTION_HH
+#define DUMUX_COMMON_GEOMETRY_INTERSECTION_HH
 
-#include <tuple>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/geometryintersection.hh"
 
-#include <dune/common/exceptions.hh>
-#include <dune/common/promotiontraits.hh>
-#include <dune/geometry/multilineargeometry.hh>
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/geometryintersection.hh>
 
-#include <dumux/common/math.hh>
-#include <dumux/common/geometry/intersectspointgeometry.hh>
-#include <dumux/common/geometry/grahamconvexhull.hh>
-#include <dumux/common/geometry/boundingboxtree.hh>
-
-namespace Dumux {
-namespace IntersectionPolicy {
-
-//! Policy structure for point-like intersections
-template<class ct, int dw>
-struct PointPolicy
-{
-    using ctype = ct;
-    using Point = Dune::FieldVector<ctype, dw>;
-
-    static constexpr int dimWorld = dw;
-    static constexpr int dimIntersection = 0;
-    using Intersection = Point;
-};
-
-//! Policy structure for segment-like intersections
-template<class ct, int dw>
-struct SegmentPolicy
-{
-    using ctype = ct;
-    using Point = Dune::FieldVector<ctype, dw>;
-    using Segment = std::array<Point, 2>;
-
-    static constexpr int dimWorld = dw;
-    static constexpr int dimIntersection = 1;
-    using Intersection = Segment;
-};
-
-//! Policy structure for polygon-like intersections
-template<class ct, int dw>
-struct PolygonPolicy
-{
-    using ctype = ct;
-    using Point = Dune::FieldVector<ctype, dw>;
-    using Polygon = std::vector<Point>;
-
-    static constexpr int dimWorld = dw;
-    static constexpr int dimIntersection = 2;
-    using Intersection = Polygon;
-};
-
-//! Policy structure for polyhedron-like intersections
-template<class ct, int dw>
-struct PolyhedronPolicy
-{
-    using ctype = ct;
-    using Point = Dune::FieldVector<ctype, dw>;
-    using Polyhedron = std::vector<Point>;
-
-    static constexpr int dimWorld = dw;
-    static constexpr int dimIntersection = 3;
-    using Intersection = Polyhedron;
-};
-
-//! default policy chooser class
-template<class Geometry1, class Geometry2>
-class DefaultPolicyChooser
-{
-    static constexpr int dimworld = Geometry1::coorddimension;
-    static constexpr int isDim = std::min( int(Geometry1::mydimension), int(Geometry2::mydimension) );
-    static_assert(dimworld == int(Geometry2::coorddimension),
-                  "Geometries must have the same coordinate dimension!");
-    static_assert(int(Geometry1::mydimension) <= 3 && int(Geometry2::mydimension) <= 3,
-                  "Geometries must have dimension 3 or less.");
-    using ctype = typename Dune::PromotionTraits<typename Geometry1::ctype, typename Geometry2::ctype>::PromotedType;
-
-    using DefaultPolicies = std::tuple<PointPolicy<ctype, dimworld>,
-                                       SegmentPolicy<ctype, dimworld>,
-                                       PolygonPolicy<ctype, dimworld>,
-                                       PolyhedronPolicy<ctype, dimworld>>;
-public:
-    using type = std::tuple_element_t<isDim, DefaultPolicies>;
-};
-
-//! Helper alias to define the default intersection policy
-template<class Geometry1, class Geometry2>
-using DefaultPolicy = typename DefaultPolicyChooser<Geometry1, Geometry2>::type;
-
-} // end namespace IntersectionPolicy
-
-namespace Detail {
-
-/*!
- * \ingroup Geometry
- * \brief Algorithm to find segment-like intersections of a polgon/polyhedron with a
- *        segment. The result is stored in the form of the local coordinates tfirst
- *        and tlast on the segment geo1.
- * \param geo1 the first geometry
- * \param geo2 the second geometry (dimGeo2 < dimGeo1)
- * \param baseEps the base epsilon used for floating point comparisons
- * \param tfirst stores the local coordinate of beginning of intersection segment
- * \param tlast stores the local coordinate of the end of intersection segment
- * \param getFacetCornerIndices Function to obtain the facet corner indices on geo1
- * \param computeNormal Function to obtain the normal vector on a facet on geo1
- */
-template< class Geo1, class Geo2, class ctype,
-          class GetFacetCornerIndices, class ComputeNormalFunction >
-bool computeSegmentIntersection(const Geo1& geo1, const Geo2& geo2, ctype baseEps,
-                                ctype& tfirst, ctype& tlast,
-                                const GetFacetCornerIndices& getFacetCornerIndices,
-                                const ComputeNormalFunction& computeNormal)
-{
-    static_assert(int(Geo2::mydimension) == 1, "Geometry2 must be a segment");
-    static_assert(int(Geo1::mydimension) > int(Geo2::mydimension),
-                  "Dimension of Geometry1 must be higher than that of Geometry2");
-
-    const auto a = geo2.corner(0);
-    const auto b = geo2.corner(1);
-    const auto d = b - a;
-
-    // The initial interval is the whole segment.
-    // Afterwards we start clipping the interval
-    // at the intersections with the facets of geo1
-    tfirst = 0.0;
-    tlast = 1.0;
-
-    const auto facets = getFacetCornerIndices(geo1);
-    for (const auto& f : facets)
-    {
-        const auto n = computeNormal(f);
-
-        const auto c0 = geo1.corner(f[0]);
-        const ctype denom = n*d;
-        const ctype dist = n*(a-c0);
-
-        // use first edge of the facet to scale eps
-        const auto edge1 = geo1.corner(f[1]) - geo1.corner(f[0]);
-        const ctype eps = baseEps*edge1.two_norm();
-
-        // if denominator is zero the segment in parallel to the edge.
-        // If the distance is positive there is no intersection
-        using std::abs;
-        if (abs(denom) < eps)
-        {
-            if (dist > eps)
-                return false;
-        }
-        else // not parallel: compute line-line intersection
-        {
-            const ctype t = -dist / denom;
-            // if entering half space cut tfirst if t is larger
-            using std::signbit;
-            if (signbit(denom))
-            {
-                if (t > tfirst)
-                    tfirst = t;
-            }
-            // if exiting half space cut tlast if t is smaller
-            else
-            {
-                if (t < tlast)
-                    tlast = t;
-            }
-            // there is no intersection of the interval is empty
-            // use unscaled epsilon since t is in local coordinates
-            if (tfirst > tlast - baseEps)
-                return false;
-        }
-    }
-
-    // If we made it until here an intersection exists.
-    return true;
-}
-
-} // end namespace Detail
-
-/*!
- * \ingroup Geometry
- * \brief A class for geometry collision detection and intersection calculation
- * The class can be specialized for combinations of dimworld, dim1, dim2, where
- * dimworld is the world dimension embedding a grid of dim1 and a grid of dim2.
- */
-template
-<class Geometry1, class Geometry2,
- class Policy = IntersectionPolicy::DefaultPolicy<Geometry1, Geometry2>,
- int dimworld = Geometry1::coorddimension,
- int dim1 = Geometry1::mydimension,
- int dim2 = Geometry2::mydimension>
-class GeometryIntersection
-{
-    static constexpr int dimWorld = Policy::dimWorld;
-
-public:
-    using ctype = typename Policy::ctype;
-    using Point = typename Policy::Point;
-    using Intersection = typename Policy::Intersection;
-
-    //! Determine if the two geometries intersect and compute the intersection geometry
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        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);
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for segment--segment intersection in 2d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 2, 1, 1>
-{
-    enum { dimworld = 2 };
-    enum { dim1 = 1 };
-    enum { dim2 = 1 };
-
-    // base epsilon for floating point comparisons
-    static constexpr typename Policy::ctype eps_ = 1.5e-7;
-
-public:
-    using ctype = typename Policy::ctype;
-    using Point = typename Policy::Point;
-    using Intersection = typename Policy::Intersection;
-
-    /*!
-     * \brief Colliding two segments
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection The intersection point
-     * \note This overload is used when point-like intersections are seeked
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        const auto v1 = geo1.corner(1) - geo1.corner(0);
-        const auto v2 = geo2.corner(1) - geo2.corner(0);
-        const auto ac = geo2.corner(0) - geo1.corner(0);
-
-        auto n2 = Point({-1.0*v2[1], v2[0]});
-        n2 /= n2.two_norm();
-
-        // compute distance of first corner on geo2 to line1
-        const auto dist12 = n2*ac;
-
-        // first check parallel segments
-        using std::abs;
-        using std::sqrt;
-
-        const auto v1Norm2 = v1.two_norm2();
-        const auto eps = eps_*sqrt(v1Norm2);
-        const auto eps2 = eps_*v1Norm2;
-
-        const auto sp = n2*v1;
-        if (abs(sp) < eps)
-        {
-            if (abs(dist12) > eps)
-                return false;
-
-            // point intersection can only be one of the corners
-            if ( (v1*v2) < 0.0 )
-            {
-                if ( ac.two_norm2() < eps2 )
-                { intersection = geo2.corner(0); return true; }
-
-                if ( (geo2.corner(1) - geo1.corner(1)).two_norm2() < eps2 )
-                { intersection = geo2.corner(1); return true; }
-            }
-            else
-            {
-                if ( (geo2.corner(1) - geo1.corner(0)).two_norm2() < eps2 )
-                { intersection = geo2.corner(1); return true; }
-
-                if ( (geo2.corner(0) - geo1.corner(1)).two_norm2() < eps2 )
-                { intersection = geo2.corner(0); return true; }
-            }
-
-            // no intersection
-            return false;
-        }
-
-        // intersection point on v1 in local coords
-        const auto t1 = dist12 / sp;
-
-        // check if the local coords are valid
-        if (t1 < -1.0*eps_ || t1 > 1.0 + eps_)
-            return false;
-
-        // compute global coordinates
-        auto isPoint = geo1.global(t1);
-
-        // check if point is in bounding box of v2
-        const auto c = geo2.corner(0);
-        const auto d = geo2.corner(1);
-
-        using std::min; using std::max;
-        std::array<ctype, 4> bBox({ min(c[0], d[0]), min(c[1], d[1]), max(c[0], d[0]), max(c[1], d[1]) });
-
-        if ( intersectsPointBoundingBox(isPoint, bBox.data()) )
-        {
-            intersection = std::move(isPoint);
-            return true;
-        }
-
-        return false;
-    }
-
-    /*!
-     * \brief Colliding two segments
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection Container to store corners of intersection segment
-     * \note this overload is used when segment-like intersections are seeked
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        const auto& a = geo1.corner(0);
-        const auto& b = geo1.corner(1);
-        const auto ab = b - a;
-
-        const auto& p = geo2.corner(0);
-        const auto& q = geo2.corner(1);
-        const auto pq = q - p;
-        Dune::FieldVector<ctype, dimworld> n2{-pq[1], pq[0]};
-
-        using std::max;
-        const auto abNorm2 = ab.two_norm2();
-        const auto pqNorm2 = pq.two_norm2();
-        const auto eps2 = eps_*max(abNorm2, pqNorm2);
-
-        // non-parallel segments do not intersect in a segment.
-        using std::abs;
-        if (abs(n2*ab) > eps2)
-            return false;
-
-        // check if the segments lie on the same line
-        const auto ap = p - a;
-        if (abs(ap*n2) > eps2)
-            return false;
-
-        // compute scaled local coordinates of corner 1/2 of segment2 on segment1
-        auto t1 = ab*ap;
-        auto t2 = ab*(q - a);
-
-        using std::swap;
-        if (t1 > t2)
-            swap(t1, t2);
-
-        using std::clamp;
-        t1 = clamp(t1, 0.0, abNorm2);
-        t2 = clamp(t2, 0.0, abNorm2);
-
-        if (abs(t2-t1) < eps2)
-            return false;
-
-        intersection = Intersection({geo1.global(t1/abNorm2), geo1.global(t2/abNorm2)});
-        return true;
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for polygon--segment intersection in 2d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 2, 2, 1>
-{
-    enum { dimworld = 2 };
-    enum { dim1 = 2 };
-    enum { dim2 = 1 };
-
-public:
-    using ctype = typename Policy::ctype;
-    using Point = typename Policy::Point;
-    using Intersection = typename Policy::Intersection;
-
-private:
-    static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons
-
-public:
-    /*!
-     * \brief Colliding segment and convex polygon
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide intersection holds the
-     *        corner points of the intersection object in global coordinates.
-     * \note This overload is used when segment-like intersections are seeked.
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        ctype tfirst, tlast;
-        if (intersect_(geo1, geo2, tfirst, tlast))
-        {
-            // the intersection exists. Export the intersections geometry now:
-            // s(t) = a + t(b-a) in [tfirst, tlast]
-            intersection = Intersection({geo2.global(tfirst), geo2.global(tlast)});
-            return true;
-        }
-
-        return false;
-    }
-
-    /*!
-     * \brief Colliding segment and convex polygon
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide intersection holds the
-     *        corner points of the intersection object in global coordinates.
-     * \note This overload is used when point-like intersections are seeked.
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename P::Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        ctype tfirst, tlast;
-        if (!intersect_(geo1, geo2, tfirst, tlast))
-        {
-            // if start & end point are same, the intersection is a point
-            using std::abs;
-            if ( tfirst > tlast - eps_ )
-            {
-                intersection = Intersection(geo2.global(tfirst));
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-private:
-    /*!
-     * \brief Obtain local coordinates of start/end point of the intersecting segment.
-     */
-     static bool intersect_(const Geometry1& geo1, const Geometry2& geo2, ctype& tfirst, ctype& tlast)
-     {
-         // lambda to obtain the facet corners on geo1
-         auto getFacetCorners = [] (const Geometry1& geo1)
-         {
-             std::vector< std::array<int, 2> > facetCorners;
-             switch (geo1.corners())
-             {
-                 case 4: // quadrilateral
-                     facetCorners = {{0, 2}, {3, 1}, {1, 0}, {2, 3}};
-                     break;
-                 case 3: // triangle
-                     facetCorners = {{1, 0}, {0, 2}, {2, 1}};
-                     break;
-                 default:
-                     DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type "
-                                    << geo1.type() << " with "<< geo1.corners() << " corners.");
-             }
-
-             return facetCorners;
-         };
-
-         // lambda to obtain the normal on a facet
-         const auto center1 = geo1.center();
-         auto computeNormal = [&geo1, &center1] (const std::array<int, 2>& facetCorners)
-         {
-             const auto c0 = geo1.corner(facetCorners[0]);
-             const auto c1 = geo1.corner(facetCorners[1]);
-             const auto edge = c1 - c0;
-
-             Dune::FieldVector<ctype, dimworld> n({-1.0*edge[1], edge[0]});
-             n /= n.two_norm();
-
-             // orientation of the element is not known
-             // make sure normal points outwards of element
-             if ( n*(center1-c0) > 0.0 )
-                 n *= -1.0;
-
-             return n;
-         };
-
-         return Detail::computeSegmentIntersection(geo1, geo2, eps_, tfirst, tlast, getFacetCorners, computeNormal);
-     }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for segment--polygon intersection in 2d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 2, 1, 2>
-: public GeometryIntersection<Geometry2, Geometry1, Policy, 2, 2, 1>
-{
-    using Base = GeometryIntersection<Geometry2, Geometry1, Policy, 2, 2, 1>;
-
-public:
-    /*!
-     * \brief Colliding segment and convex polygon
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide intersection holds the
-     *        corner points of the intersection object in global coordinates.
-     * \note This forwards to the polygon-segment specialization with swapped arguments.
-     */
-    template<class P = Policy>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename Base::Intersection& intersection)
-    {
-        return Base::intersection(geo2, geo1, intersection);
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for polygon--polygon intersection in 2d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 2, 2, 2>
-{
-    enum { dimworld = 2 };
-    enum { dim1 = 2 };
-    enum { dim2 = 2 };
-
-public:
-    using ctype = typename Policy::ctype;
-    using Point = typename Policy::Point;
-    using Intersection = typename Policy::Intersection;
-
-private:
-    static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons
-
-public:
-    /*!
-     * \brief Colliding two polygons
-     * \note First we find the vertex candidates for the intersection region as follows:
-     *       Add polygon vertices that are inside the other polygon
-     *       Add intersections of polygon edges
-     *       Remove duplicate points from the list
-     *       Compute the convex hull polygon
-     *       Return a triangulation of that polygon as intersection
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection Container to store the corner points of the polygon (as convex hull)
-     * \note This overload is used when polygon like intersections are seeked
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 2, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        // the candidate intersection points
-        std::vector<Point> points; points.reserve(6);
-
-        // add polygon1 corners that are inside polygon2
-        for (int i = 0; i < geo1.corners(); ++i)
-            if (intersectsPointGeometry(geo1.corner(i), geo2))
-                points.emplace_back(geo1.corner(i));
-
-        const auto numPoints1 = points.size();
-        if (numPoints1 != geo1.corners())
-        {
-            // add polygon2 corners that are inside polygon1
-            for (int i = 0; i < geo2.corners(); ++i)
-                if (intersectsPointGeometry(geo2.corner(i), geo1))
-                    points.emplace_back(geo2.corner(i));
-
-            if (points.empty())
-                return false;
-
-            if (points.size() - numPoints1 != geo2.corners())
-            {
-                const auto refElement1 = referenceElement(geo1);
-                const auto refElement2 = referenceElement(geo2);
-
-                // add intersections of edges
-                using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
-                using PointPolicy = IntersectionPolicy::PointPolicy<ctype, dimworld>;
-                for (int i = 0; i < refElement1.size(dim1-1); ++i)
-                {
-                    const auto localEdgeGeom1 = refElement1.template geometry<dim1-1>(i);
-                    const auto edge1 = SegGeometry( Dune::GeometryTypes::line,
-                                                    std::vector<Point>( {geo1.global(localEdgeGeom1.corner(0)),
-                                                                         geo1.global(localEdgeGeom1.corner(1))} ));
-
-                    for (int j = 0; j < refElement2.size(dim2-1); ++j)
-                    {
-                        const auto localEdgeGeom2 = refElement2.template geometry<dim2-1>(j);
-                        const auto edge2 = SegGeometry( Dune::GeometryTypes::line,
-                                                        std::vector<Point>( {geo2.global(localEdgeGeom2.corner(0)),
-                                                                             geo2.global(localEdgeGeom2.corner(1))} ));
-
-                        using EdgeTest = GeometryIntersection<SegGeometry, SegGeometry, PointPolicy>;
-                        typename EdgeTest::Intersection edgeIntersection;
-                        if (EdgeTest::intersection(edge1, edge2, edgeIntersection))
-                            points.emplace_back(edgeIntersection);
-                    }
-                }
-            }
-        }
-
-        if (points.empty())
-            return false;
-
-        // remove duplicates
-        const auto eps = (geo1.corner(0) - geo1.corner(1)).two_norm()*eps_;
-        std::sort(points.begin(), points.end(), [&eps](const auto& a, const auto& b) -> bool
-        {
-            using std::abs;
-            return (abs(a[0]-b[0]) > eps ? a[0] < b[0] : a[1] < b[1]);
-        });
-
-        auto removeIt = std::unique(points.begin(), points.end(), [&eps](const auto& a, const auto&b)
-        {
-            return (b-a).two_norm() < eps;
-        });
-
-        points.erase(removeIt, points.end());
-
-        // return false if we don't have at least three unique points
-        if (points.size() < 3)
-            return false;
-
-        // intersection polygon is convex hull of above points
-        intersection = grahamConvexHull<2>(points);
-        assert(!intersection.empty());
-        return true;
-    }
-
-    /*!
-     * \brief Colliding two polygons
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection Container to store the corners of intersection segment
-     * \note this overload is used when segment-like intersections are seeked
-     * \todo implement this query
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-        DUNE_THROW(Dune::NotImplemented, "Polygon-polygon intersection detection for segment-like intersections");
-    }
-
-    /*!
-     * \brief Colliding two polygons
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection The intersection point
-     * \note this overload is used when point-like intersections are seeked
-     * \todo implement this query
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-        DUNE_THROW(Dune::NotImplemented, "Polygon-polygon intersection detection for touching points");
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for polyhedron--segment intersection in 3d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 3, 1>
-{
-    enum { dimworld = 3 };
-    enum { dim1 = 3 };
-    enum { dim2 = 1 };
-
-public:
-    using ctype = typename Policy::ctype;
-    using Point = typename Policy::Point;
-    using Intersection = typename Policy::Intersection;
-
-private:
-    static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons
-
-public:
-    /*!
-     *  \brief Colliding segment and convex polyhedron
-     *  \note Algorithm based on the one from "Real-Time Collision Detection" by Christer Ericson,
-     *        published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.
-     *        Basis is the theorem that for any two non-intersecting convex polyhedrons
-     *        a separating plane exists.
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide intersection holds the corner points of
-     *        the intersection object in global coordinates.
-     * \note This overload is used when segment-like intersections are seeked.
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        ctype tfirst, tlast;
-        if (intersect_(geo1, geo2, tfirst, tlast))
-        {
-            // Intersection exists. Export the intersections geometry now:
-            // s(t) = a + t(b-a) in [tfirst, tlast]
-            intersection = Intersection({geo2.global(tfirst), geo2.global(tlast)});
-            return true;
-        }
-
-        return false;
-    }
-
-    /*!
-     *  \brief Colliding segment and convex polyhedron
-     *  \note Algorithm based on the one from "Real-Time Collision Detection" by Christer Ericson,
-     *        published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.
-     *        Basis is the theorem that for any two non-intersecting convex polyhedrons
-     *        a separating plane exists.
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide intersection holds the corner points of
-     *        the intersection object in global coordinates.
-     * \note This overload is used when point-like intersections are seeked.
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        ctype tfirst, tlast;
-        if (intersect_(geo1, geo2, tfirst, tlast))
-        {
-            // if start & end point are same, the intersection is a point
-            using std::abs;
-            if ( abs(tfirst - tlast) < eps_ )
-            {
-                intersection = Intersection(geo2.global(tfirst));
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-private:
-    /*!
-     * \brief Obtain local coordinates of start/end point of the intersecting segment.
-     */
-     static bool intersect_(const Geometry1& geo1, const Geometry2& geo2, ctype& tfirst, ctype& tlast)
-     {
-         // lambda to obtain facet corners on geo1
-         auto getFacetCorners = [] (const Geometry1& geo1)
-         {
-             std::vector< std::vector<int> > facetCorners;
-             // 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
-                     facetCorners = {{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
-                     facetCorners = {{1, 0, 2}, {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 facetCorners;
-         };
-
-         // lambda to obtain the normal on a facet
-         auto computeNormal = [&geo1] (const std::vector<int>& facetCorners)
-         {
-             const auto v0 = geo1.corner(facetCorners[1]) - geo1.corner(facetCorners[0]);
-             const auto v1 = geo1.corner(facetCorners[2]) - geo1.corner(facetCorners[0]);
-
-             auto n = crossProduct(v0, v1);
-             n /= n.two_norm();
-
-             return n;
-         };
-
-         return Detail::computeSegmentIntersection(geo1, geo2, eps_, tfirst, tlast, getFacetCorners, computeNormal);
-     }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for segment--polyhedron intersection in 3d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 1, 3>
-: public GeometryIntersection<Geometry2, Geometry1, Policy, 3, 3, 1>
-{
-    using Base = GeometryIntersection<Geometry2, Geometry1, Policy, 3, 3, 1>;
-public:
-    /*!
-     * \brief Colliding segment and convex polyhedron
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide intersection holds the
-     *        corner points of the intersection object in global coordinates.
-     * \note This forwards to the polyhedron-segment specialization with swapped arguments.
-     */
-    template<class P = Policy>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename Base::Intersection& intersection)
-    {
-        return Base::intersection(geo2, geo1, intersection);
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for polyhedron--polygon intersection in 3d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 3, 2>
-{
-    enum { dimworld = 3 };
-    enum { dim1 = 3 };
-    enum { dim2 = 2 };
-
-public:
-    using ctype = typename Policy::ctype;
-    using Point = typename Policy::Point;
-    using Intersection = typename Policy::Intersection;
-
-private:
-    static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons
-
-public:
-    /*!
-     * \brief Colliding polygon and convex polyhedron
-     * \note First we find the vertex candidates for the intersection region as follows:
-     *       Add triangle vertices that are inside the tetrahedron
-     *       Add tetrahedron vertices that are inside the triangle
-     *       Add all intersection points of tetrahedron edges (codim 2) with the triangle (codim 0) (6*1 tests)
-     *       Add all intersection points of triangle edges (codim 1) with tetrahedron faces (codim 1) (3*4 tests)
-     *       Remove duplicate points from the list
-     *       Compute the convex hull polygon
-     *       Return a triangulation of that polygon as intersection
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection Container to store the corner points of the polygon (as convex hull)
-     * \note This overload is used when polygon like intersections are seeked
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 2, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        // the candidate intersection points
-        std::vector<Point> points; points.reserve(10);
-
-        // add 3d geometry corners that are inside the 2d geometry
-        for (int i = 0; i < geo1.corners(); ++i)
-            if (intersectsPointGeometry(geo1.corner(i), geo2))
-                points.emplace_back(geo1.corner(i));
-
-        // add 2d geometry corners that are inside the 3d geometry
-        for (int i = 0; i < geo2.corners(); ++i)
-            if (intersectsPointGeometry(geo2.corner(i), geo1))
-                points.emplace_back(geo2.corner(i));
-
-        // get some geometry types
-        using PolyhedronFaceGeometry = Dune::MultiLinearGeometry<ctype, 2, dimworld>;
-        using SegGeometry = Dune::MultiLinearGeometry<ctype, 1, dimworld>;
-
-        const auto refElement1 = referenceElement(geo1);
-        const auto refElement2 = referenceElement(geo2);
-
-        // intersection policy for point-like intersections (used later)
-        using PointPolicy = IntersectionPolicy::PointPolicy<ctype, dimworld>;
-
-        // add intersection points of all polyhedron edges (codim dim-1) with the polygon
-        for (int i = 0; i < refElement1.size(dim1-1); ++i)
-        {
-            const auto localEdgeGeom = refElement1.template geometry<dim1-1>(i);
-            const auto p = geo1.global(localEdgeGeom.corner(0));
-            const auto q = geo1.global(localEdgeGeom.corner(1));
-            const auto segGeo = SegGeometry(Dune::GeometryTypes::line, std::vector<Point>{p, q});
-
-            using PolySegTest = GeometryIntersection<Geometry2, SegGeometry, PointPolicy>;
-            typename PolySegTest::Intersection polySegIntersection;
-            if (PolySegTest::intersection(geo2, segGeo, polySegIntersection))
-                points.emplace_back(polySegIntersection);
-        }
-
-        // add intersection points of all polygon faces (codim 1) with the polyhedron faces
-        for (int i = 0; i < refElement1.size(1); ++i)
-        {
-            const auto faceGeo = [&]()
-            {
-                const auto localFaceGeo = refElement1.template geometry<1>(i);
-                if (localFaceGeo.corners() == 4)
-                {
-                    const auto a = geo1.global(localFaceGeo.corner(0));
-                    const auto b = geo1.global(localFaceGeo.corner(1));
-                    const auto c = geo1.global(localFaceGeo.corner(2));
-                    const auto d = geo1.global(localFaceGeo.corner(3));
-
-                    return PolyhedronFaceGeometry(Dune::GeometryTypes::cube(2), std::vector<Point>{a, b, c, d});
-                }
-                else
-                {
-                    const auto a = geo1.global(localFaceGeo.corner(0));
-                    const auto b = geo1.global(localFaceGeo.corner(1));
-                    const auto c = geo1.global(localFaceGeo.corner(2));
-
-                    return PolyhedronFaceGeometry(Dune::GeometryTypes::simplex(2), std::vector<Point>{a, b, c});
-                }
-            }();
-
-            for (int j = 0; j < refElement2.size(1); ++j)
-            {
-                const auto localEdgeGeom = refElement2.template geometry<1>(j);
-                const auto p = geo2.global(localEdgeGeom.corner(0));
-                const auto q = geo2.global(localEdgeGeom.corner(1));
-
-                const auto segGeo = SegGeometry(Dune::GeometryTypes::line, std::vector<Point>{p, q});
-
-                using PolySegTest = GeometryIntersection<PolyhedronFaceGeometry, SegGeometry, PointPolicy>;
-                typename PolySegTest::Intersection polySegIntersection;
-                if (PolySegTest::intersection(faceGeo, segGeo, polySegIntersection))
-                    points.emplace_back(polySegIntersection);
-            }
-        }
-
-        // return if no intersection points were found
-        if (points.empty()) return false;
-
-        // remove duplicates
-        const auto eps = (geo1.corner(0) - geo1.corner(1)).two_norm()*eps_;
-        std::sort(points.begin(), points.end(), [&eps](const auto& a, const auto& b) -> bool
-        {
-            using std::abs;
-            return (abs(a[0]-b[0]) > eps ? a[0] < b[0] : (abs(a[1]-b[1]) > eps ? a[1] < b[1] : (a[2] < b[2])));
-        });
-
-        auto removeIt = std::unique(points.begin(), points.end(), [&eps](const auto& a, const auto&b)
-        {
-            return (b-a).two_norm() < eps;
-        });
-
-        points.erase(removeIt, points.end());
-
-        // return false if we don't have more than three unique points
-        if (points.size() < 3) return false;
-
-        // intersection polygon is convex hull of above points
-        intersection = grahamConvexHull<2>(points);
-        assert(!intersection.empty());
-
-        return true;
-    }
-
-    /*!
-     * \brief Colliding segment and convex polyhedron
-     * \note First we find the vertex candidates for the intersection region as follows:
-     *       Add triangle vertices that are inside the tetrahedron
-     *       Add tetrahedron vertices that are inside the triangle
-     *       Add all intersection points of tetrahedron edges (codim 2) with the triangle (codim 0) (6*1 tests)
-     *       Add all intersection points of triangle edges (codim 1) with tetrahedron faces (codim 1) (3*4 tests)
-     *       Remove duplicate points from the list
-     *       Compute the convex hull polygon
-     *       Return a triangulation of that polygon as intersection
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection Container to store the intersection result
-     * \todo implement overloads for segment or point-like intersections
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection != 2, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-        DUNE_THROW(Dune::NotImplemented, "Polyhedron-polygon intersection detection only implemented for polygon-like intersections");
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for polygon--polyhedron intersection in 3d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 2, 3>
-: public GeometryIntersection<Geometry2, Geometry1, Policy, 3, 3, 2>
-{
-    using Base = GeometryIntersection<Geometry2, Geometry1, Policy, 3, 3, 2>;
-public:
-    /*!
-     * \brief Colliding polygon and convex polyhedron
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide intersection holds the
-     *        corner points of the intersection object in global coordinates.
-     * \note This forwards to the polyhedron-polygon specialization with swapped arguments.
-     */
-    template<class P = Policy>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename Base::Intersection& intersection)
-    {
-        return Base::intersection(geo2, geo1, intersection);
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for polygon--segment intersection in 3d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 2, 1>
-{
-    enum { dimworld = 3 };
-    enum { dim1 = 2 };
-    enum { dim2 = 1 };
-
-public:
-    using ctype = typename Policy::ctype;
-    using Point = typename Policy::Point;
-    using Intersection = typename Policy::Intersection;
-
-private:
-    static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons
-
-public:
-    /*!
-     *  \brief Colliding segment and convex polyhedron
-     *  \note Algorithm based on the one from "Real-Time Collision Detection" by Christer Ericson,
-     *        published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc. (Chapter 5.3.6)
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide, is holds the corner points of
-     *        the intersection object in global coordinates.
-     * \note This overload is used when point-like intersections are seeked
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        ctype tfirst, tlast;
-        if (intersect_(geo1, geo2, tfirst, tlast))
-        {
-            // the intersection exists. Export the intersections geometry now:
-            // s(t) = a + t(b-a) in [tfirst, tlast]
-            intersection = Intersection({geo2.global(tfirst), geo2.global(tlast)});
-            return true;
-        }
-
-        return false;
-    }
-
-    /*!
-     *  \brief Colliding segment and convex polyhedron
-     *  \note Algorithm based on the one from "Real-Time Collision Detection" by Christer Ericson,
-     *        published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc. (Chapter 5.3.6)
-     * \param geo1/geo2 The geometries to intersect
-     * \param is If the geometries collide, is holds the corner points of
-     *        the intersection object in global coordinates.
-     * \note This overload is used when point-like intersections are seeked
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& is)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        const auto p = geo2.corner(0);
-        const auto q = geo2.corner(1);
-
-        const auto a = geo1.corner(0);
-        const auto b = geo1.corner(1);
-        const auto c = geo1.corner(2);
-
-        if (geo1.corners() == 3)
-            return intersect_<Policy>(a, b, c, p, q, is);
-
-        else if (geo1.corners() == 4)
-        {
-            Intersection is1, is2;
-            bool hasSegment1, hasSegment2;
-
-            const auto d = geo1.corner(3);
-            const bool intersects1 = intersect_<Policy>(a, b, d, p, q, is1, hasSegment1);
-            const bool intersects2 = intersect_<Policy>(a, d, c, p, q, is2, hasSegment2);
-
-            if (hasSegment1 || hasSegment2)
-                return false;
-
-            if (intersects1) { is = is1; return true; }
-            if (intersects2) { is = is2; return true; }
-
-            return false;
-        }
-
-        else
-            DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type "
-                          << geo1.type() << ", "<< geo1.corners() << " corners.");
-    }
-
-private:
-    /*!
-     * \brief Obtain local coordinates of start/end point of the intersecting segment.
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0>
-    static bool intersect_(const Geometry1& geo1, const Geometry2& geo2, ctype& tfirst, ctype& tlast)
-    {
-        // lambda to obtain the facet corners on geo1
-        auto getFacetCorners = [] (const Geometry1& geo1)
-        {
-            std::vector< std::array<int, 2> > facetCorners;
-            switch (geo1.corners())
-            {
-                case 4: // quadrilateral
-                    facetCorners = {{0, 2}, {3, 1}, {1, 0}, {2, 3}};
-                    break;
-                case 3: // triangle
-                    facetCorners = {{1, 0}, {0, 2}, {2, 1}};
-                    break;
-                default:
-                    DUNE_THROW(Dune::NotImplemented, "Collision of segment and geometry of type "
-                                   << geo1.type() << " with "<< geo1.corners() << " corners.");
-            }
-
-            return facetCorners;
-        };
-
-        const auto center1 = geo1.center();
-        const auto normal1 = crossProduct(geo1.corner(1) - geo1.corner(0),
-                                          geo1.corner(2) - geo1.corner(0));
-
-        // lambda to obtain the normal on a facet
-        auto computeNormal = [&center1, &normal1, &geo1] (const std::array<int, 2>& facetCorners)
-        {
-            const auto c0 = geo1.corner(facetCorners[0]);
-            const auto c1 = geo1.corner(facetCorners[1]);
-            const auto edge = c1 - c0;
-
-            Dune::FieldVector<ctype, dimworld> n = crossProduct(edge, normal1);
-            n /= n.two_norm();
-
-            // orientation of the element is not known
-            // make sure normal points outwards of element
-            if ( n*(center1-c0) > 0.0 )
-                n *= -1.0;
-
-            return n;
-        };
-
-        return Detail::computeSegmentIntersection(geo1, geo2, eps_, tfirst, tlast, getFacetCorners, computeNormal);
-    }
-
-    /*!
-     * \brief triangle--segment point-like intersection with points as input.
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0>
-    static bool intersect_(const Point& a, const Point& b, const Point& c,
-                           const Point& p, const Point& q,
-                           Intersection& is)
-    {
-        bool hasSegment;
-        return intersect_(a, b, c, p, q, is, hasSegment);
-    }
-
-    /*!
-     * \brief triangle--segment point-like intersection with points as input. Also
-     *        stores if a segment-like intersection was found in the provided boolean.
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0>
-    static bool intersect_(const Point& a, const Point& b, const Point& c,
-                           const Point& p, const Point& q,
-                           Intersection& is, bool& hasSegmentIs)
-    {
-        hasSegmentIs = false;
-
-        const auto ab = b - a;
-        const auto ac = c - a;
-        const auto qp = p - q;
-
-        // compute the triangle normal that defines the triangle plane
-        const auto normal = crossProduct(ab, ac);
-
-        // compute the denominator
-        // if denom is 0 the segment is parallel and we can return
-        const auto denom = normal*qp;
-        const auto abnorm2 = ab.two_norm2();
-        const auto eps = eps_*abnorm2*qp.two_norm();
-        using std::abs;
-        if (abs(denom) < eps)
-        {
-            const auto pa = a - p;
-            const auto denom2 = normal*pa;
-            if (abs(denom2) > eps_*pa.two_norm()*abnorm2)
-                return false;
-
-            // if we get here, we are in-plane. Check if a
-            // segment-like intersection with geometry 1 exists.
-            using SegmentPolicy = typename IntersectionPolicy::SegmentPolicy<ctype, dimworld>;
-            using Triangle = Dune::AffineGeometry<ctype, 2, dimworld>;
-            using Segment = Dune::AffineGeometry<ctype, 1, dimworld>;
-            using SegmentIntersectionAlgorithm = GeometryIntersection<Triangle, Segment, SegmentPolicy>;
-            using SegmentIntersectionType = typename SegmentIntersectionAlgorithm::Intersection;
-            SegmentIntersectionType segmentIs;
-
-            Triangle triangle(Dune::GeometryTypes::simplex(2), std::array<Point, 3>({a, b, c}));
-            Segment segment(Dune::GeometryTypes::simplex(1), std::array<Point, 2>({p, q}));
-            if (SegmentIntersectionAlgorithm::intersection(triangle, segment, segmentIs))
-            {
-                hasSegmentIs = true;
-                return false;
-            }
-
-            // We are in-plane. A point-like
-            // intersection can only be on the edges
-            for (const auto& ip : {p, q})
-            {
-                if ( intersectsPointSimplex(ip, a, b)
-                     || intersectsPointSimplex(ip, b, c)
-                     || intersectsPointSimplex(ip, c, a) )
-                {
-                    is = ip;
-                    return true;
-                }
-            }
-
-            return false;
-        }
-
-        // compute intersection t value of pq with plane of triangle.
-        // a segment intersects if and only if 0 <= t <= 1.
-        const auto ap = p - a;
-        const auto t = (ap*normal)/denom;
-        if (t < 0.0 - eps_) return false;
-        if (t > 1.0 + eps_) return false;
-
-        // compute the barycentric coordinates and check if the intersection point
-        // is inside the bounds of the triangle
-        const auto e = crossProduct(qp, ap);
-        const auto v = (ac*e)/denom;
-        if (v < -eps_ || v > 1.0 + eps_) return false;
-        const auto w = -(ab*e)/denom;
-        if (w < -eps_ || v + w > 1.0 + eps_) return false;
-
-        // Now we are sure there is an intersection points
-        // Perform delayed division compute the last barycentric coordinate component
-        const auto u = 1.0 - v - w;
-
-        Point ip(0.0);
-        ip.axpy(u, a);
-        ip.axpy(v, b);
-        ip.axpy(w, c);
-        is = ip;
-        return true;
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for segment--polygon intersection in 3d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 1, 2>
-: public GeometryIntersection<Geometry2, Geometry1, Policy, 3, 2, 1>
-{
-    using Base = GeometryIntersection<Geometry2, Geometry1, Policy, 3, 2, 1>;
-public:
-    /*!
-     * \brief Colliding segment and convex polygon
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide intersection holds the
-     *        corner points of the intersection object in global coordinates.
-     * \note This forwards to the polyhedron-polygon specialization with swapped arguments.
-     */
-    template<class P = Policy>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, typename Base::Intersection& intersection)
-    {
-        return Base::intersection(geo2, geo1, intersection);
-    }
-};
-
-/*!
- * \ingroup Geometry
- * \brief A class for segment--segment intersection in 3d space
- */
-template <class Geometry1, class Geometry2, class Policy>
-class GeometryIntersection<Geometry1, Geometry2, Policy, 3, 1, 1>
-{
-    enum { dimworld = 3 };
-    enum { dim1 = 1 };
-    enum { dim2 = 1 };
-
-public:
-    using ctype = typename Policy::ctype;
-    using Point = typename Policy::Point;
-    using Intersection = typename Policy::Intersection;
-
-private:
-    static constexpr ctype eps_ = 1.5e-7; // base epsilon for floating point comparisons
-
-public:
-    /*!
-     * \brief Colliding two segments
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection Container to store corners of intersection segment
-     * \note this overload is used when point-like intersections are seeked
-     * \todo implement this query
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 0, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-        DUNE_THROW(Dune::NotImplemented, "segment-segment intersection detection for point-like intersections");
-    }
-
-    /*!
-     *  \brief Colliding two segments in 3D
-     * \param geo1/geo2 The geometries to intersect
-     * \param intersection If the geometries collide, is holds the corner points of
-     *        the intersection object in global coordinates.
-     * \note This overload is used when segment-like intersections are seeked
-     */
-    template<class P = Policy, std::enable_if_t<P::dimIntersection == 1, int> = 0>
-    static bool intersection(const Geometry1& geo1, const Geometry2& geo2, Intersection& intersection)
-    {
-        static_assert(int(dimworld) == int(Geometry2::coorddimension), "Can only collide geometries of same coordinate dimension");
-
-        const auto& a = geo1.corner(0);
-        const auto& b = geo1.corner(1);
-        const auto ab = b-a;
-
-        const auto& p = geo2.corner(0);
-        const auto& q = geo2.corner(1);
-        const auto pq = q-p;
-
-        const auto abNorm2 = ab.two_norm2();
-        const auto pqNorm2 = pq.two_norm2();
-
-        using std::max;
-        const auto eps2 = eps_*max(abNorm2, pqNorm2);
-
-        // if the segment are not parallel there is no segment intersection
-        using std::abs;
-        if (crossProduct(ab, pq).two_norm2() > eps2*eps2)
-            return false;
-
-        const auto ap = (p-a);
-        const auto aq = (q-a);
-
-        // points have to be colinear
-        if (crossProduct(ap, aq).two_norm2() > eps2*eps2)
-            return false;
-
-        // scaled local coordinates
-        // we save the division for the normalization for now
-        // and do it in the very end if we find an intersection
-        auto tp = ap*ab;
-        auto tq = aq*ab;
-
-        // make sure they are sorted
-        using std::swap;
-        if (tp > tq)
-            swap(tp, tq);
-
-        using std::clamp;
-        tp = clamp(tp, 0.0, abNorm2);
-        tq = clamp(tq, 0.0, abNorm2);
-
-        if (abs(tp-tq) < eps2)
-            return false;
-
-        intersection = Intersection({geo1.global(tp/abNorm2), geo1.global(tq/abNorm2)});
-        return true;
-    }
-};
-
-} // end namespace Dumux
-
-# endif
+#endif
diff --git a/dumux/common/geometry/grahamconvexhull.hh b/dumux/common/geometry/grahamconvexhull.hh
index 3ed273d9e8a98772345d5d41ea3b7d5783f89830..b1a3155bfe7b4b89ce44fe2e0d18277b61f5f830 100644
--- a/dumux/common/geometry/grahamconvexhull.hh
+++ b/dumux/common/geometry/grahamconvexhull.hh
@@ -19,200 +19,15 @@
  * \ingroup Geometry
  * \brief A function to compute the convex hull of a point cloud
  *        and a function to triangulate the polygon area spanned by the convex hull
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_GRAHAM_CONVEX_HULL_HH
-#define DUMUX_GRAHAM_CONVEX_HULL_HH
+#ifndef DUMUX_COMMON_GEOMETRY_GRAHAM_CONVEX_HULL_HH
+#define DUMUX_COMMON_GEOMETRY_GRAHAM_CONVEX_HULL_HH
 
-#include <vector>
-#include <array>
-#include <algorithm>
-#include <iterator>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/grahamconvexhull.hh"
 
-#include <dune/common/exceptions.hh>
-#include <dune/common/fvector.hh>
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/grahamconvexhull.hh>
 
-#include <dumux/common/math.hh>
-#include <dumux/common/geometry/triangulation.hh>
-
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief Returns the orientation of a sequence a-->b-->c in one plane (defined by normal vector)
- * \return -1   if a-->b-->c forms a counter-clockwise turn (given the normal vector)
- *         +1   for a clockwise turn,
- *          0   if they are on one line (colinear)
- */
-template<class ctype>
-int getOrientation(const Dune::FieldVector<ctype, 3>& a,
-                   const Dune::FieldVector<ctype, 3>& b,
-                   const Dune::FieldVector<ctype, 3>& c,
-                   const Dune::FieldVector<ctype, 3>& normal)
-{
-    const auto d = b-a;
-    const auto e = c-b;
-    const auto f = Dumux::crossProduct(d, e);
-    const auto area = f*normal;
-    return Dumux::sign(-area);
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the points making up the convex hull around the given set of unordered points
- * \note We assume that all points are coplanar and there are no indentical points in the list
- * \note This algorithm changes the order of the given points a bit
- *       as they are unordered anyway this shouldn't matter too much
- */
-template<int dim, class ctype,
-         std::enable_if_t<(dim==2), int> = 0>
-std::vector<Dune::FieldVector<ctype, 3>>
-grahamConvexHullImpl(std::vector<Dune::FieldVector<ctype, 3>>& points)
-{
-    using Point = Dune::FieldVector<ctype, 3>;
-    std::vector<Point> convexHull;
-
-    // return empty convex hull
-    if (points.size() < 3)
-        return convexHull;
-
-    // return the points (already just one triangle)
-    if (points.size() == 3)
-        return points;
-
-    // try to compute the normal vector of the plane
-    const auto a = points[1] - points[0];
-    auto b = points[2] - points[0];
-    auto normal = Dumux::crossProduct(a, b);
-
-    // make sure the normal vector has non-zero length
-    std::size_t k = 2;
-    auto norm = normal.two_norm();
-    while (norm == 0.0 && k < points.size()-1)
-    {
-        b = points[++k];
-        normal = Dumux::crossProduct(a, b);
-        norm = normal.two_norm();
-    }
-
-    // if all given points are colinear -> return empty convex hull
-    if (norm == 0.0)
-        return convexHull;
-
-    using std::sqrt;
-    const auto eps = 1e-7*sqrt(norm);
-    normal /= norm;
-
-    // find the element with the smallest x coordinate (if x is the same, smallest y coordinate, and so on...)
-    auto minIt = std::min_element(points.begin(), points.end(), [&eps](const auto& a, const auto& b)
-    {
-        using std::abs;
-        return (abs(a[0]-b[0]) > eps ? a[0] < b[0] : (abs(a[1]-b[1]) > eps ? a[1] < b[1] : (a[2] < b[2])));
-    });
-
-    // swap the smallest element to the front
-    std::iter_swap(minIt, points.begin());
-
-    // choose the first (min element) as the pivot point
-    // sort in counter-clockwise order around pivot point
-    const auto pivot = points[0];
-    std::sort(points.begin()+1, points.end(), [&](const auto& a, const auto& b)
-    {
-        const int order = getOrientation(pivot, a, b, normal);
-        if (order == 0)
-             return (a-pivot).two_norm() < (b-pivot).two_norm();
-        else
-             return (order == -1);
-    });
-
-    // push the first three points
-    convexHull.reserve(50);
-    convexHull.push_back(points[0]);
-    convexHull.push_back(points[1]);
-    convexHull.push_back(points[2]);
-
-    // This is the heart of the algorithm
-    // pop_back until the last point in the queue forms a counter-clockwise oriented line
-    // with the next two vertices. Then add these points to the queue.
-    for (std::size_t i = 3; i < points.size(); ++i)
-    {
-        Point p = convexHull.back();
-        convexHull.pop_back();
-        // keep popping until the orientation a->b->currentp is counter-clockwise
-        while (getOrientation(convexHull.back(), p, points[i], normal) != -1)
-        {
-            // make sure the queue doesn't get empty
-            if (convexHull.size() == 1)
-            {
-                // before we reach i=size-1 there has to be a good candidate
-                // as not all points are colinear (a non-zero plane normal exists)
-                assert(i < points.size()-1);
-                p = points[i++];
-            }
-            else
-            {
-                p = convexHull.back();
-                convexHull.pop_back();
-            }
-        }
-
-        // add back the last popped point and this point
-        convexHull.emplace_back(std::move(p));
-        convexHull.push_back(points[i]);
-    }
-
-    return convexHull;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the points making up the convex hull around the given set of unordered points
- * \note This is the specialization for 2d space. Here, we make use of the generic implementation
- *       for the case of coplanar points in 3d space (a more efficient implementation could be provided).
- */
-template<int dim, class ctype,
-         std::enable_if_t<(dim==2), int> = 0>
-std::vector<Dune::FieldVector<ctype, 2>>
-grahamConvexHullImpl(const std::vector<Dune::FieldVector<ctype, 2>>& points)
-{
-    std::vector<Dune::FieldVector<ctype, 3>> points3D;
-    points3D.reserve(points.size());
-    std::transform(points.begin(), points.end(), std::back_inserter(points3D),
-                   [](const auto& p) { return Dune::FieldVector<ctype, 3>({p[0], p[1], 0.0}); });
-
-    const auto result3D = grahamConvexHullImpl<2>(points3D);
-
-    std::vector<Dune::FieldVector<ctype, 2>> result2D;
-    result2D.reserve(result3D.size());
-    std::transform(result3D.begin(), result3D.end(), std::back_inserter(result2D),
-                   [](const auto& p) { return Dune::FieldVector<ctype, 2>({p[0], p[1]}); });
-
-    return result2D;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the points making up the convex hull around the given set of unordered points
- * \note We assume that all points are coplanar and there are no indentical points in the list
- */
-template<int dim, class ctype, int dimWorld>
-std::vector<Dune::FieldVector<ctype, dimWorld>> grahamConvexHull(std::vector<Dune::FieldVector<ctype, dimWorld>>& points)
-{
-    return grahamConvexHullImpl<dim>(points);
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the points making up the convex hull around the given set of unordered points
- * \note We assume that all points are coplanar and there are no indentical points in the list
- * \note This is the overload if we are not allowed to write into the given points vector
- */
-template<int dim, class ctype, int dimWorld>
-std::vector<Dune::FieldVector<ctype, dimWorld>> grahamConvexHull(const std::vector<Dune::FieldVector<ctype, dimWorld>>& points)
-{
-    auto copyPoints = points;
-    return grahamConvexHullImpl<dim>(copyPoints);
-}
-
-} // end namespace Dumux
-
-# endif
+#endif
diff --git a/dumux/common/geometry/intersectingentities.hh b/dumux/common/geometry/intersectingentities.hh
index 15378819faf88a687851de7877fc9414ff4da72f..4d529eab1a94baf82d5b5edfac087330ffaf147e 100644
--- a/dumux/common/geometry/intersectingentities.hh
+++ b/dumux/common/geometry/intersectingentities.hh
@@ -18,378 +18,15 @@
  * \file
  * \ingroup Geometry
  * \brief Algorithms that finds which geometric entites intersect
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_INTERSECTING_ENTITIES_HH
-#define DUMUX_INTERSECTING_ENTITIES_HH
+#ifndef DUMUX_COMMON_GEOMETRY_INTERSECTING_ENTITIES_HH
+#define DUMUX_COMMON_GEOMETRY_INTERSECTING_ENTITIES_HH
 
-#include <cmath>
-#include <type_traits>
-#include <vector>
-#include <algorithm>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/intersectingentities.hh"
 
-#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/triangulation.hh>
-
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief An intersection object resulting from the intersection of two primitives in an entity set
- * \note this is used as return type for some of the intersectingEntities overloads below
- */
-template<int dimworld, class CoordTypeA, class CoordTypeB = CoordTypeA>
-class IntersectionInfo
-{
-public:
-    using ctype = typename Dune::PromotionTraits<CoordTypeA, CoordTypeB>::PromotedType;
-    static constexpr int dimensionworld = dimworld;
-    using GlobalPosition = Dune::FieldVector<ctype, dimworld>;
-
-    template<class Corners>
-    explicit IntersectionInfo(std::size_t a, std::size_t b, Corners&& c)
-    : a_(a)
-    , b_(b)
-    , corners_(c.begin(), c.end())
-    {}
-
-    //! 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
-};
-
-/*!
- * \ingroup Geometry
- * \brief 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,
-                     bool isCartesianGrid = false)
-{
-    // Call the recursive find function to find candidates
-    std::vector<std::size_t> entities;
-    intersectingEntities(point, tree, tree.numBoundingBoxes() - 1, entities, isCartesianGrid);
-    return entities;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute intersections with point for all nodes of the bounding box tree recursively
- */
-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,
-                          bool isCartesianGrid = false)
-{
-    // 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;
-        // for structured cube grids skip the primitive test
-        if (isCartesianGrid)
-            entities.push_back(entityIdx);
-        else
-        {
-            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, isCartesianGrid);
-        intersectingEntities(point, tree, bBox.child1, entities, isCartesianGrid);
-    }
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute all intersections between a geometry and a bounding box tree
- */
-template<class Geometry, class EntitySet>
-inline std::vector<IntersectionInfo<Geometry::coorddimension, typename Geometry::ctype, typename EntitySet::ctype>>
-intersectingEntities(const Geometry& geometry,
-                     const BoundingBoxTree<EntitySet>& tree)
-{
-    // check if the world dimensions match
-    static_assert(int(Geometry::coorddimension) == int(EntitySet::dimensionworld),
-        "Can only intersect geometry and bounding box tree of same world dimension");
-
-    // Create data structure for return type
-    std::vector<IntersectionInfo<Geometry::coorddimension, typename Geometry::ctype, typename EntitySet::ctype>> intersections;
-    using ctype = typename IntersectionInfo<Geometry::coorddimension, typename Geometry::ctype, typename EntitySet::ctype>::ctype;
-    static constexpr int dimworld = Geometry::coorddimension;
-
-    // compute the bounding box of the given geometry
-    std::array<ctype, 2*Geometry::coorddimension> bBox;
-    ctype* xMin = bBox.data(); ctype* xMax = xMin + Geometry::coorddimension;
-
-    // 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]);
-        }
-    }
-
-    // Call the recursive find function to find candidates
-    intersectingEntities(geometry, tree,
-                         bBox, tree.numBoundingBoxes() - 1,
-                         intersections);
-
-    return intersections;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute intersections with point for all nodes of the bounding box tree recursively
- */
-template<class Geometry, class EntitySet>
-void intersectingEntities(const Geometry& geometry,
-                          const BoundingBoxTree<EntitySet>& tree,
-                          const std::array<typename Geometry::ctype, 2*Geometry::coorddimension>& bBox,
-                          std::size_t nodeIdx,
-                          std::vector<IntersectionInfo<Geometry::coorddimension,
-                                                       typename Geometry::ctype,
-                                                       typename EntitySet::ctype>>& intersections)
-{
-    // if the two bounding boxes don't intersect we can stop searching
-    static constexpr int dimworld = Geometry::coorddimension;
-    if (!intersectsBoundingBoxBoundingBox<dimworld>(bBox.data(), tree.getBoundingBoxCoordinates(nodeIdx)))
-        return;
-
-    // get node info for current bounding box node
-    const auto& bBoxNode = tree.getBoundingBoxNode(nodeIdx);
-
-    // if the box is a leaf do the primitive test.
-    if (tree.isLeaf(bBoxNode, nodeIdx))
-    {
-        // eIdxA is always 0 since we intersect with exactly one geometry
-        const auto eIdxA = 0;
-        const auto eIdxB = bBoxNode.child1;
-
-        const auto geometryTree = tree.entitySet().entity(eIdxB).geometry();
-        using GeometryTree = std::decay_t<decltype(geometryTree)>;
-        using Policy = IntersectionPolicy::DefaultPolicy<Geometry, GeometryTree>;
-        using IntersectionAlgorithm = GeometryIntersection<Geometry, GeometryTree, Policy>;
-        using Intersection = typename IntersectionAlgorithm::Intersection;
-        Intersection intersection;
-
-        if (IntersectionAlgorithm::intersection(geometry, geometryTree, intersection))
-        {
-            static constexpr int dimIntersection = Policy::dimIntersection;
-            if (dimIntersection >= 2)
-            {
-                const auto triangulation = triangulate<dimIntersection, dimworld>(intersection);
-                for (unsigned int i = 0; i < triangulation.size(); ++i)
-                    intersections.emplace_back(eIdxA, eIdxB, std::move(triangulation[i]));
-            }
-            else
-                intersections.emplace_back(eIdxA, eIdxB, intersection);
-        }
-    }
-
-    // No leaf. Check both children nodes.
-    else
-    {
-        intersectingEntities(geometry, tree, bBox, bBoxNode.child0, intersections);
-        intersectingEntities(geometry, tree, bBox, bBoxNode.child1, intersections);
-    }
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute all intersections between two bounding box trees
- */
-template<class EntitySet0, class EntitySet1>
-inline std::vector<IntersectionInfo<EntitySet0::dimensionworld, typename EntitySet0::ctype, typename EntitySet1::ctype>>
-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<IntersectionInfo<EntitySet0::dimensionworld, typename EntitySet0::ctype, typename EntitySet1::ctype>> intersections;
-
-    // Call the recursive find function to find candidates
-    intersectingEntities(treeA, treeB,
-                         treeA.numBoundingBoxes() - 1,
-                         treeB.numBoundingBoxes() - 1,
-                         intersections);
-
-    return intersections;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute all intersections between two all 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<IntersectionInfo<EntitySet0::dimensionworld,
-                                                       typename EntitySet0::ctype,
-                                                       typename EntitySet1::ctype>>& 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 GeometryA = std::decay_t<decltype(geometryA)>;
-        using GeometryB = std::decay_t<decltype(geometryB)>;
-        using Policy = IntersectionPolicy::DefaultPolicy<GeometryA, GeometryB>;
-        using IntersectionAlgorithm = GeometryIntersection<GeometryA, GeometryB, Policy>;
-        using Intersection = typename IntersectionAlgorithm::Intersection;
-        Intersection intersection;
-
-        if (IntersectionAlgorithm::intersection(geometryA, geometryB, intersection))
-        {
-            static constexpr int dimIntersection = Policy::dimIntersection;
-
-            if (dimIntersection >= 2)
-            {
-                const auto triangulation = triangulate<dimIntersection, dimworld>(intersection);
-                for (unsigned int i = 0; i < triangulation.size(); ++i)
-                    intersections.emplace_back(eIdxA, eIdxB, std::move(triangulation[i]));
-            }
-            else
-                intersections.emplace_back(eIdxA, eIdxB, 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);
-    }
-}
-
-/*!
- * \ingroup Geometry
- * \brief Compute the index of the intersecting element of a Cartesian grid with a point
- * The grid is given by the lower left corner (min), the upper right corner (max)
- * and the number of cells in each direction (cells).
- * \note If there are several options the lowest matching cell index will be returned
- * \note Returns the index i + I*j + I*J*k for the intersecting element i,j,k of a grid with I,J,K cells
- */
-template<class ctype, int dimworld>
-inline std::size_t intersectingEntityCartesianGrid(const Dune::FieldVector<ctype, dimworld>& point,
-                                                   const Dune::FieldVector<ctype, dimworld>& min,
-                                                   const Dune::FieldVector<ctype, dimworld>& max,
-                                                   const std::array<int, std::size_t(dimworld)>& cells)
-{
-    std::size_t index = 0;
-    for (int i = 0; i < dimworld; ++i)
-    {
-        using std::clamp; using std::floor;
-        ctype dimOffset = clamp<ctype>(floor((point[i]-min[i])*cells[i]/(max[i]-min[i])), 0.0, cells[i]-1);
-        for (int j = 0; j < i; ++j)
-            dimOffset *= cells[j];
-        index += static_cast<std::size_t>(dimOffset);
-    }
-    return index;
-}
-
-} // end namespace Dumux
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/intersectingentities.hh>
 
 #endif
diff --git a/dumux/common/geometry/intersectionentityset.hh b/dumux/common/geometry/intersectionentityset.hh
index 7fad35dd08ab836297d62ac6a3880c064f38dfaa..6aa4b6f66f369b33af20da9948e86065b09e860e 100644
--- a/dumux/common/geometry/intersectionentityset.hh
+++ b/dumux/common/geometry/intersectionentityset.hh
@@ -20,271 +20,16 @@
  * \file
  * \ingroup Geometry
  * \brief A class representing the intersection entites two geometric entity sets
+ * DEPRECATED will be removed once this header is removed
  */
 
 #ifndef DUMUX_COMMON_GEOMETRY_INTERSECTION_ENTITY_SET_HH
 #define DUMUX_COMMON_GEOMETRY_INTERSECTION_ENTITY_SET_HH
 
-#include <algorithm>
-#include <cassert>
-#include <iostream>
-#include <memory>
-#include <type_traits>
-#include <utility>
-#include <vector>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/intersectionentityset.hh"
 
-#include <dune/common/indices.hh>
-#include <dune/common/timer.hh>
-#include <dune/common/iteratorrange.hh>
-#include <dune/common/promotiontraits.hh>
-#include <dune/common/reservedvector.hh>
-#include <dune/geometry/affinegeometry.hh>
-#include <dune/geometry/type.hh>
-
-#include <dumux/common/geometry/boundingboxtree.hh>
-#include <dumux/common/geometry/intersectingentities.hh>
-
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief A class representing the intersection entites two geometric entity sets
- */
-template<class DomainEntitySet, class TargetEntitySet>
-class IntersectionEntitySet
-{
-    using DomainTree = BoundingBoxTree<DomainEntitySet>;
-    using TargetTree = BoundingBoxTree<TargetEntitySet>;
-
-    using ctype = typename Dune::PromotionTraits<typename DomainEntitySet::ctype, typename TargetEntitySet::ctype>::PromotedType;
-
-    static constexpr int dimWorld = DomainEntitySet::dimensionworld;
-    static_assert(dimWorld == int(TargetEntitySet::dimensionworld), "Entity sets must have the same world dimension");
-
-    using GlobalPosition = Dune::FieldVector<ctype, dimWorld>;
-
-    static constexpr int dimDomain = DomainEntitySet::Entity::Geometry::mydimension;
-    static constexpr int dimTarget = TargetEntitySet::Entity::Geometry::mydimension;
-    static constexpr bool isMixedDimensional = dimDomain != dimTarget;
-
-    /*!
-     * \brief A class representing an intersection entity
-     */
-    class IntersectionEntity
-    {
-        static constexpr int dimIs = std::min(dimDomain, dimTarget);
-        using Geometry = Dune::AffineGeometry<ctype, dimIs, dimWorld>; // geometries are always simplices
-
-        // we can only have multiple neighbors in the mixeddimensional case and then only for the side with the largest dimension
-        using IndexStorage = std::pair<std::conditional_t<dimDomain <= dimTarget, Dune::ReservedVector<std::size_t, 1>, std::vector<std::size_t>>,
-                                       std::conditional_t<dimTarget <= dimDomain, Dune::ReservedVector<std::size_t, 1>, std::vector<std::size_t>>>;
-
-        static constexpr auto domainIdx = Dune::index_constant<0>{};
-        static constexpr auto targetIdx = Dune::index_constant<1>{};
-
-    public:
-        IntersectionEntity(const DomainTree& domainTree, const TargetTree& targetTree)
-        : domainTree_(domainTree)
-        , targetTree_(targetTree)
-        {}
-
-        //! set the intersection geometry corners
-        void setCorners(const std::vector<GlobalPosition>& corners)
-        {
-            corners_ = corners;
-            assert(corners.size() == dimIs + 1); // Only simplex intersections are allowed
-        }
-
-        //! add a pair of neighbor elements
-        void addNeighbors(std::size_t domain, std::size_t target)
-        {
-            if (numDomainNeighbors() == 0 && numTargetNeighbors() == 0)
-            {
-                std::get<domainIdx>(neighbors_).push_back(domain);
-                std::get<targetIdx>(neighbors_).push_back(target);
-            }
-            else if (dimDomain > dimTarget)
-                std::get<domainIdx>(neighbors_).push_back(domain);
-
-            else if (dimTarget > dimDomain)
-                std::get<targetIdx>(neighbors_).push_back(target);
-
-            else
-                DUNE_THROW(Dune::InvalidStateException, "Cannot add more than one neighbor per side for equidimensional intersection!");
-        }
-
-        //! get the intersection geometry
-        Geometry geometry() const
-        { return Geometry(Dune::GeometryTypes::simplex(dimIs), corners_); }
-
-        //! get the number of domain neighbors of this intersection
-        std::size_t numDomainNeighbors() const
-        { return std::get<domainIdx>(neighbors_).size(); }
-
-        //! get the number of target neighbors of this intersection
-        std::size_t numTargetNeighbors() const
-        { return std::get<targetIdx>(neighbors_).size(); }
-
-        //! get the nth domain neighbor entity
-        typename DomainEntitySet::Entity domainEntity(unsigned int n = 0) const
-        { return domainTree_.entitySet().entity(std::get<domainIdx>(neighbors_)[n]); }
-
-        //! get the nth target neighbor entity
-        typename TargetEntitySet::Entity targetEntity(unsigned int n = 0) const
-        { return targetTree_.entitySet().entity(std::get<targetIdx>(neighbors_)[n]); }
-
-    private:
-        IndexStorage neighbors_;
-        std::vector<GlobalPosition> corners_;
-
-        const DomainTree& domainTree_;
-        const TargetTree& targetTree_;
-    };
-
-    using Intersections = std::vector<IntersectionEntity>;
-
-public:
-    //! make intersection entity type available
-    using Entity = IntersectionEntity;
-    //! make entity iterator type available
-    using EntityIterator = typename Intersections::const_iterator;
-
-    /*!
-     * \brief Default constructor
-     */
-    IntersectionEntitySet() = default;
-
-    /*!
-     * \brief Build intersections
-     */
-    void build(std::shared_ptr<const DomainEntitySet> domainSet, std::shared_ptr<const TargetEntitySet> targetSet)
-    {
-        domainTree_ = std::make_shared<DomainTree>(domainSet);
-        targetTree_ = std::make_shared<TargetTree>(targetSet);
-        build(*domainTree_, *targetTree_);
-    }
-
-    /*!
-     * \brief Build intersections
-     */
-    void build(std::shared_ptr<const DomainTree> domainTree, std::shared_ptr<const TargetTree> targetTree)
-    {
-        // make sure the tree don't get out of scope
-        domainTree_ = domainTree;
-        targetTree_ = targetTree;
-        build(*domainTree_, *targetTree_);
-    }
-
-    /*!
-     * \brief Build intersections
-     * \note If you call this, make sure the bounding box tree stays alive for the life-time of this object
-     */
-    void build(const DomainTree& domainTree, const TargetTree& targetTree)
-    {
-        Dune::Timer timer;
-
-        // compute raw intersections
-        const auto rawIntersections = intersectingEntities(domainTree, targetTree);
-
-        // create a map to check whether intersection geometries were already inserted
-        // Note that this can only occur if the grids have different dimensionality.
-        // If this is the case, we keep track of the intersections using the indices of the lower-
-        // dimensional entities which is identical for all geometrically identical intersections.
-        std::vector<std::vector<std::vector<GlobalPosition>>> intersectionMap;
-        std::vector<std::vector<std::size_t>> intersectionIndex;
-        if constexpr (isMixedDimensional)
-        {
-            const auto numLowDimEntities = dimTarget < dimDomain ? targetTree.entitySet().size()
-                                                                 : domainTree.entitySet().size();
-            intersectionMap.resize(numLowDimEntities);
-            intersectionIndex.resize(numLowDimEntities);
-        }
-
-        // reserve memory for storing the intersections. In case of grids of
-        // different dimensionality this might be an overestimate. We get rid
-        // of the overhead memory at the end of this function though.
-        intersections_.clear();
-        intersections_.reserve(rawIntersections.size());
-
-        for (const auto& rawIntersection : rawIntersections)
-        {
-            bool add = true;
-
-            // Check if intersection was already inserted.
-            // In this case we only add new neighbor information as the geometry is identical.
-            if constexpr (isMixedDimensional)
-            {
-                const auto lowDimNeighborIdx = getLowDimNeighborIdx_(rawIntersection);
-                for (int i = 0; i < intersectionMap[lowDimNeighborIdx].size(); ++i)
-                {
-                    if (rawIntersection.cornersMatch(intersectionMap[lowDimNeighborIdx][i]))
-                    {
-                        add = false;
-                        // only add the pair of neighbors using the insertionIndex
-                        auto idx = intersectionIndex[lowDimNeighborIdx][i];
-                        intersections_[idx].addNeighbors(rawIntersection.first(), rawIntersection.second());
-                        break;
-                    }
-                }
-            }
-
-            if(add)
-            {
-                // maybe add to the map
-                if constexpr (isMixedDimensional)
-                {
-                    intersectionMap[getLowDimNeighborIdx_(rawIntersection)].push_back(rawIntersection.corners());
-                    intersectionIndex[getLowDimNeighborIdx_(rawIntersection)].push_back(intersections_.size());
-                }
-
-                // add new intersection and add the neighbors
-                intersections_.emplace_back(domainTree, targetTree);
-                intersections_.back().setCorners(rawIntersection.corners());
-                intersections_.back().addNeighbors(rawIntersection.first(), rawIntersection.second());
-            }
-        }
-
-        intersections_.shrink_to_fit();
-        std::cout << "Computed " << size() << " intersection entities in " << timer.elapsed() << std::endl;
-    }
-
-    //! return begin iterator to intersection container
-    typename Intersections::const_iterator ibegin() const
-    { return intersections_.begin(); }
-
-    //! return end iterator to intersection container
-    typename Intersections::const_iterator iend() const
-    { return intersections_.end(); }
-
-    //! the number of intersections
-    std::size_t size() const
-    { return intersections_.size(); }
-
-    /*!
-     * \brief Range generator to iterate with range-based for loops over all intersections
-     *        as follows: for (const auto& is : intersections(glue)) { ... }
-     * \note free function
-     */
-    friend Dune::IteratorRange<EntityIterator> intersections(const IntersectionEntitySet& set)
-    { return {set.ibegin(), set.iend()}; }
-
-private:
-    template<class RawIntersection,
-             bool enable = isMixedDimensional, std::enable_if_t<enable, int> = 0>
-    auto getLowDimNeighborIdx_(const RawIntersection& is)
-    {
-        if constexpr (dimTarget < dimDomain)
-            return is.second();
-        else
-            return is.first();
-    }
-
-    Intersections intersections_;
-
-    std::shared_ptr<const DomainTree> domainTree_;
-    std::shared_ptr<const TargetTree> targetTree_;
-};
-
-} // end namespace Dumux
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/intersectionentityset.hh>
 
 #endif
diff --git a/dumux/common/geometry/intersectspointgeometry.hh b/dumux/common/geometry/intersectspointgeometry.hh
index 68f0c8b115da3f04f6722e48973bca68d2efee91..909c6d1b58ae08ed67f3f014b9be2cd50b10b48c 100644
--- a/dumux/common/geometry/intersectspointgeometry.hh
+++ b/dumux/common/geometry/intersectspointgeometry.hh
@@ -18,104 +18,15 @@
  * \file
  * \ingroup Geometry
  * \brief Detect if a point intersects a geometry
+ * DEPRECATED will be removed once this header is removed
  */
 #ifndef DUMUX_INTERSECTS_POINT_GEOMETRY_HH
 #define DUMUX_INTERSECTS_POINT_GEOMETRY_HH
 
-#include <cmath>
-#include <dune/common/exceptions.hh>
-#include <dune/common/fvector.hh>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/intersectspointgeometry.hh"
 
-#include "intersectspointsimplex.hh"
-
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief 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.");
-}
-
-/*!
- * \ingroup Geometry
- * \brief 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.");
-}
-
-/*!
- * \ingroup Geometry
- * \brief 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
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/intersectspointgeometry.hh>
 
 #endif
diff --git a/dumux/common/geometry/intersectspointsimplex.hh b/dumux/common/geometry/intersectspointsimplex.hh
index d3eb254c37729eee6a5b52b37586fb987f05ff85..cb8639f536f0dc8617ce786f92dfec7ae321a0f8 100644
--- a/dumux/common/geometry/intersectspointsimplex.hh
+++ b/dumux/common/geometry/intersectspointsimplex.hh
@@ -18,208 +18,14 @@
  * \file
  * \ingroup Geometry
  * \brief Detect if a point intersects a simplex (including boundary)
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_INTERSECTS_POINT_SIMPLEX_HH
-#define DUMUX_INTERSECTS_POINT_SIMPLEX_HH
+#ifndef DUMUX_COMMON_GEOMETRY_INTERSECTS_POINT_SIMPLEX_HH
+#define DUMUX_COMMON_GEOMETRY_INTERSECTS_POINT_SIMPLEX_HH
 
-#include <cmath>
-#include <dune/common/fvector.hh>
-#include <dumux/common/math.hh>
-
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief 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;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Find out whether a point is inside a triangle (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)
-{
-    // adapted from the algorithm from from "Real-Time Collision Detection" by Christer Ericson,
-    // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc. (Chapter 5.4.2)
-    constexpr ctype eps_ = 1.0e-7;
-
-    // compute the normal of the triangle
-    const auto v1 = p0 - p2;
-    auto n = crossProduct(v1, p1 - p0);
-    const ctype nnorm = n.two_norm();
-    const ctype eps4 = eps_*nnorm*nnorm; // compute an epsilon for later
-    n /= nnorm; // normalize
-
-    // first check if we are in the plane of the triangle
-    // if not we can return early
-    using std::abs;
-    auto x = p0 - point;
-    x /= x.two_norm(); // normalize
-
-    if (abs(x*n) > eps_)
-        return false;
-
-    // translate the triangle so that 'point' is the origin
-    const auto a = p0 - point;
-    const auto b = p1 - point;
-    const auto c = p2 - point;
-
-    // compute the normal vectors for triangles P->A->B and P->B->C
-    const auto u = crossProduct(b, c);
-    const auto v = crossProduct(c, a);
-
-    // they have to point in the same direction or be orthogonal
-    if (u*v < 0.0 - eps4)
-        return false;
-
-    // compute the normal vector for triangle P->C->A
-    const auto w = crossProduct(a, b);
-
-    // it also has to point in the same direction or be orthogonal
-    if (u*w < 0.0 - eps4)
-        return false;
-
-    // check if point is on the line of one of the edges
-    if (u.two_norm2() < eps4)
-        return b*c < 0.0 + eps_*nnorm;
-    if (v.two_norm2() < eps4)
-        return a*c < 0.0 + eps_*nnorm;
-
-    // now the point must be in the triangle (or on the faces)
-    return true;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Find out whether a point is inside a triangle (p0, p1, p2, p3) (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);
-}
-
-/*!
- * \ingroup Geometry
- * \brief Find out whether a point is inside a interval (p0, p1, p2, p3) (dimworld is 3)
- * \note We assume the given interval has non-zero length and use it to scale the epsilon
- */
-template<class ctype, int dimworld, typename std::enable_if_t<(dimworld == 3 || 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;
-
-    const ctype v1norm = v1.two_norm();
-    const ctype v2norm = v2.two_norm();
-
-    // check if point and p0 are the same
-    if (v2norm < v1norm*eps_)
-        return true;
-
-    return (v1.dot(v2) > v1norm*v2norm*(1.0 - eps_) && v2norm < v1norm*(1.0 + eps_));
-}
-
-/*!
- * \ingroup Geometry
- * \brief Find out whether a point is inside a interval (p0, p1, p2, p3) (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
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/intersectspointsimplex.hh"
 
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/intersectspointsimplex.hh>
 #endif
diff --git a/dumux/common/geometry/makegeometry.hh b/dumux/common/geometry/makegeometry.hh
index 68a057e53204c65b3e82614dd0c741245f7b7ca1..2590962b50b9e04ff507b2fe51978f0597e12a08 100644
--- a/dumux/common/geometry/makegeometry.hh
+++ b/dumux/common/geometry/makegeometry.hh
@@ -18,193 +18,15 @@
  * \file
  * \ingroup Geometry
  * \brief Create Dune geometries from user-specified points
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_MAKE_GEOMETRY_HH
-#define DUMUX_MAKE_GEOMETRY_HH
+#ifndef DUMUX_COMMON_GEOMETRY_MAKE_GEOMETRY_HH
+#define DUMUX_COMMON_GEOMETRY_MAKE_GEOMETRY_HH
 
-#include <vector>
-#include <array>
-#include <limits>
-#include <dune/common/fvector.hh>
-#include <dune/common/fmatrix.hh>
-#include <dune/common/exceptions.hh>
-#include <dune/geometry/multilineargeometry.hh>
-#include <dumux/common/math.hh>
-#include <dumux/common/geometry/grahamconvexhull.hh>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/makegeometry.hh"
 
-namespace Dumux {
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/makegeometry.hh>
 
-/*!
- * \ingroup Geometry
- * \brief Checks if four points lie within the same plane
- */
-template<class CoordScalar>
-bool pointsAreCoplanar(const std::vector<Dune::FieldVector<CoordScalar, 3>>& points, const CoordScalar scale)
-{
-    if (points.size() != 4)
-        DUNE_THROW(Dune::InvalidStateException, "Check only works for 4 points!");
-
-    // (see "Real-Time Collision Detection" by Christer Ericson)
-    Dune::FieldMatrix<CoordScalar, 4, 4> M;
-    for (int i = 0; i < 3; ++i )
-        M[i] = {points[0][i], points[1][i], points[2][i], points[3][i]};
-    M[3] = {1.0*scale, 1.0*scale, 1.0*scale, 1.0*scale};
-
-    using std::abs;
-    return abs(M.determinant()) < 1.5e-7*scale*scale*scale*scale;
-}
-
-/*!
- * \ingroup Geometry
- * \brief  Checks if four points lie within the same plane.
- */
-template<class CoordScalar>
-bool pointsAreCoplanar(const std::vector<Dune::FieldVector<CoordScalar, 3>>& points)
-{
-    Dune::FieldVector<CoordScalar, 3> bBoxMin(std::numeric_limits<CoordScalar>::max());
-    Dune::FieldVector<CoordScalar, 3> bBoxMax(std::numeric_limits<CoordScalar>::lowest());
-    for (const auto& p : points)
-    {
-        for (int i=0; i<3; i++)
-        {
-            using std::min;
-            using std::max;
-            bBoxMin[i] = min(bBoxMin[i], p[i]);
-            bBoxMax[i] = max(bBoxMax[i], p[i]);
-        }
-    }
-
-    const auto size = (bBoxMax - bBoxMin).two_norm();
-
-    return pointsAreCoplanar(points, size);
-}
-
-/*!
- * \ingroup Geometry
- * \brief Returns a vector of points following the dune ordering.
- *        Convenience method that creates a temporary object in case no array of orientations is desired.
- *
- * \param points The user-specified vector of points (potentially in wrong order).
- */
-template<class CoordScalar>
-std::vector<Dune::FieldVector<CoordScalar, 3>> getReorderedPoints(const std::vector<Dune::FieldVector<CoordScalar, 3>>& points)
-{
-    std::array<int, 4> tmp;
-    return getReorderedPoints(points, tmp);
-}
-
-/*!
- * \ingroup Geometry
- * \brief Returns a vector of points following the dune ordering.
- *
- * \param points The user-specified vector of points (potentially in wrong order).
- * \param orientations An array of orientations that can be useful for further processing.
- */
-template<class CoordScalar>
-std::vector<Dune::FieldVector<CoordScalar, 3>> getReorderedPoints(const std::vector<Dune::FieldVector<CoordScalar, 3>>& points,
-                                                             std::array<int, 4>& orientations)
-{
-    if(points.size() == 4)
-    {
-        auto& p0 = points[0];
-        auto& p1 = points[1];
-        auto& p2 = points[2];
-        auto& p3 = points[3];
-
-        // check if the points define a proper quadrilateral
-        const auto normal = crossProduct((p1 - p0), (p2 - p0));
-
-        orientations = { getOrientation(p0, p3, p2, normal),
-                         getOrientation(p0, p3, p1, normal),
-                         getOrientation(p2, p1, p0, normal),
-                         getOrientation(p2, p1, p3, normal) };
-
-
-        // check if the points follow the dune ordering (see http://www.dcs.gla.ac.uk/~pat/52233/slides/Geometry1x1.pdf)
-        const bool diagonalsIntersect = (orientations[0] != orientations[1]) && (orientations[2] != orientations[3]);
-
-        // the points conform with the dune ordering
-        if(diagonalsIntersect)
-            return points;
-
-        // the points do not conform with the dune ordering, re-order
-        using GlobalPosition = Dune::FieldVector<CoordScalar, 3>;
-        if(!diagonalsIntersect && orientations[0] == 1)
-            return std::vector<GlobalPosition>{p1, p0, p2, p3};
-        else if(!diagonalsIntersect && orientations[0] == -1)
-            return std::vector<GlobalPosition>{p3, p1, p0, p2};
-        else
-            DUNE_THROW(Dune::InvalidStateException, "Could not reorder points");
-    }
-    else
-        DUNE_THROW(Dune::NotImplemented, "Reorder for " << points.size() << " points.");
-}
-
-/*!
- * \ingroup Geometry
- * \brief Creates a dune quadrilateral geometry given 4 corner points.
- *
- * \tparam CoordScalar The CoordScalar type.
- * \tparam enableSanityCheck Turn on/off sanity check and reordering of points
- * \param points The user-specified vector of points (potentially in wrong order).
- */
-template<class CoordScalar, bool enableSanityCheck = true>
-auto makeDuneQuadrilaterial(const std::vector<Dune::FieldVector<CoordScalar, 3>>& points)
-{
-    if (points.size() != 4)
-        DUNE_THROW(Dune::InvalidStateException, "A quadrilateral needs 4 corner points!");
-
-    using GlobalPosition = Dune::FieldVector<CoordScalar, 3>;
-    static constexpr auto coordDim = GlobalPosition::dimension;
-    static constexpr auto dim = coordDim-1;
-    using GeometryType = Dune::MultiLinearGeometry<CoordScalar, dim, coordDim>;
-
-    // if no sanity check if desired, use the given points directly to construct the geometry
-    if (!enableSanityCheck)
-        return GeometryType(Dune::GeometryTypes::quadrilateral, points);
-
-    // compute size
-    Dune::FieldVector<CoordScalar, 3> bBoxMin(std::numeric_limits<CoordScalar>::max());
-    Dune::FieldVector<CoordScalar, 3> bBoxMax(std::numeric_limits<CoordScalar>::lowest());
-    for (const auto& p : points)
-    {
-        for (int i = 0; i < 3; i++)
-        {
-            using std::min;
-            using std::max;
-            bBoxMin[i] = min(bBoxMin[i], p[i]);
-            bBoxMax[i] = max(bBoxMax[i], p[i]);
-        }
-    }
-
-    const auto size = (bBoxMax - bBoxMin).two_norm();
-
-    // otherwise, perform a number of checks and corrections
-    if (!pointsAreCoplanar(points, size))
-        DUNE_THROW(Dune::InvalidStateException, "Points do not lie within a plane");
-
-    auto corners = grahamConvexHull<2>(points);
-    if (corners.size() != 4)
-        DUNE_THROW(Dune::InvalidStateException, "Points do not span a strictly convex polygon!");
-
-    // make sure points conform with dune ordering
-    std::array<int, 4> orientations;
-    corners = getReorderedPoints(corners, orientations);
-
-    if (std::any_of(orientations.begin(), orientations.end(), [](auto i){ return i == 0; }))
-        DUNE_THROW(Dune::InvalidStateException, "More than two points lie on the same line.");
-
-    const auto quadrilateral = GeometryType(Dune::GeometryTypes::quadrilateral, corners);
-
-    const auto eps = 1e-7;
-    if (quadrilateral.volume() < eps*size*size)
-        DUNE_THROW(Dune::InvalidStateException, "Something went wrong, geometry has area of zero");
-
-    return quadrilateral;
-}
-
-
-
-} // end namespace Dumux
-
-#endif // DUMUX_MAKE_GEOMETRY_HH
+#endif
diff --git a/dumux/common/geometry/normal.hh b/dumux/common/geometry/normal.hh
index a6e95ecb170b8c75a6df877f8667742f85585ee7..712580c5efae33313c3765ecf60e8b3d2535186a 100644
--- a/dumux/common/geometry/normal.hh
+++ b/dumux/common/geometry/normal.hh
@@ -18,60 +18,15 @@
  * \file
  * \ingroup Geometry
  * \brief Helper functions for normals
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_GEOMETRY_NORMAL_HH
-#define DUMUX_GEOMETRY_NORMAL_HH
+#ifndef DUMUX_COMMON_GEOMETRY_NORMAL_HH
+#define DUMUX_COMMON_GEOMETRY_NORMAL_HH
 
-#include <algorithm>
-#include <dune/common/float_cmp.hh>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/normal.hh"
 
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief Create a vector normal to the given one (v is expected to be non-zero)
- * \note This returns some orthogonal vector with arbitrary length
- */
-template<class Vector>
-inline Vector normal(const Vector& v)
-{
-    static_assert(Vector::size() > 1, "normal expects a coordinate dimension > 1");
-
-    if constexpr (Vector::size() == 2)
-        return Vector({-v[1], v[0]});
-
-    const auto it = std::find_if(v.begin(), v.end(), [](const auto& x) { return Dune::FloatCmp::ne(x, 0.0); });
-    const auto index = std::distance(v.begin(), it);
-    if (index != Vector::size()-1)
-    {
-        Vector normal(0.0);
-        normal[index] = -v[index+1];
-        normal[index+1] = v[index];
-        return normal;
-    }
-    else
-    {
-        Vector normal(0.0);
-        normal[index-1] = -v[index];
-        normal[index] = v[index-1];
-        return normal;
-
-    }
-}
-
-/*!
- * \ingroup Geometry
- * \brief Create a vector normal to the given one (v is expected to be non-zero)
- * \note This returns some orthogonal vector with unit length
- */
-template<class Vector>
-inline Vector unitNormal(const Vector& v)
-{
-    auto normal = Dumux::normal(v);
-    normal /= normal.two_norm();
-    return normal;
-}
-
-} // end namespace Dumux
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/normal.hh>
 
 #endif
diff --git a/dumux/common/geometry/refinementquadraturerule.hh b/dumux/common/geometry/refinementquadraturerule.hh
index d2996c623ef0c64b8b7c2ab37c56c12ca80fcc71..0778c474a0d5a9ee06bf920204f048d19ffa15b5 100644
--- a/dumux/common/geometry/refinementquadraturerule.hh
+++ b/dumux/common/geometry/refinementquadraturerule.hh
@@ -21,74 +21,16 @@
  * \ingroup Geometry
  * \author Timo Koch
  * \brief A quadrature based on refinement
+ * DEPRECATED will be removed once this header is removed
  */
 
-#ifndef DUMUX_COMMON_REFINEMENT_QUADRATURERULE_HH
-#define DUMUX_COMMON_REFINEMENT_QUADRATURERULE_HH
+#ifndef DUMUX_COMMON_GEOMETRY_REFINEMENT_QUADRATURERULE_HH
+#define DUMUX_COMMON_GEOMETRY_REFINEMENT_QUADRATURERULE_HH
 
-#include <dune/geometry/quadraturerules.hh>
-#include <dune/geometry/virtualrefinement.hh>
-#include <dumux/common/math.hh>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/refinementquadraturerule.hh"
 
-namespace Dumux {
-
-/*!
- * \ingroup Geometry
- * \brief A "quadrature" based on virtual refinement
- */
-template<typename ct, int mydim>
-class RefinementQuadratureRule final : public Dune::QuadratureRule<ct, mydim>
-{
-public:
-    //! The space dimension
-    static constexpr int dim = mydim;
-
-    //! The highest quadrature order available
-    static constexpr int highest_order = 1;
-
-    ~RefinementQuadratureRule() final {}
-
-    RefinementQuadratureRule(Dune::GeometryType type, int levels)
-    : Dune::QuadratureRule<ct, dim>(type, highest_order)
-    {
-        auto& refinement = Dune::buildRefinement<dim, ct>(type, type);
-        const auto tag = Dune::refinementLevels(levels);
-
-        // get the vertices
-        const auto numVertices = refinement.nVertices(tag);
-        std::vector<Dune::FieldVector<ct, dim>> points; points.reserve(numVertices);
-        auto vIt = refinement.vBegin(tag);
-        const auto vItEnd = refinement.vEnd(tag);
-        for (; vIt != vItEnd; ++vIt)
-            points.emplace_back(vIt.coords());
-
-        // go over all elements and get center and volume
-        const auto numElements = refinement.nElements(tag);
-        this->reserve(numElements);
-        auto eIt = refinement.eBegin(tag);
-        const auto eItEnd = refinement.eEnd(tag);
-        for (; eIt != eItEnd; ++eIt)
-        {
-            // quadrature point in the centroid of the sub-element and weight is its volume
-            const auto weight = computeVolume_(type, points, eIt.vertexIndices());
-            this->emplace_back(eIt.coords(), weight);
-        }
-    }
-
-private:
-    template<class VertexIndices>
-    ct computeVolume_(Dune::GeometryType t, const std::vector<Dune::FieldVector<ct, dim>>& points, const VertexIndices& indices) const
-    {
-        if (t != Dune::GeometryTypes::simplex(2))
-            DUNE_THROW(Dune::NotImplemented, "Only implemented for 2d simplices");
-
-        const auto ab = points[indices[1]] - points[indices[0]];
-        const auto ac = points[indices[2]] - points[indices[0]];
-        using std::abs;
-        return abs(crossProduct(ab, ac))*0.5;
-    }
-};
-
-} // end namespace Dumux
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/refinementquadraturerule.hh>
 
 #endif
diff --git a/dumux/common/geometry/triangulation.hh b/dumux/common/geometry/triangulation.hh
index 2b04870cd6e7357f7d9ebc18a1fd2323caac982a..1cba28a5832a197fe6d09cbce8d3ec216fe2f7be 100644
--- a/dumux/common/geometry/triangulation.hh
+++ b/dumux/common/geometry/triangulation.hh
@@ -18,117 +18,15 @@
  * \file
  * \ingroup Geometry
  * \brief Functionality to triangulate point clouds
+ * DEPRECATED will be removed once this header is removed
  */
-#ifndef DUMUX_TRIANGULATION_HH
-#define DUMUX_TRIANGULATION_HH
+#ifndef DUMUX_COMMON_GEOMETRY_TRIANGULATION_HH
+#define DUMUX_COMMON_GEOMETRY_TRIANGULATION_HH
 
-#include <vector>
-#include <array>
-#include <algorithm>
-#include <type_traits>
+#warning "This header is deprecated and will be removed after release 3.3. Please use dumux/geometry/triangulation.hh"
 
-#include <dune/common/exceptions.hh>
-#include <dune/common/fvector.hh>
+// This header, and all other geometry headers have been moved to their own folder.
+// Please use the geometry headers in dumux/geometry/, as this will be removed after release 3.3.
+#include <dumux/geometry/triangulation.hh>
 
-#include <dumux/common/math.hh>
-
-namespace Dumux {
-namespace TriangulationPolicy {
-
-//! Policy that expects a point cloud that represents a convex
-//! hull. Inserts the mid point and connects it to the points of the hull.
-struct MidPointPolicy {};
-
-//! Delaunay-type triangulations.
-struct DelaunayPolicy {};
-
-template<int dim, int dimWorld>
-using DefaultPolicy = std::conditional_t< dim >= 2, MidPointPolicy, DelaunayPolicy >;
-
-} // end namespace TriangulationPolicy
-
-//! The data type to store triangulations
-template<int dim, int dimWorld, class ctype>
-using Triangulation = std::vector< std::array<Dune::FieldVector<ctype, dimWorld>, dim+1> >;
-
-/*!
- * \ingroup Geometry
- * \brief Triangulate area given points of a convex hull
- * \tparam dim Specifies the dimension of the resulting triangulation (2 or 3)
- * \tparam dimWorld The dimension of the coordinate space
- * \tparam Policy Specifies the algorithm to be used for triangulation
- *
- * \note this specialization is for 2d triangulations using mid point policy
- * \note Assumes all points of the convex hull are coplanar
- * \note This inserts a mid point and connects all corners with that point to triangles
- */
-template< int dim, int dimWorld, class Policy = TriangulationPolicy::DefaultPolicy<dim, dimWorld>,
-          class RandomAccessContainer,
-          std::enable_if_t< std::is_same<Policy, TriangulationPolicy::MidPointPolicy>::value
-                            && dim == 2, int> = 0 >
-inline Triangulation<dim, dimWorld, typename RandomAccessContainer::value_type::value_type>
-triangulate(const RandomAccessContainer& convexHull)
-{
-    using ctype = typename RandomAccessContainer::value_type::value_type;
-    using Point = Dune::FieldVector<ctype, dimWorld>;
-    using Triangle = std::array<Point, 3>;
-
-    static_assert(std::is_same<typename RandomAccessContainer::value_type, Point>::value,
-                  "Triangulation expects Dune::FieldVector as point type");
-
-    if (convexHull.size() < 3)
-        DUNE_THROW(Dune::InvalidStateException, "Try to triangulate point cloud with less than 3 points!");
-
-    if (convexHull.size() == 3)
-        return std::vector<Triangle>(1, {convexHull[0], convexHull[1], convexHull[2]});
-
-    Point midPoint(0.0);
-    for (const auto p : convexHull)
-        midPoint += p;
-    midPoint /= convexHull.size();
-
-    std::vector<Triangle> triangulation;
-    triangulation.reserve(convexHull.size());
-
-    for (std::size_t i = 0; i < convexHull.size()-1; ++i)
-        triangulation.emplace_back(Triangle{midPoint, convexHull[i], convexHull[i+1]});
-
-    triangulation.emplace_back(Triangle{midPoint, convexHull[convexHull.size()-1], convexHull[0]});
-
-    return triangulation;
-}
-
-/*!
- * \ingroup Geometry
- * \brief Triangulate area given points of a convex hull
- * \tparam dim Specifies the dimension of the resulting triangulation (2 or 3)
- * \tparam dimWorld The dimension of the coordinate space
- * \tparam Policy Specifies the algorithm to be used for triangulation
- *
- * \note this specialization is for 1d discretization using segments
- * \note sorts the points and connects them via segments
- */
-template< int dim, int dimWorld, class Policy = TriangulationPolicy::DefaultPolicy<dim, dimWorld>,
-          class RandomAccessContainer,
-          std::enable_if_t< std::is_same<Policy, TriangulationPolicy::DelaunayPolicy>::value
-                            && dim == 1, int> = 0 >
-inline Triangulation<dim, dimWorld, typename RandomAccessContainer::value_type::value_type>
-triangulate(const RandomAccessContainer& points)
-{
-    using ctype = typename RandomAccessContainer::value_type::value_type;
-    using Point = Dune::FieldVector<ctype, dimWorld>;
-
-    static_assert(std::is_same<typename RandomAccessContainer::value_type, Point>::value,
-                  "Triangulation expects Dune::FieldVector as point type");
-
-    if (points.size() == 2)
-        return Triangulation<dim, dimWorld, ctype>({ {points[0], points[1]} });
-
-    //! \todo sort points and create polyline
-    assert(points.size() > 1);
-    DUNE_THROW(Dune::NotImplemented, "1d triangulation for point cloud size > 2");
-}
-
-} // end namespace Dumux
-
-# endif
+#endif