diff --git a/dumux/discretization/cellcentered/tpfa/darcyslaw.hh b/dumux/discretization/cellcentered/tpfa/darcyslaw.hh
index 3a3143739464163573a757f40d09403c5a765160..a87ed7610372948dd2ba72d3335d516bdb7f6c34 100644
--- a/dumux/discretization/cellcentered/tpfa/darcyslaw.hh
+++ b/dumux/discretization/cellcentered/tpfa/darcyslaw.hh
@@ -51,6 +51,7 @@ NEW_PROP_TAG(ProblemEnableGravity);
 template <class TypeTag>
 class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
 {
+    using Implementation = DarcysLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>;
     using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
     using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
@@ -60,6 +61,7 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
     using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
     using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
     using ElementFluxVarsCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache);
+    using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache);
 
     using Element = typename GridView::template Codim<0>::Entity;
     using IndexType = typename GridView::IndexSet::IndexType;
@@ -70,10 +72,56 @@ class DarcysLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
     using DimWorldMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
     using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
 
+    class TpfaDarcysLawCache
+    {
+    public:
+        void updateAdvection(const Problem& problem,
+                             const Element& element,
+                             const FVElementGeometry& fvGeometry,
+                             const ElementVolumeVariables& elemVolVars,
+                             const SubControlVolumeFace &scvf)
+        {
+            tij_ = Implementation::calculateTransmissibilities(problem, element, fvGeometry, elemVolVars, scvf);
+        }
+
+        const Scalar& tij() const
+        { return tij_; }
+
+    private:
+        Scalar tij_;
+    };
+
+    //! Class that fills the cache corresponding to tpfa Darcy's Law
+    class TpfaDarcysLawCacheFiller
+    {
+    public:
+        //! Function to fill a TpfaDarcysLawCache of a given scvf
+        //! This interface has to be met by any advection-related cache filler class
+        template<class FluxVariablesCacheFiller>
+        static void fill(FluxVariablesCache& scvfFluxVarsCache,
+                         const Problem& problem,
+                         const Element& element,
+                         const FVElementGeometry& fvGeometry,
+                         const ElementVolumeVariables& elemVolVars,
+                         const SubControlVolumeFace& scvf,
+                         const FluxVariablesCacheFiller& fluxVarsCacheFiller)
+        {
+            scvfFluxVarsCache.updateAdvection(problem,
+                                              element,
+                                              fvGeometry,
+                                              elemVolVars,
+                                              scvf);
+        }
+    };
+
 public:
     // state the discretization method this implementation belongs to
     static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCTpfa;
 
+    // state the type for the corresponding cache and its filler
+    using Cache = TpfaDarcysLawCache;
+    using CacheFiller = TpfaDarcysLawCacheFiller;
+
     static Scalar flux(const Problem& problem,
                        const Element& element,
                        const FVElementGeometry& fvGeometry,
diff --git a/dumux/discretization/cellcentered/tpfa/elementfluxvariablescache.hh b/dumux/discretization/cellcentered/tpfa/elementfluxvariablescache.hh
index 343e7d13e7f24c10c755a36d30cfde0813cd7b41..f2360b74848afe0ac31467cdbe70723fdc4c8933 100644
--- a/dumux/discretization/cellcentered/tpfa/elementfluxvariablescache.hh
+++ b/dumux/discretization/cellcentered/tpfa/elementfluxvariablescache.hh
@@ -24,6 +24,7 @@
 #define DUMUX_DISCRETIZATION_CCTPFA_ELEMENT_FLUXVARSCACHE_HH
 
 #include <dumux/implicit/properties.hh>
+#include <dumux/discretization/cellcentered/tpfa/fluxvariablescachefiller.hh>
 
 namespace Dumux
 {
@@ -111,8 +112,7 @@ class CCTpfaElementFluxVariablesCache<TypeTag, false>
     using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache);
     using GlobalFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, GlobalFluxVariablesCache);
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
-
-    static const bool solDependentAdvection = GET_PROP_VALUE(TypeTag, SolutionDependentAdvection);
+    using FluxVariablesCacheFiller = CCTpfaFluxVariablesCacheFiller<TypeTag>;
 
 public:
     CCTpfaElementFluxVariablesCache(const GlobalFluxVariablesCache& global)
@@ -128,12 +128,15 @@ public:
         const auto numScvf = fvGeometry.numScvf();
         fluxVarsCache_.resize(numScvf);
         globalScvfIndices_.resize(numScvf);
-        IndexType localScvfIdx = 0;
 
+        // instantiate helper class to fill the caches
+        FluxVariablesCacheFiller filler(globalFluxVarsCache().problem_());
+
+        IndexType localScvfIdx = 0;
         // fill the containers
         for (auto&& scvf : scvfs(fvGeometry))
         {
-            fluxVarsCache_[localScvfIdx].update(globalFluxVarsCache().problem_(), element, fvGeometry, elemVolVars, scvf);
+            filler.fill(*this, fluxVarsCache_[localScvfIdx], element, fvGeometry, elemVolVars, scvf);
             globalScvfIndices_[localScvfIdx] = scvf.index();
             localScvfIdx++;
         }
@@ -150,6 +153,9 @@ public:
         const auto& assemblyMapI = problem.model().localJacobian().assemblyMap()[globalI];
         const auto numNeighbors = assemblyMapI.size();
 
+        // instantiate helper class to fill the caches
+        FluxVariablesCacheFiller filler(problem);
+
         // find the number of scv faces that need to be prepared
         auto numScvf = fvGeometry.numScvf();
         for (unsigned int localIdxJ = 0; localIdxJ < numNeighbors; ++localIdxJ)
@@ -161,7 +167,7 @@ public:
         unsigned int localScvfIdx = 0;
         for (auto&& scvf : scvfs(fvGeometry))
         {
-            fluxVarsCache_[localScvfIdx].update(problem, element, fvGeometry, elemVolVars, scvf);
+            filler.fill(*this, fluxVarsCache_[localScvfIdx], element, fvGeometry, elemVolVars, scvf);
             globalScvfIndices_[localScvfIdx] = scvf.index();
             localScvfIdx++;
         }
@@ -173,7 +179,7 @@ public:
             for (auto scvfIdx : assemblyMapI[localIdxJ].scvfsJ)
             {
                 auto&& scvfJ = fvGeometry.scvf(scvfIdx);
-                fluxVarsCache_[localScvfIdx].update(problem, elementJ, fvGeometry, elemVolVars, scvfJ);
+                filler.fill(*this, fluxVarsCache_[localScvfIdx], elementJ, fvGeometry, elemVolVars, scvfJ);
                 globalScvfIndices_[localScvfIdx] = scvfJ.index();
                 localScvfIdx++;
             }
@@ -188,7 +194,10 @@ public:
         fluxVarsCache_.resize(1);
         globalScvfIndices_.resize(1);
 
-        fluxVarsCache_[0].update(globalFluxVarsCache().problem_(), element, fvGeometry, elemVolVars, scvf);
+        // instantiate helper class to fill the caches
+        FluxVariablesCacheFiller filler(globalFluxVarsCache().problem_());
+
+        filler.fill(*this, fluxVarsCache_[0], element, fvGeometry, elemVolVars, scvf);
         globalScvfIndices_[0] = scvf.index();
     }
 
@@ -211,8 +220,29 @@ private:
                 const FVElementGeometry& fvGeometry,
                 const ElementVolumeVariables& elemVolVars)
     {
-        if (solDependentAdvection)
-            bind(element, fvGeometry, elemVolVars);
+        static const bool isSolIndependent = FluxVariablesCacheFiller::isSolutionIndependent();
+
+        if (!isSolIndependent)
+        {
+            const auto& problem = globalFluxVarsCache().problem_();
+            const auto globalI = problem.elementMapper().index(element);
+
+            // instantiate filler class
+            FluxVariablesCacheFiller filler(problem);
+
+            // let the filler class update the caches
+            for (unsigned int localScvfIdx = 0; localScvfIdx < fluxVarsCache_.size(); ++localScvfIdx)
+            {
+                const auto& scvf = fvGeometry.scvf(globalScvfIndices_[localScvfIdx]);
+
+                const auto scvfInsideScvIdx = scvf.insideScvIdx();
+                const auto& insideElement = scvfInsideScvIdx == globalI ?
+                                            element :
+                                            problem.model().globalFvGeometry().element(scvfInsideScvIdx);
+
+                filler.fill(*this, fluxVarsCache_[localScvfIdx], insideElement, fvGeometry, elemVolVars, scvf);
+            }
+        }
     }
 
     // get index of scvf in the local container
diff --git a/dumux/discretization/cellcentered/tpfa/fickslaw.hh b/dumux/discretization/cellcentered/tpfa/fickslaw.hh
index 7b05340bfad569bf72afc7fdff95d0d794c53d9d..4634f678473d928d7f351c9689808365a4d9781e 100644
--- a/dumux/discretization/cellcentered/tpfa/fickslaw.hh
+++ b/dumux/discretization/cellcentered/tpfa/fickslaw.hh
@@ -61,6 +61,7 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCTpfa >
     using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
     using Element = typename GridView::template Codim<0>::Entity;
     using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache);
+    using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache);
 
     static const int dim = GridView::dimension;
     static const int dimWorld = GridView::dimensionworld;
@@ -69,10 +70,36 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCTpfa >
     using DimWorldMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
     using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
 
+    //! We don't store anything for this law
+    class TpfaFicksLawCache
+    {};
+
+    //! The corresponding filler class
+    class TpfaFicksLawCacheFiller
+    {
+    public:
+      //! Function to fill a TpfaFicksLawCache (empty cache) of a given scvf
+      //! We have to fulfill the interface of a diffusion-related cache filler class
+      template<class FluxVariablesCacheFiller>
+      static void fill(FluxVariablesCache& scvfFluxVarsCache,
+                       unsigned int phaseIdx, unsigned int compIdx,
+                       const Problem& problem,
+                       const Element& element,
+                       const FVElementGeometry& fvGeometry,
+                       const ElementVolumeVariables& elemVolVars,
+                       const SubControlVolumeFace& scvf,
+                       const FluxVariablesCacheFiller& fluxVarsCacheFiller)
+      {}
+    };
+
 public:
     // state the discretization method this implementation belongs to
     static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCTpfa;
 
+    // state the type for the corresponding cache and its filler
+    using Cache = TpfaFicksLawCache;
+    using CacheFiller = TpfaFicksLawCacheFiller;
+
     static Scalar flux(const Problem& problem,
                        const Element& element,
                        const FVElementGeometry& fvGeometry,
diff --git a/dumux/discretization/cellcentered/tpfa/fluxvariablescachefiller.hh b/dumux/discretization/cellcentered/tpfa/fluxvariablescachefiller.hh
new file mode 100644
index 0000000000000000000000000000000000000000..285ee8bc5c8aad50bafdefa5d4df17d2597d3e94
--- /dev/null
+++ b/dumux/discretization/cellcentered/tpfa/fluxvariablescachefiller.hh
@@ -0,0 +1,233 @@
+// -*- 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 The flux variables cache filler class for the cell-centered TPFA scheme
+ */
+#ifndef DUMUX_DISCRETIZATION_CCTPFA_FLUXVARSCACHE_FILLER_HH
+#define DUMUX_DISCRETIZATION_CCTPFA_FLUXVARSCACHE_FILLER_HH
+
+#include <dumux/implicit/properties.hh>
+#include <dumux/discretization/methods.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup ImplicitModel
+ * \brief Helper class to fill the flux var caches
+ */
+template<class TypeTag>
+class CCTpfaFluxVariablesCacheFiller
+{
+    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
+    using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
+    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
+    using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
+    using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache);
+
+    using Element = typename GridView::template Codim<0>::Entity;
+
+    static constexpr bool doAdvection = GET_PROP_VALUE(TypeTag, EnableAdvection);
+    static constexpr bool doDiffusion = GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion);
+    static constexpr bool doHeatConduction = GET_PROP_VALUE(TypeTag, EnableEnergyBalance);
+
+    static constexpr bool soldependentAdvection = GET_PROP_VALUE(TypeTag, SolutionDependentAdvection);
+    static constexpr bool soldependentDiffusion = GET_PROP_VALUE(TypeTag, SolutionDependentMolecularDiffusion);
+    static constexpr bool soldependentHeatConduction = GET_PROP_VALUE(TypeTag, SolutionDependentHeatConduction);
+
+    enum ProcessIndices : unsigned int
+    {
+        advectionIdx,
+        diffusionIdx,
+        heatConductionIdx
+    };
+
+public:
+    //! The constructor. Sets the problem pointer
+    CCTpfaFluxVariablesCacheFiller(const Problem& problem) : problemPtr_(&problem) {}
+
+    /*!
+     * \brief function to fill the flux variables caches
+     *
+     * \param fluxVarsCacheContainer Either the element or global flux variables cache
+     * \param scvfFluxVarsCache The flux var cache to be updated corresponding to the given scvf
+     * \param element The finite element
+     * \param fvGeometry The finite volume geometry
+     * \param elemVolVars The element volume variables
+     * \param scvf The corresponding sub-control volume face
+     * \param doSubCaches Array of bools indicating which sub caches have to be updated
+     */
+    template<class FluxVariablesCacheContainer>
+    void fill(FluxVariablesCacheContainer& fluxVarsCacheContainer,
+              FluxVariablesCache& scvfFluxVarsCache,
+              const Element& element,
+              const FVElementGeometry& fvGeometry,
+              const ElementVolumeVariables& elemVolVars,
+              const SubControlVolumeFace& scvf,
+              const std::array<bool, 3>& doSubCaches = std::array<bool, 3>({true, true, true}))
+    {
+        // fill the physics-related quantities of the caches
+        if (doSubCaches[ProcessIndices::advectionIdx])
+          fillAdvection(scvfFluxVarsCache, element, fvGeometry, elemVolVars, scvf);
+        if (doSubCaches[ProcessIndices::diffusionIdx])
+          fillDiffusion(scvfFluxVarsCache, element, fvGeometry, elemVolVars, scvf);
+        if (doSubCaches[ProcessIndices::heatConductionIdx])
+          fillHeatConduction(scvfFluxVarsCache, element, fvGeometry, elemVolVars, scvf);
+    }
+
+    /*!
+     * \brief function to update the flux variables caches during derivative calculation
+     *
+     * \copydoc fill
+     */
+    template<class FluxVariablesCacheContainer>
+    void update(FluxVariablesCacheContainer& fluxVarsCacheContainer,
+                FluxVariablesCache& scvfFluxVarsCache,
+                const Element& element,
+                const FVElementGeometry& fvGeometry,
+                const ElementVolumeVariables& elemVolVars,
+                const SubControlVolumeFace& scvf)
+    {
+        // array of bool with which we indicate the sub-caches which have to be
+        // filled. During update, we only update solution-dependent quantities.
+        static const std::array<bool, 3> updateSubCaches = []()
+        {
+            std::array<bool, 3> tmp;
+            tmp[ProcessIndices::advectionIdx] = doAdvection && soldependentAdvection;
+            tmp[ProcessIndices::diffusionIdx] = doDiffusion && soldependentDiffusion;
+            tmp[ProcessIndices::heatConductionIdx] = doHeatConduction && soldependentHeatConduction;
+            return tmp;
+        } ();
+
+        // forward to fill routine
+        fill(fluxVarsCacheContainer, scvfFluxVarsCache, element, fvGeometry, elemVolVars, scvf, updateSubCaches);
+    }
+
+    static bool isSolutionIndependent()
+    {
+        static const bool isSolDependent = (doAdvection && soldependentAdvection) ||
+                                           (doDiffusion && soldependentDiffusion) ||
+                                           (doHeatConduction && soldependentHeatConduction);
+        return !isSolDependent;
+    }
+
+private:
+
+    const Problem& problem() const
+    { return *problemPtr_; }
+
+    //! method to fill the advective quantities
+    template<bool advectionEnabled = doAdvection>
+    typename std::enable_if<advectionEnabled>::type
+    fillAdvection(FluxVariablesCache& scvfFluxVarsCache,
+                  const Element& element,
+                  const FVElementGeometry& fvGeometry,
+                  const ElementVolumeVariables& elemVolVars,
+                  const SubControlVolumeFace& scvf)
+    {
+        using AdvectionType = typename GET_PROP_TYPE(TypeTag, AdvectionType);
+        using AdvectionFiller = typename AdvectionType::CacheFiller;
+
+        // forward to the filler for the advective quantities
+        AdvectionFiller::fill(scvfFluxVarsCache, problem(), element, fvGeometry, elemVolVars, scvf, *this);
+    }
+
+    //! do nothing if advection is not enabled
+    template<bool advectionEnabled = doAdvection>
+    typename std::enable_if<!advectionEnabled>::type
+    fillAdvection(FluxVariablesCache& scvfFluxVarsCache,
+                  const Element& element,
+                  const FVElementGeometry& fvGeometry,
+                  const ElementVolumeVariables& elemVolVars,
+                  const SubControlVolumeFace& scvf)
+    {}
+
+    //! method to fill the diffusive quantities
+    template<bool diffusionEnabled = doDiffusion>
+    typename std::enable_if<diffusionEnabled>::type
+    fillDiffusion(FluxVariablesCache& scvfFluxVarsCache,
+                  const Element& element,
+                  const FVElementGeometry& fvGeometry,
+                  const ElementVolumeVariables& elemVolVars,
+                  const SubControlVolumeFace& scvf)
+    {
+        using DiffusionType = typename GET_PROP_TYPE(TypeTag, MolecularDiffusionType);
+        using DiffusionFiller = typename DiffusionType::CacheFiller;
+
+        static constexpr int numPhases = GET_PROP_VALUE(TypeTag, NumPhases);
+        static constexpr int numComponents = GET_PROP_VALUE(TypeTag, NumComponents);
+
+        for (unsigned int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            for (unsigned int compIdx = 0; compIdx < numComponents; ++compIdx)
+            {
+                if (phaseIdx == compIdx)
+                    continue;
+
+                // forward to the filler of the diffusive quantities
+                DiffusionFiller::fill(scvfFluxVarsCache, phaseIdx, compIdx, problem(), element, fvGeometry, elemVolVars, scvf, *this);
+            }
+        }
+    }
+
+    //! do nothing if diffusion is not enabled
+    template<bool diffusionEnabled = doDiffusion>
+    typename std::enable_if<!diffusionEnabled>::type
+    fillDiffusion(FluxVariablesCache& scvfFluxVarsCache,
+                  const Element& element,
+                  const FVElementGeometry& fvGeometry,
+                  const ElementVolumeVariables& elemVolVars,
+                  const SubControlVolumeFace& scvf)
+    {}
+
+    //! method to fill the quantities related to heat conduction
+    template<bool heatConductionEnabled = doHeatConduction>
+    typename std::enable_if<heatConductionEnabled>::type
+    fillHeatConduction(FluxVariablesCache& scvfFluxVarsCache,
+                       const Element& element,
+                       const FVElementGeometry& fvGeometry,
+                       const ElementVolumeVariables& elemVolVars,
+                       const SubControlVolumeFace& scvf)
+    {
+        using HeatConductionType = typename GET_PROP_TYPE(TypeTag, HeatConductionType);
+        using HeatConductionFiller = typename HeatConductionType::CacheFiller;
+
+        // forward to the filler of the diffusive quantities
+        HeatConductionFiller::fill(scvfFluxVarsCache, problem(), element, fvGeometry, elemVolVars, scvf, *this);
+    }
+
+    //! do nothing if heat conduction is disabled
+    template<bool heatConductionEnabled = doHeatConduction>
+    typename std::enable_if<!heatConductionEnabled>::type
+    fillHeatConduction(FluxVariablesCache& scvfFluxVarsCache,
+                       const Element& element,
+                       const FVElementGeometry& fvGeometry,
+                       const ElementVolumeVariables& elemVolVars,
+                       const SubControlVolumeFace& scvf)
+    {}
+
+    const Problem* problemPtr_;
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/discretization/cellcentered/tpfa/fourierslaw.hh b/dumux/discretization/cellcentered/tpfa/fourierslaw.hh
index c46876547ae2ff4f9a4f60fb44861d615272fa46..a7aba69b2804559fd13887792c20808540396da2 100644
--- a/dumux/discretization/cellcentered/tpfa/fourierslaw.hh
+++ b/dumux/discretization/cellcentered/tpfa/fourierslaw.hh
@@ -57,6 +57,7 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
     using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
     using Element = typename GridView::template Codim<0>::Entity;
     using ElementFluxVarsCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache);
+    using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache);
 
     static const int dim = GridView::dimension;
     static const int dimWorld = GridView::dimensionworld;
@@ -66,10 +67,35 @@ class FouriersLawImplementation<TypeTag, DiscretizationMethods::CCTpfa>
 
     using ThermalConductivityModel = typename GET_PROP_TYPE(TypeTag, ThermalConductivityModel);
 
+    //! We don't store anything for this law
+    class TpfaFouriersLawCache
+    {};
+
+    //! The corresponding filler class
+    class TpfaFouriersLawCacheFiller
+    {
+    public:
+      //! Function to fill a TpfaFicksLawCache (empty cache) of a given scvf
+      //! We have to fulfill the interface of a heat conduction related cache filler class
+      template<class FluxVariablesCacheFiller>
+      static void fill(FluxVariablesCache& scvfFluxVarsCache,
+                       const Problem& problem,
+                       const Element& element,
+                       const FVElementGeometry& fvGeometry,
+                       const ElementVolumeVariables& elemVolVars,
+                       const SubControlVolumeFace& scvf,
+                       const FluxVariablesCacheFiller& fluxVarsCacheFiller)
+      {}
+    };
+
 public:
     // state the discretization method this implementation belongs to
     static const DiscretizationMethods myDiscretizationMethod = DiscretizationMethods::CCTpfa;
 
+    // state the type for the corresponding cache and its filler
+    using Cache = TpfaFouriersLawCache;
+    using CacheFiller = TpfaFouriersLawCacheFiller;
+
     static Scalar flux(const Problem& problem,
                        const Element& element,
                        const FVElementGeometry& fvGeometry,
diff --git a/dumux/discretization/cellcentered/tpfa/globalfluxvariablescache.hh b/dumux/discretization/cellcentered/tpfa/globalfluxvariablescache.hh
index 2718ffcf18bcf34b2b695aac548cb3c0e045cc8b..aba839d8eb379c9ce3568829792c3f6f324dc681 100644
--- a/dumux/discretization/cellcentered/tpfa/globalfluxvariablescache.hh
+++ b/dumux/discretization/cellcentered/tpfa/globalfluxvariablescache.hh
@@ -24,6 +24,7 @@
 #define DUMUX_DISCRETIZATION_CCTPFA_GLOBAL_FLUXVARSCACHE_HH
 
 #include <dumux/implicit/properties.hh>
+#include <dumux/discretization/cellcentered/tpfa/fluxvariablescachefiller.hh>
 
 namespace Dumux
 {
@@ -44,18 +45,26 @@ class CCTpfaGlobalFluxVariablesCache<TypeTag, true>
 {
     // the local class needs access to the problem
     friend typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache);
+    // the filler class needs access to the access operators
+    friend CCTpfaFluxVariablesCacheFiller<TypeTag>;
+
     using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
     using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
     using IndexType = typename GridView::IndexSet::IndexType;
     using FluxVariablesCache = typename GET_PROP_TYPE(TypeTag, FluxVariablesCache);
     using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache);
     using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
+    using FluxVariablesCacheFiller = CCTpfaFluxVariablesCacheFiller<TypeTag>;
 
 public:
     // When global caching is enabled, precompute transmissibilities and stencils for all the scv faces
     void update(Problem& problem)
     {
         problemPtr_ = &problem;
+
+        // instantiate helper class to fill the caches
+        FluxVariablesCacheFiller filler(problem);
+
         const auto& globalFvGeometry = problem.model().globalFvGeometry();
         fluxVarsCache_.resize(globalFvGeometry.numScvf());
         for (const auto& element : elements(problem.gridView()))
@@ -69,7 +78,7 @@ public:
 
             for (auto&& scvf : scvfs(fvGeometry))
             {
-                fluxVarsCache_[scvf.index()].update(problem, element, fvGeometry, elemVolVars, scvf);
+                filler.fill(*this, fluxVarsCache_[scvf.index()], element, fvGeometry, elemVolVars, scvf);
             }
         }
     }
@@ -83,7 +92,13 @@ public:
     { return ElementFluxVariablesCache(global); }
 
 private:
-    // access operators in the case of caching
+    // // access operators in the case of caching
+    // const FluxVariablesCache& operator [](const SubControlVolumeFace& scvf) const
+    // { return fluxVarsCache_[scvf.index()]; }
+
+    // FluxVariablesCache& operator [](const SubControlVolumeFace& scvf)
+    // { return fluxVarsCache_[scvf.index()]; }
+
     const FluxVariablesCache& operator [](IndexType scvfIdx) const
     { return fluxVarsCache_[scvfIdx]; }
 
diff --git a/dumux/porousmediumflow/implicit/fluxvariablescache.hh b/dumux/porousmediumflow/implicit/fluxvariablescache.hh
index 181aa3240c0082cdfb00a0adf7641b20c77e4783..21c62a763c73e75729176b2272ce6c6ea44cb3ba 100644
--- a/dumux/porousmediumflow/implicit/fluxvariablescache.hh
+++ b/dumux/porousmediumflow/implicit/fluxvariablescache.hh
@@ -40,15 +40,24 @@ namespace Properties
 NEW_PROP_TAG(NumPhases);
 }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//! The cache is dependent on the active physical processes (advection, diffusion, heat conduction)
+//! For each type of process there is a base cache storing the data required to compute the respective fluxes
+//! Specializations of the overall cache are provided for combinations of processes
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
 /*!
  * \ingroup ImplicitModel
  * \brief The flux variables cache classes for porous media.
- *        Store flux stencils and data required for flux calculation
+ *        Store data required for flux calculation. For each type of physical process (advection, diffusion, heat conduction)
+ *        there is a base cache storing the data required to compute the respective fluxes. Specializations of the overall
+ *        cache class are provided for different combinations of processes.
  */
 template<class TypeTag>
 using PorousMediumFluxVariablesCache = PorousMediumFluxVariablesCacheImplementation<TypeTag, GET_PROP_VALUE(TypeTag, DiscretizationMethod)>;
 
-// specialization for the Box Method
+//! We only store discretization-related quantities for the box method.
+//! Thus, we need no physics-dependent specialization.
 template<class TypeTag>
 class PorousMediumFluxVariablesCacheImplementation<TypeTag, DiscretizationMethods::Box>
 {
@@ -100,65 +109,44 @@ public:
     const JacobianInverseTransposed& jacInvT() const
     { return jacInvT_; }
 
-    // The stencil info is obsolete for the box method.
-    // It is here for compatibility with cc methods
-    const Stencil& stencil() const
-    {
-        return stencil_;
-    }
-
 private:
     std::vector<ShapeJacobian> shapeJacobian_;
     std::vector<ShapeValue> shapeValues_;
     JacobianInverseTransposed jacInvT_;
-
-    Stencil stencil_;
 };
 
+// forward declaration of the base class of the tpfa flux variables cache
+template<class TypeTag, bool EnableAdvection, bool EnableMolecularDiffusion, bool EnableEnergyBalance>
+class CCTpfaPorousMediumFluxVariablesCache;
+
 // specialization for the cell centered tpfa method
 template<class TypeTag>
 class PorousMediumFluxVariablesCacheImplementation<TypeTag, DiscretizationMethods::CCTpfa>
-{
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-    using FluxVariables = typename GET_PROP_TYPE(TypeTag, FluxVariables);
-    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
-    using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
-    using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
-    using AdvectionType = typename GET_PROP_TYPE(TypeTag, AdvectionType);
-    using Element = typename GridView::template Codim<0>::Entity;
-    using IndexType = typename GridView::IndexSet::IndexType;
-    using Stencil = std::vector<IndexType>;
+      : public CCTpfaPorousMediumFluxVariablesCache<TypeTag, GET_PROP_VALUE(TypeTag, EnableAdvection),
+                                                             GET_PROP_VALUE(TypeTag, EnableMolecularDiffusion),
+                                                             GET_PROP_VALUE(TypeTag, EnableEnergyBalance)> {};
 
-public:
-    void update(const Problem& problem,
-                const Element& element,
-                const FVElementGeometry& fvGeometry,
-                const ElementVolumeVariables& elemVolVars,
-                const SubControlVolumeFace &scvf)
-    {
-        stencil_ = FluxVariables::computeStencil(problem, element, fvGeometry, scvf);
-        tij_ = AdvectionType::calculateTransmissibilities(problem, element, fvGeometry, elemVolVars, scvf);
-    }
+// specialization for the case of pure advection
+template<class TypeTag>
+class CCTpfaPorousMediumFluxVariablesCache<TypeTag, true, false, false> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache {};
 
-    const Stencil& stencil() const
-    { return stencil_; }
+// specialization for the case of advection & diffusion
+template<class TypeTag>
+class CCTpfaPorousMediumFluxVariablesCache<TypeTag, true, true, false> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache,
+                                                                         public GET_PROP_TYPE(TypeTag, MolecularDiffusionType)::Cache {};
 
-    const Scalar& tij() const
-    { return tij_; }
+// specialization for the case of advection & heat conduction
+template<class TypeTag>
+class CCTpfaPorousMediumFluxVariablesCache<TypeTag, true, false, true> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache,
+                                                                         public GET_PROP_TYPE(TypeTag, HeatConductionType)::Cache {};
 
-private:
-    Stencil stencil_;
-    Scalar tij_;
-};
+// specialization for the case of advection, diffusion & heat conduction
+template<class TypeTag>
+class CCTpfaPorousMediumFluxVariablesCache<TypeTag, true, true, true> : public GET_PROP_TYPE(TypeTag, AdvectionType)::Cache,
+                                                                        public GET_PROP_TYPE(TypeTag, MolecularDiffusionType)::Cache,
+                                                                        public GET_PROP_TYPE(TypeTag, HeatConductionType)::Cache {};
 
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////
-//! Classes building up the porous medium flux variables cache for mpfa methods
-//! The cache is dependent on the active physical processes (advection, diffusion, heat conduction)
-//! For each type of process there is a base cache storing the data required to compute the respective fluxes
-//! Specializations of the overall cache are provided for combinations of processes
-//////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// TODO further specializations
 
 // forward declaration of the base class of the mpfa flux variables cache
 template<class TypeTag, bool EnableAdvection, bool EnableMolecularDiffusion, bool EnableEnergyBalance>