diff --git a/dumux/decoupled/2p/transport/fv/evalcflflux_coats.hh b/dumux/decoupled/2p/transport/fv/evalcflflux_coats.hh
new file mode 100644
index 0000000000000000000000000000000000000000..63dcb95120ae9541b65abf95806414f30cdf15e3
--- /dev/null
+++ b/dumux/decoupled/2p/transport/fv/evalcflflux_coats.hh
@@ -0,0 +1,438 @@
+// $Id$
+/*****************************************************************************
+ *   Copyright (C) 2010 by Markus Wolff                                 *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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, as long as this copyright notice    *
+ *   is included in its original form.                                       *
+ *                                                                           *
+ *   This program is distributed WITHOUT ANY WARRANTY.                       *
+ *****************************************************************************/
+#ifndef DUMUX_EVALCFLFLUX_COATS_HH
+#define DUMUX_EVALCFLFLUX_COATS_HH
+
+/**
+ * @file
+ * @brief  CFL-flux-function to evaluate a CFL-Condition after Coats 2003
+ * @author Markus Wolff
+ */
+
+#include "evalcflflux_default.hh"
+
+namespace Dumux
+{
+/*!\ingroup Transport2p
+ * @brief  CFL-flux-function to evaluate a CFL-Condition after Coats 2003
+ *
+ *
+ * Template parameters are:
+
+ - TypeTag PropertyTag of the problem implementation
+ */
+template<class TypeTag>
+class EvalCflFluxCoats: public EvalCflFluxDefault<TypeTag>
+{
+private:
+    typedef EvalCflFluxDefault<TypeTag> ParentType;typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) SpatialParameters;
+    typedef typename SpatialParameters::MaterialLaw MaterialLaw;typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidState)) FluidState;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(TwoPIndices)) Indices;
+
+    enum
+    {
+        dim = GridView::dimension, dimWorld = GridView::dimensionworld
+    };
+    enum
+    {
+        wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx
+    };
+
+    enum
+    {
+        pw = Indices::pressureW,
+        pn = Indices::pressureNW,
+        pglobal = Indices::pressureGlobal,
+        vw = Indices::velocityW,
+        vn = Indices::velocityNW,
+        vt = Indices::velocityTotal,
+        Sw = Indices::saturationW,
+        Sn = Indices::saturationNW,
+    };
+
+    typedef typename GridView::Traits::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::EntityPointer ElementPointer;
+    typedef typename GridView::Intersection Intersection;
+
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+    typedef Dune::FieldMatrix<Scalar, dim, dim> FieldMatrix;
+
+public:
+
+    void addFlux(Scalar& lambdaW, Scalar& lambdaNW, Scalar& viscosityW, Scalar& viscosityNW, Scalar flux,
+            const Element& element, int phaseIdx = -1)
+    {
+        ParentType::addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, flux, element, phaseIdx);
+    }
+
+    void addFlux(Scalar& lambdaW, Scalar& lambdaNW, Scalar& viscosityW, Scalar& viscosityNW, Scalar flux,
+            const Intersection& intersection, int phaseIdx = -1)
+    {
+        Scalar parentMob = 0.5;
+        Scalar parentVis = 1;
+        //        ParentType::addFlux(lambdaW, lambdaNW, viscosityW, viscosityNW, flux, intersection, phaseIdx);
+        ParentType::addFlux(parentMob, parentMob, parentVis, parentVis, flux, intersection, phaseIdx);
+
+        //coordinates of cell center
+        const GlobalPosition& globalPos = intersection.inside()->geometry().center();
+
+        // cell index
+        int globalIdxI = problem_.variables().index(*(intersection.inside()));
+
+        int indexInInside = intersection.indexInInside();
+
+        // get absolute permeability
+        const FieldMatrix& permeabilityI(problem_.spatialParameters().intrinsicPermeability(globalPos,
+                *(intersection.inside())));
+
+        Scalar satI = problem_.variables().saturation()[globalIdxI];
+        Scalar lambdaWI = problem_.variables().mobilityWetting(globalIdxI);
+        Scalar lambdaNWI = problem_.variables().mobilityNonwetting(globalIdxI);
+
+        Scalar dPcdSI = MaterialLaw::dpC_dSw(problem_.spatialParameters().materialLawParams(globalPos,
+                *(intersection.inside())), satI);
+
+        const Dune::FieldVector<Scalar, dimWorld>& unitOuterNormal = intersection.centerUnitOuterNormal();
+
+        if (intersection.neighbor())
+        {
+            const GlobalPosition& globalPosNeighbor = intersection.outside()->geometry().center();
+
+            // distance vector between barycenters
+            Dune::FieldVector < Scalar, dimWorld > distVec = globalPosNeighbor - globalPos;
+
+            // compute distance between cell centers
+            Scalar dist = distVec.two_norm();
+
+            int globalIdxJ = problem_.variables().index(*(intersection.outside()));
+
+            //calculate potential gradients
+            Scalar potentialW = 0;
+            Scalar potentialNW = 0;
+
+            potentialW = problem_.variables().potentialWetting(globalIdxI, indexInInside);
+            potentialNW = problem_.variables().potentialNonwetting(globalIdxI, indexInInside);
+
+            Scalar satJ = problem_.variables().saturation()[globalIdxI];
+            Scalar lambdaWJ = problem_.variables().mobilityWetting(globalIdxJ);
+            Scalar lambdaNWJ = problem_.variables().mobilityNonwetting(globalIdxJ);
+
+            Scalar dPcdSJ = MaterialLaw::dpC_dSw(problem_.spatialParameters().materialLawParams(globalPosNeighbor,
+                    (*intersection.outside())), satJ);
+
+            // get absolute permeability
+            const FieldMatrix& permeabilityJ(problem_.spatialParameters().intrinsicPermeability(globalPos,
+                    *(intersection.outside())));
+
+            // compute vectorized permeabilities
+            FieldMatrix meanPermeability(0);
+
+            //                // harmonic mean of permeability
+            for (int x = 0; x < dim; x++)
+            {
+                meanPermeability[x][x] = 2 * permeabilityI[x][x] * permeabilityJ[x][x] / (permeabilityI[x][x]
+                        + permeabilityJ[x][x]);
+                for (int y = 0; y < dim; y++)
+                {
+                    if (x != y)
+                    {//use arithmetic mean for the off-diagonal entries to keep the tensor property!
+                        meanPermeability[x][y] = 0.5 * (permeabilityI[x][y] + permeabilityJ[x][y]);
+                    }
+                }
+            }
+
+            Dune::FieldVector < Scalar, dim > permeability(0);
+            meanPermeability.mv(unitOuterNormal, permeability);
+
+            Scalar transmissibility = (unitOuterNormal * permeability) * intersection.geometry().volume() / dist;
+
+            Scalar satUpw = 0;
+            if (potentialW >= 0)
+            {
+                satUpw = std::max(satI, 0.0);
+            }
+            else
+            {
+                satUpw = std::max(satJ, 0.0);
+            }
+
+            Scalar dS = eps_;
+
+            Scalar satPlus = satUpw + eps_;
+            Scalar satMinus = satUpw;
+            if (satMinus - eps_ > 0.0)
+            {
+                satMinus -= eps_;
+                dS += eps_;
+            }
+
+            Scalar dLambdaWdS = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.outside())), std::abs(satPlus)) / viscosityW;
+            dLambdaWdS -= MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.outside())), std::abs(satMinus)) / viscosityW;
+            dLambdaWdS /= (dS);
+
+            if (potentialNW >= 0)
+            {
+                satUpw = std::max(1 - satI, 0.0);
+            }
+            else
+            {
+                satUpw = std::max(1 - satJ, 0.0);
+            }
+
+            dS = eps_;
+
+            satPlus = satUpw + eps_;
+            satMinus = satUpw;
+            if (satMinus - eps_ > 0.0)
+            {
+                satMinus -= eps_;
+                dS += eps_;
+            }
+
+            Scalar dLambdaNWdS = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.outside())), satPlus) / viscosityNW;
+            dLambdaNWdS -= MaterialLaw::krn(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.outside())), satMinus) / viscosityNW;
+            dLambdaNWdS /= (dS);
+
+            Scalar lambdaWCap = 0.5 * (lambdaWI + lambdaWJ);
+            Scalar lambdaNWCap = 0.5 * (lambdaNWI + lambdaNWJ);
+
+            if (phaseIdx == wPhaseIdx)
+            {
+                if (flux != 0)
+                {
+                    cflFluxFunction_ += lambdaNW * dLambdaWdS * std::abs(flux) / (lambdaW * (lambdaW + lambdaNW));
+                }
+
+                cflFluxFunction_ -= transmissibility * lambdaWCap * lambdaNWCap * (dPcdSI + dPcdSJ) / (lambdaW
+                        + lambdaNW);
+            }
+            if (phaseIdx == nPhaseIdx)
+            {
+                if (flux != 0)
+                {
+                    cflFluxFunction_ -= lambdaW * dLambdaNWdS * std::abs(flux) / (lambdaNW * (lambdaW + lambdaNW));
+                }
+            }
+        }
+        else
+        {
+            // center of face in global coordinates
+            GlobalPosition globalPosFace = intersection.geometry().center();
+
+            //get boundary type
+            BoundaryConditions::Flags bcTypeSat = problem_.bctypeSat(globalPosFace, intersection);
+
+            // distance vector between barycenters
+            Dune::FieldVector < Scalar, dimWorld > distVec = globalPosFace - globalPos;
+
+            // compute distance between cell centers
+            Scalar dist = distVec.two_norm();
+
+            //multiply with normal vector at the boundary
+            Dune::FieldVector < Scalar, dim > permeability(0);
+            permeabilityI.mv(unitOuterNormal, permeability);
+
+            Scalar satBound = 0;
+            if (bcTypeSat == BoundaryConditions::dirichlet)
+            {
+                satBound = problem_.dirichletSat(globalPosFace, intersection);
+            }
+            else
+            {
+                satBound = problem_.variables().saturation()[globalIdxI];
+            }
+
+            //determine phase saturations from primary saturation variable
+            Scalar satW;
+            Scalar satNW;
+            switch (saturationType_)
+            {
+            case Sw:
+            {
+                satW = satBound;
+                satNW = 1 - satBound;
+                break;
+            }
+            case Sn:
+            {
+                satW = 1 - satBound;
+                satNW = satBound;
+                break;
+            }
+            default:
+            {
+                DUNE_THROW(Dune::RangeError, "saturation type not implemented");
+            }
+            }
+
+            Scalar dPcdSBound = MaterialLaw::dpC_dSw(problem_.spatialParameters().materialLawParams(globalPos,
+                    *(intersection.inside())), satBound);
+
+            Scalar lambdaWBound = 0;
+            Scalar lambdaNWBound = 0;
+
+            Scalar temperature = problem_.temperature(globalPosFace, (*intersection.inside()));
+            Scalar referencePressure = problem_.referencePressure(globalPos, (*intersection.inside()));
+            FluidState fluidState;
+            Scalar viscosityWBound = FluidSystem::phaseViscosity(wPhaseIdx, temperature, referencePressure, fluidState);
+            Scalar viscosityNWBound =
+                    FluidSystem::phaseViscosity(nPhaseIdx, temperature, referencePressure, fluidState);
+            lambdaWBound = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.inside())), satW) / viscosityWBound;
+            lambdaNWBound = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.inside())), satW) / viscosityNWBound;
+
+            Scalar potentialW = 0;
+            Scalar potentialNW = 0;
+
+            potentialW = problem_.variables().potentialWetting(globalIdxI, indexInInside);
+            potentialNW = problem_.variables().potentialNonwetting(globalIdxI, indexInInside);
+
+            Scalar transmissibility = (unitOuterNormal * permeability) * intersection.geometry().volume() / dist;
+
+            Scalar satUpw = 0;
+            if (potentialW >= 0)
+            {
+                satUpw = std::max(satI, 0.0);
+            }
+            else
+            {
+                satUpw = std::max(satBound, 0.0);
+            }
+
+            Scalar dS = eps_;
+
+            Scalar satPlus = satUpw + eps_;
+            Scalar satMinus = satUpw;
+            if (satMinus - eps_ > 0.0)
+            {
+                satMinus -= eps_;
+                dS += eps_;
+            }
+
+            Scalar dLambdaWdS = MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.inside())), satPlus) / viscosityW;
+            dLambdaWdS -= MaterialLaw::krw(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.inside())), satMinus) / viscosityW;
+            dLambdaWdS /= (dS);
+
+            if (potentialNW >= 0)
+            {
+                satUpw = std::max(1 - satI, 0.0);
+            }
+            else
+            {
+                satUpw = std::max(1 - satBound, 0.0);
+            }
+
+            dS = eps_;
+
+            satPlus = satUpw + eps_;
+            satMinus = satUpw;
+            if (satMinus - eps_ > 0.0)
+            {
+                satMinus -= eps_;
+                dS += eps_;
+            }
+
+            Scalar dLambdaNWdS = MaterialLaw::krn(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.inside())), satPlus) / viscosityNW;
+            dLambdaNWdS -= MaterialLaw::krn(problem_.spatialParameters().materialLawParams(globalPos,
+                    (*intersection.inside())), satMinus) / viscosityNW;
+            dLambdaNWdS /= (dS);
+
+            Scalar lambdaWCap = 0.5 * (lambdaWI + lambdaWBound);
+            Scalar lambdaNWCap = 0.5 * (lambdaNWI + lambdaNWBound);
+
+            if (phaseIdx == wPhaseIdx)
+            {
+                if (flux != 0)
+                {
+                    cflFluxFunction_ += lambdaNW * dLambdaWdS * std::abs(flux) / (lambdaW * (lambdaW + lambdaNW));
+                }
+
+                cflFluxFunction_ -= transmissibility * lambdaWCap * lambdaNWCap * (dPcdSI + dPcdSBound) / (lambdaW
+                        + lambdaNW);
+            }
+            if (phaseIdx == nPhaseIdx)
+            {
+                if (flux != 0)
+                {
+                    cflFluxFunction_ -= lambdaW * dLambdaNWdS * std::abs(flux) / (lambdaNW * (lambdaW + lambdaNW));
+                }
+            }
+        }
+    }
+
+    Scalar getCflFluxFunction(const GlobalPosition& globalPos, const Element& element)
+    {
+        Scalar cflFluxDefault = 1 / ParentType::getCflFluxFunction(globalPos, element);
+
+        if (std::isnan(cflFluxFunction_) || std::isinf(cflFluxFunction_) || cflFluxFunction_ > 100 * cflFluxDefault)
+        {
+            cflFluxFunction_ = 0;
+        }
+
+        if (cflFluxDefault > 1)
+            std::cout << "cflFluxDefault = " << cflFluxDefault << "\n";
+
+        if (cflFluxFunction_ > 1)
+            std::cout << "cflFluxFunction_ = " << cflFluxFunction_ << "\n";
+
+        Scalar returnValue = std::max(cflFluxFunction_, cflFluxDefault);
+        reset();
+
+        if (returnValue > 0)
+        {
+            return (returnValue == cflFluxDefault) ? 0.95 / returnValue : 1 / returnValue;
+        }
+        else
+            return 1e100;
+    }
+
+    void reset()
+    {
+        ParentType::reset();
+        cflFluxFunction_ = 0;
+    }
+
+    EvalCflFluxCoats(Problem& problem) :
+        ParentType(problem), problem_(problem)
+    {
+        reset();
+    }
+
+private:
+    Problem& problem_;//problem data
+    Scalar cflFluxFunction_;
+    static const int pressureType_ = GET_PROP_VALUE(TypeTag, PTAG(PressureFormulation));
+    static const int velocityType_ = GET_PROP_VALUE(TypeTag, PTAG(VelocityFormulation));
+    static const int saturationType_ = GET_PROP_VALUE(TypeTag, PTAG(SaturationFormulation));
+    static const Scalar eps_ = 1e-2;
+};
+
+}
+
+#endif