diff --git a/dumux/discretization/cellcentered/tpfa/fickslaw.hh b/dumux/discretization/cellcentered/tpfa/fickslaw.hh
index 7d7eade67090dac8051686d9b142e8a1655be8ec..b9ed615ca78ebaf0be472eaa1a4e1ee5281917e9 100644
--- a/dumux/discretization/cellcentered/tpfa/fickslaw.hh
+++ b/dumux/discretization/cellcentered/tpfa/fickslaw.hh
@@ -60,13 +60,14 @@ class FicksLawImplementation<TypeTag, DiscretizationMethods::CCTpfa >
     using IndexType = typename GridView::IndexSet::IndexType;
     using Stencil = typename std::vector<IndexType>;
     using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
+    using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
     using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
     using Element = typename GridView::template Codim<0>::Entity;
     using ElementFluxVariablesCache = typename GET_PROP_TYPE(TypeTag, ElementFluxVariablesCache);
 
-    enum { dim = GridView::dimension} ;
-    enum { dimWorld = GridView::dimensionworld} ;
-    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases)} ;
+    static const int dim = GridView::dimension;
+    static const int dimWorld = GridView::dimensionworld;
+    static const int numPhases = GET_PROP_VALUE(TypeTag, NumPhases);
 
     using DimWorldMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
     using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
@@ -87,31 +88,27 @@ public:
         // diffusion tensors are always solution dependent
         Scalar tij = calculateTransmissibility_(problem, element, fvGeometry, elemVolVars, scvf, phaseIdx, compIdx);
 
-        // Get the inside volume variables
-        const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
-        const auto& insideVolVars = elemVolVars[insideScv];
-
-        // and the outside volume variables
+        // get inside/outside volume variables
+        const auto& insideVolVars = elemVolVars[scvf.insideScvIdx()];
         const auto& outsideVolVars = elemVolVars[scvf.outsideScvIdx()];
 
-        // compute the diffusive flux using mole fractions
-        if (useMoles)
-        {
-            const auto xInside = insideVolVars.moleFraction(phaseIdx, compIdx);
-            const auto xOutside = outsideVolVars.moleFraction(phaseIdx, compIdx);
-            const auto rho = 0.5*(insideVolVars.molarDensity(phaseIdx) + outsideVolVars.molarDensity(phaseIdx));
+        // lambdas to get mole/mass fractions & densities
+        auto getX = [useMoles, phaseIdx, compIdx] (const VolumeVariables& volVars)
+        { return useMoles ? volVars.moleFraction(phaseIdx, compIdx) : volVars.massFraction(phaseIdx, compIdx); };
 
-            return rho*tij*(xInside - xOutside);
-        }
-        // compute the diffusive flux using mass fractions
-        else
-        {
-            const auto xInside = insideVolVars.massFraction(phaseIdx, compIdx);
-            const auto xOutside = outsideVolVars.massFraction(phaseIdx, compIdx);
-            const auto rho = 0.5*(insideVolVars.density(phaseIdx) + outsideVolVars.density(phaseIdx));
+        auto getRho = [useMoles, phaseIdx](const VolumeVariables& volVars)
+        { return useMoles? volVars.molarDensity(phaseIdx) : volVars.density(phaseIdx); };
 
-            return rho*tij*(xInside - xOutside);
-        }
+        // interpolate density
+        const auto rho = scvf.numOutsideScvs() == 1 ? 0.5*(getRho(insideVolVars)+ getRho(outsideVolVars))
+                         : branchingFacetDensity_(elemVolVars, scvf, getRho, getRho(insideVolVars));
+
+        // the inside and outside mole/mass fractions
+        auto xInside = getX(insideVolVars);
+        auto xOutside = scvf.numOutsideScvs() == 1 ? getX(outsideVolVars)
+                        : branchingFacetX_(problem, element, fvGeometry, elemVolVars, scvf, getX, xInside, tij, phaseIdx, compIdx);
+
+        return rho*tij*(xInside - xOutside);
     }
 
     static Stencil stencil(const Problem& problem,
@@ -127,13 +124,58 @@ public:
 
 private:
 
+    //! compute the mole/mass fraction at branching facets for network grids
+    template<typename GetXFunction>
+    static Scalar branchingFacetX_(const Problem& problem,
+                                   const Element& element,
+                                   const FVElementGeometry& fvGeometry,
+                                   const ElementVolumeVariables& elemVolVars,
+                                   const SubControlVolumeFace& scvf,
+                                   const GetXFunction& getX,
+                                   Scalar insideX, Scalar insideTi,
+                                   int phaseIdx, int compIdx)
+    {
+        Scalar sumTi(insideTi);
+        Scalar sumXTi(insideTi*insideX);
+
+        for (unsigned int i = 0; i < scvf.numOutsideScvs(); ++i)
+        {
+            const auto outsideScvIdx = scvf.outsideScvIdx(i);
+            const auto& outsideVolVars = elemVolVars[outsideScvIdx];
+            const auto outsideElement = fvGeometry.globalFvGeometry().element(outsideScvIdx);
+            const auto& flippedScvf = fvGeometry.flipScvf(scvf.index(), i);
+
+            auto outsideTi = calculateTransmissibility_(problem, outsideElement, fvGeometry, elemVolVars, flippedScvf, phaseIdx, compIdx);
+            sumTi += outsideTi;
+            sumXTi += outsideTi*getX(outsideVolVars);
+        }
+        return sumXTi/sumTi;
+    }
+
+    //! compute the density at branching facets for network grids as arithmetic mean
+    template<typename GetRhoFunction>
+    static Scalar branchingFacetDensity_(const ElementVolumeVariables& elemVolVars,
+                                         const SubControlVolumeFace& scvf,
+                                         const GetRhoFunction& getRho,
+                                         Scalar insideRho)
+    {
+        Scalar rho(insideRho);
+        for (unsigned int i = 0; i < scvf.numOutsideScvs(); ++i)
+        {
+            const auto outsideScvIdx = scvf.outsideScvIdx(i);
+            const auto& outsideVolVars = elemVolVars[outsideScvIdx];
+            rho += getRho(outsideVolVars);
+        }
+        return rho/(scvf.numOutsideScvs()+1);
+    }
+
 
     static Scalar calculateTransmissibility_(const Problem& problem,
                                              const Element& element,
                                              const FVElementGeometry& fvGeometry,
                                              const ElementVolumeVariables& elemVolVars,
                                              const SubControlVolumeFace& scvf,
-                                             const int phaseIdx, const int compIdx)
+                                             int phaseIdx, int compIdx)
     {
         Scalar tij;
 
@@ -145,15 +187,28 @@ private:
         insideD = EffDiffModel::effectiveDiffusivity(insideVolVars.porosity(), insideVolVars.saturation(phaseIdx), insideD);
         Scalar ti = calculateOmega_(problem, element, scvf, insideD, insideScv);
 
-        if (!scvf.boundary())
+        // for the boundary (dirichlet) or at branching points we only need ti
+        if (scvf.boundary() || scvf.numOutsideScvs() > 1)
+        {
+            tij = scvf.area()*ti;
+        }
+        // otherwise we compute a tpfa harmonic mean
+        else
         {
             const auto outsideScvIdx = scvf.outsideScvIdx();
             const auto& outsideScv = fvGeometry.scv(outsideScvIdx);
             const auto& outsideVolVars = elemVolVars[outsideScvIdx];
+            const auto outsideElement = fvGeometry.globalFvGeometry().element(outsideScvIdx);
 
             auto outsideD = outsideVolVars.diffusionCoefficient(phaseIdx, compIdx);
             outsideD = EffDiffModel::effectiveDiffusivity(outsideVolVars.porosity(), outsideVolVars.saturation(phaseIdx), outsideD);
-            Scalar tj = -1.0*calculateOmega_(problem, element, scvf, outsideD, outsideScv);
+
+            Scalar tj;
+            if (dim == dimWorld)
+                // assume the normal vector from outside is anti parallel so we save flipping a vector
+                tj = -1.0*calculateOmega_(problem, outsideElement, scvf, outsideD, outsideScv);
+            else
+                tj = calculateOmega_(problem, outsideElement, fvGeometry.flipScvf(scvf.index()), outsideD, outsideScv);
 
             // check if we are dividing by zero!
             if (ti*tj <= 0.0)
@@ -161,10 +216,6 @@ private:
             else
                 tij = scvf.area()*(ti * tj)/(ti + tj);
         }
-        else
-        {
-            tij = scvf.area()*ti;
-        }
 
         return tij;
     }