diff --git a/dumux/flux/cctpfa/forchheimerslaw.hh b/dumux/flux/cctpfa/forchheimerslaw.hh
index b0b4efe83598f4bb9d79e0b551cdc4c3624bd105..f787f60a5f439fe16ca32d20b1d61cc9d18bbb55 100644
--- a/dumux/flux/cctpfa/forchheimerslaw.hh
+++ b/dumux/flux/cctpfa/forchheimerslaw.hh
@@ -50,7 +50,7 @@ class ForchheimersLawImplementation;
  * \tparam GridGeometry the grid geometry
  * \tparam isNetwork whether we are computing on a network grid embedded in a higher world dimension
  */
-template<class Scalar, class GridGeometry, bool isNetwork>
+template<class Scalar, class GridGeometry, class FluxVariables, bool isNetwork>
 class CCTpfaForchheimersLaw;
 
 /*!
@@ -61,8 +61,9 @@ class CCTpfaForchheimersLaw;
 template <class TypeTag>
 class ForchheimersLawImplementation<TypeTag, DiscretizationMethod::cctpfa>
 : public CCTpfaForchheimersLaw<GetPropType<TypeTag, Properties::Scalar>,
-                         GetPropType<TypeTag, Properties::GridGeometry>,
-                         (GetPropType<TypeTag, Properties::GridGeometry>::GridView::dimension < GetPropType<TypeTag, Properties::GridGeometry>::GridView::dimensionworld)>
+                               GetPropType<TypeTag, Properties::GridGeometry>,
+                               GetPropType<TypeTag, Properties::FluxVariables>,
+                              (GetPropType<TypeTag, Properties::GridGeometry>::GridView::dimension < GetPropType<TypeTag, Properties::GridGeometry>::GridView::dimensionworld)>
 {};
 
 /*!
@@ -136,10 +137,10 @@ private:
  * \ingroup CCTpfaFlux
  * \brief Specialization of the CCTpfaForchheimersLaw grids where dim=dimWorld
  */
-template<class ScalarType, class GridGeometry>
-class CCTpfaForchheimersLaw<ScalarType, GridGeometry, /*isNetwork*/ false>
+template<class ScalarType, class GridGeometry, class FluxVariables>
+class CCTpfaForchheimersLaw<ScalarType, GridGeometry, FluxVariables, /*isNetwork*/ false>
 {
-    using ThisType = CCTpfaForchheimersLaw<ScalarType, GridGeometry, /*isNetwork*/ false>;
+    using ThisType = CCTpfaForchheimersLaw<ScalarType, GridGeometry, FluxVariables, /*isNetwork*/ false>;
     using FVElementGeometry = typename GridGeometry::LocalView;
     using SubControlVolume = typename GridGeometry::SubControlVolume;
     using SubControlVolumeFace = typename GridGeometry::SubControlVolumeFace;
@@ -155,6 +156,7 @@ class CCTpfaForchheimersLaw<ScalarType, GridGeometry, /*isNetwork*/ false>
     using DimWorldMatrix = Dune::FieldMatrix<ScalarType, dimWorld, dimWorld>;
 
     using DarcysLaw = CCTpfaDarcysLaw<ScalarType, GridGeometry, /*isNetwork*/ false>;
+    using UpwindScheme = typename FluxVariables::UpwindScheme;
 
   public:
     //! state the scalar type of the law
@@ -354,10 +356,9 @@ private:
     {
         // Get the volume flux based on Darcy's law. The value returned by this method needs to be multiplied with the
         // mobility (upwinding).
-        Scalar darcyFlux = DarcysLaw::flux(problem, element, fvGeometry, elemVolVars, scvf, phaseIdx, elemFluxVarsCache);
+        Scalar flux = DarcysLaw::flux(problem, element, fvGeometry, elemVolVars, scvf, phaseIdx, elemFluxVarsCache);
         auto upwindTerm = [phaseIdx](const auto& volVars){ return volVars.mobility(phaseIdx); };
-        const Scalar darcyUpwindMobility = doUpwind_(scvf, elemVolVars, upwindTerm, !std::signbit(darcyFlux) /*insideIsUpstream*/);
-        darcyFlux *= darcyUpwindMobility;
+        const auto darcyFlux = UpwindScheme::apply(elemVolVars, scvf, upwindTerm, flux, phaseIdx);
 
         // Convert to Darcy velocity
         DimWorldVector darcyVelocity = scvf.unitOuterNormal();
@@ -412,8 +413,8 @@ private:
 
         // The fluxvariables expect a value on which an upwinding of the mobility is performed.
         // We therefore divide by the mobility here.
-        const Scalar forchheimerUpwindMobility = doUpwind_(scvf, elemVolVars, upwindTerm,
-                                                           !std::signbit(velocity * scvf.unitOuterNormal()) /*insideIsUpstream*/);
+        const auto fluxSign = std::copysign(1.0, velocity * scvf.unitOuterNormal());
+        const auto forchheimerUpwindMobility = fluxSign* UpwindScheme::apply(elemVolVars, scvf, upwindTerm, fluxSign, phaseIdx);
 
         // Do not divide by zero. If the mobility is zero, the resulting flux with upwinding will be zero anyway.
         if (forchheimerUpwindMobility > 0.0)
@@ -440,8 +441,8 @@ private:
 
          // residual += c_F rho / mu abs(v) sqrt(K) v
          auto upwindTerm = [phaseIdx](const auto& volVars){ return volVars.density(phaseIdx) / volVars.viscosity(phaseIdx); };
-         bool insideIsUpstream = !std::signbit(oldVelocity * scvf.unitOuterNormal());
-         const Scalar rhoOverMu = doUpwind_(scvf, elemVolVars, upwindTerm, insideIsUpstream);
+         const auto fluxSign = std::copysign(1.0, oldVelocity * scvf.unitOuterNormal());
+         const Scalar rhoOverMu = fluxSign * UpwindScheme::apply(elemVolVars, scvf, upwindTerm, fluxSign, phaseIdx);
          sqrtK.usmv(forchCoeff * rhoOverMu * oldVelocity.two_norm(), oldVelocity, residual);
      }
 
@@ -461,7 +462,6 @@ private:
         derivative = 0.0;
 
         auto upwindTerm = [phaseIdx](const auto& volVars){ return volVars.density(phaseIdx) / volVars.viscosity(phaseIdx); };
-        bool insideIsUpstream = !std::signbit(velocity * scvf.unitOuterNormal());
 
         const Scalar absV = velocity.two_norm() ;
         // This part of the derivative is only calculated if the velocity is sufficiently small:
@@ -473,7 +473,8 @@ private:
         // phase has a velocity of zero (kr=0).
         // f = sqrtK * vTimesV (this is  a matrix)
         // f *= forchCoeff density / |velocity| / viscosity (multiply all entries with scalars)
-        const Scalar rhoOverMu = doUpwind_(scvf, elemVolVars, upwindTerm, insideIsUpstream);
+        const auto fluxSign = std::copysign(1.0, velocity * scvf.unitOuterNormal());
+        const Scalar rhoOverMu = fluxSign * UpwindScheme::apply(elemVolVars, scvf, upwindTerm, fluxSign, phaseIdx);
         if (absV > 1e-20)
         {
             for (int i = 0; i < dim; i++)
@@ -495,25 +496,6 @@ private:
             derivative[i][i] += (1.0 + (sqrtK[i][i]*forchCoeff * absV * rhoOverMu));
     }
 
-     template<class ElementVolumeVariables, class UpwindTermFunction>
-     static Scalar doUpwind_(const SubControlVolumeFace& scvf,
-                             const ElementVolumeVariables& elemVolVars,
-                             const UpwindTermFunction& upwindTerm,
-                             const bool insideIsUpstream)
-     {
-         static const Scalar upwindWeight = getParam<Scalar>("Flux.UpwindWeight");
-
-         const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
-         const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
-
-         if (!insideIsUpstream) // if sign of flux is negative
-             return (upwindWeight*upwindTerm(outsideVolVars)
-                          + (1.0 - upwindWeight)*upwindTerm(insideVolVars));
-         else
-             return (upwindWeight*upwindTerm(insideVolVars)
-                          + (1.0 - upwindWeight)*upwindTerm(outsideVolVars));
-     }
-
     /*!
      * \brief Check whether all off-diagonal entries of a tensor are zero.
      *
@@ -554,8 +536,8 @@ private:
  * \ingroup CCTpfaFlux
  * \brief Specialization of the CCTpfaForchheimersLaw grids where dim<dimWorld
  */
-template<class ScalarType, class GridGeometry>
-class CCTpfaForchheimersLaw<ScalarType, GridGeometry, /*isNetwork*/ true>
+template<class ScalarType, class GridGeometry, class FluxVariables>
+class CCTpfaForchheimersLaw<ScalarType, GridGeometry, FluxVariables, /*isNetwork*/ true>
 {
     static_assert(AlwaysFalse<ScalarType>::value, "Forchheimer not implemented for network grids");
 };
diff --git a/dumux/porousmediumflow/fluxvariables.hh b/dumux/porousmediumflow/fluxvariables.hh
index 1ae4fdbc6c5fcd08d68b926f5cfb2eff5e9f8a1e..3a3478f3138e39948cb1886702ab77332ffc8c2c 100644
--- a/dumux/porousmediumflow/fluxvariables.hh
+++ b/dumux/porousmediumflow/fluxvariables.hh
@@ -40,11 +40,11 @@ namespace Dumux {
  *        molecular diffusive and heat conduction fluxes.
  *
  * \param TypeTag The type tag for access to type traits
- * \param UpwindScheme The upwind scheme to be applied to advective fluxes
+ * \param UpScheme The upwind scheme to be applied to advective fluxes
  * \note  Not all specializations are currently implemented
  */
 template<class TypeTag,
-         class UpwindScheme = UpwindScheme<GetPropType<TypeTag, Properties::GridGeometry>> >
+         class UpScheme = UpwindScheme<GetPropType<TypeTag, Properties::GridGeometry>> >
 class PorousMediumFluxVariables
 : public FluxVariablesBase<GetPropType<TypeTag, Properties::Problem>,
                            typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView,
@@ -61,6 +61,7 @@ class PorousMediumFluxVariables
     };
 
 public:
+    using UpwindScheme = UpScheme;
     using AdvectionType = GetPropType<TypeTag, Properties::AdvectionType>;
     using MolecularDiffusionType = GetPropType<TypeTag, Properties::MolecularDiffusionType>;
     using HeatConductionType = GetPropType<TypeTag, Properties::HeatConductionType>;