diff --git a/dumux/geometry/geometricentityset.hh b/dumux/geometry/geometricentityset.hh
index 4b69c89c9ae3b2e175560acea4216078c98b4364..78b308f7ac8c44594267d9312e678c4375e52cd1 100644
--- a/dumux/geometry/geometricentityset.hh
+++ b/dumux/geometry/geometricentityset.hh
@@ -14,7 +14,12 @@
 #ifndef DUMUX_GEOMETRY_GEOMETRIC_ENTITY_SET_HH
 #define DUMUX_GEOMETRY_GEOMETRIC_ENTITY_SET_HH
 
+#include <array>
+#include <vector>
 #include <memory>
+#include <utility>
+#include <initializer_list>
+
 #include <dune/grid/common/mcmgmapper.hh>
 #include <dune/geometry/multilineargeometry.hh>
 #include <dumux/common/entitymap.hh>
@@ -98,6 +103,52 @@ private:
     std::shared_ptr<const EntityMap> entityMap_;
 };
 
+} // end namespace Dumux
+
+#ifndef DOXYGEN
+namespace Dumux::Detail::GeometricEntity {
+
+/*!
+* \brief Wrapper to turn a geometry into a geometric entity
+*/
+template<class GeoType>
+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_;
+};
+
+} // end namespace Dumux::Detail::GeometricEntity
+#endif // DOXYGEN
+
+namespace Dumux {
+
 /*!
  * \ingroup Geometry
  * \brief An interface for a set of geometric entities
@@ -107,43 +158,8 @@ private:
 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;
+    using Entity = Detail::GeometricEntity::EntityWrapper<GeoType>;
 
     /*!
      * \brief Constructor for initializer_list
@@ -223,6 +239,90 @@ private:
     std::vector<Entity> entities_;
 };
 
+/*!
+ * \ingroup Geometry
+ * \brief An interface for a fixed-size set of geometric entities
+ * \note This can be used e.g. to construct a bounding box volume hierarchy of a grid
+ * It defines the minimum requirement for such a set
+ */
+template<class GeoType, std::size_t N>
+class FixedSizeGeometriesEntitySet
+{
+    template<class GT, std::size_t... I>
+    FixedSizeGeometriesEntitySet(GT&& gt, std::index_sequence<I...>)
+    : entities_{{ Entity(std::get<I>(gt), I)... }}
+    { static_assert(sizeof...(I) == N, "Number of geometries must match the size of the entity set"); }
+
+public:
+    using Entity = Detail::GeometricEntity::EntityWrapper<GeoType>;
+
+    /*!
+     * \brief Constructor with one or more geometries as arguments
+     * \note The number of geometries must match the size of the entity set
+     */
+    template<class... G>
+    FixedSizeGeometriesEntitySet(G&&... g)
+    : FixedSizeGeometriesEntitySet(std::forward_as_tuple(std::forward<G>(g)...), std::make_index_sequence<N>{})
+    {}
+
+    /*!
+     * \brief The world dimension of the entity set
+     */
+    static constexpr int dimensionworld = Entity::Geometry::coorddimension;
+
+    /*!
+     * \brief the coordinate type
+     */
+    using ctype = typename Entity::Geometry::ctype;
+
+    /*!
+     * \brief the number of entities in this set
+     */
+    constexpr 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
+     */
+    const Entity& entity(std::size_t index) const
+    { assert(index < entities_.size()); return entities_[index]; }
+
+private:
+    std::array<Entity, N> entities_;
+};
+
+/*!
+ * \ingroup Geometry
+ * \brief An interface for a geometric entity set with a single geometry
+ */
+template<class GeoType>
+class SingleGeometryEntitySet
+: public FixedSizeGeometriesEntitySet<GeoType, 1>
+{
+    using ParentType = FixedSizeGeometriesEntitySet<GeoType, 1>;
+public:
+    using ParentType::ParentType;
+};
+
 } // end namespace Dumux
 
 #endif
diff --git a/test/geometry/test_intersectionentityset.cc b/test/geometry/test_intersectionentityset.cc
index 1aa6520075b2b840629f6c17454dc600a9ed4943..2e6703ce151dac45c0fee946f844fedc37e6a955 100644
--- a/test/geometry/test_intersectionentityset.cc
+++ b/test/geometry/test_intersectionentityset.cc
@@ -152,6 +152,31 @@ int main (int argc, char *argv[])
                 testPolyLineIntersections(i, j);
     }
 
+    {
+        std::cout << "\nIntersect two polylines testing fixed size geometric entity sets:\n" << std::endl;
+        std::cout << "-- Test number of segments: " << 1 << " and " << 2 << "\n";
+
+        using Geo = Dune::AffineGeometry<double, 1, 2>;
+        using Point = Geo::GlobalCoordinate;
+
+        // once test constructor with l-values
+        const auto geo1 = Geo(Dune::GeometryTypes::line, std::array<Point, 2>{{Point({0.0, 0.0}), Point({1.0, 1.0})}});
+        const auto geo2 = Geo(Dune::GeometryTypes::line, std::array<Point, 2>{{Point({1.0, 1.0}), Point({2.0, 2.0})}});
+        auto geoSet0 = std::make_shared<FixedSizeGeometriesEntitySet<Geo, 2>>(geo1, geo2);
+
+        // once test constructor with move semantics
+        auto geoSet1 = std::make_shared<SingleGeometryEntitySet<Geo>>(
+            Geo(Dune::GeometryTypes::line, std::array<Point, 2>{{Point({0.0, 0.0}), Point({2.0, 2.0})}})
+        );
+
+        IntersectionEntitySet<FixedSizeGeometriesEntitySet<Geo, 2>, SingleGeometryEntitySet<Geo>> intersectionEntitySet;
+        intersectionEntitySet.build(geoSet0, geoSet1);
+
+        if (intersectionEntitySet.size() != 2)
+            DUNE_THROW(Dune::Exception, "Wrong number of line segment intersections."
+                        << " Expected " << 2 << " got " << intersectionEntitySet.size());
+    }
+
     std::cout << "All tests passed!" << std::endl;
     return 0;
 }