diff --git a/dumux/common/properties.hh b/dumux/common/properties.hh
index 4899e913ebb381a2709c9706823b7a343c2ba63b..cb6e6de4c836c9237fa0ef1b280063f831d9e457 100644
--- a/dumux/common/properties.hh
+++ b/dumux/common/properties.hh
@@ -107,7 +107,7 @@ NEW_PROP_TAG(MpfaMethod);                          //!< Specifies the mpfa metho
 NEW_PROP_TAG(MpfaHelper);                          //!< A Helper class depending on the mpfa method and grid dimension
 NEW_PROP_TAG(PrimaryInteractionVolume);            //!< The primary interaction volume type
 NEW_PROP_TAG(SecondaryInteractionVolume);          //!< The secondary interaction volume type used e.g. on the boundaries
-
+NEW_PROP_TAG(DualGridNodalIndexSet);               //!< The type used for the nodal index sets of the dual grid
 
 /////////////////////////////////////////////////////////////
 // Properties used by models involving flow in porous media:
diff --git a/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh b/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh
index 52817810a3787d72f3259f47afd5935c80cae7d2..a93c7ce63970a589ca92cdf883dd9547556e1ee2 100644
--- a/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh
+++ b/dumux/discretization/cellcentered/mpfa/dualgridindexset.hh
@@ -28,6 +28,8 @@
 #include <vector>
 #include <algorithm>
 
+#include <dune/common/reservedvector.hh>
+
 namespace Dumux
 {
 
@@ -39,20 +41,40 @@ namespace Dumux
  * \tparam GI The type used for indices on the grid
  * \tparam LI The type used for indexing in interaction volumes
  * \tparam dim The dimension of the grid
+ * \tparam maxE The maximum admissible number of elements around vertices.
+ * \tparam maxB The maximum admissible number of branches on intersections.
+ *              This is only to be specified for network grids and defaults to 1
+ *              for normal grids.
  */
-template< class GI, class LI, int dim >
-class DualGridNodalIndexSet
+template< class GI, class LI, int dim, int maxE, int maxB = 2 >
+class CCMpfaDualGridNodalIndexSet
 {
+    using DimIndexVector = Dune::ReservedVector<GI, dim>;
+
 public:
+    //! Export the used index types
     using GridIndexType = GI;
     using LocalIndexType = LI;
 
-    // we use dynamic containers to store indices here
-    using GridIndexContainer = std::vector<GridIndexType>;
-    using LocalIndexContainer = std::vector<LocalIndexType>;
+    //! Export the specified maximum admissible sizes
+    static constexpr int dimension = dim;
+    static constexpr int maxBranches = maxB;
+    static constexpr int maxNumElementsAtNode = maxE*(maxBranches-1);
+    static constexpr int maxNumScvfsAtNode = maxNumElementsAtNode*dim;
+
+    //! Export the stencil types used
+    using GridStencilType = Dune::ReservedVector<GridIndexType, maxNumElementsAtNode>;
+    using LocalStencilType = Dune::ReservedVector<LocalIndexType, maxNumElementsAtNode>;
+
+    //! Export the type used for storing the global scvf indices at this node
+    using GridScvfStencilType = Dune::ReservedVector<GridIndexType, maxNumScvfsAtNode>;
+
+    //! Data structure to store the neighboring scv indices of an scvf (grid/local indices)
+    using ScvfNeighborIndexSet = Dune::ReservedVector<GridIndexType, maxBranches>;
+    using ScvfNeighborLocalIndexSet = Dune::ReservedVector<LocalIndexType, maxBranches>;
 
     //! Constructor
-    DualGridNodalIndexSet() : numBoundaryScvfs_(0) {}
+    CCMpfaDualGridNodalIndexSet() : numBoundaryScvfs_(0) {}
 
     //! Inserts data for a given scvf
     template<typename SubControlVolumeFace>
@@ -78,10 +100,10 @@ public:
         const LocalIndexType curScvfLocalIdx = scvfIndices_.size();
 
         // add grid scvf data
-        GridIndexContainer scvIndices;
-        scvIndices.reserve(outsideScvIndices.size()+1);
+        ScvfNeighborIndexSet scvIndices;
         scvIndices.push_back(insideScvIdx);
-        scvIndices.insert(scvIndices.end(), outsideScvIndices.begin(), outsideScvIndices.end());
+        for (const auto& outsideIdx : outsideScvIndices)
+                scvIndices.push_back(outsideIdx);
 
         // if scvf is on boundary, increase counter
         if (boundary)
@@ -90,7 +112,7 @@ public:
         // insert data on the new scv
         scvfIndices_.push_back(scvfIdx);
         scvfIsOnBoundary_.push_back(boundary);
-        scvfNeighborScvIndices_.emplace_back( std::move(scvIndices) );
+        scvfNeighborScvIndices_.push_back(scvIndices);
 
         // if entry for the inside scv exists, append scvf local index, create otherwise
         auto it = std::find( scvIndices_.begin(), scvIndices_.end(), insideScvIdx );
@@ -98,10 +120,8 @@ public:
             localScvfIndicesInScv_[ std::distance(scvIndices_.begin(), it) ].push_back(curScvfLocalIdx);
         else
         {
-            LocalIndexContainer localScvfIndices;
-            localScvfIndices.reserve(dim);
-            localScvfIndices.push_back(curScvfLocalIdx);
-            localScvfIndicesInScv_.emplace_back( std::move(localScvfIndices) );
+            localScvfIndicesInScv_.push_back({});
+            localScvfIndicesInScv_.back().push_back(curScvfLocalIdx);
             scvIndices_.push_back(insideScvIdx);
         }
     }
@@ -116,10 +136,10 @@ public:
     std::size_t numBoundaryScvfs() const { return numBoundaryScvfs_; }
 
     //! returns the global scv indices connected to this dual grid node
-    const GridIndexContainer& globalScvIndices() const { return scvIndices_; }
+    const GridStencilType& globalScvIndices() const { return scvIndices_; }
 
     //! returns the global scvf indices connected to this dual grid node
-    const GridIndexContainer& globalScvfIndices() const { return scvfIndices_; }
+    const GridScvfStencilType& globalScvfIndices() const { return scvfIndices_; }
 
     //! returns whether or not the i-th scvf is on a domain boundary
     bool scvfIsOnBoundary(unsigned int i) const { return scvfIsOnBoundary_[i]; }
@@ -145,39 +165,40 @@ public:
     }
 
     //! returns the indices of the neighboring scvs of the i-th scvf
-    const GridIndexContainer& neighboringScvIndices(unsigned int i) const
+    const ScvfNeighborIndexSet& neighboringScvIndices(unsigned int i) const
     { return scvfNeighborScvIndices_[i]; }
 
 private:
-    GridIndexContainer scvIndices_;                          //!< The indices of the scvs around a dual grid node
-    std::vector<LocalIndexContainer> localScvfIndicesInScv_; //!< Maps to each scv a list of scvf indices embedded in it
+    GridStencilType scvIndices_;                                                       //!< The indices of the scvs around a dual grid node
+    Dune::ReservedVector<DimIndexVector, maxNumElementsAtNode> localScvfIndicesInScv_; //!< Maps to each scv a list of scvf indices embedded in it
+
+    GridScvfStencilType scvfIndices_;                             //!< the indices of the scvfs around a dual grid node
+    std::size_t numBoundaryScvfs_;                                //!< stores how many boundary scvfs are embedded in this dual grid node
+    Dune::ReservedVector<bool, maxNumScvfsAtNode> scvfIsOnBoundary_; //!< Maps to each scvf a boolean to indicate if it is on the boundary
 
-    GridIndexContainer scvfIndices_;                         //!< the indices of the scvfs around a dual grid node
-    std::vector<bool> scvfIsOnBoundary_;                     //!< Maps to each scvf a boolean to indicate if it is on the boundary
-    std::vector<GridIndexContainer> scvfNeighborScvIndices_; //!< The neighboring scvs for the scvfs (order: 0 - inside, 1..n - outside)
-    std::size_t numBoundaryScvfs_;                           //!< stores how many boundary scvfs are embedded in this dual grid node
+    //! The neighboring scvs for the scvfs (order: 0 - inside, 1..n - outside)
+    Dune::ReservedVector<ScvfNeighborIndexSet, maxNumScvfsAtNode> scvfNeighborScvIndices_;
 };
 
 /*!
  * \ingroup CCMpfaDiscretization
  * \brief Class for the index sets of the dual grid in mpfa schemes.
  *
- * \tparam GridIndexType The type used for indices on the grid
- * \tparam LocalIndexType The type used for indexing in interaction volumes
- * \tparam dim The dimension of the grid
+ * \tparam NI The type used for the nodal index sets.
  */
-template< class GridIndexType, class LocalIndexType, int dim >
+template< class NI >
 class CCMpfaDualGridIndexSet
 {
 public:
-    using NodalIndexSet = DualGridNodalIndexSet< GridIndexType, LocalIndexType, dim >;
+    using NodalIndexSet = NI;
+    using GridIndexType = typename NodalIndexSet::GridIndexType;
 
     //! Default constructor should not be used
     CCMpfaDualGridIndexSet() = delete;
 
     //! Constructor taking a grid view
     template< class GridView >
-    CCMpfaDualGridIndexSet(const GridView& gridView) : nodalIndexSets_(gridView.size(dim)) {}
+    CCMpfaDualGridIndexSet(const GridView& gridView) : nodalIndexSets_(gridView.size(NodalIndexSet::dimension)) {}
 
     //! Access with an scvf
     template< class SubControlVolumeFace >
diff --git a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh
index f3fbca56476ed92c90b1194dbb6e5c5f1e1e73ff..44b8f899fe6fdb14221087ea24a8bd92bf36fb6b 100644
--- a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh
+++ b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh
@@ -59,16 +59,22 @@ class CCMpfaFVElementGeometry<TypeTag, true>
     using ThisType = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
     using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
     using Element = typename GridView::template Codim<0>::Entity;
-
     using GridIndexType = typename GridView::IndexSet::IndexType;
+
+    static constexpr int dim = GridView::dimension;
+
+public:
+    //! export type of subcontrol volume
     using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
+    //! export type of subcontrol volume face
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
+    //! export type of finite volume grid geometry
     using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    //! the maximum number of scvs per element
+    static constexpr std::size_t maxNumElementScvs = 1;
+    //! the maximum number of scvfs per element (use cubes for maximum)
+    static constexpr std::size_t maxNumElementScvfs = dim == 3 ? 24 : 8;
 
-    using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::vector<GridIndexType>, ThisType>;
-    using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType>;
-
-public:
     //! Constructor
     CCMpfaFVElementGeometry(const FVGridGeometry& fvGridGeometry)
     : fvGridGeometryPtr_(&fvGridGeometry) {}
@@ -97,9 +103,10 @@ public:
     //! This is a free function found by means of ADL
     //! To iterate over all sub control volumes of this FVElementGeometry use
     //! for (auto&& scv : scvs(fvGeometry))
-    friend inline Dune::IteratorRange<ScvIterator>
+    friend inline Dune::IteratorRange< ScvIterator<SubControlVolume, std::array<GridIndexType, 1>, ThisType> >
     scvs(const CCMpfaFVElementGeometry& fvGeometry)
     {
+        using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::array<GridIndexType, 1>, ThisType>;
         return Dune::IteratorRange<ScvIterator>(ScvIterator(fvGeometry.scvIndices_.begin(), fvGeometry),
                                                 ScvIterator(fvGeometry.scvIndices_.end(), fvGeometry));
     }
@@ -109,11 +116,12 @@ public:
     //! This is a free function found by means of ADL
     //! To iterate over all sub control volume faces of this FVElementGeometry use
     //! for (auto&& scvf : scvfs(fvGeometry))
-    friend inline Dune::IteratorRange<ScvfIterator>
+    friend inline Dune::IteratorRange< ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType> >
     scvfs(const CCMpfaFVElementGeometry& fvGeometry)
     {
         const auto& g = fvGeometry.fvGridGeometry();
         const auto scvIdx = fvGeometry.scvIndices_[0];
+        using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType>;
         return Dune::IteratorRange<ScvfIterator>(ScvfIterator(g.scvfIndicesOfScv(scvIdx).begin(), fvGeometry),
                                                  ScvfIterator(g.scvfIndicesOfScv(scvIdx).end(), fvGeometry));
     }
@@ -139,7 +147,7 @@ public:
     //! Bind only element-local
     void bindElement(const Element& element)
     {
-        scvIndices_ = std::vector<GridIndexType>({fvGridGeometry().elementMapper().index(element)});
+        scvIndices_[0] = fvGridGeometry().elementMapper().index(element);
     }
 
     //! The global finite volume geometry we are a restriction of
@@ -148,7 +156,7 @@ public:
 
 private:
 
-    std::vector<GridIndexType> scvIndices_;
+    std::array<GridIndexType, 1> scvIndices_;
     const FVGridGeometry* fvGridGeometryPtr_;
 };
 
@@ -168,12 +176,6 @@ class CCMpfaFVElementGeometry<TypeTag, false>
     using GridIndexType = typename GridView::IndexSet::IndexType;
 
     using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper);
-    using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
-    using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
-
-    using ScvIterator = Dumux::ScvIterator<SubControlVolume, std::vector<GridIndexType>, ThisType>;
-    using ScvfIterator = Dumux::ScvfIterator<SubControlVolumeFace, std::vector<GridIndexType>, ThisType>;
 
     static const int dim = GridView::dimension;
     static const int dimWorld = GridView::dimensionworld;
@@ -182,6 +184,17 @@ class CCMpfaFVElementGeometry<TypeTag, false>
     using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
 
 public:
+    //! export type of subcontrol volume
+    using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
+    //! export type of subcontrol volume face
+    using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
+    //! export type of finite volume grid geometry
+    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    //! the maximum number of scvs per element
+    static constexpr std::size_t maxNumElementScvs = 1;
+    //! the maximum number of scvfs per element (use cubes for maximum)
+    static constexpr std::size_t maxNumElementScvfs = dim == 3 ? 24 : 8;
+
     //! Constructor
     CCMpfaFVElementGeometry(const FVGridGeometry& fvGridGeometry)
     : fvGridGeometryPtr_(&fvGridGeometry) {}
@@ -234,11 +247,11 @@ public:
     //! This is a free function found by means of ADL
     //! To iterate over all sub control volumes of this FVElementGeometry use
     //! for (auto&& scv : scvs(fvGeometry))
-    friend inline Dune::IteratorRange<typename std::vector<SubControlVolume>::const_iterator>
+    friend inline Dune::IteratorRange<typename std::array<SubControlVolume, 1>::const_iterator>
     scvs(const ThisType& g)
     {
-        using Iter = typename std::vector<SubControlVolume>::const_iterator;
-        return Dune::IteratorRange<Iter>(g.scvs_.begin(), g.scvs_.end());
+        using IteratorType = typename std::array<SubControlVolume, 1>::const_iterator;
+        return Dune::IteratorRange<IteratorType>(g.scvs_.begin(), g.scvs_.end());
     }
 
     //! iterator range for sub control volumes faces. Iterates over
@@ -249,8 +262,8 @@ public:
     friend inline Dune::IteratorRange<typename std::vector<SubControlVolumeFace>::const_iterator>
     scvfs(const ThisType& g)
     {
-        using Iter = typename std::vector<SubControlVolumeFace>::const_iterator;
-        return Dune::IteratorRange<Iter>(g.scvfs_.begin(), g.scvfs_.end());
+        using IteratorType = typename std::vector<SubControlVolumeFace>::const_iterator;
+        return Dune::IteratorRange<IteratorType>(g.scvfs_.begin(), g.scvfs_.end());
     }
 
     //! number of sub control volumes in this fv element geometry
@@ -336,8 +349,8 @@ private:
     {
         // make the scv
         const auto eIdx = fvGridGeometry().elementMapper().index(element);
-        scvs_.emplace_back(element.geometry(), eIdx);
-        scvIndices_.emplace_back(eIdx);
+        scvs_[0] = SubControlVolume(element.geometry(), eIdx);
+        scvIndices_[0] = eIdx;
 
         // get data on the scv faces
         const auto& scvFaceIndices = fvGridGeometry().scvfIndicesOfScv(eIdx);
@@ -617,9 +630,7 @@ private:
     //! clear all containers
     void clear()
     {
-        scvIndices_.clear();
         scvfIndices_.clear();
-        scvs_.clear();
         scvfs_.clear();
 
         neighborScvIndices_.clear();
@@ -634,9 +645,9 @@ private:
     const FVGridGeometry* fvGridGeometryPtr_;
 
     // local storage after binding an element
-    std::vector<GridIndexType> scvIndices_;
+    std::array<GridIndexType, 1> scvIndices_;
     std::vector<GridIndexType> scvfIndices_;
-    std::vector<SubControlVolume> scvs_;
+    std::array<SubControlVolume, 1> scvs_;
     std::vector<SubControlVolumeFace> scvfs_;
 
     std::vector<GridIndexType> neighborScvIndices_;
diff --git a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh
index 0b1e09f5d9722e5a3babc41ab78ad4a2b3adb46d..dfba3592e209700e45d4642e397f517b5433f180 100644
--- a/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh
+++ b/dumux/discretization/cellcentered/mpfa/fvgridgeometry.hh
@@ -64,6 +64,7 @@ class CCMpfaFVGridGeometry<TypeTag, true> : public BaseFVGridGeometry<TypeTag>
 
     using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper);
     using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume);
+    using DualGridNodalIndexSet = typename GET_PROP_TYPE(TypeTag, DualGridNodalIndexSet);
 
     using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
@@ -164,7 +165,7 @@ public:
         const auto isGhostVertex = MpfaHelper::findGhostVertices(this->gridView(), this->vertexMapper());
 
         // instantiate the dual grid index set (to be used for construction of interaction volumes)
-        CCMpfaDualGridIndexSet<GridIndexType, LocalIndexType, dim> dualIdSet(this->gridView());
+        CCMpfaDualGridIndexSet< DualGridNodalIndexSet > dualIdSet(this->gridView());
 
         // Build the SCVs and SCV faces
         GridIndexType scvfIdx = 0;
@@ -405,6 +406,7 @@ class CCMpfaFVGridGeometry<TypeTag, false> : public BaseFVGridGeometry<TypeTag>
 
     using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper);
     using PrimaryInteractionVolume = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume);
+    using DualGridNodalIndexSet = typename GET_PROP_TYPE(TypeTag, DualGridNodalIndexSet);
 
     using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
@@ -505,7 +507,7 @@ public:
         isGhostVertex_ = MpfaHelper::findGhostVertices(this->gridView(), this->vertexMapper());
 
         // instantiate the dual grid index set (to be used for construction of interaction volumes)
-        CCMpfaDualGridIndexSet<GridIndexType, LocalIndexType, dim> dualIdSet(this->gridView());
+        CCMpfaDualGridIndexSet< DualGridNodalIndexSet > dualIdSet(this->gridView());
 
         // Build the SCVs and SCV faces
         numScvf_ = 0;
diff --git a/dumux/discretization/cellcentered/mpfa/gridinteractionvolumeindexsets.hh b/dumux/discretization/cellcentered/mpfa/gridinteractionvolumeindexsets.hh
index 5a7a7882f0ddfcfe07e9b4ed0005244d9e0ef336..7ace724febac7f73d204653a76a66ea72fc4ac84 100644
--- a/dumux/discretization/cellcentered/mpfa/gridinteractionvolumeindexsets.hh
+++ b/dumux/discretization/cellcentered/mpfa/gridinteractionvolumeindexsets.hh
@@ -43,6 +43,7 @@ class CCMpfaGridInteractionVolumeIndexSets
     using GridIndexType = typename GridView::IndexSet::IndexType;
     using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
+    using DualGridNodalIndexSet = typename GET_PROP_TYPE(TypeTag, DualGridNodalIndexSet);
 
     using PrimaryIV = typename GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume);
     using PrimaryIVIndexSet = typename PrimaryIV::Traits::IndexSet;
@@ -51,7 +52,7 @@ class CCMpfaGridInteractionVolumeIndexSets
 
     static constexpr int dim = GridView::dimension;
     using LocalIndexType = typename PrimaryIV::Traits::LocalIndexType;
-    using DualGridIndexSet = CCMpfaDualGridIndexSet< GridIndexType, LocalIndexType, dim>;
+    using DualGridIndexSet = CCMpfaDualGridIndexSet< DualGridNodalIndexSet >;
 
 public:
     /*!
diff --git a/dumux/discretization/cellcentered/mpfa/helper.hh b/dumux/discretization/cellcentered/mpfa/helper.hh
index f129138540b5be817f3789ac4880a4f75802f17c..5a32421a9ed42b371e90f08cf5fd5fae8155fb0c 100644
--- a/dumux/discretization/cellcentered/mpfa/helper.hh
+++ b/dumux/discretization/cellcentered/mpfa/helper.hh
@@ -654,8 +654,8 @@ public:
     { return !std::is_same<PrimaryInteractionVolume, SecondaryInteractionVolume>::value; }
 
     //! returns whether or not a value exists in a vector
-    template<typename V1, typename V2>
-    static bool vectorContainsValue(const std::vector<V1>& vector, const V2 value)
+    template<typename V, typename T>
+    static bool vectorContainsValue(const V& vector, const T value)
     { return std::find(vector.begin(), vector.end(), value) != vector.end(); }
 };
 
diff --git a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh
index 298ec506bd6461955c8b68fe6ee4c25d3417d8ab..0a8f754d6fdbc29fbf4dac6e41cc65bcc1cedf27 100644
--- a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh
+++ b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh
@@ -51,7 +51,8 @@ template< class TypeTag >
 struct CCMpfaODefaultInteractionVolumeTraits
 {
 private:
-    using GridIndexType = typename GET_PROP_TYPE(TypeTag, GridView)::IndexSet::IndexType;
+    using NodalIndexSet = typename GET_PROP_TYPE(TypeTag, DualGridNodalIndexSet);
+    using GridIndexType = typename NodalIndexSet::GridIndexType;
     static constexpr int dim = GET_PROP_TYPE(TypeTag, GridView)::dimension;
     static constexpr int dimWorld = GET_PROP_TYPE(TypeTag, GridView)::dimensionworld;
 
@@ -69,9 +70,9 @@ public:
     //! export the type of the mpfa helper class
     using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper);
     //! export the type used for local indices
-    using LocalIndexType = std::uint8_t;
+    using LocalIndexType = typename NodalIndexSet::LocalIndexType;
     //! export the type for the interaction volume index set
-    using IndexSet = CCMpfaOInteractionVolumeIndexSet< DualGridNodalIndexSet<GridIndexType, LocalIndexType, dim> >;
+    using IndexSet = CCMpfaOInteractionVolumeIndexSet< NodalIndexSet >;
     //! export the type of interaction-volume local scvs
     using LocalScvType = CCMpfaOInteractionVolumeLocalScv< IndexSet, ScalarType, dim, dimWorld >;
     //! export the type of interaction-volume local scvfs
@@ -83,7 +84,7 @@ public:
     //! export the type used for iv-local vectors
     using Vector = Dune::DynamicVector< ScalarType >;
     //! export the type used for the iv-stencils
-    using Stencil = std::vector< GridIndexType >;
+    using Stencil = typename NodalIndexSet::GridStencilType;
     //! export the data handle type for this iv
     using DataHandle = InteractionVolumeDataHandle< TypeTag, Matrix, Vector, LocalIndexType >;
 };
@@ -122,10 +123,10 @@ class CCMpfaOInteractionVolume : public CCMpfaInteractionVolumeBase< CCMpfaOInte
     using Stencil = typename Traits::Stencil;
 
     //! For the o method, the interaction volume stencil can be taken directly
-    //! from the nodal index set, which always uses dynamic types to be compatible
-    //! on the boundaries and unstructured grids. Thus, we have to make sure that
+    //! from the nodal index set, which always uses Dune::ReservedVector with a maximum
+    //! admissible number of elements per node. Thus, we have to make sure that
     //! the type set for the stencils in the traits is castable.
-    static_assert( std::is_convertible<Stencil*, typename IndexSet::GridIndexContainer*>::value,
+    static_assert( std::is_convertible<Stencil*, typename IndexSet::GridStencilType*>::value,
                    "The o-method uses the (dynamic) nodal index set's stencil as the interaction volume stencil. "
                    "Using a different type is not permissive here." );
 
diff --git a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolumeindexset.hh b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolumeindexset.hh
index 84a26f7a4e4a253f905b1ca6405f6b1e2a2bdd65..1d63d804f259675a3619111b2056aa24dcd9430f 100644
--- a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolumeindexset.hh
+++ b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolumeindexset.hh
@@ -24,6 +24,8 @@
 #ifndef DUMUX_DISCRETIZATION_MPFA_O_INTERACTIONVOLUME_INDEXSET_HH
 #define DUMUX_DISCRETIZATION_MPFA_O_INTERACTIONVOLUME_INDEXSET_HH
 
+#include <dune/common/reservedvector.hh>
+
 #include <dumux/discretization/cellcentered/mpfa/dualgridindexset.hh>
 
 namespace Dumux
@@ -38,46 +40,27 @@ template< class DualGridNodalIndexSet >
 class CCMpfaOInteractionVolumeIndexSet
 {
 public:
+    //! Export the type used for the nodal grid index sets
+    using NodalIndexSet = DualGridNodalIndexSet;
+
+    //! Export the types used for local/grid indices
     using LocalIndexType = typename DualGridNodalIndexSet::LocalIndexType;
     using GridIndexType = typename DualGridNodalIndexSet::GridIndexType;
 
-    using LocalIndexContainer = typename DualGridNodalIndexSet::LocalIndexContainer;
-    using GridIndexContainer = typename DualGridNodalIndexSet::GridIndexContainer;
-
-    /*!
-     * \brief The constructor
-     * \note The actual type used for the nodal index sets might be different, as maybe
-     *       a different type for the local indexes is used. We therefore template this
-     *       constructor. However, a static assertion enforces you to use the same LocalIndexType
-     *       in the traits for both the secondary and the primary interaction volume traits.
-     *
-     * \tparam NodalIndexSet Possibly differing type for the DualGridNodalIndexSet
-     */
-    template< class NodalIndexSet >
-    CCMpfaOInteractionVolumeIndexSet(const NodalIndexSet& nodalIndexSet)
-    : nodalIndexSet_( static_cast<const DualGridNodalIndexSet&>(nodalIndexSet) )
-    {
-        // make sure the index types used are the same in order to avoid any losses due to type conversion
-        static_assert(std::is_same<GridIndexType, typename NodalIndexSet::GridIndexType>::value,
-                      "Provided nodal index set does not use the same type for grid indices as the given template argument");
-        static_assert(std::is_same<LocalIndexType, typename NodalIndexSet::LocalIndexType>::value,
-                      "Provided nodal index set does not use the same type for local indices as the given template argument");
+    // Export the types used for local/grid stencils
+    using LocalStencilType = typename DualGridNodalIndexSet::LocalStencilType;
+    using GridStencilType = typename DualGridNodalIndexSet::GridStencilType;
+    using GridScvfStencilType = typename DualGridNodalIndexSet::GridScvfStencilType;
 
+    //! Export the type used for the neighbor scv index sets of the scvfs
+    using ScvfNeighborLocalIndexSet = typename DualGridNodalIndexSet::ScvfNeighborLocalIndexSet;
+
+    //! The constructor
+    CCMpfaOInteractionVolumeIndexSet(const NodalIndexSet& nodalIndexSet) : nodalIndexSet_(nodalIndexSet)
+    {
         // determine the number of iv-local faces for memory reservation
         // note that this might be a vast overestimation on surface grids!
         const auto numNodalScvfs = nodalIndexSet.numScvfs();
-        const auto numBoundaryScvfs = nodalIndexSet.numBoundaryScvfs();
-        const std::size_t numFaceEstimate = numBoundaryScvfs + (numNodalScvfs-numBoundaryScvfs)/2;
-
-        // make sure we found a reasonable number of faces
-        assert((numNodalScvfs-numBoundaryScvfs)%2 == 0);
-
-        // index transformation from interaction-volume-local to node-local
-        ivToNodeScvf_.reserve(numFaceEstimate);
-        nodeToIvScvf_.resize(numNodalScvfs);
-
-        // the local neighboring scv indices of the faces
-        scvfNeighborScvLocalIndices_.reserve(numFaceEstimate);
 
         // keeps track of which nodal scvfs have been handled already
         std::vector<bool> isHandled(numNodalScvfs, false);
@@ -172,7 +155,7 @@ public:
     { return nodeToIvScvf_[ nodalIndexSet_.scvfIdxLocal(scvIdxLocal, i) ]; }
 
     //! returns the local indices of the neighboring scvs of an scvf
-    const LocalIndexContainer& neighboringLocalScvIndices(LocalIndexType ivLocalScvfIdx) const
+    const ScvfNeighborLocalIndexSet& neighboringLocalScvIndices(LocalIndexType ivLocalScvfIdx) const
     { return scvfNeighborScvLocalIndices_[ivLocalScvfIdx]; }
 
     //! returns the number of faces in the interaction volume
@@ -182,10 +165,10 @@ public:
     std::size_t numScvs() const { return nodalIndexSet_.numScvs(); }
 
     //! returns the global scv indices connected to this dual grid node
-    const GridIndexContainer& globalScvIndices() const { return nodalIndexSet_.globalScvIndices(); }
+    const GridStencilType& globalScvIndices() const { return nodalIndexSet_.globalScvIndices(); }
 
     //! returns the global scvf indices connected to this dual grid node
-    const GridIndexContainer& globalScvfIndices() const { return nodalIndexSet_.globalScvfIndices(); }
+    const GridScvfStencilType& globalScvfIndices() const { return nodalIndexSet_.globalScvfIndices(); }
 
 private:
     //! returns the local scv index to a given global scv index
@@ -199,11 +182,12 @@ private:
     const DualGridNodalIndexSet& nodalIndexSet_;
 
     std::size_t numFaces_;
-    std::vector<LocalIndexType> ivToNodeScvf_;
-    std::vector<LocalIndexType> nodeToIvScvf_;
+    Dune::ReservedVector< LocalIndexType, NodalIndexSet::maxNumScvfsAtNode > ivToNodeScvf_;
+    Dune::ReservedVector< LocalIndexType, NodalIndexSet::maxNumScvfsAtNode > nodeToIvScvf_;
+
     // maps to each scvf a list of neighbouring scv indices
     // ordering: 0 - inside scv idx; 1..n - outside scv indices
-    std::vector< LocalIndexContainer > scvfNeighborScvLocalIndices_;
+    Dune::ReservedVector< ScvfNeighborLocalIndexSet, NodalIndexSet::maxNumScvfsAtNode > scvfNeighborScvLocalIndices_;
 };
 
 } // end namespace Dumux
diff --git a/dumux/discretization/cellcentered/mpfa/omethod/localsubcontrolentities.hh b/dumux/discretization/cellcentered/mpfa/omethod/localsubcontrolentities.hh
index 7ddded18c3abba12cc578707e0358606da02597d..510ace43c52a0393a4acfa1003eb7d3482409b6a 100644
--- a/dumux/discretization/cellcentered/mpfa/omethod/localsubcontrolentities.hh
+++ b/dumux/discretization/cellcentered/mpfa/omethod/localsubcontrolentities.hh
@@ -134,7 +134,7 @@ private:
 template< class IvIndexSet >
 struct CCMpfaOInteractionVolumeLocalScvf
 {
-  using LocalIndexContainer = typename IvIndexSet::LocalIndexContainer;
+  using ScvfNeighborLocalIndexSet = typename IvIndexSet::ScvfNeighborLocalIndexSet;
 
 public:
     // export index types
@@ -154,7 +154,7 @@ public:
      */
     template< class SubControlVolumeFace >
     CCMpfaOInteractionVolumeLocalScvf(const SubControlVolumeFace& scvf,
-                                      const LocalIndexContainer& localScvIndices,
+                                      const ScvfNeighborLocalIndexSet& localScvIndices,
                                       const LocalIndexType localDofIdx,
                                       const bool isDirichlet)
     : isDirichlet_(isDirichlet)
@@ -171,7 +171,7 @@ public:
     GridIndexType globalScvfIndex() const { return scvfIdxGlobal_; }
 
     //! Returns the local indices of the scvs neighboring this scvf
-    const LocalIndexContainer& neighboringLocalScvIndices() const { return *neighborScvIndicesLocal_; }
+    const ScvfNeighborLocalIndexSet& neighboringLocalScvIndices() const { return *neighborScvIndicesLocal_; }
 
     //! states if this is scvf is on a Dirichlet boundary
     bool isDirichlet() const { return isDirichlet_; }
@@ -180,7 +180,7 @@ private:
     bool isDirichlet_;
     GridIndexType scvfIdxGlobal_;
     LocalIndexType localDofIndex_;
-    const LocalIndexContainer* neighborScvIndicesLocal_;
+    const ScvfNeighborLocalIndexSet* neighborScvIndicesLocal_;
 };
 
 } // end namespace Dumux
diff --git a/dumux/discretization/cellcentered/mpfa/omethod/staticinteractionvolume.hh b/dumux/discretization/cellcentered/mpfa/omethod/staticinteractionvolume.hh
index d4401e178678120e2d3c807aa683281c052f6a35..c57a82f3ac745683675b6674c03e764af349c7a6 100644
--- a/dumux/discretization/cellcentered/mpfa/omethod/staticinteractionvolume.hh
+++ b/dumux/discretization/cellcentered/mpfa/omethod/staticinteractionvolume.hh
@@ -52,7 +52,8 @@ template< class TypeTag, int localSize >
 struct CCMpfaODefaultStaticInteractionVolumeTraits
 {
 private:
-    using GridIndexType = typename GET_PROP_TYPE(TypeTag, GridView)::IndexSet::IndexType;
+    using NodalIndexSet = typename GET_PROP_TYPE(TypeTag, DualGridNodalIndexSet);
+    using GridIndexType = typename NodalIndexSet::GridIndexType;
     static constexpr int dim = GET_PROP_TYPE(TypeTag, GridView)::dimension;
     static constexpr int dimWorld = GET_PROP_TYPE(TypeTag, GridView)::dimensionworld;
 
@@ -70,9 +71,9 @@ public:
     //! export the type of the mpfa helper class
     using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper);
     //! export the type used for local indices
-    using LocalIndexType = std::uint8_t;
+    using LocalIndexType = typename NodalIndexSet::LocalIndexType;
     //! export the type for the interaction volume index set
-    using IndexSet = CCMpfaOInteractionVolumeIndexSet< DualGridNodalIndexSet<GridIndexType, LocalIndexType, dim> >;
+    using IndexSet = CCMpfaOInteractionVolumeIndexSet< NodalIndexSet >;
     //! export the type of interaction-volume local scvs
     using LocalScvType = CCMpfaOInteractionVolumeLocalScv< IndexSet, ScalarType, dim, dimWorld >;
     //! export the type of interaction-volume local scvfs
@@ -84,7 +85,7 @@ public:
     //! export the type used for iv-local vectors
     using Vector = Dune::FieldVector< ScalarType, localSize >;
     //! export the type used for the iv-stencils
-    using Stencil = std::vector< GridIndexType >;
+    using Stencil = typename NodalIndexSet::GridStencilType;
     //! export the data handle type for this iv
     using DataHandle = InteractionVolumeDataHandle< TypeTag, Matrix, Vector, LocalIndexType >;
 };
@@ -132,7 +133,7 @@ class CCMpfaOStaticInteractionVolume : public CCMpfaInteractionVolumeBase< CCMpf
     //! from the nodal index set, which always uses dynamic types to be compatible
     //! on the boundaries and unstructured grids. Thus, we have to make sure that
     //! the type set for the stencils in the traits is castable.
-    static_assert( std::is_convertible<Stencil*, typename IndexSet::GridIndexContainer*>::value,
+    static_assert( std::is_convertible<Stencil*, typename IndexSet::GridStencilType*>::value,
                    "The o-method uses the (dynamic) nodal index set's stencil as the interaction volume stencil. "
                    "Using a different type is not permissive here." );
 
diff --git a/dumux/discretization/cellcentered/mpfa/properties.hh b/dumux/discretization/cellcentered/mpfa/properties.hh
index 1a5e96d98a389f00c0976233008b749cc5f4e1d0..1b23351b354a8c10f336069bbce11669a95c409e 100644
--- a/dumux/discretization/cellcentered/mpfa/properties.hh
+++ b/dumux/discretization/cellcentered/mpfa/properties.hh
@@ -47,10 +47,10 @@
 #include <dumux/discretization/cellcentered/mpfa/elementvolumevariables.hh>
 #include <dumux/discretization/cellcentered/mpfa/elementfluxvariablescache.hh>
 #include <dumux/discretization/cellcentered/mpfa/subcontrolvolumeface.hh>
+#include <dumux/discretization/cellcentered/mpfa/dualgridindexset.hh>
 #include <dumux/discretization/cellcentered/mpfa/helper.hh>
 
 #include <dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh>
-#include <dumux/discretization/cellcentered/mpfa/omethod/staticinteractionvolume.hh>
 
 namespace Dumux
 {
@@ -71,6 +71,44 @@ SET_PROP(CCMpfaModel, MpfaMethod)
     static const MpfaMethods value = GET_PROP_TYPE(TypeTag, PrimaryInteractionVolume)::MpfaMethod;
 };
 
+//! Set the maximum admissible number of branches per scvf
+SET_PROP(CCMpfaModel, MaxNumBranchesPerScvf)
+{
+private:
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    static constexpr int dim = GridView::dimension;
+    static constexpr int dimWorld = GridView::dimensionworld;
+
+public:
+    // Per default, we allow for 8 neighbors on network/surface grids
+    static const std::size_t value = dim < dimWorld ? 9 : 2;
+};
+
+//! Set the index set type used on the dual grid nodes
+SET_PROP(CCMpfaModel, DualGridNodalIndexSet)
+{
+private:
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+
+    // Use the grid view's index type for grid indices
+    using GI = typename GridView::IndexSet::IndexType;
+
+    // per default, use uint8_t as iv-local index type
+    using LI = std::uint8_t;
+
+    // the specified maximum admissible number of branches per scvf
+    static constexpr int maxB = GET_PROP_VALUE(TypeTag, MaxNumBranchesPerScvf);
+
+    // maximum admissible number of elements around a node
+    // if for a given grid this number is still not high enough,
+    // overwrite this property in your problem with a higher number
+    static constexpr int dim = GridView::dimension;
+    static constexpr int maxE = dim == 3 ? 45 : 15;
+
+public:
+    using type = CCMpfaDualGridNodalIndexSet<GI, LI, dim, maxE, maxB>;
+};
+
 //! The mpfa helper class
 SET_TYPE_PROP(CCMpfaModel, MpfaHelper, CCMpfaHelper<TypeTag>);
 
diff --git a/dumux/discretization/cellcentered/tpfa/properties.hh b/dumux/discretization/cellcentered/tpfa/properties.hh
index 4e77be6a2f5e28d9573d0f3d902b364b464acaab..008770527745e92c7791bd11ac82717d2c6ec539 100644
--- a/dumux/discretization/cellcentered/tpfa/properties.hh
+++ b/dumux/discretization/cellcentered/tpfa/properties.hh
@@ -91,7 +91,7 @@ private:
     static constexpr int dimWorld = GridView::dimensionworld;
 
 public:
-    //! Per default, we allow for 8 neighbors on network/surface grids
+    // Per default, we allow for 8 neighbors on network/surface grids
     static const std::size_t value = dim < dimWorld ? 9 : 2;
 };
 
diff --git a/dumux/discretization/fluxstencil.hh b/dumux/discretization/fluxstencil.hh
index 6ee56e89d2050398bc4905ca2fd30ed37677e16e..6c7f329ddc19970d15fa0f37557ab3101011f239 100644
--- a/dumux/discretization/fluxstencil.hh
+++ b/dumux/discretization/fluxstencil.hh
@@ -100,13 +100,36 @@ class FluxStencilImplementation<TypeTag, DiscretizationMethods::CCMpfa>
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
     using Element = typename GridView::template Codim<0>::Entity;
     using IndexType = typename GridView::IndexSet::IndexType;
+    static constexpr int dim = GridView::dimension;
+
+    // Use the stencil type of the primary interaction volume
+    using NodalIndexSet = typename GET_PROP_TYPE(TypeTag, DualGridNodalIndexSet);
 
 public:
-    using Stencil = std::vector<IndexType>;
+    //! The maximum number of elements in a flux stencil (equal to number of elements at node)
+    static constexpr int maxFluxStencilSize = NodalIndexSet::maxNumElementsAtNode;
 
-    static Stencil stencil(const Element& element,
-                           const FVElementGeometry& fvGeometry,
-                           const SubControlVolumeFace& scvf)
+    //! States how many scvfs of an element J might have an element I in the flux stencil
+    //! We use cubes here for determining the maximum. Only basic geometries are not supported.
+    static constexpr int maxNumScvfJForI = dim == 3 ? 12 : 4;
+
+    //! The flux stencil type
+    using Stencil = typename NodalIndexSet::GridStencilType;
+
+    /*
+     * \brief Returns a set of grid element indices that participate in the
+     *        flux calculations on a given scvf.
+     *
+     * \note The interaction volume index sets must use the same type for the
+     *       stencils as the nodal index set. If not, the compiler will complain here.
+     *
+     * \param element The grid element
+     * \param fvGeometry The finite volume geometry of this element
+     * \param scvf The sub-control volume face embedded in this element
+     */
+    static const Stencil& stencil(const Element& element,
+                                  const FVElementGeometry& fvGeometry,
+                                  const SubControlVolumeFace& scvf)
     {
         const auto& fvGridGeometry = fvGeometry.fvGridGeometry();