diff --git a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh
index e79a41db5eca80335665f9585cb48af9f002a811..3be824293ef4db33eb2fb33d195895e6209847e9 100644
--- a/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh
+++ b/dumux/discretization/cellcentered/mpfa/fvelementgeometry.hh
@@ -261,18 +261,19 @@ public:
 
         // reserve memory
         const auto numNeighbors = assemblyMapI.size();
-        const auto estimate = neighborScvfEstimate_(element, numNeighbors);
+        const auto numNeighborScvfs = numNeighborScvfs_(assemblyMapI);
         neighborScvs_.reserve(numNeighbors);
         neighborScvIndices_.reserve(numNeighbors);
-        neighborScvfIndices_.reserve(estimate);
-        neighborScvfs_.reserve(estimate);
+        neighborScvfIndices_.reserve(numNeighborScvfs);
+        neighborScvfs_.reserve(numNeighborScvfs);
 
         // make neighbor geometries
         // use the assembly map to determine which faces are necessary
         for (auto&& dataJ : assemblyMapI)
             makeNeighborGeometries(globalFvGeometry().element(dataJ.globalJ),
                                    dataJ.globalJ,
-                                   dataJ.scvfsJ);
+                                   dataJ.scvfsJ,
+                                   dataJ.additionalScvfs);
 
         // set up the scvf flip indices for network grids
         if (dim < dimWorld)
@@ -309,31 +310,13 @@ private:
 
     //! Estimates the number of neighboring scvfs that have to be prepared
     //! The estimate holds for inner elements, overestimats on the boundary
-    int neighborScvfEstimate_(const Element& element, int numNeighbors)
+    template<class DataJ>
+    unsigned int numNeighborScvfs_(const std::vector<DataJ>& dataJVector)
     {
-        auto type = element.geometry().type();
-
-        if (type == Dune::GeometryType(Dune::GeometryType::simplex, dim))
-        {
-            if (dim == 2)
-                return 6 + ( (numNeighbors-3 > 0) ? (numNeighbors-3)*2 : 0 );
-            if (dim == 3)
-                return 12 + ( (numNeighbors-4 > 0) ? (numNeighbors-4)*3 : 0 );
-        }
-        else if (type == Dune::GeometryType(Dune::GeometryType::cube, dim))
-        {
-            if (dim == 2)
-                return 16;
-            if (dim == 3)
-                return 120;
-        }
-        else if (type == Dune::GeometryType(Dune::GeometryType::pyramid, dim))
-            return 16 + ( (numNeighbors-4 > 0) ? (numNeighbors-4)*3 : 0 );
-        else if (type == Dune::GeometryType(Dune::GeometryType::prism, dim))
-            return 18 + ( (numNeighbors-4 > 0) ? (numNeighbors-4)*3 : 0 );
-        else
-            DUNE_THROW(Dune::NotImplemented, "Mpfa for given geometry type.");
-
+        unsigned int numNeighborScvfs = 0;
+        for (const auto& dataJ : dataJVector)
+            numNeighborScvfs += dataJ.scvfsJ.size() + dataJ.additionalScvfs.size();
+        return numNeighborScvfs;
     }
 
     //! create scvs and scvfs of the bound element
@@ -424,7 +407,10 @@ private:
 
     //! create the scv and necessary scvfs of a neighboring element
     template<typename IndexVector>
-    void makeNeighborGeometries(const Element& element, IndexType eIdxGlobal, const IndexVector& scvfIndices)
+    void makeNeighborGeometries(const Element& element,
+                                IndexType eIdxGlobal,
+                                const IndexVector& scvfIndices,
+                                const IndexVector& additionalScvfs)
     {
         // create the neighbor scv if it doesn't exist yet
         neighborScvs_.emplace_back(element.geometry(), eIdxGlobal);
@@ -483,7 +469,8 @@ private:
                     continue;
 
                 // only build the scvf if it is in the list of necessary indices
-                if (MpfaHelper::contains(scvfIndices, scvFaceIndices[scvfCounter]))
+                if (MpfaHelper::contains(scvfIndices, scvFaceIndices[scvfCounter])
+                    || MpfaHelper::contains(additionalScvfs, scvFaceIndices[scvfCounter]))
                 {
                     neighborScvfs_.emplace_back(MpfaHelper(),
                                                 MpfaHelper::getScvfCorners(isCorners, c),
diff --git a/dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh b/dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh
index 32af446ad2a96ed62aeadc991d5cd6a2222e5ba8..144e7881fb81cad5e8b12ebd5c2195c0be1c2683 100644
--- a/dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh
+++ b/dumux/discretization/cellcentered/mpfa/interactionvolumebase.hh
@@ -91,6 +91,8 @@ public:
           isOutside(isOut) {}
     };
 
+    using GlobalLocalFaceDataPair = std::pair<const SubControlVolumeFace*, LocalFaceData>;
+
     //! solves the local equation system for the computation of the transmissibilities
     template<typename GetTensorFunction>
     void solveLocalSystem(const GetTensorFunction& getTensor)
@@ -104,10 +106,6 @@ public:
     const PositionVector& volVarsPositions() const
     { DUNE_THROW(Dune::NotImplemented, "Actual interaction volume implementation does not provide a volVarsPositions() method."); }
 
-    //! returns a list of global scvf indices that are connected to this interaction volume
-    const GlobalIndexSet& globalScvfs() const
-    { DUNE_THROW(Dune::NotImplemented, "Actual interaction volume implementation does not provide a globalScvfs() method."); }
-
     //! returns the local index of an scvf in the IV and a boolean whether or not it is on the negative side of the local scvf (flux has to be inverted)
     LocalFaceData getLocalFaceData(const SubControlVolumeFace& scvf) const
     { DUNE_THROW(Dune::NotImplemented, "Actual interaction volume implementation does not provide a getLocalFaceData() method."); }
@@ -128,6 +126,10 @@ public:
         assert(it != vector.end() && "could not find local index in the vector for the given global index!");
         return std::distance(vector.begin(), it);
     }
+
+    //! returns GlobalLocalFaceDataPair objects for the scvfs involved in this interaction volume
+    const std::vector<GlobalLocalFaceDataPair>& globalLocalScvfPairedData() const
+    { DUNE_THROW(Dune::NotImplemented, "Actual interaction volume implementation does not provide a globalLocalScvfPairedData() method."); }
 };
 
 } // end namespace
diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/globalinteractionvolumeseeds.hh b/dumux/discretization/cellcentered/mpfa/lmethod/globalinteractionvolumeseeds.hh
index 8a3da8af4f4bdc17d2e75722b525f3dc270592e9..d9fe0f67c7a7c67b03f904fe58100e5f5c151d66 100644
--- a/dumux/discretization/cellcentered/mpfa/lmethod/globalinteractionvolumeseeds.hh
+++ b/dumux/discretization/cellcentered/mpfa/lmethod/globalinteractionvolumeseeds.hh
@@ -141,12 +141,7 @@ public:
     }
 
     bool isLocalMaxLevel_(const Element& element, const SubControlVolumeFace& scvf) const
-    {
-        auto inLevel = element.level();
-        if (this->problem().model().globalFvGeometry().element(scvf.outsideScvIdx()).level() > inLevel)
-            return false;
-        return true;
-    }
+    { return this->problem().model().globalFvGeometry().element(scvf.outsideScvIdx()).level() <= element.level(); }
 };
 
 } // end namespace
diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/helper.hh b/dumux/discretization/cellcentered/mpfa/lmethod/helper.hh
index f5d88a68972c485f9b8111d617c90e6b3f744612..1ca199a5d2ae2d837d6a01611d03dbae7f7fa480 100644
--- a/dumux/discretization/cellcentered/mpfa/lmethod/helper.hh
+++ b/dumux/discretization/cellcentered/mpfa/lmethod/helper.hh
@@ -98,7 +98,6 @@ public:
                                              const Matrix& M1,
                                              const Matrix& M2)
     {
-        Scalar eps = 1e-10;
         Scalar t11, t12, t21, t22;
         t11 = M1[I1.contiFaceLocalIdx][0];
         t21 = M2[I2.contiFaceLocalIdx][0];
@@ -116,7 +115,7 @@ public:
         Scalar s1 = std::abs(t11-t12);
         Scalar s2 = std::abs(t22-t21);
 
-        if (s1 < s2 + eps*s1)
+        if (s1 < s2)
             return 0;
         else
             return 1;
@@ -132,16 +131,16 @@ private:
                                  const SubControlVolumeFace& scvf)
     {
         // make the first scv seed, we know this element will NOT be on the lowest local level
-        auto scvfVector = Implementation::getScvFacesAtVertex(scvf.vertexIndex(), element, fvGeometry);
-        auto localScvfIdx = Implementation::getLocalFaceIndex(scvf, scvfVector);
+        const auto scvfVector = Implementation::getScvFacesAtVertex(scvf.vertexIndex(), element, fvGeometry);
+        const auto localScvfIdx = Implementation::getLocalFaceIndex(scvf, scvfVector);
         scvSeeds.emplace_back( GlobalIndexSet({scvfVector[0]->index(), scvfVector[1]->index()}),
                                scvf.insideScvIdx(),
                                localScvfIdx );
 
         // get the surrounding elements and "outside" data
         LocalIndexType otherScvfIdx = 1-localScvfIdx;
-        auto e2 = problem.model().globalFvGeometry().element(scvf.outsideScvIdx());
-        auto e3 = problem.model().globalFvGeometry().element(scvfVector[otherScvfIdx]->outsideScvIdx());
+        const auto e2 = problem.model().globalFvGeometry().element(scvf.outsideScvIdx());
+        const auto e3 = problem.model().globalFvGeometry().element(scvfVector[otherScvfIdx]->outsideScvIdx());
 
         auto e2Geometry = localView(problem.model().globalFvGeometry());
         auto e3Geometry = localView(problem.model().globalFvGeometry());
@@ -166,10 +165,10 @@ private:
                                    e3Scvfs[localScvfIdx]->index());
 
         // Outer seed for outside of e2, we know the local scvf index here will be localScvfIdx in 2d
-        auto e4 = problem.model().globalFvGeometry().element(e2Scvfs[localScvfIdx]->outsideScvIdx());
+        const auto e4 = problem.model().globalFvGeometry().element(e2Scvfs[localScvfIdx]->outsideScvIdx());
         auto e4Geometry = localView(problem.model().globalFvGeometry());
         e4Geometry.bindElement(e4);
-        auto e4Scvfs = Implementation::getCommonAndNextScvFace(*e2Scvfs[localScvfIdx], e4Geometry, /*clockwise?*/localScvfIdx == 1);
+        const auto e4Scvfs = Implementation::getCommonAndNextScvFace(*e2Scvfs[localScvfIdx], e4Geometry, /*clockwise?*/localScvfIdx == 1);
 
         outerScvSeeds.emplace_back(e4Scvfs[otherScvfIdx]->insideScvIdx(),
                                    e4Scvfs[otherScvfIdx]->index());
diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/interactionregions.hh b/dumux/discretization/cellcentered/mpfa/lmethod/interactionregions.hh
index fc4c039ea1d955f95c7aa93de31bbc978e0217dd..17380bc1a95bd01334e766af94ce86e5109bbbe2 100644
--- a/dumux/discretization/cellcentered/mpfa/lmethod/interactionregions.hh
+++ b/dumux/discretization/cellcentered/mpfa/lmethod/interactionregions.hh
@@ -58,22 +58,22 @@ public:
     std::vector<Scalar> detX;
     std::vector<Element> elements;
 
-    std::array<GlobalIndexType, 2> globalScvfs;
+    std::array<GlobalIndexType, 2> globalScvfIndices;
 
     // Constructor signature for dim == 2
-    template<class ScvSeedType, class OuterScvSeedType>
+    template<class ScvSeed, class OuterScvSeed>
     InteractionRegion(const Problem& problem,
                       const FVElementGeometry& fvGeometry,
-                      const ScvSeedType& scvSeed,
-                      const OuterScvSeedType& outerSeed1,
-                      const OuterScvSeedType& outerSeed2,
+                      const ScvSeed& scvSeed,
+                      const OuterScvSeed& outerSeed1,
+                      const OuterScvSeed& outerSeed2,
                       const Element& element1,
                       const Element& element2,
                       const Element& element3)
     {
         contiFaceLocalIdx = scvSeed.contiFaceLocalIdx();
-        globalScvfs[0] = scvSeed.globalScvfIndices()[contiFaceLocalIdx];
-        globalScvfs[1] = contiFaceLocalIdx == 0 ? outerSeed1.globalScvfIndex() : outerSeed2.globalScvfIndex();
+        globalScvfIndices[0] = scvSeed.globalScvfIndices()[contiFaceLocalIdx];
+        globalScvfIndices[1] = contiFaceLocalIdx == 0 ? outerSeed1.globalScvfIndex() : outerSeed2.globalScvfIndex();
 
         elements.resize(3);
         elements[0] = element1;
@@ -81,11 +81,11 @@ public:
         elements[2] = element3;
 
         // The participating sub control entities
-        auto&& scv1 = fvGeometry.scv(scvSeed.globalIndex());
-        auto&& scv2 = fvGeometry.scv(outerSeed1.globalIndex());
-        auto&& scv3 = fvGeometry.scv(outerSeed2.globalIndex());
-        auto&& scvf1 = fvGeometry.scvf(scvSeed.globalScvfIndices()[0]);
-        auto&& scvf2 = fvGeometry.scvf(scvSeed.globalScvfIndices()[1]);
+        const auto& scv1 = fvGeometry.scv(scvSeed.globalIndex());
+        const auto& scv2 = fvGeometry.scv(outerSeed1.globalIndex());
+        const auto& scv3 = fvGeometry.scv(outerSeed2.globalIndex());
+        const auto& scvf1 = fvGeometry.scvf(scvSeed.globalScvfIndices()[0]);
+        const auto& scvf2 = fvGeometry.scvf(scvSeed.globalScvfIndices()[1]);
 
         // The necessary coordinates and normals
         GlobalPosition v = scvf1.vertexCorner();
diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/interactionvolume.hh b/dumux/discretization/cellcentered/mpfa/lmethod/interactionvolume.hh
index 51e7929705249eb21b8656195fdd125552499394..6ab3030efd62216e261933b8b7cb2e4d56fe7e6c 100644
--- a/dumux/discretization/cellcentered/mpfa/lmethod/interactionvolume.hh
+++ b/dumux/discretization/cellcentered/mpfa/lmethod/interactionvolume.hh
@@ -80,6 +80,7 @@ class CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::lMethod> : pub
     using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
     using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
+    using InteriorBoundaryData = typename GET_PROP_TYPE(TypeTag, InteriorBoundaryData);
 
     static const int dim = GridView::dimension;
     static const int dimWorld = GridView::dimensionworld;
@@ -93,6 +94,7 @@ class CCMpfaInteractionVolumeImplementation<TypeTag, MpfaMethods::lMethod> : pub
 
 public:
     using Matrix = typename Traits::Matrix;
+    using typename ParentType::GlobalLocalFaceDataPair;
     using typename ParentType::LocalIndexType;
     using typename ParentType::LocalIndexSet;
     using typename ParentType::LocalFaceData;
@@ -108,7 +110,8 @@ public:
                                           const Problem& problem,
                                           const FVElementGeometry& fvGeometry,
                                           const ElementVolumeVariables& elemVolVars)
-    : problemPtr_(&problem),
+    : seedPtr_(&seed),
+      problemPtr_(&problem),
       fvGeometryPtr_(&fvGeometry),
       elemVolVarsPtr_(&elemVolVars),
       regionUnique_(seed.isUnique()),
@@ -125,7 +128,9 @@ public:
         {
             const auto& ir = interactionRegions_[0];
             T_ = assembleMatrix_(getTensor, ir);
-            postSolve_(ir);
+            interactionRegionId_ = 0;
+            updateGlobalLocalFaceData();
+            systemSolved_ = true;
         }
         else
         {
@@ -133,22 +138,25 @@ public:
             M[0] = assembleMatrix_(getTensor, interactionRegions_[0]);
             M[1] = assembleMatrix_(getTensor, interactionRegions_[1]);
 
-            auto id = MpfaHelper::selectionCriterion(interactionRegions_[0], interactionRegions_[1], M[0], M[1]);
-            postSolve_(interactionRegions_[id]);
-            T_ = M[id];
+            interactionRegionId_ = MpfaHelper::selectionCriterion(interactionRegions_[0], interactionRegions_[1], M[0], M[1]);
+            updateGlobalLocalFaceData();
+            systemSolved_ = true;
+            T_ = M[interactionRegionId_];
         }
     }
 
     //! returns the local index pair. This holds the scvf's local index and a boolean whether or not the flux has to be inverted
-    LocalFaceData getLocalFaceData(const SubControlVolumeFace& scvf) const
+    const LocalFaceData getLocalFaceData(const SubControlVolumeFace& scvf) const
     {
         assert(systemSolved_ && "Scvf Indices not set yet. You have to call solveLocalSystem() beforehand.");
-        assert((scvf.index() == globalScvfIndices_[0] || scvf.index() == globalScvfIndices_[1]) && "The provided scvf is not the flux face of the interaction volume.");
+        assert((scvf.index() == globalLocalScvfPairedData_[0].first->index()
+                || scvf.index() == globalLocalScvfPairedData_[1].first->index())
+                   && "The provided scvf is not the flux face of the interaction volume.");
 
-        if (globalScvfIndices_[0] == scvf.index())
-            return LocalFaceData(contiFaceLocalIdx_, /*dummy*/0, false);
+        if (globalLocalScvfPairedData_[0].first->index() == scvf.index())
+            return globalLocalScvfPairedData_[0].second;
         else
-            return LocalFaceData(contiFaceLocalIdx_, /*dummy*/0, true);
+            return globalLocalScvfPairedData_[1].second;
     }
 
     //! returns the transmissibilities corresponding to the bound scvf
@@ -164,21 +172,18 @@ public:
 
     const GlobalIndexSet& volVarsStencil() const
     {
-        assert(systemSolved_ && "volVarsStencil not set yet. You have to call solveLocalSystem() beforehand.");
-        return volVarsStencil_;
+        assert(systemSolved_ && "stencil not set yet. You have to call solveLocalSystem() beforehand.");
+        return interactionRegion().scvIndices;
     }
 
     const PositionVector& volVarsPositions() const
     {
-        assert(systemSolved_ && "globalScvfs not set yet. You have to call solveLocalSystem() beforehand.");
-        return volVarsPositions_;
+        assert(systemSolved_ && "stencil not set yet. You have to call solveLocalSystem() beforehand.");
+        return interactionRegion().scvCenters;
     }
 
-    const GlobalIndexSet& globalScvfs() const
-    {
-        assert(systemSolved_ && "globalScvfs not set yet. You have to call solveLocalSystem() beforehand.");
-        return globalScvfIndices_;
-    }
+    const std::vector<GlobalLocalFaceDataPair>& globalLocalScvfPairedData() const
+    { return globalLocalScvfPairedData_; }
 
     //! Boundaries will be treated by a different mpfa method (e.g. o method). Thus, on
     //! faces in l-method interaction volumes there will never be a Neumann flux contribution.
@@ -192,6 +197,13 @@ public:
     const Matrix& matrix() const
     { return T_; }
 
+    const InteractionRegion& interactionRegion() const
+    { return interactionRegions_[interactionRegionId_]; }
+
+    // The l-method can't treat interior boundaries
+    const std::vector<InteriorBoundaryData> interiorBoundaryData() const
+    { return std::vector<InteriorBoundaryData>(); }
+
 private:
     //! Assembles and solves the local equation system
     //! Specialization for dim = 2
@@ -210,9 +222,9 @@ private:
         const auto scv3 = fvGeometry_().scv(ir.scvIndices[2]);
 
         // Get diffusion tensors in the three scvs
-        const auto T1 = getTensor(e1, elemVolVars_()[scv1], scv1);
-        const auto T2 = getTensor(e2, elemVolVars_()[scv2], scv2);
-        const auto T3 = getTensor(e3, elemVolVars_()[scv3], scv3);
+        const auto T1 = getTensor(problem_(), e1, elemVolVars_()[scv1], fvGeometry_(), scv1);
+        const auto T2 = getTensor(problem_(), e2, elemVolVars_()[scv2], fvGeometry_(), scv2);
+        const auto T3 = getTensor(problem_(), e3, elemVolVars_()[scv3], fvGeometry_(), scv3);
 
         // required omega factors
         Scalar w111 = calculateOmega_(ir.normal[0], ir.nu[0], ir.detX[0], T1);
@@ -248,7 +260,7 @@ private:
         B[1][1] = 0.0;
         B[1][2] = -w235 - w236;
 
-        // T = CA^-1B + D
+        // T = C*A^-1*B + D
         A.invert();
         auto T = (A.leftmultiply(C)).rightmultiplyany(B);
         T[0][0] += w111 + w112;
@@ -265,53 +277,57 @@ private:
     {
         const auto& globalFvGeometry = problem_().model().globalFvGeometry();
 
-        if (regionUnique_)
+        interactionRegions_.reserve(2);
+        auto&& scvSeed1 = seed.scvSeed(0);
+        auto&& scvSeed2 = seed.scvSeed(1);
+        auto&& outerScvSeed1 = seed.outerScvSeed(0);
+        auto&& outerScvSeed2 = seed.outerScvSeed(1);
+        auto e1 = globalFvGeometry.element(scvSeed1.globalIndex());
+        auto e2 = globalFvGeometry.element(scvSeed2.globalIndex());
+        auto e3 = globalFvGeometry.element(outerScvSeed1.globalIndex());
+        auto e4 = globalFvGeometry.element(outerScvSeed2.globalIndex());
+
+        // scvSeed1 is the one the seed construction began at
+        if (scvSeed1.contiFaceLocalIdx() == 0)
         {
-            interactionRegions_.reserve(1);
-            auto&& scvSeed1 = seed.scvSeed(0);
-            auto&& scvSeed2 = seed.outerScvSeed(0);
-            auto&& scvSeed3 = seed.outerScvSeed(1);
-            auto e1 = globalFvGeometry.element(scvSeed1.globalIndex());
-            auto e2 = globalFvGeometry.element(scvSeed2.globalIndex());
-            auto e3 = globalFvGeometry.element(scvSeed3.globalIndex());
-            interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed1, scvSeed2, scvSeed3, e1, e2, e3);
-
+            interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed1, OuterScvSeedType(scvSeed2), outerScvSeed1, e1, e2, e3);
+            interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed2, outerScvSeed2, OuterScvSeedType(scvSeed1), e2, e4, e1);
         }
         else
         {
-            interactionRegions_.reserve(2);
-            auto&& scvSeed1 = seed.scvSeed(0);
-            auto&& scvSeed2 = seed.scvSeed(1);
-            auto&& outerScvSeed1 = seed.outerScvSeed(0);
-            auto&& outerScvSeed2 = seed.outerScvSeed(1);
-            auto e1 = globalFvGeometry.element(scvSeed1.globalIndex());
-            auto e2 = globalFvGeometry.element(scvSeed2.globalIndex());
-            auto e3 = globalFvGeometry.element(outerScvSeed1.globalIndex());
-            auto e4 = globalFvGeometry.element(outerScvSeed2.globalIndex());
-
-            // scvSeed1 is the one the seed construction began at
-            if (scvSeed1.contiFaceLocalIdx() == 0)
-            {
-                interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed1, OuterScvSeedType(scvSeed2), outerScvSeed1, e1, e2, e3);
-                interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed2, outerScvSeed2, OuterScvSeedType(scvSeed1), e2, e4, e1);
-            }
-            else
-            {
-                interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed1, outerScvSeed1, OuterScvSeedType(scvSeed2), e1, e3, e2);
-                interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed2, OuterScvSeedType(scvSeed1), outerScvSeed2, e2, e1, e4);
-            }
+            interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed1, outerScvSeed1, OuterScvSeedType(scvSeed2), e1, e3, e2);
+            interactionRegions_.emplace_back(problem_(), fvGeometry, scvSeed2, OuterScvSeedType(scvSeed1), outerScvSeed2, e2, e1, e4);
         }
+
+        // as an initial guess we set the first interaction region as the one used
+        // this is updated after solution of the local system
+        interactionRegionId_ = 0;
+        updateGlobalLocalFaceData();
     }
 
-    void postSolve_(const InteractionRegion& ir)
+    //! set the global&local face data according to the current choice for the interaction region
+    void updateGlobalLocalFaceData()
     {
-        globalScvfIndices_.resize(2);
-        globalScvfIndices_[0] = ir.globalScvfs[0];
-        globalScvfIndices_[1] = ir.globalScvfs[1];
-        volVarsStencil_ = ir.scvIndices;
-        volVarsPositions_ = ir.scvCenters;
-        contiFaceLocalIdx_ = ir.contiFaceLocalIdx;
-        systemSolved_ = true;
+        const auto numPairs = globalLocalScvfPairedData_.size();
+
+        // if no data has been stored yet, initialize
+        if (numPairs == 0)
+        {
+            globalLocalScvfPairedData_.clear();
+            globalLocalScvfPairedData_.reserve(2);
+            globalLocalScvfPairedData_.emplace_back(&fvGeometry_().scvf(seed_().globalScvfIndices()[0]),
+                                                    LocalFaceData(interactionRegion().contiFaceLocalIdx, /*dummy*/0, false));
+            globalLocalScvfPairedData_.emplace_back(&fvGeometry_().scvf(seed_().globalScvfIndices()[1]),
+                                                    LocalFaceData(interactionRegion().contiFaceLocalIdx, /*dummy*/0, true));
+        }
+        // if order was swapped, change bools indicating which face is the "outside" version of the local face
+        else if (globalLocalScvfPairedData_[1].first->index() == interactionRegion().globalScvfIndices[0])
+        {
+            globalLocalScvfPairedData_[0].second.localScvfIndex = interactionRegion().contiFaceLocalIdx;
+            globalLocalScvfPairedData_[1].second.localScvfIndex = interactionRegion().contiFaceLocalIdx;
+            globalLocalScvfPairedData_[0].second.isOutside = true;
+            globalLocalScvfPairedData_[1].second.isOutside = false;
+        }
     }
 
     Scalar calculateOmega_(const GlobalPosition& normal,
@@ -347,7 +363,7 @@ private:
     }
 
     const Seed& seed_() const
-    { return seedPtr_; }
+    { return *seedPtr_; }
 
     const Problem& problem_() const
     { return *problemPtr_; }
@@ -366,12 +382,9 @@ private:
     bool regionUnique_;
     bool systemSolved_;
 
-    LocalIndexType contiFaceLocalIdx_;
-    GlobalIndexSet globalScvfIndices_;
-    GlobalIndexSet volVarsStencil_;
-    PositionVector volVarsPositions_;
-
+    LocalIndexType interactionRegionId_;
     std::vector<InteractionRegion> interactionRegions_;
+    std::vector<GlobalLocalFaceDataPair> globalLocalScvfPairedData_;
 
     Matrix T_;
 };
diff --git a/dumux/discretization/cellcentered/mpfa/lmethod/subcontrolvolumeface.hh b/dumux/discretization/cellcentered/mpfa/lmethod/subcontrolvolumeface.hh
index 13e90f8edc57ffaaea75353a59fe54a100b7250d..9468f8c2fb2b12d043f76ee6cbbf20de45f2b95e 100644
--- a/dumux/discretization/cellcentered/mpfa/lmethod/subcontrolvolumeface.hh
+++ b/dumux/discretization/cellcentered/mpfa/lmethod/subcontrolvolumeface.hh
@@ -61,8 +61,8 @@ public:
                                Scalar q,
                                bool boundary)
     : ParentType(helper,
-                 std::move(corners),
-                 std::move(unitOuterNormal),
+                 std::forward<std::vector<GlobalPosition>>(corners),
+                 std::forward<GlobalPosition>(unitOuterNormal),
                  vertexIndex,
                  localIndex,
                  scvfIndex,
diff --git a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh
index 444fc6a823bf5866652f14127c7957da6f390c29..73991700b7ae86df988dcd21ecf8c5476b41f66f 100644
--- a/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh
+++ b/dumux/discretization/cellcentered/mpfa/omethod/interactionvolume.hh
@@ -128,6 +128,7 @@ class CCMpfaOInteractionVolume : public CCMpfaInteractionVolumeBase<TypeTag, Tra
     using LocalScvfType = typename Traits::LocalScvfType;
 
 public:
+    using typename ParentType::GlobalLocalFaceDataPair;
     using typename ParentType::LocalIndexType;
     using typename ParentType::LocalIndexSet;
     using typename ParentType::LocalFaceData;
@@ -135,9 +136,6 @@ public:
     using typename ParentType::PositionVector;
     using typename ParentType::Seed;
 
-    // structure to store global and local face data
-    using GlobalLocalFaceDataPair = std::pair<const SubControlVolumeFace*, LocalFaceData>;
-
     CCMpfaOInteractionVolume(const Seed& seed,
                              const Problem& problem,
                              const FVElementGeometry& fvGeometry,
diff --git a/dumux/implicit/cellcentered/assemblymap.hh b/dumux/implicit/cellcentered/assemblymap.hh
index 58c40166350bd8dbb09184e0f71891be73101beb..eaf1ee205d8ffba74960161ea98ad8f6cdfdc363 100644
--- a/dumux/implicit/cellcentered/assemblymap.hh
+++ b/dumux/implicit/cellcentered/assemblymap.hh
@@ -22,8 +22,8 @@
  *        that contribute to the derivative calculation. This is used for
  *        finite-volume schemes with symmetric sparsity pattern in the global matrix.
  */
-#ifndef DUMUX_CC_SYMMETRIC_ASSEMBLY_MAP_HH
-#define DUMUX_CC_SYMMETRIC_ASSEMBLY_MAP_HH
+#ifndef DUMUX_CC_ASSEMBLY_MAP_HH
+#define DUMUX_CC_ASSEMBLY_MAP_HH
 
 #include <dune/istl/bcrsmatrix.hh>
 
@@ -32,8 +32,18 @@
 namespace Dumux
 {
 
+/*!
+ * \ingroup CellCentered
+ * \brief A simple version of the assembly map for cellcentered schemes.
+ *        This implementation works for schemes in which for a given cell I only
+ *        those cells J have to be prepared in whose stencil the cell I appears.
+ *        This means that for the flux calculations in the cells J (in order to compute
+ *        the derivatives with respect to cell I), we do not need data on any additional cells J
+ *        to compute these fluxes. The same holds for scvfs in the cells J, i.e. we need only those
+ *        scvfs in the cells J in which the cell I is in the stencil.
+ */
 template<class TypeTag>
-class CCSymmetricAssemblyMap
+class CCSimpleAssemblyMap
 {
     using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
     using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
@@ -45,6 +55,9 @@ class CCSymmetricAssemblyMap
     {
         IndexType globalJ;
         std::vector<IndexType> scvfsJ;
+        // A list of additional scvfs is needed for compatibility
+        // reasons with more complex assembly maps (see mpfa)
+        std::vector<IndexType> additionalScvfs;
     };
 
     using Map = std::vector<std::vector<DataJ>>;
diff --git a/dumux/implicit/cellcentered/mpfa/assemblymap.hh b/dumux/implicit/cellcentered/mpfa/assemblymap.hh
index cf9b374fba30f5b29447b9a43a31bcd151e5011d..76b6bca57a3928ff6ec4e86903acff330dae3132 100644
--- a/dumux/implicit/cellcentered/mpfa/assemblymap.hh
+++ b/dumux/implicit/cellcentered/mpfa/assemblymap.hh
@@ -25,6 +25,7 @@
 #define DUMUX_CC_MPFA_ASSEMBLY_MAP_HH
 
 #include <dumux/implicit/cellcentered/assemblymap.hh>
+#include <dumux/implicit/cellcentered/mpfa/generalassemblymap.hh>
 
 namespace Dumux
 {
@@ -36,9 +37,13 @@ class CCMpfaAssemblyMapImplementation;
 template<class TypeTag>
 using CCMpfaAssemblyMap = CCMpfaAssemblyMapImplementation<TypeTag, GET_PROP_VALUE(TypeTag, MpfaMethod)>;
 
-//! The default is simply the CCAssemblyMap
+//! The default is the general assembly map for mpfa schemes
 template<class TypeTag, MpfaMethods method>
-class CCMpfaAssemblyMapImplementation : public CCAssemblyMap<TypeTag> {};
+class CCMpfaAssemblyMapImplementation : public CCMpfaGeneralAssemblyMap<TypeTag> {};
+
+//! The o-method can use the simple assembly map
+template<class TypeTag>
+class CCMpfaAssemblyMapImplementation<TypeTag, MpfaMethods::oMethod> : public CCSimpleAssemblyMap<TypeTag> {};
 }
 
 #endif
diff --git a/dumux/implicit/cellcentered/mpfa/generalassemblymap.hh b/dumux/implicit/cellcentered/mpfa/generalassemblymap.hh
new file mode 100644
index 0000000000000000000000000000000000000000..c69911e08de49ca1dc55e01f785ea6bc8f3421e7
--- /dev/null
+++ b/dumux/implicit/cellcentered/mpfa/generalassemblymap.hh
@@ -0,0 +1,201 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Stores the face indices corresponding to the neighbors of an element
+ *        that contribute to the derivative calculation
+ */
+#ifndef DUMUX_CC_MPFA_GENERAL_ASSEMBLY_MAP_HH
+#define DUMUX_CC_MPFA_GENERAL_ASSEMBLY_MAP_HH
+
+#include <dumux/implicit/cellcentered/assemblymap.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup CellCentered
+ * \brief General version of the assembly map for cellcentered schemes. To each
+ *        cell I we store a list of cells J that are needed to compute the fluxes
+ *        in these cells J that depend on cell I. Furthermore, we store for each cell J
+ *        a list of scvfs in which cell I is in the stencil, as well as additional scvfs
+ *        that are also required to set up the transmissibilities.
+ */
+template<class TypeTag>
+class CCMpfaGeneralAssemblyMap
+{
+    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using Element = typename GridView::template Codim<0>::Entity;
+    using MpfaHelper = typename GET_PROP_TYPE(TypeTag, MpfaHelper);
+    using FluxVariables = typename GET_PROP_TYPE(TypeTag, FluxVariables);
+    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
+
+    using IndexType = typename GridView::IndexSet::IndexType;
+
+    // To each cell "globalI" there will be a list of "globalJ", in which globalI is part
+    // of the stencil. We save the scvfs over which fluxes depend on globalI and a list of
+    // additional scvfs which are needed temporarily to set up the transmissibilities of the scvfsJ
+    struct DataJ
+    {
+        IndexType globalJ;
+        std::vector<IndexType> scvfsJ;
+        std::vector<IndexType> additionalScvfs;
+    };
+
+    using Map = std::vector<std::vector<DataJ>>;
+
+public:
+
+    /*!
+     * \brief Initialize the AssemblyMap object.
+     *
+     * \param problem The problem which we want to simulate.
+     */
+    void init(const Problem& problem)
+    {
+        map_.resize(problem.gridView().size(0));
+        for (const auto& element : elements(problem.gridView()))
+        {
+            // We are looking for the elements I, for which this element J is in the flux stencil
+            auto globalJ = problem.elementMapper().index(element);
+
+            auto fvGeometry = localView(problem.model().globalFvGeometry());
+            fvGeometry.bindElement(element);
+
+            // obtain the data of J in elements I
+            std::vector<std::pair<IndexType, std::vector<DataJ>>> dataJForI;
+
+            // loop over sub control faces
+            for (auto&& scvf : scvfs(fvGeometry))
+            {
+                FluxVariables fluxVars;
+                const auto& stencil = fluxVars.computeStencil(problem, element, fvGeometry, scvf);
+
+                // insert our index in the neighbor stencils of the elements in the flux stencil
+                for (auto globalI : stencil)
+                {
+                    if (globalI == globalJ)
+                        continue;
+
+                    auto it = std::find_if(dataJForI.begin(),
+                                           dataJForI.end(),
+                                           [globalI](const auto& pair) { return pair.first == globalI; });
+
+                    if (it != dataJForI.end())
+                    {
+                        // get the data J which corresponds to the actual global J
+                        // This will be the first entry, as we do so in the else statement (see below)
+                        auto& globalJDataJ = it->second[0];
+
+                        // insert actual scvf index in the list of scvfs which couple I and J
+                        globalJDataJ.scvfsJ.push_back(scvf.index());
+
+                        // Also, all scvfs connected to a vertex together with the actual scvf
+                        // land in the list of additional scvfs. Of that list we will delete those
+                        // that are already in the list of scvfsJ later...
+                        const auto scvfVectorAtVertex = MpfaHelper::getScvFacesAtVertex(scvf.vertexIndex(), element, fvGeometry);
+                        std::vector<IndexType> scvfIndicesAtVertex(scvfVectorAtVertex.size());
+                        for (unsigned int i = 0; i < scvfVectorAtVertex.size(); ++i)
+                            scvfIndicesAtVertex[i] = scvfVectorAtVertex[i]->index();
+                        globalJDataJ.additionalScvfs.insert(globalJDataJ.additionalScvfs.end(),
+                                                            scvfIndicesAtVertex.begin(),
+                                                            scvfIndicesAtVertex.end());
+
+                        // all the other dofs in the stencil have to appear as "globalJ" to globalI as well
+                        for (auto globalJ2 : stencil)
+                        {
+                            if (globalJ2 == globalJ || globalJ2 == globalI)
+                                continue;
+
+                            auto it2 = std::find_if(it->second.begin(),
+                                                    it->second.end(),
+                                                    [globalJ2](const auto& dataJ) { return dataJ.globalJ == globalJ2; });
+
+                            // if entry for globalJ2 does not exist yet, add globalJ2 to the J-data of globalI
+                            // with an empty set of scvfs over which I and J are coupled (i.e. they aren't coupled)
+                            if (it2 == it->second.end())
+                                it->second.push_back(DataJ({globalJ2, std::vector<IndexType>()}));
+                        }
+                    }
+                    else
+                    {
+                        // No DataJ for globalI exists yet. Make it and insert data on the actual
+                        // global J as first entry in the vector of DataJs belonging to globalI
+                        dataJForI.emplace_back(std::make_pair(globalI,
+                                                              std::vector<DataJ>({DataJ({globalJ, std::vector<IndexType>({scvf.index()})})})));
+
+                        // Also, all scvfs connected to a vertex together with the actual scvf
+                        // land in the list of additional scvfs. Of that list we will delete those
+                        // that are already in the list of scvfsJ later...
+                        const auto scvfVectorAtVertex = MpfaHelper::getScvFacesAtVertex(scvf.vertexIndex(), element, fvGeometry);
+                        std::vector<IndexType> scvfIndicesAtVertex(scvfVectorAtVertex.size());
+                        for (unsigned int i = 0; i < scvfVectorAtVertex.size(); ++i)
+                            scvfIndicesAtVertex[i] = scvfVectorAtVertex[i]->index();
+                        dataJForI.back().second[0].additionalScvfs.insert(dataJForI.back().second[0].additionalScvfs.end(),
+                                                                          scvfIndicesAtVertex.begin(),
+                                                                          scvfIndicesAtVertex.end());
+
+                        // all the other dofs in the stencil will be "globalJ" to globalI as well
+                        for (auto globalJ2 : stencil)
+                            if (globalJ2 != globalJ && globalJ2 != globalI)
+                                dataJForI.back().second.push_back(DataJ({globalJ2, std::vector<IndexType>()}));
+                    }
+                }
+            }
+
+            // Insert the data into the global map
+            for (auto&& pair : dataJForI)
+            {
+                // obtain the corresponding entry in the map
+                auto& dataJVector = map_[pair.first];
+                for (auto&& dataJ : pair.second)
+                {
+                    // delete those additionalScvfs indices that are already in the list of scvfs
+                    dataJ.additionalScvfs.erase(std::remove_if(dataJ.additionalScvfs.begin(),
+                                                               dataJ.additionalScvfs.end(),
+                                                               [&dataJ] (const auto& idx) { return MpfaHelper::contains(dataJ.scvfsJ, idx); }),
+                                                dataJ.additionalScvfs.end());
+
+                    // if entry for j exists in the map already add scvf and additional scvf indices, create otherwise
+                    auto it = std::find_if(dataJVector.begin(),
+                                           dataJVector.end(),
+                                           [&dataJ](const auto& dataJofMap) { return dataJofMap.globalJ == dataJ.globalJ; });
+
+                    if (it != dataJVector.end())
+                    {
+                        it->scvfsJ.insert(it->scvfsJ.end(), dataJ.scvfsJ.begin(), dataJ.scvfsJ.end());
+                        it->additionalScvfs.insert(it->additionalScvfs.end(), dataJ.additionalScvfs.begin(), dataJ.additionalScvfs.end());
+                    }
+                    else
+                        dataJVector.emplace_back(std::move(dataJ));
+                }
+            }
+        }
+    }
+
+    const std::vector<DataJ>& operator[] (const IndexType globalI) const
+    { return map_[globalI]; }
+
+private:
+    Map map_;
+};
+}
+
+#endif
diff --git a/dumux/implicit/cellcentered/mpfa/propertydefaults.hh b/dumux/implicit/cellcentered/mpfa/propertydefaults.hh
index 483f831e8367bbe97157c1a43e74944574674f9d..0f0a0dbc26d5b7728dc8aa0605630c2f8dfca79d 100644
--- a/dumux/implicit/cellcentered/mpfa/propertydefaults.hh
+++ b/dumux/implicit/cellcentered/mpfa/propertydefaults.hh
@@ -43,6 +43,7 @@
 #include <dumux/discretization/cellcentered/mpfa/globalinteractionvolumeseeds.hh>
 #include <dumux/discretization/cellcentered/mpfa/interiorboundarydata.hh>
 #include <dumux/implicit/cellcentered/mpfa/localresidual.hh>
+#include <dumux/implicit/cellcentered/mpfa/assemblymap.hh>
 #include <dumux/implicit/cellcentered/properties.hh>
 
 namespace Dumux {
@@ -66,6 +67,9 @@ SET_PROP(CCMpfaModel, MpfaMethod)
 //! The mpfa helper class
 SET_TYPE_PROP(CCMpfaModel, MpfaHelper, CCMpfaHelper<TypeTag>);
 
+//! The assembly map for mpfa schemes
+SET_TYPE_PROP(CCMpfaModel, AssemblyMap, CCMpfaAssemblyMap<TypeTag>);
+
 //! The interaction volume class
 SET_TYPE_PROP(CCMpfaModel, InteractionVolume, CCMpfaInteractionVolume<TypeTag>);
 
diff --git a/dumux/implicit/cellcentered/propertydefaults.hh b/dumux/implicit/cellcentered/propertydefaults.hh
index 702259c31e8b32641980917887ad55f61c822ec8..99fbb8925c9fadc81dfe84ac82ad9ae3929d5e99 100644
--- a/dumux/implicit/cellcentered/propertydefaults.hh
+++ b/dumux/implicit/cellcentered/propertydefaults.hh
@@ -76,8 +76,8 @@ SET_TYPE_PROP(CCModel, GlobalVolumeVariables, CCGlobalVolumeVariables<TypeTag, G
 //! Set the BaseLocalResidual to CCLocalResidual
 SET_TYPE_PROP(CCModel, BaseLocalResidual, CCLocalResidual<TypeTag>);
 
-//! Set the AssemblyMap to the CCAssemblyMap (default: symmetric occupation pattern)
-SET_TYPE_PROP(CCModel, AssemblyMap, Dumux::CCSymmetricAssemblyMap<TypeTag>);
+//! Set the AssemblyMap to the CCAssemblyMap per default
+SET_TYPE_PROP(CCModel, AssemblyMap, Dumux::CCSimpleAssemblyMap<TypeTag>);
 
 // By default, we disable interior boundaries
 SET_BOOL_PROP(CCModel, EnableInteriorBoundaries, false);