diff --git a/dumux/porousmediumflow/implicit/cellcentered/tpfa/darcyfluxvariables.hh b/dumux/porousmediumflow/implicit/cellcentered/tpfa/darcyfluxvariables.hh
new file mode 100644
index 0000000000000000000000000000000000000000..aeaa46d3b3c8a0771c737356084202fb623d5857
--- /dev/null
+++ b/dumux/porousmediumflow/implicit/cellcentered/tpfa/darcyfluxvariables.hh
@@ -0,0 +1,239 @@
+// -*- 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 This file contains the data which is required to calculate
+ *        volume and mass fluxes of fluid phases over a face of a finite volume by means
+ *        of the Darcy approximation.
+ */
+#ifndef DUMUX_CC_TPFA_DARCY_FLUX_VARIABLES_HH
+#define DUMUX_CC_TPFA_DARCY_FLUX_VARIABLES_HH
+
+#include <dune/common/float_cmp.hh>
+
+#include <dumux/common/math.hh>
+#include <dumux/common/parameters.hh>
+
+#include <dumux/implicit/properties.hh>
+
+
+namespace Dumux
+{
+
+namespace Properties
+{
+// forward declaration of properties
+NEW_PROP_TAG(NumPhases);
+NEW_PROP_TAG(ProblemEnableGravity);
+}
+
+/*!
+ * \ingroup ImplicitFluxVariables
+ * \brief Evaluates the normal component of the Darcy velocity
+ * on a (sub)control volume face.
+ */
+template <class TypeTag>
+class CCTpfaImplicitDarcyFluxVariables
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SubControlVolume) SubControlVolume;
+    typedef typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace) SubControlVolumeFace;
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    enum { dim = GridView::dimension} ;
+    enum { dimWorld = GridView::dimensionworld} ;
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ;
+
+    typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> DimWorldMatrix;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+public:
+
+    void update(const Problem &problem, SubControlVolumeFace scvFace)
+    {
+        problemPtr_ = &problem;
+        scvFace_ = &scvFace;
+
+        updateTransmissivitesAndStencil_();
+    }
+
+    /*!
+     * \brief A function to calculate the mass flux over a sub control volume face
+     *
+     * \param phaseIdx The index of the phase of which the flux is to be calculated
+     * \param upwindFunction A function which does the upwinding
+     */
+    template<FunctionType>
+    Scalar calculateFlux(const int phaseIdx, FunctionType upwindFunction)
+    {
+        // Set the inside-/outside volume variables provisionally
+        const VolumeVariables &insideVolVars = problem_().model().curVolVars(stencil_[0]);
+        const VolumeVariables &outsideVolVars = insideVolVars;
+
+        // calculate the piezometric heights in the two cells
+        // and set the downstream volume variables
+        Scalar hInside = insideVolVars.pressure(phaseIdx);
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity))
+        {
+            // ask for the gravitational acceleration in the inside cell
+            const auto insideScvIdx = scvFace_.insideScvIdx();
+            const auto& insideScv = problem_().model().fvGeometries().subControlVolume(insideScvIdx);
+            GlobalPosition gInside(problem_().gravityAtPos(insideScv.center()));
+            Scalar rhoInside = insideVolVars.density(phaseIdx);
+
+            hInside -= rhoInside*gInside*insideScv.center();
+        }
+
+        Scalar hOutside;
+        if (!scvFace_.boundary())
+        {
+            outsideVolVars = problem_().model().curVolVars(stencil_[1]);
+            hOutside = outsideVolVars.pressure(phaseIdx);
+
+            // if switched on, ask for the gravitational acceleration in the outside cell
+            if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity))
+            {
+                const auto outsideScvIdx = scvFace_.outsideScvIdx();
+                const auto& outsideScv = problem_().model().fvGeometries().subControlVolume(outsideScvIdx);
+                GlobalPosition gOutside(problem_().gravityAtPos(outsideScv.center()));
+                Scalar rhoOutside = outsideVolVars.density(phaseIdx);
+
+                hOutside -= rhoOutside*gOutside*outsideScv.center();
+            }
+        }
+        else
+        {
+            // if (complexBCTreatment)
+            // outsideVolVars = problem_().model().constructBoundaryVolumeVariables(scvFace_);
+            // else
+            // {
+                PrimaryVariables dirichletPV = problem_().dirichlet(scvFace_);
+                const auto insideScvIdx = scvFace_.insideScvIdx();
+                const auto& insideScv = problem_().model().fvGeometries().subControlVolume(insideScvIdx);
+                outsideVolVars.update(dirichletPV, problem_(), outsideScv);
+            // }
+            h2 = outsideVolVars.pressure(phaseIdx);
+
+            // if switched on, ask for the gravitational acceleration in the outside cell
+            if (GET_PARAM_FROM_GROUP(TypeTag, bool, Problem, EnableGravity))
+            {
+                GlobalPosition gOutside(problem_().gravityAtPos(scvFace_.center()));
+                Scalar rhoOutside = outsideVolVars.density(phaseIdx);
+
+                hOutside += rhoOutside*gOutside*scvFace_.center();
+            }
+        }
+
+        volumeFlux_ = t_*(hOutside - hInside);
+
+        if (volumeFlux > 0)
+            return volumeFlux_*upwindFunction(insideVolVars, outsideVolVars);
+        else
+            return volumeFlux_*upwindFunction(outsideVolVars, insideVolVars);
+    }
+
+    std::set<unsigned int> stencil() const
+    {
+        return std::set<unsigned int>(stencil_.begin(), stencil.end());
+    }
+
+protected:
+
+
+    void updateTransmissivitesAndStencil_()
+    {
+        if (!scvFace_.boundary())
+        {
+            const auto insideScvIdx = scvFace_.insideScvIdx();
+            const auto& insideScv = problem_().model().fvGeometries().subControlVolume(insideScvIdx);
+            const auto insideK = problem_().spatialParams().intrinsicPermeability(insideScv);
+            Scalar omega1 = calculateOmega_(insideK, insideScv);
+
+            const auto outsideScvIdx = scvFace_.outsideScvIdx();
+            const auto& outsideScv = problem_().model().fvGeometries().subControlVolume(outsideScvIdx);
+            const auto outsideK = problem_().spatialParams().intrinsicPermeability(outsideScv);
+            Scalar omega2 = calculateOmega_(outsideK, outsideScv);
+
+            t_ = omega1*omega2;
+            t_ /= omega1 - omega2;
+            t_ *= -1;
+
+            stencil_[0] = scvFace_.insideVolVarsIdx();
+            stencil_[1] = scvFace_.outsideVolVarsIdx();
+        }
+        else
+        {
+            const auto insideScvIdx = scvFace_.insideScvIdx();
+            const auto& insideScv = problem_().model().fvGeometries().subControlVolume(insideScvIdx);
+            const auto insideK = problem_().spatialParams().intrinsicPermeability(insideScv);
+            Scalar omega1 = calculateOmega_(insideK, insideScv);
+
+            t_ = omega1;
+
+            stencil_[0] = scvFace_.insideVolVarsIdx();
+        }
+    }
+
+    Scalar calculateOmega_(const DimWorldMatrix &K, const SubControlVolume &scv) const
+    {
+        GlobalPosition connectVec = scvFace_.center();
+        connectVec -= scv.geometry().center();
+        connectVec /= connectVec.two_norm2();
+
+        GlobalPosition Kconnect(0);
+        K.mv(connectVec, Kconnect);
+
+        Scalar omega = Kconnect * scvFace_.normal();
+        omega *= scvFace_.area()*problem_().model().curVolVars(scv).extrusionFactor();
+        omega *= -1;
+
+        return omega;
+    }
+
+    Scalar calculateOmega_(Scalar k, const SubControlVolume &scv) const
+    {
+        GlobalPosition connectVec = scvFace_.center();
+        connectVec -= scv.geometry().center();
+        connectVec /= connectVec.two_norm2();
+
+        Scalar omega = connectVec * scvFace_.normal();
+        omega *= scvFace_.area()*problem_().model().curVolVars(scv).extrusionFactor();
+        omega *= k;
+        omega *= -1;
+
+        return omega;
+    }
+
+    const Problem &problem_()
+    {
+        return *problemPtr_;
+    }
+
+    const Problem *problem_;
+    const SubControlVolumeFace *scvFace_;       //!< Pointer to the sub control volume face for which the flux variables are created
+    Scalar t_;                                            //!< transmissivities for the flux calculation
+    std::array<Scalar, 2> stencil_;                       //!< Indices of the cells of which the pressure is needed for the flux calculation
+};
+
+} // end namespace
+
+#endif // DUMUX_CC_TPFA_DARCY_FLUX_VARIABLES_HH