diff --git a/dumux/discretization/staggered/fvelementgeometry.hh b/dumux/discretization/staggered/fvelementgeometry.hh
index 2a2213acac579eb4a7c2cb1695aa76a4d8f22437..1b98bcc29d61abbeae9a2e11d1dc1e66219c2c44 100644
--- a/dumux/discretization/staggered/fvelementgeometry.hh
+++ b/dumux/discretization/staggered/fvelementgeometry.hh
@@ -28,18 +28,30 @@
 
 namespace Dumux {
 
+/*!
+ * \ingroup StaggeredDiscretization
+ * \brief Stencil-local finite volume geometry (scvs and scvfs) for staggered models
+ *        This builds up the sub control volumes and sub control volume faces
+ *        for each element in the local scope we are restricting to, e.g. stencil or element.
+ * \tparam GG the finite volume grid geometry type
+ * \tparam enableFVGridGeometryCache if the grid geometry is cached or not
+ * \note This class is specialized for versions with and without caching the fv geometries on the grid view
+ */
+template<class GG, bool enableFVGridGeometryCache>
+class StaggeredFVElementGeometry;
+
 /*!
  * \ingroup StaggeredDiscretization
  * \brief Base class for the finite volume geometry vector for staggered models
  *        This locally builds up the sub control volumes and sub control volume faces
  *        for each element.
+ *        Specialization for grid caching enabled
  * \tparam GG the finite volume grid geometry type
- * \tparam enableFVGridGeometryCache if the grid geometry is cached or not
  */
-template<class GG, bool enableFVGridGeometryCache>
-class StaggeredFVElementGeometry : public CCTpfaFVElementGeometry<GG, enableFVGridGeometryCache>
+template<class GG>
+class StaggeredFVElementGeometry<GG, true> : public CCTpfaFVElementGeometry<GG, true>
 {
-    using ParentType = CCTpfaFVElementGeometry<GG, enableFVGridGeometryCache>;
+    using ParentType = CCTpfaFVElementGeometry<GG, true>;
     using IndexType = typename GG::GridView::IndexSet::IndexType;
 public:
     //! export type of subcontrol volume face
@@ -60,6 +72,254 @@ public:
     }
 };
 
+/*!
+ * \ingroup StaggeredDiscretization
+ * \brief Base class for the finite volume geometry vector for staggered models
+ *        This locally builds up the sub control volumes and sub control volume faces
+ *        for each element.
+ *        Specialization for grid caching enabled
+ * \tparam GG the finite volume grid geometry type
+ */
+template<class GG>
+class StaggeredFVElementGeometry<GG, false>
+{
+    using ThisType = StaggeredFVElementGeometry<GG, false>;
+    using GridView = typename GG::GridView;
+    using IndexType = typename GridView::IndexSet::IndexType;
+    using Element = typename GridView::template Codim<0>::Entity;
+public:
+    //! export type of subcontrol volume
+    using SubControlVolume = typename GG::SubControlVolume;
+    //! export type of subcontrol volume face
+    using SubControlVolumeFace = typename GG::SubControlVolumeFace;
+    //! export type of finite volume grid geometry
+    using FVGridGeometry = GG;
+
+    //! Constructor getting a auxiliary cell center of face specific FvGridGeometry type.
+    //! Needed for the multi-domain framework.
+    template<class CellCenterOrFaceFVGridGeometry>
+    StaggeredFVElementGeometry(const CellCenterOrFaceFVGridGeometry& fvGridGeometry)
+    : fvGridGeometryPtr_(&fvGridGeometry.actualfvGridGeometry()) {}
+
+    //! Constructor
+    StaggeredFVElementGeometry(const FVGridGeometry& fvGridGeometry)
+    : fvGridGeometryPtr_(&fvGridGeometry) {}
+
+    //! Get a sub control volume face with an element index and a local scvf index
+    const SubControlVolumeFace& scvf(IndexType eIdx, IndexType localScvfIdx) const
+    {
+        return scvf(this->fvGridGeometry().localToGlobalScvfIndex(eIdx, localScvfIdx));
+    }
+
+    //! Get an elment sub control volume with a global scv index
+    //! We separate element and neighbor scvs to speed up mapping
+    const SubControlVolume& scv(IndexType scvIdx) const
+    {
+        if (scvIdx == scvIndices_[0])
+            return scvs_[0];
+        else
+            return neighborScvs_[findLocalIndex_(scvIdx, neighborScvIndices_)];
+    }
+
+    //! Get an element sub control volume face with a global scvf index
+    //! We separate element and neighbor scvfs to speed up mapping
+    const SubControlVolumeFace& scvf(IndexType scvfIdx) const
+    {
+        auto it = std::find(scvfIndices_.begin(), scvfIndices_.end(), scvfIdx);
+        if (it != scvfIndices_.end())
+            return scvfs_[std::distance(scvfIndices_.begin(), it)];
+        else
+            return neighborScvfs_[findLocalIndex_(scvfIdx, neighborScvfIndices_)];
+    }
+
+    //! iterator range for sub control volumes. Iterates over
+    //! all scvs of the bound element (not including neighbor scvs)
+    //! 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::array<SubControlVolume, 1>::const_iterator>
+    scvs(const ThisType& g)
+    {
+        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
+    //! all scvfs of the bound element (not including neighbor scvfs)
+    //! 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<typename std::vector<SubControlVolumeFace>::const_iterator>
+    scvfs(const ThisType& g)
+    {
+        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
+    std::size_t numScv() const
+    { return scvs_.size(); }
+
+    //! number of sub control volumes in this fv element geometry
+    std::size_t numScvf() const
+    { return scvfs_.size(); }
+
+    //! Binding of an element preparing the geometries of the whole stencil
+    //! called by the local jacobian to prepare element assembly
+    void bind(const Element& element)
+    {
+        bindElement(element);
+
+        neighborScvs_.reserve(element.subEntities(1));
+        neighborScvfIndices_.reserve(element.subEntities(1));
+        neighborScvfs_.reserve(element.subEntities(1));
+
+        std::vector<IndexType> handledNeighbors;
+        handledNeighbors.reserve(element.subEntities(1));
+        for (const auto& intersection : intersections(fvGridGeometry().gridView(), element))
+        {
+            if (intersection.neighbor())
+            {
+                const auto outside = intersection.outside();
+                const auto outsideIdx = fvGridGeometry().elementMapper().index(outside);
+
+                // make outside geometries only if not done yet (could happen on non-conforming grids)
+                if ( std::find(handledNeighbors.begin(), handledNeighbors.end(), outsideIdx) == handledNeighbors.end() )
+                {
+                    makeNeighborGeometries_(outside, outsideIdx);
+                    handledNeighbors.push_back(outsideIdx);
+                }
+            }
+        }
+    }
+
+    //! Binding of an element preparing the geometries only inside the element
+    void bindElement(const Element& element)
+    {
+        clear_();
+        elementPtr_ = &element;
+        scvfs_.reserve(element.subEntities(1));
+        scvfIndices_.reserve(element.subEntities(1));
+        makeElementGeometries_(element);
+    }
+
+    //! The global finite volume geometry we are a restriction of
+    const FVGridGeometry& fvGridGeometry() const
+    { return *fvGridGeometryPtr_; }
+
+private:
+
+    //! create scvs and scvfs of the bound element
+    void makeElementGeometries_(const Element& element)
+    {
+        const auto eIdx = fvGridGeometry().elementMapper().index(element);
+        scvs_[0] = SubControlVolume(element.geometry(), eIdx);
+        scvIndices_[0] = eIdx;
+
+        const auto& scvFaceIndices = fvGridGeometry().scvfIndicesOfScv(eIdx);
+        const auto& neighborVolVarIndices = fvGridGeometry().neighborVolVarIndices(eIdx);
+
+        typename FVGridGeometry::GeometryHelper geometryHelper(element, fvGridGeometry().gridView());
+
+        int scvfCounter = 0;
+        for (const auto& intersection : intersections(fvGridGeometry().gridView(), element))
+        {
+            const auto& scvfNeighborVolVarIndex = neighborVolVarIndices[scvfCounter];
+
+            if (intersection.neighbor() || intersection.boundary())
+            {
+                geometryHelper.updateLocalFace(fvGridGeometry().intersectionMapper(), intersection);
+                std::vector<IndexType> scvIndices{eIdx, scvfNeighborVolVarIndex};
+                scvfs_.emplace_back(intersection,
+                                    intersection.geometry(),
+                                    scvFaceIndices[scvfCounter],
+                                    scvIndices,
+                                    geometryHelper);
+                scvfIndices_.emplace_back(scvFaceIndices[scvfCounter]);
+                scvfCounter++;
+            }
+        }
+    }
+
+    //! create the necessary scvs and scvfs of the neighbor elements to the bound elements
+    void makeNeighborGeometries_(const Element& element, const IndexType eIdx)
+    {
+        // using ScvfGridIndexStorage = typename SubControlVolumeFace::Traits::GridIndexStorage;
+
+        // create the neighbor scv
+        neighborScvs_.emplace_back(element.geometry(), eIdx);
+        neighborScvIndices_.push_back(eIdx);
+
+        const auto& scvFaceIndices = fvGridGeometry().scvfIndicesOfScv(eIdx);
+        const auto& neighborVolVarIndices = fvGridGeometry().neighborVolVarIndices(eIdx);
+
+        typename FVGridGeometry::GeometryHelper geometryHelper(element, fvGridGeometry().gridView());
+
+        int scvfCounter = 0;
+        for (const auto& intersection : intersections(fvGridGeometry().gridView(), element))
+        {
+            const auto& scvfNeighborVolVarIndex = neighborVolVarIndices[scvfCounter];
+            geometryHelper.updateLocalFace(fvGridGeometry().intersectionMapper(), intersection);
+
+            if (intersection.neighbor())
+            {
+                // only create subcontrol faces where the outside element is the bound element
+                if (intersection.outside() == *elementPtr_)
+                {
+                    std::vector<IndexType> scvIndices{eIdx, scvfNeighborVolVarIndex};
+                    neighborScvfs_.emplace_back(intersection,
+                                                intersection.geometry(),
+                                                scvFaceIndices[scvfCounter],
+                                                scvIndices,
+                                                geometryHelper);
+
+                    neighborScvfIndices_.push_back(scvFaceIndices[scvfCounter]);
+                }
+                scvfCounter++;
+            }
+            else if (intersection.boundary())
+                scvfCounter++;
+        }
+    }
+
+    const IndexType findLocalIndex_(const IndexType idx,
+                                    const std::vector<IndexType>& indices) const
+    {
+        auto it = std::find(indices.begin(), indices.end(), idx);
+        assert(it != indices.end() && "Could not find the scv/scvf! Make sure to properly bind this class!");
+        return std::distance(indices.begin(), it);
+    }
+
+    //! Clear all local data
+    void clear_()
+    {
+        scvfIndices_.clear();
+        scvfs_.clear();
+
+        neighborScvIndices_.clear();
+        neighborScvfIndices_.clear();
+        neighborScvs_.clear();
+        neighborScvfs_.clear();
+    }
+
+    const Element* elementPtr_; //!< the element to which this fvgeometry is bound
+    const FVGridGeometry* fvGridGeometryPtr_;  //!< the grid fvgeometry
+
+    // local storage after binding an element
+    std::array<IndexType, 1> scvIndices_;
+    std::array<SubControlVolume, 1> scvs_;
+
+    std::vector<IndexType> scvfIndices_;
+    std::vector<SubControlVolumeFace> scvfs_;
+
+    std::vector<IndexType> neighborScvIndices_;
+    std::vector<SubControlVolume> neighborScvs_;
+
+    std::vector<IndexType> neighborScvfIndices_;
+    std::vector<SubControlVolumeFace> neighborScvfs_;
+};
+
+
 } // end namespace
 
 #endif
diff --git a/dumux/discretization/staggered/fvgridgeometry.hh b/dumux/discretization/staggered/fvgridgeometry.hh
index 3fde8bfb994c58a68b6478a67f7be8d56ab1a9e9..dde1e9930ab4873bd4690364e6ca4692a0a5868f 100644
--- a/dumux/discretization/staggered/fvgridgeometry.hh
+++ b/dumux/discretization/staggered/fvgridgeometry.hh
@@ -223,7 +223,7 @@ public:
     {
         // Check if the overlap size is what we expect
         if (!CheckOverlapSize<DiscretizationMethod::staggered>::isValid(gridView))
-            DUNE_THROW(Dune::InvalidStateException, "The satggered discretization method needs at least an overlap of 1 for parallel computations. "
+            DUNE_THROW(Dune::InvalidStateException, "The staggered discretization method needs at least an overlap of 1 for parallel computations. "
                                                      << " Set the parameter \"Grid.Overlap\" in the input file.");
     }
 
@@ -314,8 +314,7 @@ public:
                                         intersection.geometry(),
                                         scvfIdx,
                                         std::vector<IndexType>({eIdx, nIdx}),
-                                        geometryHelper
-                                        );
+                                        geometryHelper);
                     localToGlobalScvfIndices_[eIdx][localFaceIndex] = scvfIdx;
                     scvfsIndexSet.push_back(scvfIdx++);
                 }
@@ -326,8 +325,7 @@ public:
                                         intersection.geometry(),
                                         scvfIdx,
                                         std::vector<IndexType>({eIdx, this->gridView().size(0) + numBoundaryScvf_++}),
-                                        geometryHelper
-                                        );
+                                        geometryHelper);
                     localToGlobalScvfIndices_[eIdx][localFaceIndex] = scvfIdx;
                     scvfsIndexSet.push_back(scvfIdx++);
                 }
@@ -421,8 +419,208 @@ private:
  */
 template<class GV, class Traits>
 class StaggeredFVGridGeometry<GV, false, Traits>
+: public BaseFVGridGeometry<StaggeredFVGridGeometry<GV, false, Traits>, GV, Traits>
 {
-    // TODO: implement without caching
+    using ThisType = StaggeredFVGridGeometry<GV, false, Traits>;
+    using ParentType = BaseFVGridGeometry<ThisType, GV, Traits>;
+    using IndexType = typename GV::IndexSet::IndexType;
+    using Element = typename GV::template Codim<0>::Entity;
+
+    using IntersectionMapper = typename Traits::IntersectionMapper;
+    using ConnectivityMap = typename Traits::template ConnectivityMap<ThisType>;
+
+public:
+    //! export discretization method
+    static constexpr DiscretizationMethod discMethod = DiscretizationMethod::staggered;
+
+    using GeometryHelper = typename Traits::GeometryHelper;
+
+    //! export the type of the fv element geometry (the local view type)
+    using LocalView = typename Traits::template LocalView<ThisType, false>;
+    //! export the type of sub control volume
+    using SubControlVolume = typename Traits::SubControlVolume;
+    //! export the type of sub control volume
+    using SubControlVolumeFace = typename Traits::SubControlVolumeFace;
+    //! export the grid view type
+    using GridView = GV;
+    //! export the dof type indices
+    using DofTypeIndices = typename Traits::DofTypeIndices;
+
+    //! return a integral constant for cell center dofs
+    static constexpr auto cellCenterIdx()
+    { return typename DofTypeIndices::CellCenterIdx{}; }
+
+    //! return a integral constant for face dofs
+    static constexpr auto faceIdx()
+    { return typename DofTypeIndices::FaceIdx{}; }
+
+    using CellCenterFVGridGeometryType = CellCenterFVGridGeometry<ThisType>;
+    using FaceFVGridGeometryType = FaceFVGridGeometry<ThisType>;
+
+    using FVGridGeometryTuple = std::tuple< CellCenterFVGridGeometry<ThisType>, FaceFVGridGeometry<ThisType> >;
+
+    //! Constructor
+    StaggeredFVGridGeometry(const GridView& gridView)
+    : ParentType(gridView)
+    , intersectionMapper_(gridView)
+    {
+        // Check if the overlap size is what we expect
+        if (!CheckOverlapSize<DiscretizationMethod::staggered>::isValid(gridView))
+            DUNE_THROW(Dune::InvalidStateException, "The staggered discretization method needs at least an overlap of 1 for parallel computations. "
+                                                     << " Set the parameter \"Grid.Overlap\" in the input file.");
+    }
+
+    //! update all fvElementGeometries (do this again after grid adaption)
+    void update()
+    {
+        // clear containers (necessary after grid refinement)
+        scvfIndicesOfScv_.clear();
+        intersectionMapper_.update();
+        neighborVolVarIndices_.clear();
+
+        numScvs_ = numCellCenterDofs();
+        numScvf_ = 0;
+        numBoundaryScvf_ = 0;
+        scvfIndicesOfScv_.resize(numScvs_);
+        localToGlobalScvfIndices_.resize(numScvs_);
+        neighborVolVarIndices_.resize(numScvs_);
+
+        // Build the scvs and scv faces
+        for (const auto& element : elements(this->gridView()))
+        {
+            auto eIdx = this->elementMapper().index(element);
+
+            // the element-wise index sets for finite volume geometry
+            auto numLocalFaces = intersectionMapper_.numFaces(element);
+            std::vector<IndexType> scvfsIndexSet;
+            scvfsIndexSet.reserve(numLocalFaces);
+            localToGlobalScvfIndices_[eIdx].resize(numLocalFaces);
+
+            std::vector<IndexType> neighborVolVarIndexSet;
+            neighborVolVarIndexSet.reserve(numLocalFaces);
+
+            for (const auto& intersection : intersections(this->gridView(), element))
+            {
+                const auto localFaceIndex = intersection.indexInInside();
+                localToGlobalScvfIndices_[eIdx][localFaceIndex] = numScvf_;
+                scvfsIndexSet.push_back(numScvf_++);
+
+                if (intersection.neighbor())
+                {
+                    const auto nIdx = this->elementMapper().index(intersection.outside());
+                    neighborVolVarIndexSet.emplace_back(nIdx);
+                }
+                else
+                    neighborVolVarIndexSet.emplace_back(numScvs_ + numBoundaryScvf_++);
+            }
+
+            // Save the scvf indices belonging to this scv to build up fv element geometries fast
+            scvfIndicesOfScv_[eIdx] = scvfsIndexSet;
+            neighborVolVarIndices_[eIdx] = neighborVolVarIndexSet;
+        }
+
+        // build the connectivity map for an effecient assembly
+        connectivityMap_.update(*this);
+    }
+
+    //! The total number of sub control volumes
+    std::size_t numScv() const
+    {
+        return numScvs_;
+    }
+
+    //! The total number of sub control volume faces
+    std::size_t numScvf() const
+    {
+        return numScvf_;
+    }
+
+    //! The total number of boundary sub control volume faces
+    std::size_t numBoundaryScvf() const
+    {
+        return numBoundaryScvf_;
+    }
+
+    //! The total number of intersections
+    std::size_t numIntersections() const
+    {
+        return intersectionMapper_.numIntersections();
+    }
+
+    //! the total number of dofs
+    std::size_t numDofs() const
+    { return numCellCenterDofs() + numFaceDofs(); }
+
+    std::size_t numCellCenterDofs() const
+    { return this->gridView().size(0); }
+
+    std::size_t numFaceDofs() const
+    { return this->gridView().size(1); }
+
+    const std::vector<IndexType>& scvfIndicesOfScv(IndexType scvIdx) const
+    { return scvfIndicesOfScv_[scvIdx]; }
+
+    IndexType localToGlobalScvfIndex(IndexType eIdx, IndexType localScvfIdx) const
+    {
+        return localToGlobalScvfIndices_[eIdx][localScvfIdx];
+    }
+
+    /*!
+     * \brief Returns the connectivity map of which dofs have derivatives with respect
+     *        to a given dof.
+     */
+    const ConnectivityMap &connectivityMap() const
+    { return connectivityMap_; }
+
+    //! Returns a pointer the cell center specific auxiliary class. Required for the multi-domain FVAssembler's ctor.
+    std::unique_ptr<CellCenterFVGridGeometry<ThisType>> cellCenterFVGridGeometryPtr() const
+    {
+        return std::make_unique<CellCenterFVGridGeometry<ThisType>>(this);
+    }
+
+    //! Returns a pointer the face specific auxiliary class. Required for the multi-domain FVAssembler's ctor.
+    std::unique_ptr<FaceFVGridGeometry<ThisType>> faceFVGridGeometryPtr() const
+    {
+        return std::make_unique<FaceFVGridGeometry<ThisType>>(this);
+    }
+
+    //! Return a copy of the cell center specific auxiliary class.
+    CellCenterFVGridGeometry<ThisType> cellCenterFVGridGeometry() const
+    {
+        return CellCenterFVGridGeometry<ThisType>(this);
+    }
+
+    //! Return a copy of the face specific auxiliary class.
+    FaceFVGridGeometry<ThisType> faceFVGridGeometry() const
+    {
+        return FaceFVGridGeometry<ThisType>(this);
+    }
+
+    //! Return a reference to the intersection mapper
+    const IntersectionMapper& intersectionMapper() const
+    {
+        return intersectionMapper_;
+    }
+
+    //! Return the neighbor volVar indices for all scvfs in the scv with index scvIdx
+    const std::vector<IndexType>& neighborVolVarIndices(IndexType scvIdx) const
+    { return neighborVolVarIndices_[scvIdx]; }
+
+private:
+
+    //! Information on the global number of geometries
+    IndexType numScvs_;
+    IndexType numScvf_;
+    IndexType numBoundaryScvf_;
+    std::vector<std::vector<IndexType>> localToGlobalScvfIndices_;
+    std::vector<std::vector<IndexType>> neighborVolVarIndices_;
+
+    // mappers
+    ConnectivityMap connectivityMap_;
+    IntersectionMapper intersectionMapper_;
+
+    //! vectors that store the global data
+    std::vector<std::vector<IndexType>> scvfIndicesOfScv_;
 };
 
 } // end namespace