diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2p.hh
index beb3910b8073854adb410518621b1b0e29f85786..8f6f2bad4f7549fceb575a367a08c10e200c1892 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2p.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2p.hh
@@ -22,6 +22,7 @@
 #include <dumux/decoupled/common/fv/mpfa/mpfalinteractionvolume.hh>
 #include <dumux/decoupled/2p/diffusion/diffusionproperties2p.hh>
 #include <dumux/decoupled/common/fv/mpfa/fvmpfaproperties.hh>
+#include "fvmpfal2dtransmissibilitycalculator.hh"
 
 /**
  * @file
@@ -136,6 +137,7 @@ public:
      *
      */
     typedef Dumux::FVMPFALInteractionVolume<TypeTag> InteractionVolume;
+    typedef Dumux::FvMpfaL2dTransmissibilityCalculator<TypeTag> TransmissibilityCalculator;
 private:
 
     typedef std::vector<InteractionVolume> GlobalInteractionVolumeVector;
@@ -396,7 +398,7 @@ public:
      * \param problem A problem class object
      */
     FvMpfaL2dPressure2p(Problem& problem) :
-            ParentType(problem), problem_(problem), R_(0),
+            ParentType(problem), problem_(problem), transmissibilityCalculator_(problem),
                     gravity_(problem.gravity()),
                     maxError_(0.), timeStep_(1.)
     {
@@ -417,13 +419,6 @@ public:
             DUNE_THROW(Dune::NotImplemented, "Dimension not supported!");
         }
 
-        // evaluate matrix R
-        if (dim == 2)
-        {
-            R_[0][1] = 1;
-            R_[1][0] = -1;
-        }
-
         ErrorTermFactor_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Impet, ErrorTermFactor);
         ErrorTermLowerBound_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Impet, ErrorTermLowerBound);
         ErrorTermUpperBound_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Impet, ErrorTermUpperBound);
@@ -438,17 +433,10 @@ public:
 
 private:
     Problem& problem_;
-    DimMatrix R_;
+    TransmissibilityCalculator transmissibilityCalculator_;
 
 protected:
 
-    // Calculates tranmissibility matrix
-    bool calculateTransmissibility(
-            Dune::FieldMatrix<Scalar,dim,2*dim-dim+1>& transmissibility,
-            InteractionVolume& interactionVolume,
-            std::vector<DimVector >& lambda,
-            int idx1, int idx2, int idx3, int idx4);
-
     GlobalInteractionVolumeVector interactionVolumes_;//!< Global Vector of interaction volumes
     InnerBoundaryVolumeFaces innerBoundaryVolumeFaces_; //!< Vector marking faces which intersect the boundary
 
@@ -1472,9 +1460,9 @@ void FvMpfaL2dPressure2p<TypeTag>::assemble()
             Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
             Dune::FieldMatrix<Scalar,dim,2*dim-dim+1> T(0);
 
-            bool rightTriangle = calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
+            int lType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
 
-            if (rightTriangle)
+            if (lType == TransmissibilityCalculator::rightTriangle)
             {
                 if (innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
                 {
@@ -1521,9 +1509,9 @@ void FvMpfaL2dPressure2p<TypeTag>::assemble()
                 pcPotential12 = Tu[1];
             }
 
-            rightTriangle = calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
+            lType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
 
-            if (rightTriangle)
+            if (lType == TransmissibilityCalculator::rightTriangle)
             {
                 if (innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
                 {
@@ -1570,9 +1558,9 @@ void FvMpfaL2dPressure2p<TypeTag>::assemble()
                 pcPotential32 = -Tu[1];
             }
 
-            rightTriangle = calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
+            lType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
 
-            if (rightTriangle)
+            if (lType == TransmissibilityCalculator::rightTriangle)
             {
                 if (innerBoundaryVolumeFaces_[globalIdx3][interactionVolume.getIndexOnElement(2, 0)])
                 {
@@ -1619,9 +1607,9 @@ void FvMpfaL2dPressure2p<TypeTag>::assemble()
                 pcPotential34 = Tu[1];
             }
 
-            rightTriangle = calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
+            lType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
 
-            if (rightTriangle)
+            if (lType == TransmissibilityCalculator::rightTriangle)
             {
                 if (innerBoundaryVolumeFaces_[globalIdx4][interactionVolume.getIndexOnElement(3, 0)])
                 {
@@ -2006,318 +1994,6 @@ void FvMpfaL2dPressure2p<TypeTag>::assemble()
     return;
 }
 
-/*! \brief Calculates tranmissibility matrix
- *
- * Calculates tranmissibility matrix of an L-shape for a certain flux face.
- * Automatically selects one of the two possible L-shape (left, or right).
- *
- * \param transmissibility Matrix for the resulting transmissibility
- * \param interactionVolume The interaction volume object (includes geometric information)
- * \param lambda Mobilities of cells 1-4
- * \param idx1 Index of cell 1 of the L-stencil
- * \param idx2 Index of cell 2 of the L-stencil
- * \param idx3 Index of cell 3 of the L-stencil
- * \param idx4 Index of cell 4 of the L-stencil
- */
-template<class TypeTag>
-bool FvMpfaL2dPressure2p<TypeTag>::calculateTransmissibility(
-        Dune::FieldMatrix<Scalar,dim,2*dim-dim+1>& transmissibility,
-        InteractionVolume& interactionVolume,
-        std::vector<DimVector >& lambda,
-        int idx1, int idx2, int idx3, int idx4)
-{
-    ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(idx1);
-    ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(idx2);
-    ElementPointer& elementPointer3 = interactionVolume.getSubVolumeElement(idx3);
-    ElementPointer& elementPointer4 = interactionVolume.getSubVolumeElement(idx4);
-
-    // get global coordinate of cell centers
-    const GlobalPosition& globalPos1 = elementPointer1->geometry().center();
-    const GlobalPosition& globalPos2 = elementPointer2->geometry().center();
-    const GlobalPosition& globalPos3 = elementPointer3->geometry().center();
-    const GlobalPosition& globalPos4 = elementPointer4->geometry().center();
-
-    const GlobalPosition& globalPosCenter = interactionVolume.getCenterPosition();
-
-    const DimMatrix& K1 = problem_.spatialParams().intrinsicPermeability(*elementPointer1);
-    const DimMatrix& K2 = problem_.spatialParams().intrinsicPermeability(*elementPointer2);
-    const DimMatrix& K3 = problem_.spatialParams().intrinsicPermeability(*elementPointer3);
-    const DimMatrix& K4 = problem_.spatialParams().intrinsicPermeability(*elementPointer4);
-
-    const GlobalPosition& globalPosFace12 = interactionVolume.getFacePosition(idx1,0);
-    const GlobalPosition& globalPosFace23 = interactionVolume.getFacePosition(idx2,0);
-
-    // compute normal vectors nu1-nu7 in triangle R for first half edge
-    DimVector nu1R1(0);
-    R_.mv(globalPosFace12-globalPos2 ,nu1R1);
-
-    DimVector nu2R1(0);
-    R_.mv(globalPos2-globalPosFace23, nu2R1);
-
-    DimVector nu3R1(0);
-    R_.mv(globalPosFace23-globalPos3, nu3R1);
-
-    DimVector nu4R1(0);
-    R_.mv(globalPos3-globalPosCenter, nu4R1);
-
-    DimVector nu5R1(0);
-    R_.mv(globalPosCenter-globalPos1, nu5R1);
-
-    DimVector nu6R1(0);
-    R_.mv(globalPos1-globalPosFace12, nu6R1);
-
-    DimVector nu7R1(0);
-    R_.mv(globalPosCenter-globalPos2, nu7R1);
-
-    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
-    DimVector Rnu2R1(0);
-    R_.mv(nu2R1, Rnu2R1);
-    Scalar T1R1 = nu1R1 * Rnu2R1;
-
-    DimVector Rnu4R1(0);
-    R_.mv(nu4R1, Rnu4R1);
-    Scalar T2R1 = nu3R1 * Rnu4R1;
-
-    DimVector Rnu6R1(0);
-    R_.mv(nu6R1, Rnu6R1);
-    Scalar T3R1 = nu5R1 * Rnu6R1;
-
-    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
-    DimVector K2nu1R1(0);
-    K2.mv(nu1R1, K2nu1R1);
-    DimVector K2nu2R1(0);
-    K2.mv(nu2R1, K2nu2R1);
-    DimVector K4nu3R1(0);
-    K3.mv(nu3R1, K4nu3R1);
-    DimVector K4nu4R1(0);
-    K3.mv(nu4R1, K4nu4R1);
-    DimVector K1nu5R1(0);
-    K1.mv(nu5R1, K1nu5R1);
-    DimVector K1nu6R1(0);
-    K1.mv(nu6R1, K1nu6R1);
-
-    DimVector Rnu1R1(0);
-    R_.mv(nu1R1, Rnu1R1);
-
-    DimVector &outerNormaln1R1 =  interactionVolume.getNormal(idx2, 0);
-    DimVector &outerNormaln2 =  interactionVolume.getNormal(idx1, 0);
-
-//    std::cout<<"outerNormaln1R1 = "<<outerNormaln1R1<<"\n";
-//    std::cout<<"outerNormaln2 = "<<outerNormaln2<<"\n";
-
-    Scalar omega111R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 0)/T1R1;
-    Scalar omega112R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 0)/T1R1;
-    Scalar omega211R1 = lambda[idx2][1] * (outerNormaln2 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 1)/T1R1;
-    Scalar omega212R1 = lambda[idx2][1] * (outerNormaln2 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 1)/T1R1;
-    Scalar omega123R1 = lambda[idx3][1] * (outerNormaln1R1 * K4nu3R1) * interactionVolume.getFaceArea(idx3, 1)/T2R1;
-    Scalar omega124R1 = lambda[idx3][1] * (outerNormaln1R1 * K4nu4R1) * interactionVolume.getFaceArea(idx3, 1)/T2R1;
-    Scalar omega235R1 = lambda[idx1][0] * (outerNormaln2 * K1nu5R1) * interactionVolume.getFaceArea(idx1, 0)/T3R1;
-    Scalar omega236R1 = lambda[idx1][0] * (outerNormaln2 * K1nu6R1) * interactionVolume.getFaceArea(idx1, 0)/T3R1;
-    Scalar chi711R1 = (nu7R1 * Rnu1R1)/T1R1;
-    Scalar chi712R1 = (nu7R1 * Rnu2R1)/T1R1;
-
-    // compute transmissibility matrix TR1 = CA^{-1}B+D
-    DimMatrix C(0), A(0);
-    Dune::FieldMatrix<Scalar,dim,2*dim-dim+1> D(0), B(0);
-
-    // evaluate matrix C, D, A, B
-    C[0][0] = -omega111R1;
-    C[0][1] = -omega112R1;
-    C[1][0] = -omega211R1;
-    C[1][1] = -omega212R1;
-
-    D[0][0] = omega111R1 + omega112R1;
-    D[1][0] = omega211R1 + omega212R1;
-
-    A[0][0] = omega111R1 - omega124R1 - omega123R1*chi711R1;
-    A[0][1] = omega112R1 - omega123R1*chi712R1;
-    A[1][0] = omega211R1 - omega236R1*chi711R1;
-    A[1][1] = omega212R1 - omega235R1 - omega236R1*chi712R1;
-
-    B[0][0] = omega111R1 + omega112R1 + omega123R1*(1.0 - chi711R1 - chi712R1);
-    B[0][1] = -omega123R1 - omega124R1;
-    B[1][0] = omega211R1 + omega212R1 + omega236R1*(1.0 - chi711R1 - chi712R1);
-    B[1][2] = -omega235R1 - omega236R1;
-
-//    std::cout<<"AR = "<<A<<"\n";
-
-    // compute TR1
-    A.invert();
-    D += B.leftmultiply(C.rightmultiply(A));
-    Dune::FieldMatrix<Scalar,dim,2*dim-dim+1> TR1(D);
-
-
-    // 2.use triangle L to compute the transmissibility of half edge
-    const GlobalPosition& globalPosFace14 = interactionVolume.getFacePosition(idx1,1);
-
-//    std::cout<<"globalPosFace14 = "<<globalPosFace14<<"\n";
-
-    // compute normal vectors nu1-nu7 in triangle L for first half edge
-    DimVector nu1L1(0);
-    R_.mv(globalPosFace12-globalPos1 ,nu1L1);
-
-    DimVector nu2L1(0);
-    R_.mv(globalPos1-globalPosFace14, nu2L1);
-
-    DimVector nu3L1(0);
-    R_.mv(globalPosFace14-globalPos4, nu3L1);
-
-    DimVector nu4L1(0);
-    R_.mv(globalPos4-globalPosCenter, nu4L1);
-
-    DimVector nu5L1(0);
-    R_.mv(globalPosCenter-globalPos2, nu5L1);
-
-    DimVector nu6L1(0);
-    R_.mv(globalPos2-globalPosFace12, nu6L1);
-
-    DimVector nu7L1(0);
-    R_.mv(globalPosCenter-globalPos1, nu7L1);
-
-    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
-    DimVector Rnu2L1(0);
-    R_.mv(nu2L1, Rnu2L1);
-    Scalar T1L1 = nu1L1 * Rnu2L1;
-
-    DimVector Rnu4L1(0);
-    R_.mv(nu4L1, Rnu4L1);
-    Scalar T2L1 = nu3L1 * Rnu4L1;
-
-    DimVector Rnu6L1(0);
-    R_.mv(nu6L1, Rnu6L1);
-    Scalar T3L1 = nu5L1 * Rnu6L1;
-
-    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
-    DimVector K1nu1L1(0);
-    K1.mv(nu1L1, K1nu1L1);
-    DimVector K1nu2L1(0);
-    K1.mv(nu2L1, K1nu2L1);
-    DimVector K3nu3L1(0);
-    K4.mv(nu3L1, K3nu3L1);
-    DimVector K3nu4L1(0);
-    K4.mv(nu4L1, K3nu4L1);
-    DimVector K2nu5L1(0);
-    K2.mv(nu5L1, K2nu5L1);
-    DimVector K2nu6L1(0);
-    K2.mv(nu6L1, K2nu6L1);
-
-    DimVector Rnu1L1(0);
-    R_.mv(nu1L1, Rnu1L1);
-
-    DimVector &outerNormaln1L1 =  interactionVolume.getNormal(idx1, 1);
-//    std::cout<<"outerNormaln1L1 = "<<outerNormaln1L1<<"\n";
-
-    Scalar omega111L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu1L1)* interactionVolume.getFaceArea(idx1, 1)/T1L1;
-    Scalar omega112L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu2L1)* interactionVolume.getFaceArea(idx1, 1)/T1L1;
-    Scalar omega211L1 = lambda[idx1][0] * (outerNormaln2 * K1nu1L1)* interactionVolume.getFaceArea(idx1, 0)/T1L1;
-    Scalar omega212L1 = lambda[idx1][0] * (outerNormaln2 * K1nu2L1)* interactionVolume.getFaceArea(idx1, 0)/T1L1;
-    Scalar omega123L1 = lambda[idx4][0] * (outerNormaln1L1 * K3nu3L1)* interactionVolume.getFaceArea(idx4, 0)/T2L1;
-    Scalar omega124L1 = lambda[idx4][0] * (outerNormaln1L1 * K3nu4L1)* interactionVolume.getFaceArea(idx4, 0)/T2L1;
-    Scalar omega235L1 = lambda[idx2][1] * (outerNormaln2 * K2nu5L1)* interactionVolume.getFaceArea(idx2, 1)/T3L1;
-    Scalar omega236L1 = lambda[idx2][1] * (outerNormaln2 * K2nu6L1)* interactionVolume.getFaceArea(idx2, 1)/T3L1;
-    Scalar chi711L1 = (nu7L1 * Rnu1L1)/T1L1;
-    Scalar chi712L1 = (nu7L1 * Rnu2L1)/T1L1;
-
-    // compute transmissibility matrix TL1 = CA^{-1}B+D
-    C = 0;
-    A = 0;
-    D = 0;
-    B = 0;
-
-    // evaluate matrix C, D, A, B
-    C[0][0] = -omega111L1;
-    C[0][1] = -omega112L1;
-    C[1][0] = -omega211L1;
-    C[1][1] = -omega212L1;
-
-    D[0][0] = omega111L1 + omega112L1;
-    D[1][0] = omega211L1 + omega212L1;
-
-    A[0][0] = omega111L1 - omega124L1 - omega123L1*chi711L1;
-    A[0][1] = omega112L1 - omega123L1*chi712L1;
-    A[1][0] = omega211L1 - omega236L1*chi711L1;
-    A[1][1] = omega212L1 - omega235L1 - omega236L1*chi712L1;
-
-    B[0][0] = omega111L1 + omega112L1 + omega123L1*(1.0 - chi711L1 - chi712L1);
-    B[0][1] = -omega123L1 - omega124L1;
-    B[1][0] = omega211L1 + omega212L1 + omega236L1*(1.0 - chi711L1 - chi712L1);
-    B[1][2] = -omega235L1 - omega236L1;
-
-//    std::cout<<"AL = "<<A<<"\n";
-
-    // compute TL1
-    A.invert();
-    D += B.leftmultiply(C.rightmultiply(A));
-    Dune::FieldMatrix<Scalar,dim,2*dim-dim+1> TL1(D);
-
-    Scalar sR = std::abs(TR1[1][2] - TR1[1][0]);
-    Scalar sL = std::abs(TL1[1][0] - TL1[1][2]);
-
-    // 3.decide which triangle (which transmissibility coefficients) to use
-    if (sR <= sL)
-    {
-        transmissibility = TR1;
-//        if (std::isnan(transmissibility.frobenius_norm()))
-//        {
-//                    std::cout<<"right transmissibility = "<<transmissibility<<"\n";
-//                std::cout<<"globalPos1 = "<<globalPos1<<"\n";
-//                std::cout<<"globalPos2 = "<<globalPos2<<"\n";
-//                std::cout<<"globalPos3 = "<<globalPos3<<"\n";
-//                std::cout<<"globalPos4 = "<<globalPos4<<"\n";
-//                std::cout<<"globalPosCenter = "<<globalPosCenter<<"\n";
-//                std::cout<<"outerNormaln1L1 = "<<outerNormaln1L1<<"\n";
-//                std::cout<<"globalPosFace14 = "<<globalPosFace14<<"\n";
-//                std::cout<<"outerNormaln1R1 = "<<outerNormaln1R1<<"\n";
-//                std::cout<<"outerNormaln2 = "<<outerNormaln2<<"\n";
-//                std::cout<<"globalPosFace12 = "<<globalPosFace12<<"\n";
-//                std::cout<<"globalPosFace23 = "<<globalPosFace23<<"\n";
-//                std::cout<<"perm1 = "<<K1<<"\n";
-//                std::cout<<"perm2 = "<<K2<<"\n";
-//                std::cout<<"perm3 = "<<K3<<"\n";
-//                std::cout<<"perm4 = "<<K4<<"\n";
-//                std::cout<<"lambda = ";
-//                for (int i = 0; i < lambda.size(); i++)
-//                {
-//                    std::cout<<lambda[i]<<" ";
-//                }
-//                std::cout<<"\n";
-//        }
-//        std::cout<<"transmissibility = "<<transmissibility<<"\n";
-        return true;
-    }
-    else
-    {
-        transmissibility = TL1;
-//        if (std::isnan(transmissibility.frobenius_norm()))
-//        {
-//                    std::cout<<"left transmissibility = "<<transmissibility<<"\n";
-//                std::cout<<"globalPos1 = "<<globalPos1<<"\n";
-//                std::cout<<"globalPos2 = "<<globalPos2<<"\n";
-//                std::cout<<"globalPos3 = "<<globalPos3<<"\n";
-//                std::cout<<"globalPos4 = "<<globalPos4<<"\n";
-//                std::cout<<"globalPosCenter = "<<globalPosCenter<<"\n";
-//                std::cout<<"outerNormaln1L1 = "<<outerNormaln1L1<<"\n";
-//                std::cout<<"globalPosFace14 = "<<globalPosFace14<<"\n";
-//                std::cout<<"outerNormaln1R1 = "<<outerNormaln1R1<<"\n";
-//                std::cout<<"outerNormaln2 = "<<outerNormaln2<<"\n";
-//                std::cout<<"globalPosFace12 = "<<globalPosFace12<<"\n";
-//                std::cout<<"globalPosFace23 = "<<globalPosFace23<<"\n";
-//                std::cout<<"perm1 = "<<K1<<"\n";
-//                std::cout<<"perm2 = "<<K2<<"\n";
-//                std::cout<<"perm3 = "<<K3<<"\n";
-//                std::cout<<"perm4 = "<<K4<<"\n";
-//                std::cout<<"lambda = ";
-//                for (int i = 0; i < lambda.size(); i++)
-//                {
-//                    std::cout<<lambda[i]<<" ";
-//                }
-//                std::cout<<"\n";
-//        }
-//        std::cout<<"left transmissibility = "<<transmissibility<<"\n";
-        return false;
-    }
-}
-
 /*! \brief Updates constitutive relations and stores them in the variable class
  *
  * Stores mobility, fractional flow function and capillary pressure for all grid cells.
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2padaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2padaptive.hh
index 26ea43072ed6de874f108fe4cb90ce472d7133e5..4bf579f4cb8783ee162ef169e1b1d315e93b86a6 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2padaptive.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2padaptive.hh
@@ -22,6 +22,7 @@
 #include <dumux/decoupled/common/fv/mpfa/mpfalinteractionvolume.hh>
 #include <dumux/decoupled/2p/diffusion/diffusionproperties2p.hh>
 #include <dumux/decoupled/common/fv/mpfa/fvmpfaproperties.hh>
+#include "fvmpfal2dtransmissibilitycalculator.hh"
 
 /**
  * @file
@@ -136,12 +137,7 @@ class FvMpfaL2dPressure2pAdaptive: public FVPressure<TypeTag>
     typedef Dune::FieldVector<Scalar, dim> DimVector;
 
 public:
-    enum
-    {
-        leftTriangle = -1,
-        noTransmissibility = 0,
-        rightTriangle = 1
-    };
+
 
     /*! \brief Type of the interaction volume objects
      *
@@ -150,6 +146,7 @@ public:
      *
      */
     typedef Dumux::FVMPFALInteractionVolume<TypeTag> InteractionVolume;
+    typedef Dumux::FvMpfaL2dTransmissibilityCalculator<TypeTag> TransmissibilityCalculator;
 private:
 
     typedef std::vector<InteractionVolume> GlobalInteractionVolumeVector;
@@ -437,7 +434,7 @@ public:
      * \param problem A problem class object
      */
     FvMpfaL2dPressure2pAdaptive(Problem& problem) :
-        ParentType(problem), problem_(problem), R_(0),
+        ParentType(problem), problem_(problem), transmissibilityCalculator_(problem),
                     gravity_(problem.gravity()),
                     maxError_(0.), timeStep_(1.)
     {
@@ -464,13 +461,6 @@ public:
             DUNE_THROW(Dune::NotImplemented, "Dimension not supported!");
         }
 
-        // evaluate matrix R
-        if (dim == 2)
-        {
-            R_[0][1] = 1;
-            R_[1][0] = -1;
-        }
-
         ErrorTermFactor_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Impet, ErrorTermFactor);
         ErrorTermLowerBound_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Impet, ErrorTermLowerBound);
         ErrorTermUpperBound_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Impet, ErrorTermUpperBound);
@@ -485,26 +475,7 @@ public:
 
 private:
     Problem& problem_;
-    DimMatrix R_;
-
-public:
-    // Calculates tranmissibility matrix
-    int calculateTransmissibility(Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1>& transmissibility,
-    InteractionVolume& interactionVolume,
-    std::vector<DimVector >& lambda,
-    int idx1, int idx2, int idx3, int idx4);
-
-    // Calculates tranmissibility matrix of left L-shape
-    int calculateLeftHNTransmissibility(Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1>& transmissibility,
-    InteractionVolume& interactionVolume,
-    std::vector<DimVector >& lambda,
-    int idx1, int idx2, int idx3);
-
-    // Calculates tranmissibility matrix of right L-shape
-    int calculateRightHNTransmissibility(Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1>& transmissibility,
-    InteractionVolume& interactionVolume,
-    std::vector<DimVector >& lambda,
-    int idx1, int idx2, int idx3);
+    TransmissibilityCalculator transmissibilityCalculator_;
 
 protected:
     GlobalInteractionVolumeVector interactionVolumes_;//!< Global Vector of interaction volumes
@@ -2021,9 +1992,9 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                 Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
                 Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
 
-                int transmissibilityType = calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
+                int transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
 
-                if (transmissibilityType == rightTriangle)
+                if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
                     {
@@ -2046,7 +2017,7 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     pcFlux[0] = Tu[1];
                     pcPotential12 = Tu[1];
                 }
-                else if (transmissibilityType == leftTriangle)
+                else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
                     {
@@ -2070,9 +2041,9 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     pcPotential12 = Tu[1];
                 }
 
-                transmissibilityType = calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
+                transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
 
-                if (transmissibilityType == rightTriangle)
+                if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
                     {
@@ -2095,7 +2066,7 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     pcFlux[1] = Tu[1];
                     pcPotential32 = -Tu[1];
                 }
-                else if (transmissibilityType == leftTriangle)
+                else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
                     {
@@ -2119,9 +2090,9 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     pcPotential32 = -Tu[1];
                 }
 
-                transmissibilityType = calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
+                transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
 
-                if (transmissibilityType == rightTriangle)
+                if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx3][interactionVolume.getIndexOnElement(2, 0)])
                     {
@@ -2144,7 +2115,7 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     pcFlux[2] = Tu[1];
                     pcPotential34 = Tu[1];
                 }
-                else if (transmissibilityType == leftTriangle)
+                else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx3][interactionVolume.getIndexOnElement(2, 0)])
                     {
@@ -2168,9 +2139,9 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     pcPotential34 = Tu[1];
                 }
 
-                transmissibilityType = calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
+                transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
 
-                if (transmissibilityType == rightTriangle)
+                if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx4][interactionVolume.getIndexOnElement(3, 0)])
                     {
@@ -2193,7 +2164,7 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     pcFlux[3] = Tu[1];
                     pcPotential14 = -Tu[1];
                 }
-                else if (transmissibilityType == leftTriangle)
+                else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx4][interactionVolume.getIndexOnElement(3, 0)])
                     {
@@ -2381,9 +2352,9 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                 Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
                 Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
 
-                int transmissibilityType = calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 3, 3);
+                int transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 3, 3);
 
-                if (transmissibilityType == rightTriangle)
+                if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
                     {
@@ -2406,7 +2377,7 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     pcFlux[0] = Tu[1];
                     pcPotential12 = Tu[1];
                 }
-                else if (transmissibilityType == leftTriangle)
+                else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
                     {
@@ -2434,9 +2405,9 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     DUNE_THROW(Dune::RangeError, "Could not calculate Tranmissibility!");
                 }
 
-                transmissibilityType = calculateLeftHNTransmissibility(T, interactionVolume, lambda, 1, 3, 0);
+                transmissibilityType = transmissibilityCalculator_.calculateLeftHNTransmissibility(T, interactionVolume, lambda, 1, 3, 0);
 
-                if (transmissibilityType == leftTriangle)
+                if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
                     {
@@ -2464,9 +2435,9 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
                     DUNE_THROW(Dune::RangeError, "Could not calculate Tranmissibility!");
                 }
 
-                transmissibilityType = calculateRightHNTransmissibility(T, interactionVolume, lambda, 3, 0, 1);
+                transmissibilityType = transmissibilityCalculator_.calculateRightHNTransmissibility(T, interactionVolume, lambda, 3, 0, 1);
 
-                if (transmissibilityType == rightTriangle)
+                if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
                 {
                     if (innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 1)])
                     {
@@ -2824,550 +2795,6 @@ void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
     return;
 }
 
-/*! \brief Calculates tranmissibility matrix
- *
- * Calculates tranmissibility matrix of an L-shape for a certain flux face.
- * Automatically selects one of the two possible L-shape (left, or right).
- *
- * \param transmissibility Matrix for the resulting transmissibility
- * \param interactionVolume The interaction volume object (includes geometric information)
- * \param lambda Mobilities of cells 1-4
- * \param idx1 Index of cell 1 of the L-stencil
- * \param idx2 Index of cell 2 of the L-stencil
- * \param idx3 Index of cell 3 of the L-stencil
- * \param idx4 Index of cell 4 of the L-stencil
- */
-template<class TypeTag>
-int FvMpfaL2dPressure2pAdaptive<TypeTag>::calculateTransmissibility(
-        Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1>& transmissibility,
-        InteractionVolume& interactionVolume,
-        std::vector<DimVector >& lambda,
-        int idx1, int idx2, int idx3, int idx4)
-{
-    ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(idx1);
-    ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(idx2);
-    ElementPointer& elementPointer3 = interactionVolume.getSubVolumeElement(idx3);
-    ElementPointer& elementPointer4 = interactionVolume.getSubVolumeElement(idx4);
-
-    if (elementPointer3 == elementPointer4 && elementPointer1->level() != elementPointer2->level())
-    {
-        return noTransmissibility;
-    }
-
-    // get global coordinate of cell centers
-    const GlobalPosition& globalPos1 = elementPointer1->geometry().center();
-    const GlobalPosition& globalPos2 = elementPointer2->geometry().center();
-    const GlobalPosition& globalPos3 = elementPointer3->geometry().center();
-    const GlobalPosition& globalPos4 = elementPointer4->geometry().center();
-
-    const GlobalPosition& globalPosCenter = interactionVolume.getCenterPosition();
-
-    const DimMatrix& K1 = problem_.spatialParams().intrinsicPermeability(*elementPointer1);
-    const DimMatrix& K2 = problem_.spatialParams().intrinsicPermeability(*elementPointer2);
-    const DimMatrix& K3 = problem_.spatialParams().intrinsicPermeability(*elementPointer3);
-    const DimMatrix& K4 = problem_.spatialParams().intrinsicPermeability(*elementPointer4);
-
-    const GlobalPosition& globalPosFace12 = interactionVolume.getFacePosition(idx1, 0);
-    const GlobalPosition& globalPosFace23 = interactionVolume.getFacePosition(idx2, 0);
-
-    // compute normal vectors nu1-nu7 in triangle R for first half edge
-    DimVector nu1R1(0);
-    R_.mv(globalPosFace12 - globalPos2, nu1R1);
-
-    DimVector nu2R1(0);
-    R_.mv(globalPos2 - globalPosFace23, nu2R1);
-
-    DimVector nu3R1(0);
-    R_.mv(globalPosFace23 - globalPos3, nu3R1);
-
-    DimVector nu4R1(0);
-    R_.mv(globalPos3 - globalPosCenter, nu4R1);
-
-    DimVector nu5R1(0);
-    R_.mv(globalPosCenter - globalPos1, nu5R1);
-
-    DimVector nu6R1(0);
-    R_.mv(globalPos1 - globalPosFace12, nu6R1);
-
-    DimVector nu7R1(0);
-    R_.mv(globalPosCenter - globalPos2, nu7R1);
-
-    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
-    DimVector Rnu2R1(0);
-    R_.mv(nu2R1, Rnu2R1);
-    Scalar T1R1 = nu1R1 * Rnu2R1;
-
-    DimVector Rnu4R1(0);
-    R_.mv(nu4R1, Rnu4R1);
-    Scalar T2R1 = nu3R1 * Rnu4R1;
-
-    DimVector Rnu6R1(0);
-    R_.mv(nu6R1, Rnu6R1);
-    Scalar T3R1 = nu5R1 * Rnu6R1;
-
-    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
-    DimVector K2nu1R1(0);
-    K2.mv(nu1R1, K2nu1R1);
-    DimVector K2nu2R1(0);
-    K2.mv(nu2R1, K2nu2R1);
-    DimVector K4nu3R1(0);
-    K3.mv(nu3R1, K4nu3R1);
-    DimVector K4nu4R1(0);
-    K3.mv(nu4R1, K4nu4R1);
-    DimVector K1nu5R1(0);
-    K1.mv(nu5R1, K1nu5R1);
-    DimVector K1nu6R1(0);
-    K1.mv(nu6R1, K1nu6R1);
-
-    DimVector Rnu1R1(0);
-    R_.mv(nu1R1, Rnu1R1);
-
-    DimVector &outerNormaln1R1 = interactionVolume.getNormal(idx2, 0);
-    DimVector &outerNormaln2 = interactionVolume.getNormal(idx1, 0);
-
-    Scalar omega111R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 0) / T1R1;
-    Scalar omega112R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 0) / T1R1;
-    Scalar omega211R1 = lambda[idx2][1] * (outerNormaln2 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 1) / T1R1;
-    Scalar omega212R1 = lambda[idx2][1] * (outerNormaln2 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 1) / T1R1;
-    Scalar omega123R1 = lambda[idx3][1] * (outerNormaln1R1 * K4nu3R1) * interactionVolume.getFaceArea(idx3, 1) / T2R1;
-    Scalar omega124R1 = lambda[idx3][1] * (outerNormaln1R1 * K4nu4R1) * interactionVolume.getFaceArea(idx3, 1) / T2R1;
-    Scalar omega235R1 = lambda[idx1][0] * (outerNormaln2 * K1nu5R1) * interactionVolume.getFaceArea(idx1, 0) / T3R1;
-    Scalar omega236R1 = lambda[idx1][0] * (outerNormaln2 * K1nu6R1) * interactionVolume.getFaceArea(idx1, 0) / T3R1;
-    Scalar chi711R1 = (nu7R1 * Rnu1R1) / T1R1;
-    Scalar chi712R1 = (nu7R1 * Rnu2R1) / T1R1;
-
-    // compute transmissibility matrix TR1 = CA^{-1}B+D
-    DimMatrix C(0), A(0);
-    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> D(0), B(0);
-
-    // evaluate matrix C, D, A, B
-    C[0][0] = -omega111R1;
-    C[0][1] = -omega112R1;
-    C[1][0] = -omega211R1;
-    C[1][1] = -omega212R1;
-
-    D[0][0] = omega111R1 + omega112R1;
-    D[1][0] = omega211R1 + omega212R1;
-
-    A[0][0] = omega111R1 - omega124R1 - omega123R1 * chi711R1;
-    A[0][1] = omega112R1 - omega123R1 * chi712R1;
-    A[1][0] = omega211R1 - omega236R1 * chi711R1;
-    A[1][1] = omega212R1 - omega235R1 - omega236R1 * chi712R1;
-
-    B[0][0] = omega111R1 + omega112R1 + omega123R1 * (1.0 - chi711R1 - chi712R1);
-    B[0][1] = -omega123R1 - omega124R1;
-    B[1][0] = omega211R1 + omega212R1 + omega236R1 * (1.0 - chi711R1 - chi712R1);
-    B[1][2] = -omega235R1 - omega236R1;
-
-    // compute TR1
-    A.invert();
-    D += B.leftmultiply(C.rightmultiply(A));
-    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> TR1(D);
-
-    // 2.use triangle L to compute the transmissibility of half edge
-    const GlobalPosition& globalPosFace14 = interactionVolume.getFacePosition(idx1, 1);
-
-    // compute normal vectors nu1-nu7 in triangle L for first half edge
-    DimVector nu1L1(0);
-    R_.mv(globalPosFace12 - globalPos1, nu1L1);
-
-    DimVector nu2L1(0);
-    R_.mv(globalPos1 - globalPosFace14, nu2L1);
-
-    DimVector nu3L1(0);
-    R_.mv(globalPosFace14 - globalPos4, nu3L1);
-
-    DimVector nu4L1(0);
-    R_.mv(globalPos4 - globalPosCenter, nu4L1);
-
-    DimVector nu5L1(0);
-    R_.mv(globalPosCenter - globalPos2, nu5L1);
-
-    DimVector nu6L1(0);
-    R_.mv(globalPos2 - globalPosFace12, nu6L1);
-
-    DimVector nu7L1(0);
-    R_.mv(globalPosCenter - globalPos1, nu7L1);
-
-    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
-    DimVector Rnu2L1(0);
-    R_.mv(nu2L1, Rnu2L1);
-    Scalar T1L1 = nu1L1 * Rnu2L1;
-
-    DimVector Rnu4L1(0);
-    R_.mv(nu4L1, Rnu4L1);
-    Scalar T2L1 = nu3L1 * Rnu4L1;
-
-    DimVector Rnu6L1(0);
-    R_.mv(nu6L1, Rnu6L1);
-    Scalar T3L1 = nu5L1 * Rnu6L1;
-
-    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
-    DimVector K1nu1L1(0);
-    K1.mv(nu1L1, K1nu1L1);
-    DimVector K1nu2L1(0);
-    K1.mv(nu2L1, K1nu2L1);
-    DimVector K3nu3L1(0);
-    K4.mv(nu3L1, K3nu3L1);
-    DimVector K3nu4L1(0);
-    K4.mv(nu4L1, K3nu4L1);
-    DimVector K2nu5L1(0);
-    K2.mv(nu5L1, K2nu5L1);
-    DimVector K2nu6L1(0);
-    K2.mv(nu6L1, K2nu6L1);
-
-    DimVector Rnu1L1(0);
-    R_.mv(nu1L1, Rnu1L1);
-
-    DimVector &outerNormaln1L1 = interactionVolume.getNormal(idx1, 1);
-
-    Scalar omega111L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu1L1) * interactionVolume.getFaceArea(idx1, 1) / T1L1;
-    Scalar omega112L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu2L1) * interactionVolume.getFaceArea(idx1, 1) / T1L1;
-    Scalar omega211L1 = lambda[idx1][0] * (outerNormaln2 * K1nu1L1) * interactionVolume.getFaceArea(idx1, 0) / T1L1;
-    Scalar omega212L1 = lambda[idx1][0] * (outerNormaln2 * K1nu2L1) * interactionVolume.getFaceArea(idx1, 0) / T1L1;
-    Scalar omega123L1 = lambda[idx4][0] * (outerNormaln1L1 * K3nu3L1) * interactionVolume.getFaceArea(idx4, 0) / T2L1;
-    Scalar omega124L1 = lambda[idx4][0] * (outerNormaln1L1 * K3nu4L1) * interactionVolume.getFaceArea(idx4, 0) / T2L1;
-    Scalar omega235L1 = lambda[idx2][1] * (outerNormaln2 * K2nu5L1) * interactionVolume.getFaceArea(idx2, 1) / T3L1;
-    Scalar omega236L1 = lambda[idx2][1] * (outerNormaln2 * K2nu6L1) * interactionVolume.getFaceArea(idx2, 1) / T3L1;
-    Scalar chi711L1 = (nu7L1 * Rnu1L1) / T1L1;
-    Scalar chi712L1 = (nu7L1 * Rnu2L1) / T1L1;
-
-    // compute transmissibility matrix TL1 = CA^{-1}B+D
-    C = 0;
-    A = 0;
-    D = 0;
-    B = 0;
-
-    // evaluate matrix C, D, A, B
-    C[0][0] = -omega111L1;
-    C[0][1] = -omega112L1;
-    C[1][0] = -omega211L1;
-    C[1][1] = -omega212L1;
-
-    D[0][0] = omega111L1 + omega112L1;
-    D[1][0] = omega211L1 + omega212L1;
-
-    A[0][0] = omega111L1 - omega124L1 - omega123L1 * chi711L1;
-    A[0][1] = omega112L1 - omega123L1 * chi712L1;
-    A[1][0] = omega211L1 - omega236L1 * chi711L1;
-    A[1][1] = omega212L1 - omega235L1 - omega236L1 * chi712L1;
-
-    B[0][0] = omega111L1 + omega112L1 + omega123L1 * (1.0 - chi711L1 - chi712L1);
-    B[0][1] = -omega123L1 - omega124L1;
-    B[1][0] = omega211L1 + omega212L1 + omega236L1 * (1.0 - chi711L1 - chi712L1);
-    B[1][2] = -omega235L1 - omega236L1;
-
-    // compute TL1
-    A.invert();
-    D += B.leftmultiply(C.rightmultiply(A));
-    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> TL1(D);
-
-    //selection criterion
-    Scalar sR = std::abs(TR1[1][2] - TR1[1][0]);
-    Scalar sL = std::abs(TL1[1][0] - TL1[1][2]);
-
-    // 3.decide which triangle (which transmissibility coefficients) to use
-    if (sR <= sL)
-    {
-        transmissibility = TR1;
-        return rightTriangle;
-    }
-    else
-    {
-        transmissibility = TL1;
-        return leftTriangle;
-    }
-}
-
-/*! \brief Calculates tranmissibility matrix
- *
- * Calculates tranmissibility matrix of an L-shape for a certain flux face.
- * Calculates only the transmissibility of the left L-shape (needed at hanging nodes HN).
- *
- * \param transmissibilityLeft Matrix for the resulting transmissibility
- * \param interactionVolume The interaction volume object (includes geometric information)
- * \param lambda Mobilities of cells 1-3
- * \param idx1 Index of cell 1 of the L-stencil
- * \param idx2 Index of cell 2 of the L-stencil
- * \param idx3 Index of cell 3 of the L-stencil
- */
-template<class TypeTag>
-int FvMpfaL2dPressure2pAdaptive<TypeTag>::calculateLeftHNTransmissibility(
-        Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1>& transmissibilityLeft,
-        InteractionVolume& interactionVolume,
-        std::vector<DimVector >& lambda,
-        int idx1, int idx2, int idx3)
-{
-    ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(idx1);
-    ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(idx2);
-    ElementPointer& elementPointer3 = interactionVolume.getSubVolumeElement(idx3);
-
-    if (elementPointer1->level() != elementPointer3->level())
-    {
-        return noTransmissibility;
-    }
-
-    // get global coordinate of cell centers
-    const GlobalPosition& globalPos1 = elementPointer1->geometry().center();
-    const GlobalPosition& globalPos2 = elementPointer2->geometry().center();
-    const GlobalPosition& globalPos3 = elementPointer3->geometry().center();
-
-    const GlobalPosition& globalPosCenter = interactionVolume.getCenterPosition();
-
-    const DimMatrix& K1 = problem_.spatialParams().intrinsicPermeability(*elementPointer1);
-    const DimMatrix& K2 = problem_.spatialParams().intrinsicPermeability(*elementPointer2);
-    const DimMatrix& K3 = problem_.spatialParams().intrinsicPermeability(*elementPointer3);
-
-    const GlobalPosition& globalPosFace12 = interactionVolume.getFacePosition(idx1, 0);
-    DimVector &outerNormaln2 = interactionVolume.getNormal(idx1, 0);
-
-    // compute transmissibility matrix TR1 = CA^{-1}B+D
-    DimMatrix C(0), A(0);
-    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> D(0), B(0);
-
-    // 2.use triangle L to compute the transmissibility of half edge
-    const GlobalPosition& globalPosFace14 = interactionVolume.getFacePosition(idx1, 1);
-
-    // compute normal vectors nu1-nu7 in triangle L for first half edge
-    DimVector nu1L1(0);
-    R_.mv(globalPosFace12 - globalPos1, nu1L1);
-
-    DimVector nu2L1(0);
-    R_.mv(globalPos1 - globalPosFace14, nu2L1);
-
-    DimVector nu3L1(0);
-    R_.mv(globalPosFace14 - globalPos3, nu3L1);
-
-    DimVector nu4L1(0);
-    R_.mv(globalPos3 - globalPosCenter, nu4L1);
-
-    DimVector nu5L1(0);
-    R_.mv(globalPosCenter - globalPos2, nu5L1);
-
-    DimVector nu6L1(0);
-    R_.mv(globalPos2 - globalPosFace12, nu6L1);
-
-    DimVector nu7L1(0);
-    R_.mv(globalPosCenter - globalPos1, nu7L1);
-
-    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
-    DimVector Rnu2L1(0);
-    R_.mv(nu2L1, Rnu2L1);
-    Scalar T1L1 = nu1L1 * Rnu2L1;
-
-    DimVector Rnu4L1(0);
-    R_.mv(nu4L1, Rnu4L1);
-    Scalar T2L1 = nu3L1 * Rnu4L1;
-
-    DimVector Rnu6L1(0);
-    R_.mv(nu6L1, Rnu6L1);
-    Scalar T3L1 = nu5L1 * Rnu6L1;
-
-    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
-    DimVector K1nu1L1(0);
-    K1.mv(nu1L1, K1nu1L1);
-    DimVector K1nu2L1(0);
-    K1.mv(nu2L1, K1nu2L1);
-    DimVector K3nu3L1(0);
-    K3.mv(nu3L1, K3nu3L1);
-    DimVector K3nu4L1(0);
-    K3.mv(nu4L1, K3nu4L1);
-    DimVector K2nu5L1(0);
-    K2.mv(nu5L1, K2nu5L1);
-    DimVector K2nu6L1(0);
-    K2.mv(nu6L1, K2nu6L1);
-
-    DimVector Rnu1L1(0);
-    R_.mv(nu1L1, Rnu1L1);
-
-    DimVector &outerNormaln1L1 = interactionVolume.getNormal(idx1, 1);
-
-    Scalar omega111L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu1L1) * interactionVolume.getFaceArea(idx1, 1) / T1L1;
-    Scalar omega112L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu2L1) * interactionVolume.getFaceArea(idx1, 1) / T1L1;
-    Scalar omega211L1 = lambda[idx1][0] * (outerNormaln2 * K1nu1L1) * interactionVolume.getFaceArea(idx1, 0) / T1L1;
-    Scalar omega212L1 = lambda[idx1][0] * (outerNormaln2 * K1nu2L1) * interactionVolume.getFaceArea(idx1, 0) / T1L1;
-    Scalar omega123L1 = lambda[idx3][0] * (outerNormaln1L1 * K3nu3L1) * interactionVolume.getFaceArea(idx3, 0) / T2L1;
-    Scalar omega124L1 = lambda[idx3][0] * (outerNormaln1L1 * K3nu4L1) * interactionVolume.getFaceArea(idx3, 0) / T2L1;
-    Scalar omega235L1 = lambda[idx2][1] * (outerNormaln2 * K2nu5L1) * interactionVolume.getFaceArea(idx2, 1) / T3L1;
-    Scalar omega236L1 = lambda[idx2][1] * (outerNormaln2 * K2nu6L1) * interactionVolume.getFaceArea(idx2, 1) / T3L1;
-    Scalar chi711L1 = (nu7L1 * Rnu1L1) / T1L1;
-    Scalar chi712L1 = (nu7L1 * Rnu2L1) / T1L1;
-
-    // compute transmissibility matrix TL1 = CA^{-1}B+D
-    C = 0;
-    A = 0;
-    D = 0;
-    B = 0;
-
-    // evaluate matrix C, D, A, B
-    C[0][0] = -omega111L1;
-    C[0][1] = -omega112L1;
-    C[1][0] = -omega211L1;
-    C[1][1] = -omega212L1;
-
-    D[0][0] = omega111L1 + omega112L1;
-    D[1][0] = omega211L1 + omega212L1;
-
-    A[0][0] = omega111L1 - omega124L1 - omega123L1 * chi711L1;
-    A[0][1] = omega112L1 - omega123L1 * chi712L1;
-    A[1][0] = omega211L1 - omega236L1 * chi711L1;
-    A[1][1] = omega212L1 - omega235L1 - omega236L1 * chi712L1;
-
-    B[0][0] = omega111L1 + omega112L1 + omega123L1 * (1.0 - chi711L1 - chi712L1);
-    B[0][1] = -omega123L1 - omega124L1;
-    B[1][0] = omega211L1 + omega212L1 + omega236L1 * (1.0 - chi711L1 - chi712L1);
-    B[1][2] = -omega235L1 - omega236L1;
-
-    // compute TL1
-    A.invert();
-    D += B.leftmultiply(C.rightmultiply(A));
-    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> TL1(D);
-
-    // 3.decide which triangle (which transmissibility coefficients) to use
-    transmissibilityLeft = TL1;
-    return leftTriangle;
-}
-
-/*! \brief Calculates tranmissibility matrix
- *
- * Calculates tranmissibility matrix of an L-shape for a certain flux face.
- * Calculates only the transmissibility of the right L-shape (needed at hanging nodes HN).
- *
- * \param transmissibilityRight Matrix for the resulting transmissibility
- * \param interactionVolume The interaction volume object (includes geometric information)
- * \param lambda Mobilities of cells 1-3
- * \param idx1 Index of cell 1 of the L-stencil
- * \param idx2 Index of cell 2 of the L-stencil
- * \param idx3 Index of cell 3 of the L-stencil
- */
-template<class TypeTag>
-int FvMpfaL2dPressure2pAdaptive<TypeTag>::calculateRightHNTransmissibility(
-        Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1>& transmissibilityRight,
-        InteractionVolume& interactionVolume,
-        std::vector<DimVector >& lambda,
-        int idx1, int idx2, int idx3)
-{
-    ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(idx1);
-    ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(idx2);
-    ElementPointer& elementPointer3 = interactionVolume.getSubVolumeElement(idx3);
-
-    if (elementPointer2->level() != elementPointer3->level())
-    {
-        return noTransmissibility;
-    }
-
-    // get global coordinate of cell centers
-    const GlobalPosition& globalPos1 = elementPointer1->geometry().center();
-    const GlobalPosition& globalPos2 = elementPointer2->geometry().center();
-    const GlobalPosition& globalPos3 = elementPointer3->geometry().center();
-
-    const GlobalPosition& globalPosCenter = interactionVolume.getCenterPosition();
-
-    const DimMatrix& K1 = problem_.spatialParams().intrinsicPermeability(*elementPointer1);
-    const DimMatrix& K2 = problem_.spatialParams().intrinsicPermeability(*elementPointer2);
-    const DimMatrix& K3 = problem_.spatialParams().intrinsicPermeability(*elementPointer3);
-
-    const GlobalPosition& globalPosFace12 = interactionVolume.getFacePosition(idx1, 0);
-    const GlobalPosition& globalPosFace23 = interactionVolume.getFacePosition(idx2, 0);
-
-    // compute normal vectors nu1-nu7 in triangle R for first half edge
-    DimVector nu1R1(0);
-    R_.mv(globalPosFace12 - globalPos2, nu1R1);
-
-    DimVector nu2R1(0);
-    R_.mv(globalPos2 - globalPosFace23, nu2R1);
-
-    DimVector nu3R1(0);
-    R_.mv(globalPosFace23 - globalPos3, nu3R1);
-
-    DimVector nu4R1(0);
-    R_.mv(globalPos3 - globalPosCenter, nu4R1);
-
-    DimVector nu5R1(0);
-    R_.mv(globalPosCenter - globalPos1, nu5R1);
-
-    DimVector nu6R1(0);
-    R_.mv(globalPos1 - globalPosFace12, nu6R1);
-
-    DimVector nu7R1(0);
-    R_.mv(globalPosCenter - globalPos2, nu7R1);
-
-    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
-    DimVector Rnu2R1(0);
-    R_.mv(nu2R1, Rnu2R1);
-    Scalar T1R1 = nu1R1 * Rnu2R1;
-
-    DimVector Rnu4R1(0);
-    R_.mv(nu4R1, Rnu4R1);
-    Scalar T2R1 = nu3R1 * Rnu4R1;
-
-    DimVector Rnu6R1(0);
-    R_.mv(nu6R1, Rnu6R1);
-    Scalar T3R1 = nu5R1 * Rnu6R1;
-
-    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
-    DimVector K2nu1R1(0);
-    K2.mv(nu1R1, K2nu1R1);
-    DimVector K2nu2R1(0);
-    K2.mv(nu2R1, K2nu2R1);
-    DimVector K3nu3R1(0);
-    K3.mv(nu3R1, K3nu3R1);
-    DimVector K3nu4R1(0);
-    K3.mv(nu4R1, K3nu4R1);
-    DimVector K1nu5R1(0);
-    K1.mv(nu5R1, K1nu5R1);
-    DimVector K1nu6R1(0);
-    K1.mv(nu6R1, K1nu6R1);
-
-    DimVector Rnu1R1(0);
-    R_.mv(nu1R1, Rnu1R1);
-
-    DimVector &outerNormaln1R1 = interactionVolume.getNormal(idx2, 0);
-    DimVector &outerNormaln2 = interactionVolume.getNormal(idx1, 0);
-
-    Scalar omega111R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 0) / T1R1;
-    Scalar omega112R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 0) / T1R1;
-    Scalar omega211R1 = lambda[idx2][1] * (outerNormaln2 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 1) / T1R1;
-    Scalar omega212R1 = lambda[idx2][1] * (outerNormaln2 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 1) / T1R1;
-    Scalar omega123R1 = lambda[idx3][1] * (outerNormaln1R1 * K3nu3R1) * interactionVolume.getFaceArea(idx3, 1) / T2R1;
-    Scalar omega124R1 = lambda[idx3][1] * (outerNormaln1R1 * K3nu4R1) * interactionVolume.getFaceArea(idx3, 1) / T2R1;
-    Scalar omega235R1 = lambda[idx1][0] * (outerNormaln2 * K1nu5R1) * interactionVolume.getFaceArea(idx1, 0) / T3R1;
-    Scalar omega236R1 = lambda[idx1][0] * (outerNormaln2 * K1nu6R1) * interactionVolume.getFaceArea(idx1, 0) / T3R1;
-    Scalar chi711R1 = (nu7R1 * Rnu1R1) / T1R1;
-    Scalar chi712R1 = (nu7R1 * Rnu2R1) / T1R1;
-
-    // compute transmissibility matrix TR1 = CA^{-1}B+D
-    DimMatrix C(0), A(0);
-    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> D(0), B(0);
-
-    // evaluate matrix C, D, A, B
-    C[0][0] = -omega111R1;
-    C[0][1] = -omega112R1;
-    C[1][0] = -omega211R1;
-    C[1][1] = -omega212R1;
-
-    D[0][0] = omega111R1 + omega112R1;
-    D[1][0] = omega211R1 + omega212R1;
-
-    A[0][0] = omega111R1 - omega124R1 - omega123R1 * chi711R1;
-    A[0][1] = omega112R1 - omega123R1 * chi712R1;
-    A[1][0] = omega211R1 - omega236R1 * chi711R1;
-    A[1][1] = omega212R1 - omega235R1 - omega236R1 * chi712R1;
-
-    B[0][0] = omega111R1 + omega112R1 + omega123R1 * (1.0 - chi711R1 - chi712R1);
-    B[0][1] = -omega123R1 - omega124R1;
-    B[1][0] = omega211R1 + omega212R1 + omega236R1 * (1.0 - chi711R1 - chi712R1);
-    B[1][2] = -omega235R1 - omega236R1;
-
-    // compute TR1
-    A.invert();
-    D += B.leftmultiply(C.rightmultiply(A));
-    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> TR1(D);
-
-    transmissibilityRight = TR1;
-    return rightTriangle;
-}
-
 /*! \brief Updates constitutive relations and stores them in the variable class
  *
  * Stores mobility, fractional flow function and capillary pressure for all grid cells.
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressureproperties2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressureproperties2p.hh
index fb9bf8de72a529472bb482054fa01db704c68b92..6e9979377cd07bb92f577c14451a327834cecf56 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressureproperties2p.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressureproperties2p.hh
@@ -40,12 +40,15 @@ NEW_TYPE_TAG(FvMpfaL2dPressureTwoP, INHERITS_FROM(PressureTwoP, MPFAProperties))
 }
 
 #include "fvmpfal2dpressurevelocity2p.hh"
+#include <dumux/decoupled/common/fv/mpfa/fvmpfavelocityintransport.hh>
 
 namespace Dumux
 {
 namespace Properties
 {
 SET_TYPE_PROP(FvMpfaL2dPressureTwoP, PressureModel, Dumux::FvMpfaL2dPressureVelocity2p<TypeTag>);
+//! Set velocity reconstruction implementation standard cell centered finite volume schemes as default
+SET_TYPE_PROP( FvMpfaL2dPressureTwoP, Velocity, Dumux::FvMpfaVelocityInTransport<TypeTag> );
 }
 }// end of Dune namespace
 #endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressureproperties2padaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressureproperties2padaptive.hh
index 3e676f24604729a3f3e9e0a83764e7cb37b910d9..f3929f0379ca11a55c5c683afcb870ebeca842b5 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressureproperties2padaptive.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressureproperties2padaptive.hh
@@ -40,12 +40,15 @@ NEW_TYPE_TAG(FvMpfaL2dPressureTwoPAdaptive, INHERITS_FROM(PressureTwoP, MPFAProp
 }
 
 #include "fvmpfal2dpressurevelocity2padaptive.hh"
+#include <dumux/decoupled/common/fv/mpfa/fvmpfavelocityintransport.hh>
 
 namespace Dumux
 {
 namespace Properties
 {
 SET_TYPE_PROP(FvMpfaL2dPressureTwoPAdaptive, PressureModel, Dumux::FvMpfaL2dPressureVelocity2pAdaptive<TypeTag>);
+//! Set velocity reconstruction implementation standard cell centered finite volume schemes as default
+SET_TYPE_PROP( FvMpfaL2dPressureTwoPAdaptive, Velocity, Dumux::FvMpfaVelocityInTransport<TypeTag> );
 }
 }// end of Dune namespace
 #endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressurevelocity2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressurevelocity2p.hh
index 5d944a059c9d710e5107ef0a632c0075da405812..66522762147bc4fea68081147c522ca498a6468f 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressurevelocity2p.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressurevelocity2p.hh
@@ -19,6 +19,7 @@
 #define DUMUX_MPFAL2DPRESSUREVELOCITY2P_HH
 
 #include "fvmpfal2dpressure2p.hh"
+#include "fvmpfal2dvelocity2p.hh"
 
 /**
  * @file
@@ -61,6 +62,10 @@ template<class TypeTag> class FvMpfaL2dPressureVelocity2p: public FvMpfaL2dPress
 
     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
     typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes;
+    typedef typename SolutionTypes::PrimaryVariables PrimaryVariables;
 
 #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
     typedef typename Dune::ReferenceElements<Scalar, dim> ReferenceElements;
@@ -78,23 +83,12 @@ template<class TypeTag> class FvMpfaL2dPressureVelocity2p: public FvMpfaL2dPress
     typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
     typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
 
-    typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes;
-    typedef typename SolutionTypes::PrimaryVariables PrimaryVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData;
-
-    typedef typename GridView::Grid Grid;
     typedef typename GridView::IndexSet IndexSet;
     typedef typename GridView::template Codim<0>::Iterator ElementIterator;
     typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
     typedef typename GridView::IntersectionIterator IntersectionIterator;
-    typedef typename Grid::template Codim<0>::EntityPointer ElementPointer;
-
-    typedef typename Grid::template Codim<0>::Entity::Geometry Geometry;
-    #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
-        typedef typename Geometry::JacobianTransposed JacobianTransposed;
-    #else
-        typedef typename Geometry::Jacobian JacobianTransposed;
-    #endif
+    typedef typename GridView::template Codim<0>::EntityPointer ElementPointer;
+    typedef typename GridView::Intersection Intersection;
 
     typedef typename ParentType::InteractionVolume InteractionVolume;
 
@@ -103,10 +97,7 @@ template<class TypeTag> class FvMpfaL2dPressureVelocity2p: public FvMpfaL2dPress
         pw = Indices::pressureW,
         pn = Indices::pressureNw,
         sw = Indices::saturationW,
-        sn = Indices::saturationNw
-    };
-    enum
-    {
+        sn = Indices::saturationNw,
         wPhaseIdx = Indices::wPhaseIdx,
         nPhaseIdx = Indices::nPhaseIdx,
         pressureIdx = Indices::pressureIdx,
@@ -116,20 +107,8 @@ template<class TypeTag> class FvMpfaL2dPressureVelocity2p: public FvMpfaL2dPress
         numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
     };
 
-    enum
-    {
-        globalCorner = 2,
-        globalEdge = 3,
-        neumannNeumann = 0,
-        dirichletDirichlet = 1,
-        dirichletNeumann = 2,
-        neumannDirichlet = 3
-    };
-
-    typedef Dune::FieldVector<Scalar, dim> LocalPosition;
     typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
     typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
-    typedef Dune::FieldVector<Scalar, dim> DimVector;
 
 public:
     //! Constructs a FvMpfaL2dPressureVelocity2p object
@@ -137,32 +116,31 @@ public:
      * \param problem A problem class object
      */
     FvMpfaL2dPressureVelocity2p(Problem& problem) :
-            ParentType(problem), problem_(problem), gravity_(problem.gravity())
+            ParentType(problem), problem_(problem), velocity_(problem)
     {
         density_[wPhaseIdx] = 0.;
         density_[nPhaseIdx] = 0.;
         viscosity_[wPhaseIdx] = 0.;
         viscosity_[nPhaseIdx] = 0.;
 
-        vtkOutputLevel_ = GET_PARAM_FROM_GROUP(TypeTag, int, Vtk, OutputLevel);
+        calcVelocityInTransport_ = GET_PARAM_FROM_GROUP(TypeTag, bool, MPFA, CalcVelocityInTransport);
     }
 
     //Calculates the velocities at all cell-cell interfaces.
     void calculateVelocity();
 
+    // Calculates the velocity at a cell-cell interface.
+    void calculateVelocity(const Intersection&, CellData&);
+    void calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData);
+
     void updateVelocity()
     {
         this->updateMaterialLaws();
 
-        //reset velocities
-        int size = problem_.gridView().size(0);
-        for (int i = 0; i < size; i++)
-        {
-            CellData& cellData = problem_.variables().cellData(i);
-            cellData.fluxData().resetVelocity();
-        }
+        this->storePressureSolution();
 
-        calculateVelocity();
+        if (!calculateVelocityInTransport())
+            calculateVelocity();
     }
 
     /*! \brief Initializes pressure and velocity
@@ -171,8 +149,6 @@ public:
      */
     void initialize()
     {
-        ParentType::initialize();
-
         ElementIterator element = problem_.gridView().template begin<0>();
         FluidState fluidState;
         fluidState.setPressure(wPhaseIdx, problem_.referencePressure(*element));
@@ -185,7 +161,10 @@ public:
         viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
         viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
 
-        calculateVelocity();
+        ParentType::initialize();
+        velocity_.initialize();
+        if (!calculateVelocityInTransport())
+            calculateVelocity();
 
         return;
     }
@@ -198,10 +177,17 @@ public:
     void update()
     {
         ParentType::update();
+        if (!calculateVelocityInTransport())
+            calculateVelocity();
+    }
 
-        calculateVelocity();
-
-        return;
+    /*! \brief Indicates if velocity is reconstructed in the pressure step or in the transport step
+     *
+     * Returns true (In the standard finite volume discretization the velocity is calculated during the saturation transport.)
+     */
+    bool calculateVelocityInTransport()
+    {
+        return calcVelocityInTransport_;
     }
 
     /*! \brief Adds velocity output to the output file
@@ -218,86 +204,17 @@ public:
     void addOutputVtkFields(MultiWriter &writer)
     {
         ParentType::addOutputVtkFields(writer);
-
-        if (vtkOutputLevel_ > 0)
-        {
-            Dune::BlockVector < DimVector > &velocityWetting = *(writer.template allocateManagedBuffer<
-                    Scalar, dim>(problem_.gridView().size(0)));
-            Dune::BlockVector < DimVector > &velocityNonwetting =
-            *(writer.template allocateManagedBuffer<Scalar, dim>(problem_.gridView().size(0)));
-
-            // compute update vector
-            ElementIterator eEndIt = problem_.gridView().template end<0>();
-            for (ElementIterator eIt = problem_.gridView().template begin<0>(); eIt != eEndIt; ++eIt)
-            {
-                // cell index
-                int globalIdx = problem_.variables().index(*eIt);
-
-                CellData& cellData = problem_.variables().cellData(globalIdx);
-
-                Dune::FieldVector < Scalar, 2 * dim > fluxW(0);
-                Dune::FieldVector < Scalar, 2 * dim > fluxNw(0);
-                // run through all intersections with neighbors and boundary
-                IntersectionIterator isEndIt = problem_.gridView().iend(*eIt);
-                for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isEndIt; ++isIt)
-                {
-                    int isIndex = isIt->indexInInside();
-
-                    fluxW[isIndex] = isIt->geometry().volume()
-                    * (isIt->centerUnitOuterNormal() * cellData.fluxData().velocity(wPhaseIdx, isIndex));
-                    fluxNw[isIndex] =
-                    isIt->geometry().volume()
-                    * (isIt->centerUnitOuterNormal()
-                            * cellData.fluxData().velocity(nPhaseIdx, isIndex));
-                }
-
-                DimVector refVelocity(0);
-                for (int i = 0; i < dim; i++)
-                refVelocity[i] = 0.5 * (fluxW[2*i + 1] - fluxW[2*i]);
-
-                const DimVector localPos =
-                ReferenceElements::general(eIt->geometry().type()).position(0, 0);
-
-                // get the transposed Jacobian of the element mapping
-                const JacobianTransposed jacobianT = eIt->geometry().jacobianTransposed(localPos);
-
-                // calculate the element velocity by the Piola transformation
-                DimVector elementVelocity(0);
-                jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
-
-                velocityWetting[globalIdx] = elementVelocity;
-
-                refVelocity = 0;
-                for (int i = 0; i < dim; i++)
-                refVelocity[i] = 0.5 * (fluxNw[2*i + 1] - fluxNw[2*i]);
-
-                // calculate the element velocity by the Piola transformation
-                elementVelocity = 0;
-                jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
-
-                velocityNonwetting[globalIdx] = elementVelocity;
-            }
-
-            writer.attachCellData(velocityWetting, "wetting-velocity", dim);
-            writer.attachCellData(velocityNonwetting, "non-wetting-velocity", dim);
-
-        }
-        return;
+        velocity_.addOutputVtkFields(writer);
     }
 
 private:
     Problem& problem_;
-    const GlobalPosition& gravity_; //!< vector including the gravity constant
+    FvMpfaL2dVelocity2p<TypeTag> velocity_;
 
     Scalar density_[numPhases];
     Scalar viscosity_[numPhases];
+    bool calcVelocityInTransport_;
 
-    int vtkOutputLevel_;
-
-    static constexpr Scalar threshold_ = 1e-15;
-    static const int velocityType_ = GET_PROP_VALUE(TypeTag, VelocityFormulation); //!< gives kind of velocity used (\f$ 0 = v_w\f$, \f$ 1 = v_n\f$, \f$ 2 = v_t\f$)
     static const int pressureType_ = GET_PROP_VALUE(TypeTag, PressureFormulation); //!< gives kind of pressure used (\f$ 0 = p_w\f$, \f$ 1 = p_n\f$, \f$ 2 = p_{global}\f$)
     static const int saturationType_ = GET_PROP_VALUE(TypeTag, SaturationFormulation); //!< gives kind of saturation used (\f$ 0 = S_w\f$, \f$ 1 = S_n\f$)
 };
@@ -338,604 +255,305 @@ void FvMpfaL2dPressureVelocity2p<TypeTag>::calculateVelocity()
             CellData& cellData3 = problem_.variables().cellData(globalIdx3);
             CellData& cellData4 = problem_.variables().cellData(globalIdx4);
 
-            // get pressure values
-            Dune::FieldVector < Scalar, 2 * dim > potW(0);
-            Dune::FieldVector < Scalar, 2 * dim > potNw(0);
+            velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume, cellData1, cellData2, cellData3, cellData4, this->innerBoundaryVolumeFaces_);
 
-            potW[0] = cellData1.potential(wPhaseIdx);
-            potW[1] = cellData2.potential(wPhaseIdx);
-            potW[2] = cellData3.potential(wPhaseIdx);
-            potW[3] = cellData4.potential(wPhaseIdx);
+        }
+        // at least one face on boundary!
+        else
+        {
+            for (int elemIdx = 0; elemIdx < 2 * dim; elemIdx++)
+            {
+                bool isOutside = false;
+                for (int faceIdx = 0; faceIdx < dim; faceIdx++)
+                {
+                    int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
+                    if (interactionVolume.isOutsideFace(intVolFaceIdx))
+                    {
+                        isOutside = true;
+                        break;
+                    }
+                }
+                if (isOutside)
+                {
+                    continue;
+                }
+                ElementPointer & elementPointer = interactionVolume.getSubVolumeElement(elemIdx);
 
-            potNw[0] = cellData1.potential(nPhaseIdx);
-            potNw[1] = cellData2.potential(nPhaseIdx);
-            potNw[2] = cellData3.potential(nPhaseIdx);
-            potNw[3] = cellData4.potential(nPhaseIdx);
+                // cell index
+                int globalIdx = problem_.variables().index(*elementPointer);
+                //get the cell Data
+                CellData& cellData = problem_.variables().cellData(globalIdx);
 
-            //get mobilities of the phases
-            Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
-            lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
+                velocity_.calculateBoundaryInteractionVolumeVelocity(interactionVolume, cellData, elemIdx);
+            }
 
-            //compute total mobility of cell 1
-            Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
+        } // end boundaries
 
-            //get mobilities of the phases
-            Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
-            lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
+    } // end vertex iterator
 
-            //compute total mobility of cell 1
-            Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
+//    }
+    return;
+} // end method calcTotalVelocity
 
-            //get mobilities of the phases
-            Dune::FieldVector<Scalar, numPhases> lambda3(cellData3.mobility(wPhaseIdx));
-            lambda3[nPhaseIdx] = cellData3.mobility(nPhaseIdx);
 
-            //compute total mobility of cell 1
-            Scalar lambdaTotal3 = lambda3[wPhaseIdx] + lambda3[nPhaseIdx];
+template<class TypeTag>
+void FvMpfaL2dPressureVelocity2p<TypeTag>::calculateVelocity(const Intersection& intersection, CellData& cellData)
+{
+    int numVertices = intersection.geometry().corners();
 
-            //get mobilities of the phases
-            Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
-            lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
+    ElementPointer elementPtrI = intersection.inside();
+    ElementPointer elementPtrJ = intersection.outside();
 
-            //compute total mobility of cell 1
-            Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
+    int globalIdxI = problem_.variables().index(*elementPtrI);
+    int globalIdxJ = problem_.variables().index(*elementPtrJ);
 
-            std::vector < DimVector > lambda(2 * dim);
+    CellData& cellDataJ = problem_.variables().cellData(globalIdxJ);
 
-            lambda[0][0] = lambdaTotal1;
-            lambda[0][1] = lambdaTotal1;
-            lambda[1][0] = lambdaTotal2;
-            lambda[1][1] = lambdaTotal2;
-            lambda[2][0] = lambdaTotal3;
-            lambda[2][1] = lambdaTotal3;
-            lambda[3][0] = lambdaTotal4;
-            lambda[3][1] = lambdaTotal4;
+    const ReferenceElement& referenceElement = ReferenceElements::general(elementPtrI->geometry().type());
 
-            Scalar potentialDiffW12 = 0;
-            Scalar potentialDiffW14 = 0;
-            Scalar potentialDiffW32 = 0;
-            Scalar potentialDiffW34 = 0;
+    int indexInInside = intersection.indexInInside();
+    int indexInOutside = intersection.indexInOutside();
 
-            Scalar potentialDiffNw12 = 0;
-            Scalar potentialDiffNw14 = 0;
-            Scalar potentialDiffNw32 = 0;
-            Scalar potentialDiffNw34 = 0;
+    Dune::FieldVector<CellData, 4> cellDataTemp;
 
-            //flux vector
-            Dune::FieldVector < Scalar, 2 * dim > fluxW(0);
-            Dune::FieldVector < Scalar, 2 * dim > fluxNw(0);
+    for (int vIdx = 0; vIdx < numVertices; vIdx++)
+    {
+        int localVertIdx = referenceElement.subEntity(indexInInside, dim - 1, vIdx, dim);
 
-            Dune::FieldMatrix < Scalar, dim, 2 * dim - dim + 1 > T(0);
-            DimVector Tu(0);
-            Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
+        int globalVertIdx = problem_.variables().index(
+                *((*elementPtrI).template subEntity < dim > (localVertIdx)));
 
-            bool rightTriangle = this->calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
+        InteractionVolume& interactionVolume = this->interactionVolumes_[globalVertIdx];
 
-            if (rightTriangle)
-            {
-                u[0] = potW[1];
-                u[1] = potW[2];
-                u[2] = potW[0];
+        if (interactionVolume.isInnerVolume())
+        {
 
-                T.mv(u, Tu);
+        ElementPointer & elementPointer1 = interactionVolume.getSubVolumeElement(0);
+        ElementPointer & elementPointer2 = interactionVolume.getSubVolumeElement(1);
+        ElementPointer & elementPointer3 = interactionVolume.getSubVolumeElement(2);
+        ElementPointer & elementPointer4 = interactionVolume.getSubVolumeElement(3);
 
-                fluxW[0] = Tu[1];
-                potentialDiffW12 = Tu[1];
+        // cell index
+        int globalIdx[4];
+        globalIdx[0] = problem_.variables().index(*elementPointer1);
+        globalIdx[1] = problem_.variables().index(*elementPointer2);
+        globalIdx[2] = problem_.variables().index(*elementPointer3);
+        globalIdx[3] = problem_.variables().index(*elementPointer4);
 
-                u[0] = potNw[1];
-                u[1] = potNw[2];
-                u[2] = potNw[0];
+        //get the cell Data
+        cellDataTemp[0] = problem_.variables().cellData(globalIdx[0]);
+        cellDataTemp[1] = problem_.variables().cellData(globalIdx[1]);
+        cellDataTemp[2] = problem_.variables().cellData(globalIdx[2]);
+        cellDataTemp[3] = problem_.variables().cellData(globalIdx[3]);
 
-                T.mv(u, Tu);
+        velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume, cellDataTemp[0], cellDataTemp[1], cellDataTemp[2], cellDataTemp[3], this->innerBoundaryVolumeFaces_);
 
-                fluxNw[0] = Tu[1];
-                potentialDiffNw12 = Tu[1];
-            }
-            else
+        for (int i = 0; i < 4; i++)
+        {
+            if (globalIdx[i] == globalIdxI)
             {
-                u[0] = potW[0];
-                u[1] = potW[3];
-                u[2] = potW[1];
-
-                T.mv(u, Tu);
-
-                fluxW[0] = Tu[1];
-                potentialDiffW12 = Tu[1];
-
-                u[0] = potNw[0];
-                u[1] = potNw[3];
-                u[2] = potNw[1];
-
-                T.mv(u, Tu);
-
-                fluxNw[0] = Tu[1];
-                potentialDiffNw12 = Tu[1];
+                 cellData.fluxData().setVelocity(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInInside));
+                 cellData.fluxData().setVelocity(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInInside));
+                 cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInInside));
+                 cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInInside));
             }
-
-            rightTriangle = this->calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
-
-            if (rightTriangle)
+            else if (globalIdx[i] == globalIdxJ)
             {
-                u[0] = potW[2];
-                u[1] = potW[3];
-                u[2] = potW[1];
-
-                T.mv(u, Tu);
-
-                fluxW[1] = Tu[1];
-                potentialDiffW32 = -Tu[1];
-
-                u[0] = potNw[2];
-                u[1] = potNw[3];
-                u[2] = potNw[1];
-
-                T.mv(u, Tu);
-
-                fluxNw[1] = Tu[1];
-                potentialDiffNw32 = -Tu[1];
+                cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInOutside));
             }
-            else
-            {
-                u[0] = potW[1];
-                u[1] = potW[0];
-                u[2] = potW[2];
-
-                T.mv(u, Tu);
-
-                fluxW[1] = Tu[1];
-                potentialDiffW32 = -Tu[1];
+        }
+    }
+    }
+    cellData.fluxData().setVelocityMarker(indexInInside);
+    cellDataJ.fluxData().setVelocityMarker(indexInOutside);
+}
 
-                u[0] = potNw[1];
-                u[1] = potNw[0];
-                u[2] = potNw[2];
+template<class TypeTag>
+void FvMpfaL2dPressureVelocity2p<TypeTag>::calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData)
+{
+    ElementPointer element = intersection.inside();
 
-                T.mv(u, Tu);
+    //get face index
+    int isIndex = intersection.indexInInside();
 
-                fluxNw[1] = Tu[1];
-                potentialDiffNw32 = -Tu[1];
-            }
+    //get face normal
+    const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
 
-            rightTriangle = this->calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
+    BoundaryTypes bcType;
+    //get boundary type
+    problem_.boundaryTypes(bcType, intersection);
+    PrimaryVariables boundValues(0.0);
 
-            if (rightTriangle)
-            {
-                u[0] = potW[3];
-                u[1] = potW[0];
-                u[2] = potW[2];
+    if (bcType.isDirichlet(pressEqIdx))
+    {
+        problem_.dirichlet(boundValues, intersection);
 
-                T.mv(u, Tu);
+        // get global coordinates of cell centers
+        const GlobalPosition& globalPosI = element->geometry().center();
 
-                fluxW[2] = Tu[1];
-                potentialDiffW34 = Tu[1];
+        // center of face in global coordinates
+        const GlobalPosition& globalPosJ = intersection.geometry().center();
 
-                u[0] = potNw[3];
-                u[1] = potNw[0];
-                u[2] = potNw[2];
+        // get mobilities and fractional flow factors
+        Scalar lambdaWI = cellData.mobility(wPhaseIdx);
+        Scalar lambdaNwI = cellData.mobility(nPhaseIdx);
 
-                T.mv(u, Tu);
+        // get capillary pressure
+        Scalar pcI = cellData.capillaryPressure();
 
-                fluxNw[2] = Tu[1];
-                potentialDiffNw34 = Tu[1];
-            }
-            else
-            {
-                u[0] = potW[2];
-                u[1] = potW[1];
-                u[2] = potW[3];
+        // distance vector between barycenters
+        GlobalPosition distVec = globalPosJ - globalPosI;
 
-                T.mv(u, Tu);
+        // compute distance between cell centers
+        Scalar dist = distVec.two_norm();
 
-                fluxW[2] = Tu[1];
-                potentialDiffW34 = Tu[1];
+        //permeability vector at boundary
+        // compute vectorized permeabilities
+        DimMatrix meanPermeability(0);
 
-                u[0] = potNw[2];
-                u[1] = potNw[1];
-                u[2] = potNw[3];
+        problem_.spatialParams().meanK(meanPermeability, problem_.spatialParams().intrinsicPermeability(*element));
 
-                T.mv(u, Tu);
+        Dune::FieldVector<Scalar, dim> permeability(0);
+        meanPermeability.mv(unitOuterNormal, permeability);
 
-                fluxNw[2] = Tu[1];
-                potentialDiffNw34 = Tu[1];
+        //determine saturation at the boundary -> if no saturation is known directly at the boundary use the cell saturation
+        Scalar satW = 0;
+        Scalar satNw = 0;
+        if (bcType.isDirichlet(satEqIdx))
+        {
+            switch (saturationType_)
+            {
+            case sw:
+            {
+                satW = boundValues[saturationIdx];
+                satNw = 1 - boundValues[saturationIdx];
+                break;
             }
-
-            rightTriangle = this->calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
-
-            if (rightTriangle)
+            case sn:
             {
-                u[0] = potW[0];
-                u[1] = potW[1];
-                u[2] = potW[3];
+                satW = 1 - boundValues[saturationIdx];
+                satNw = boundValues[saturationIdx];
+                break;
+            }
+            }
+        }
+        else
+        {
+            satW = cellData.saturation(wPhaseIdx);
+            satNw = cellData.saturation(nPhaseIdx);
+        }
 
-                T.mv(u, Tu);
+        Scalar pressBound = boundValues[pressureIdx];
+        Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(*element), satW);
 
-                fluxW[3] = Tu[1];
-                potentialDiffW14 = -Tu[1];
+        //determine phase pressures from primary pressure variable
+        Scalar pressWBound = 0;
+        Scalar pressNwBound = 0;
+        if (pressureType_ == pw)
+        {
+            pressWBound = pressBound;
+            pressNwBound = pressBound + pcBound;
+        }
+        else if (pressureType_ == pn)
+        {
+            pressWBound = pressBound - pcBound;
+            pressNwBound = pressBound;
+        }
 
-                u[0] = potNw[0];
-                u[1] = potNw[1];
-                u[2] = potNw[3];
+        Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(*element), satW)
+                / viscosity_[wPhaseIdx];
+        Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(*element), satW)
+                / viscosity_[nPhaseIdx];
 
-                T.mv(u, Tu);
+        Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex);
+        Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex);
 
-                fluxNw[3] = Tu[1];
-                potentialDiffNw14 = -Tu[1];
-            }
-            else
-            {
-                u[0] = potW[3];
-                u[1] = potW[2];
-                u[2] = potW[0];
+        //calculate potential gradient
+        potentialDiffW = (cellData.pressure(wPhaseIdx) - pressWBound);
+        potentialDiffNw = (cellData.pressure(nPhaseIdx) - pressNwBound);
 
-                T.mv(u, Tu);
+        potentialDiffW += density_[wPhaseIdx] * (distVec * problem_.gravity());
+        potentialDiffNw += density_[nPhaseIdx] * (distVec * problem_.gravity());
 
-                fluxW[3] = Tu[1];
-                potentialDiffW14 = -Tu[1];
+        //store potential gradients for further calculations
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, potentialDiffW);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, potentialDiffNw);
 
-                u[0] = potNw[3];
-                u[1] = potNw[2];
-                u[2] = potNw[0];
+        //do the upwinding of the mobility depending on the phase potentials
+        Scalar lambdaW = (potentialDiffW > 0.) ? lambdaWI : lambdaWBound;
+        lambdaW = (potentialDiffW == 0) ? 0.5 * (lambdaWI + lambdaWBound) : lambdaW;
+        Scalar lambdaNw = (potentialDiffNw > 0.) ? lambdaNwI : lambdaNwBound;
+        lambdaNw = (potentialDiffNw == 0) ? 0.5 * (lambdaNwI + lambdaNwBound) : lambdaNw;
 
-                T.mv(u, Tu);
 
-                fluxNw[3] = Tu[1];
-                potentialDiffNw14 = -Tu[1];
-            }
+        Scalar scalarPerm = permeability.two_norm();
 
-            //store potentials for further calculations (saturation, ...)
-            cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffW12);
-            cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffNw12);
-            cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffW14);
-            cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffNw14);
-            cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 0), -potentialDiffW32);
-            cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 0), -potentialDiffNw32);
-            cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffW12);
-            cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffNw12);
-            cellData3.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(2, 0), potentialDiffW34);
-            cellData3.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(2, 0), potentialDiffNw34);
-            cellData3.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(2, 1), potentialDiffW32);
-            cellData3.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(2, 1), potentialDiffNw32);
-            cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffW14);
-            cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffNw14);
-            cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffW34);
-            cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffNw34);
-
-            //compute mobilities of face 1
-            Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
-            lambda12Upw[wPhaseIdx] = (potentialDiffW12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
-            lambda12Upw[nPhaseIdx] = (potentialDiffNw12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
-
-            //compute mobilities of face 4
-            Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
-            lambda14Upw[wPhaseIdx] = (potentialDiffW14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
-            lambda14Upw[nPhaseIdx] = (potentialDiffNw14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
-
-            //compute mobilities of face 2
-            Dune::FieldVector<Scalar, numPhases> lambda32Upw(0.0);
-            lambda32Upw[wPhaseIdx] = (potentialDiffW32 >= 0) ? lambda3[wPhaseIdx] : lambda2[wPhaseIdx];
-            lambda32Upw[nPhaseIdx] = (potentialDiffNw32 >= 0) ? lambda3[nPhaseIdx] : lambda2[nPhaseIdx];
-
-            //compute mobilities of face 3
-            Dune::FieldVector<Scalar, numPhases> lambda34Upw(0.0);
-            lambda34Upw[wPhaseIdx] = (potentialDiffW34 >= 0) ? lambda3[wPhaseIdx] : lambda4[wPhaseIdx];
-            lambda34Upw[nPhaseIdx] = (potentialDiffNw34 >= 0) ? lambda3[nPhaseIdx] : lambda4[nPhaseIdx];
-
-            for (int i = 0; i < numPhases; i++)
-            {
-                // evaluate parts of velocity --> always take the normal for which the flux is calculated!
-                DimVector vel12 = interactionVolume.getNormal(0, 0);
-                DimVector vel14 = interactionVolume.getNormal(3, 0);
-                DimVector vel23 = interactionVolume.getNormal(1, 0);
-                DimVector vel21 = interactionVolume.getNormal(0, 0);
-                DimVector vel34 = interactionVolume.getNormal(2, 0);
-                DimVector vel32 = interactionVolume.getNormal(1, 0);
-                DimVector vel41 = interactionVolume.getNormal(3, 0);
-                DimVector vel43 = interactionVolume.getNormal(2, 0);
-
-                Dune::FieldVector<Scalar, 2 * dim> flux(0);
-                switch (i)
-                {
-                case wPhaseIdx:
-                {
-                    flux = fluxW;
-                    break;
-                }
-                case nPhaseIdx:
-                {
-                    flux = fluxNw;
-                    break;
-                }
-                }
+        //calculate the gravity term
+        Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
+        Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
 
-                vel12 *= flux[0] / (2 * interactionVolume.getFaceArea(0, 0)); //divide by 2 because the flux is related to the half face!
-                vel14 *= flux[3] / (2 * interactionVolume.getFaceArea(0, 1));
-                vel23 *= flux[1] / (2 * interactionVolume.getFaceArea(1, 0));
-                vel21 *= flux[0] / (2 * interactionVolume.getFaceArea(1, 1));
-                vel34 *= flux[2] / (2 * interactionVolume.getFaceArea(2, 0));
-                vel32 *= flux[1] / (2 * interactionVolume.getFaceArea(2, 1));
-                vel41 *= flux[3] / (2 * interactionVolume.getFaceArea(3, 0));
-                vel43 *= flux[2] / (2 * interactionVolume.getFaceArea(3, 1));
-
-                Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
-                Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
-                Scalar lambdaT32 = lambda32Upw[wPhaseIdx] + lambda32Upw[nPhaseIdx];
-                Scalar lambdaT34 = lambda34Upw[wPhaseIdx] + lambda34Upw[nPhaseIdx];
-                Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
-                Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
-                Scalar fracFlow32 = (lambdaT32 > threshold_) ? lambda32Upw[i] / (lambdaT32) : 0.0;
-                Scalar fracFlow34 = (lambdaT34 > threshold_) ? lambda34Upw[i] / (lambdaT34) : 0.0;
-
-                vel12 *= fracFlow12;
-                vel14 *= fracFlow14;
-                vel23 *= fracFlow32;
-                vel21 *= fracFlow12;
-                vel34 *= fracFlow34;
-                vel32 *= fracFlow32;
-                vel41 *= fracFlow14;
-                vel43 *= fracFlow34;
-
-                if (this->innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
-                {
-                    vel12 *= 2;
-                }
-                if (this->innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 1)])
-                {
-                    vel14 *= 2;
-                }
-                if (this->innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
-                {
-                    vel23 *= 2;
-                }
-                if (this->innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 1)])
-                {
-                    vel21 *= 2;
-                }
-                if (this->innerBoundaryVolumeFaces_[globalIdx3][interactionVolume.getIndexOnElement(2, 0)])
-                {
-                    vel34 *= 2;
-                }
-                if (this->innerBoundaryVolumeFaces_[globalIdx3][interactionVolume.getIndexOnElement(2, 1)])
-                {
-                    vel32 *= 2;
-                }
-                if (this->innerBoundaryVolumeFaces_[globalIdx4][interactionVolume.getIndexOnElement(3, 0)])
-                {
-                    vel41 *= 2;
-                }
-                if (this->innerBoundaryVolumeFaces_[globalIdx4][interactionVolume.getIndexOnElement(3, 1)])
-                {
-                    vel43 *= 2;
-                }
+        //calculate unit distVec
+        distVec /= dist;
+        Scalar areaScaling = (unitOuterNormal * distVec);
+        //this treatment of g allows to account for gravity flux through faces where the face normal has no z component (e.g. parallelepiped grids)
+        Scalar gravityTermW = (problem_.gravity() * distVec) * density_[wPhaseIdx] * areaScaling;
+        Scalar gravityTermNw = (problem_.gravity() * distVec) * density_[nPhaseIdx] * areaScaling;
 
-                //store velocities
-                cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 0), vel12);
-                cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 1), vel14);
-                cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 0), vel23);
-                cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 1), vel21);
-                cellData3.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(2, 0), vel34);
-                cellData3.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(2, 1), vel32);
-                cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 0), vel41);
-                cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 1), vel43);
-            }
-            //set velocity marker
-            cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 0));
-            cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 1));
-            cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 0));
-            cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 1));
-            cellData3.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(2, 0));
-            cellData3.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(2, 1));
-            cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 0));
-            cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 1));
+        //calculate velocity depending on the pressure used -> use pc = pn - pw
+        switch (pressureType_)
+        {
+        case pw:
+        {
+            velocityW *= lambdaW * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermW);
+            velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermNw)
+                    + 0.5 * (lambdaNwI + lambdaNwBound) * scalarPerm * (pcI - pcBound) / dist;
+            break;
         }
-
-        // at least one face on boundary!
-        else
+        case pn:
         {
-            for (int elemIdx = 0; elemIdx < 2 * dim; elemIdx++)
-            {
-                bool isOutside = false;
-                for (int faceIdx = 0; faceIdx < dim; faceIdx++)
-                {
-                    int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
-                    if (interactionVolume.isOutsideFace(intVolFaceIdx))
-                    {
-                        isOutside = true;
-                        break;
-                    }
-                }
-                if (isOutside)
-                {
-                    continue;
-                }
-
-                ElementPointer & elementPointer = interactionVolume.getSubVolumeElement(elemIdx);
+            velocityW *= lambdaW * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermW)
+                    - 0.5 * (lambdaWI + lambdaWBound) * scalarPerm * (pcI - pcBound) / dist;
+            velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermNw);
+            break;
+        }
+        }
 
-                // get global coordinate of cell centers
-                const GlobalPosition& globalPos = elementPointer->geometry().center();
+        //store velocities
+        cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
+        cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
+        cellData.fluxData().setVelocityMarker(isIndex);
 
-                // cell index
-                int globalIdx = problem_.variables().index(*elementPointer);
+    } //end dirichlet boundary
 
-                //get the cell Data
-                CellData& cellData = problem_.variables().cellData(globalIdx);
+    else if (bcType.isNeumann(pressEqIdx))
+    {
+        problem_.neumann(boundValues, intersection);
 
-                //permeability vector at boundary
-                DimMatrix permeability(problem_.spatialParams().intrinsicPermeability(*elementPointer));
+        Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
+        Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
 
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda(cellData.mobility(wPhaseIdx));
-                lambda[nPhaseIdx] = cellData.mobility(nPhaseIdx);
+        velocityW *= boundValues[wPhaseIdx];
+        velocityNw *= boundValues[nPhaseIdx];
 
-                for (int faceIdx = 0; faceIdx < dim; faceIdx++)
-                {
-                    int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
+            velocityW /= density_[wPhaseIdx];
+            velocityNw /= density_[nPhaseIdx];
 
-                    if (interactionVolume.isBoundaryFace(intVolFaceIdx))
-                    {
-                        if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(pressEqIdx))
-                        {
-                            int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, faceIdx);
-
-                            const ReferenceElement& referenceElement = ReferenceElements::general(
-                                    elementPointer->geometry().type());
-
-                            const LocalPosition& localPos = referenceElement.position(boundaryFaceIdx, 1);
-
-                            const GlobalPosition& globalPosFace = elementPointer->geometry().global(localPos);
-
-                            DimVector distVec(globalPosFace - globalPos);
-                            Scalar dist = distVec.two_norm();
-                            DimVector unitDistVec(distVec);
-                            unitDistVec /= dist;
-
-                            // get pc and lambda at the boundary
-                            Scalar satWBound = cellData.saturation(wPhaseIdx);
-                            //check boundary sat at face 1
-                            if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(satEqIdx))
-                            {
-                                Scalar satBound = interactionVolume.getDirichletValues(intVolFaceIdx)[saturationIdx];
-                                switch (saturationType_)
-                                {
-                                case sw:
-                                {
-                                    satWBound = satBound;
-                                      break;
-                                }
-                                case sn:
-                                {
-                                    satWBound = 1 - satBound;
-                                    break;
-                                }
-                                }
-
-                            }
-
-                            Scalar pcBound = MaterialLaw::pc(
-                                    problem_.spatialParams().materialLawParams(*elementPointer), satWBound);
-
-                            Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * problem_.gravity()
-                                    * (density_[nPhaseIdx] - density_[wPhaseIdx]);
-
-                            pcBound += gravityDiffBound;
-
-                            Dune::FieldVector<Scalar, numPhases> lambdaBound(
-                                    MaterialLaw::krw(problem_.spatialParams().materialLawParams(*elementPointer),
-                                            satWBound));
-                            lambdaBound[nPhaseIdx] = MaterialLaw::krn(
-                                    problem_.spatialParams().materialLawParams(*elementPointer), satWBound);
-                            lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx];
-                            lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx];
-
-                            Scalar gdeltaZ = (problem_.bBoxMax()-globalPosFace) * gravity_;
-                            Scalar potentialBoundW = interactionVolume.getDirichletValues(intVolFaceIdx)[pressureIdx] + density_[wPhaseIdx]*gdeltaZ;
-                            Scalar potentialBoundNw = potentialBoundW;
-
-                            //calculate potential gradients
-                            switch (pressureType_)
-                            {
-                            case pw:
-                            {
-                                potentialBoundNw += pcBound;
-                                break;
-                            }
-                            case pn:
-                            {
-                                //calculate potential gradients
-                                potentialBoundW -= pcBound;
-                                break;
-                            }
-                            }
-
-                            Scalar potentialDiffW = (cellData.potential(wPhaseIdx) - potentialBoundW) / dist;
-                            Scalar  potentialDiffNw = (cellData.potential(nPhaseIdx) - potentialBoundNw) / dist;
-
-                            //store potentials for further calculations (saturation, ...)
-                            cellData.fluxData().addUpwindPotential(wPhaseIdx, boundaryFaceIdx, potentialDiffW);
-                            cellData.fluxData().addUpwindPotential(nPhaseIdx, boundaryFaceIdx, potentialDiffNw);
-
-                            //calculated phase velocities from advective velocities -> capillary pressure velocity already added in pressure part!
-                            DimVector velocityW(0);
-                            DimVector velocityNw(0);
-
-                            // calculate capillary pressure gradient
-                            DimVector pressGradient = unitDistVec;
-                            pressGradient *= (cellData.potential(wPhaseIdx) - potentialBoundW) / dist;
-                            permeability.mv(pressGradient, velocityW);
-
-                            pressGradient = unitDistVec;
-                            pressGradient *= (cellData.potential(nPhaseIdx) - potentialBoundNw) / dist;
-                            permeability.mv(pressGradient, velocityNw);
-
-                            velocityW *= (potentialDiffW >= 0.) ? lambda[wPhaseIdx] : lambdaBound[wPhaseIdx];
-                            velocityNw *= (potentialDiffNw >= 0.) ? lambda[nPhaseIdx] : lambdaBound[nPhaseIdx];
-
-                            //velocity is calculated from two vertices of one intersection!
-                            velocityW *= 0.5;
-                            velocityNw *= 0.5;
-
-                            //store velocities
-                                velocityW += cellData.fluxData().velocity(wPhaseIdx, boundaryFaceIdx);
-                                velocityNw += cellData.fluxData().velocity(nPhaseIdx, boundaryFaceIdx);
-                                cellData.fluxData().setVelocity(wPhaseIdx, boundaryFaceIdx, velocityW);
-                                cellData.fluxData().setVelocity(nPhaseIdx, boundaryFaceIdx, velocityNw);
-                                cellData.fluxData().setVelocityMarker(boundaryFaceIdx);
-
-                        }
-                        else if (interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressEqIdx))
-                        {
-                            int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, faceIdx);
-
-                            const ReferenceElement& referenceElement = ReferenceElements::general(
-                                    elementPointer->geometry().type());
-
-                            const LocalPosition& localPos = referenceElement.position(boundaryFaceIdx, 1);
-
-                            const GlobalPosition& globalPosFace = elementPointer->geometry().global(localPos);
-
-                            DimVector distVec(globalPosFace - globalPos);
-                            Scalar dist = distVec.two_norm();
-                            DimVector unitDistVec(distVec);
-                            unitDistVec /= dist;
-
-                            // get neumann boundary value
-                            PrimaryVariables boundValues(interactionVolume.getNeumannValues(intVolFaceIdx));
-
-                            boundValues[wPhaseIdx] /= density_[wPhaseIdx];
-                            boundValues[nPhaseIdx] /= density_[nPhaseIdx];
-
-                            DimVector velocityW(unitDistVec);
-                            DimVector velocityNw(unitDistVec);
-
-                            velocityW *= boundValues[wPhaseIdx] / (2 * interactionVolume.getFaceArea(elemIdx, faceIdx));
-                            velocityNw *= boundValues[nPhaseIdx]
-                                    / (2 * interactionVolume.getFaceArea(elemIdx, faceIdx));
-
-                            //store potentials for further calculations (saturation, ...)
-                            cellData.fluxData().addUpwindPotential(wPhaseIdx, boundaryFaceIdx, boundValues[wPhaseIdx]);
-                            cellData.fluxData().addUpwindPotential(nPhaseIdx, boundaryFaceIdx, boundValues[nPhaseIdx]);
-
-                            //store velocities
-                            velocityW += cellData.fluxData().velocity(wPhaseIdx, boundaryFaceIdx);
-                            velocityNw += cellData.fluxData().velocity(nPhaseIdx, boundaryFaceIdx);
-                            cellData.fluxData().setVelocity(wPhaseIdx, boundaryFaceIdx, velocityW);
-                            cellData.fluxData().setVelocity(nPhaseIdx, boundaryFaceIdx, velocityNw);
-                            cellData.fluxData().setVelocityMarker(boundaryFaceIdx);
-                        }
-                        else
-                        {
-                            DUNE_THROW(Dune::NotImplemented,
-                                    "No valid boundary condition type defined for pressure equation!");
-                        }
-                    }
-                }
-            }
-
-        } // end boundaries
-
-    } // end vertex iterator
+        //store potential gradients for further calculations
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, boundValues[wPhaseIdx]);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, boundValues[nPhaseIdx]);
 
-//    }
-    return;
-} // end method calcTotalVelocity
+        cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
+        cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
+        cellData.fluxData().setVelocityMarker(isIndex);
+    } //end neumann boundary
+    else
+    {
+        DUNE_THROW(Dune::NotImplemented, "No valid boundary condition type defined for pressure equation!");
+    }
+}
 
 }
 // end of Dune namespace
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressurevelocity2padaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressurevelocity2padaptive.hh
index e1ebac067681653c203a019371dbe26f2ac3da3c..ebb22295398e45f2174687217e5d281959379eb6 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressurevelocity2padaptive.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressurevelocity2padaptive.hh
@@ -19,6 +19,7 @@
 #define DUMUX_MPFAL2DPRESSUREVELOCITIES2P_ADAPTIVE_HH
 
 #include "fvmpfal2dpressure2padaptive.hh"
+#include "fvmpfal2dvelocity2padaptive.hh"
 
 /**
  * @file
@@ -63,6 +64,10 @@ template<class TypeTag> class FvMpfaL2dPressureVelocity2pAdaptive: public FvMpfa
 
     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
     typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes;
+    typedef typename SolutionTypes::PrimaryVariables PrimaryVariables;
 
 #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
     typedef typename Dune::ReferenceElements<Scalar, dim> ReferenceElements;
@@ -80,17 +85,13 @@ template<class TypeTag> class FvMpfaL2dPressureVelocity2pAdaptive: public FvMpfa
     typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
     typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
 
-    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
-    typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes;
-    typedef typename SolutionTypes::PrimaryVariables PrimaryVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData;
-
     typedef typename GridView::Grid Grid;
     typedef typename GridView::IndexSet IndexSet;
     typedef typename GridView::template Codim<0>::Iterator ElementIterator;
     typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
     typedef typename GridView::IntersectionIterator IntersectionIterator;
     typedef typename Grid::template Codim<0>::EntityPointer ElementPointer;
+    typedef typename GridView::Intersection Intersection;
 
     typedef typename Grid::template Codim<0>::Entity::Geometry Geometry;
     #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
@@ -119,23 +120,6 @@ template<class TypeTag> class FvMpfaL2dPressureVelocity2pAdaptive: public FvMpfa
         numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
     };
 
-    enum
-    {
-        globalCorner = 2,
-        globalEdge = 3,
-        neumannNeumann = 0,
-        dirichletDirichlet = 1,
-        dirichletNeumann = 2,
-        neumannDirichlet = 3
-    };
-    enum
-    {
-        leftTriangle = ParentType::leftTriangle,
-        noTransmissibility = ParentType::noTransmissibility,
-        rightTriangle = ParentType::rightTriangle
-    };
-
-    typedef Dune::FieldVector<Scalar, dim> LocalPosition;
     typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
     typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
     typedef Dune::FieldVector<Scalar, dim> DimVector;
@@ -146,32 +130,31 @@ public:
      * \param problem A problem class object
      */
     FvMpfaL2dPressureVelocity2pAdaptive(Problem& problem) :
-            ParentType(problem), problem_(problem), gravity_(problem.gravity())
+            ParentType(problem), problem_(problem), velocity_(problem)
     {
         density_[wPhaseIdx] = 0.;
         density_[nPhaseIdx] = 0.;
         viscosity_[wPhaseIdx] = 0.;
         viscosity_[nPhaseIdx] = 0.;
 
-        vtkOutputLevel_ = GET_PARAM_FROM_GROUP(TypeTag, int, Vtk, OutputLevel);
+        calcVelocityInTransport_ = GET_PARAM_FROM_GROUP(TypeTag, bool, MPFA, CalcVelocityInTransport);
     }
 
     //Calculates the velocities at all cell-cell interfaces.
     void calculateVelocity();
 
+    // Calculates the velocity at a cell-cell interface.
+    void calculateVelocity(const Intersection&, CellData&);
+    void calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData);
+
     void updateVelocity()
     {
         this->updateMaterialLaws();
 
-        //reset velocities
-        int size = problem_.gridView().size(0);
-        for (int i = 0; i < size; i++)
-        {
-            CellData& cellData = problem_.variables().cellData(i);
-            cellData.fluxData().resetVelocity();
-        }
+        this->storePressureSolution();
 
-        calculateVelocity();
+        if (!calculateVelocityInTransport())
+            calculateVelocity();
     }
 
     /*! \brief Initializes pressure and velocity
@@ -180,8 +163,6 @@ public:
      */
     void initialize()
     {
-        ParentType::initialize();
-
         ElementIterator element = problem_.gridView().template begin<0>();
         FluidState fluidState;
         fluidState.setPressure(wPhaseIdx, problem_.referencePressure(*element));
@@ -194,7 +175,10 @@ public:
         viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
         viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
 
-        calculateVelocity();
+        ParentType::initialize();
+        velocity_.initialize();
+        if (!calculateVelocityInTransport())
+            calculateVelocity();
 
         return;
     }
@@ -207,10 +191,17 @@ public:
     void update()
     {
         ParentType::update();
+        if (!calculateVelocityInTransport())
+            calculateVelocity();
+    }
 
-        calculateVelocity();
-
-        return;
+    /*! \brief Indicates if velocity is reconstructed in the pressure step or in the transport step
+     *
+     * Returns true (In the standard finite volume discretization the velocity is calculated during the saturation transport.)
+     */
+    bool calculateVelocityInTransport()
+    {
+        return calcVelocityInTransport_;
     }
 
     /*! \brief Adds velocity output to the output file
@@ -227,85 +218,17 @@ public:
     void addOutputVtkFields(MultiWriter &writer)
     {
         ParentType::addOutputVtkFields(writer);
-
-        if (vtkOutputLevel_ > 0)
-        {
-            Dune::BlockVector < DimVector > &velocityWetting = *(writer.template allocateManagedBuffer<
-                    Scalar, dim>(problem_.gridView().size(0)));
-            Dune::BlockVector < DimVector > &velocityNonwetting =
-            *(writer.template allocateManagedBuffer<Scalar, dim>(problem_.gridView().size(0)));
-
-            // compute update vector
-            ElementIterator eEndIt = problem_.gridView().template end<0>();
-            for (ElementIterator eIt = problem_.gridView().template begin<0>(); eIt != eEndIt; ++eIt)
-            {
-                // cell index
-                int globalIdx = problem_.variables().index(*eIt);
-
-                CellData& cellData = problem_.variables().cellData(globalIdx);
-
-                Dune::FieldVector < Scalar, 2 * dim > fluxW(0);
-                Dune::FieldVector < Scalar, 2 * dim > fluxNw(0);
-                // run through all intersections with neighbors and boundary
-                IntersectionIterator isEndIt = problem_.gridView().iend(*eIt);
-                for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isEndIt; ++isIt)
-                {
-                    int isIndex = isIt->indexInInside();
-
-                    fluxW[isIndex] += isIt->geometry().volume()
-                    * (isIt->centerUnitOuterNormal() * cellData.fluxData().velocity(wPhaseIdx, isIndex));
-                    fluxNw[isIndex] +=
-                    isIt->geometry().volume()
-                    * (isIt->centerUnitOuterNormal()
-                            * cellData.fluxData().velocity(nPhaseIdx, isIndex));
-                }
-
-                DimVector refVelocity(0);
-                for (int i = 0; i < dim; i++)
-                refVelocity[i] = 0.5 * (fluxW[2*i + 1] - fluxW[2*i]);
-
-                const DimVector localPos =
-                ReferenceElements::general(eIt->geometry().type()).position(0, 0);
-
-                // get the transposed Jacobian of the element mapping
-                const JacobianTransposed jacobianT = eIt->geometry().jacobianTransposed(localPos);
-
-                // calculate the element velocity by the Piola transformation
-                DimVector elementVelocity(0);
-                jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
-
-                velocityWetting[globalIdx] = elementVelocity;
-
-                refVelocity = 0;
-                for (int i = 0; i < dim; i++)
-                refVelocity[i] = 0.5 * (fluxNw[2*i + 1] - fluxNw[2*i]);
-
-                // calculate the element velocity by the Piola transformation
-                elementVelocity = 0;
-                jacobianT.umtv(refVelocity, elementVelocity);
-                elementVelocity /= eIt->geometry().integrationElement(localPos);
-
-                velocityNonwetting[globalIdx] = elementVelocity;
-            }
-
-            writer.attachCellData(velocityWetting, "wetting-velocity", dim);
-            writer.attachCellData(velocityNonwetting, "non-wetting-velocity", dim);
-        }
-        return;
+        velocity_.addOutputVtkFields(writer);
     }
 
 private:
      Problem& problem_;
-     const GlobalPosition& gravity_; //!< vector including the gravity constant
+     FvMpfaL2dVelocity2pAdaptive<TypeTag> velocity_;
 
      Scalar density_[numPhases];
      Scalar viscosity_[numPhases];
+     bool calcVelocityInTransport_;
 
-     int vtkOutputLevel_;
-
-     static constexpr Scalar threshold_ = 1e-15;
-     static const int velocityType_ = GET_PROP_VALUE(TypeTag, VelocityFormulation); //!< gives kind of velocity used (\f$ 0 = v_w\f$, \f$ 1 = v_n\f$, \f$ 2 = v_t\f$)
      static const int pressureType_ = GET_PROP_VALUE(TypeTag, PressureFormulation); //!< gives kind of pressure used (\f$ 0 = p_w\f$, \f$ 1 = p_n\f$, \f$ 2 = p_{global}\f$)
      static const int saturationType_ = GET_PROP_VALUE(TypeTag, SaturationFormulation); //!< gives kind of saturation used (\f$ 0 = S_w\f$, \f$ 1 = S_n\f$)
 };
@@ -319,26 +242,6 @@ private:
 template<class TypeTag>
 void FvMpfaL2dPressureVelocity2pAdaptive<TypeTag>::calculateVelocity()
 {
-//        std::cout<<"velocityW = \n";
-//        for  (int i = 0; i<problem_.gridView().size(0);i++)
-//        {
-//            std::cout<<i<<": ";
-//            for (int j=0; j<4; j++)
-//            {
-//                std::cout<<"    ("<<j<<") "<<problem_.variables().cellData(i).fluxData().velocity(wPhaseIdx, j);
-//            }
-//            std::cout<<"\n";
-//        }
-//        std::cout<<"velocityNw = \n";
-//        for  (int i = 0; i<problem_.gridView().size(0);i++)
-//        {
-//            std::cout<<i<<": ";
-//            for (int j=0; j<4; j++)
-//            {
-//                std::cout<<"    ("<<j<<") "<<problem_.variables().cellData(i).fluxData().velocity(nPhaseIdx, j);
-//            }
-//            std::cout<<"\n";
-//        }
     // run through all elements
     VertexIterator vEndIt = problem_.gridView().template end<dim>();
     for (VertexIterator vIt = problem_.gridView().template begin<dim>(); vIt != vEndIt; ++vIt)
@@ -356,11 +259,6 @@ void FvMpfaL2dPressureVelocity2pAdaptive<TypeTag>::calculateVelocity()
                 ElementPointer & elementPointer3 = interactionVolume.getSubVolumeElement(2);
                 ElementPointer & elementPointer4 = interactionVolume.getSubVolumeElement(3);
 
-                int level1 = elementPointer1->level();
-                int level2 = elementPointer2->level();
-                int level3 = elementPointer3->level();
-                int level4 = elementPointer4->level();
-
                 // cell index
                 int globalIdx1 = problem_.variables().index(*elementPointer1);
                 int globalIdx2 = problem_.variables().index(*elementPointer2);
@@ -373,426 +271,157 @@ void FvMpfaL2dPressureVelocity2pAdaptive<TypeTag>::calculateVelocity()
                 CellData& cellData3 = problem_.variables().cellData(globalIdx3);
                 CellData& cellData4 = problem_.variables().cellData(globalIdx4);
 
-                // get pressure values
-                Dune::FieldVector < Scalar, 2 * dim > potW(0);
-                Dune::FieldVector < Scalar, 2 * dim > potNw(0);
-
-                potW[0] = cellData1.potential(wPhaseIdx);
-                potW[1] = cellData2.potential(wPhaseIdx);
-                potW[2] = cellData3.potential(wPhaseIdx);
-                potW[3] = cellData4.potential(wPhaseIdx);
-
-                potNw[0] = cellData1.potential(nPhaseIdx);
-                potNw[1] = cellData2.potential(nPhaseIdx);
-                potNw[2] = cellData3.potential(nPhaseIdx);
-                potNw[3] = cellData4.potential(nPhaseIdx);
-
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
-                lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
-
-                //compute total mobility of cell 1
-                Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
-
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
-                lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
-
-                //compute total mobility of cell 1
-                Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
-
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda3(cellData3.mobility(wPhaseIdx));
-                lambda3[nPhaseIdx] = cellData3.mobility(nPhaseIdx);
-
-                //compute total mobility of cell 1
-                Scalar lambdaTotal3 = lambda3[wPhaseIdx] + lambda3[nPhaseIdx];
+                velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume, cellData1, cellData2, cellData3, cellData4, this->innerBoundaryVolumeFaces_);
 
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
-                lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
-
-                //compute total mobility of cell 1
-                Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
-
-                std::vector < DimVector > lambda(2 * dim);
-
-                lambda[0][0] = lambdaTotal1;
-                lambda[0][1] = lambdaTotal1;
-                lambda[1][0] = lambdaTotal2;
-                lambda[1][1] = lambdaTotal2;
-                lambda[2][0] = lambdaTotal3;
-                lambda[2][1] = lambdaTotal3;
-                lambda[3][0] = lambdaTotal4;
-                lambda[3][1] = lambdaTotal4;
-
-                Scalar potentialDiffW12 = 0;
-                Scalar potentialDiffW14 = 0;
-                Scalar potentialDiffW32 = 0;
-                Scalar potentialDiffW34 = 0;
+            }
+            else if (interactionVolume.getElementNumber() == 3)
+            {
+                ElementPointer & elementPointer1 = interactionVolume.getSubVolumeElement(0);
+                  ElementPointer & elementPointer2 = interactionVolume.getSubVolumeElement(1);
+                  ElementPointer & elementPointer4 = interactionVolume.getSubVolumeElement(3);
 
-                Scalar potentialDiffNw12 = 0;
-                Scalar potentialDiffNw14 = 0;
-                Scalar potentialDiffNw32 = 0;
-                Scalar potentialDiffNw34 = 0;
+                  // cell index
+                  int globalIdx1 = problem_.variables().index(*elementPointer1);
+                  int globalIdx2 = problem_.variables().index(*elementPointer2);
+                  int globalIdx4 = problem_.variables().index(*elementPointer4);
 
-                //flux vector
-                Dune::FieldVector<Scalar, 2 * dim> fluxW(0);
-                Dune::FieldVector<Scalar, 2 * dim> fluxNw(0);
+                  //get the cell Data
+                  CellData& cellData1 = problem_.variables().cellData(globalIdx1);
+                  CellData& cellData2 = problem_.variables().cellData(globalIdx2);
+                  CellData& cellData4 = problem_.variables().cellData(globalIdx4);
 
-                Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
-                DimVector Tu(0);
-                Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
+                  velocity_.calculateHangingNodeInteractionVolumeVelocity(interactionVolume, cellData1, cellData2, cellData4, this->innerBoundaryVolumeFaces_);
 
-                int transmissibilityType = this->calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
+            }
+            else
+            {
+                DUNE_THROW(Dune::NotImplemented, "Unknown interactionvolume type!");
+            }
+        }
 
-                if (transmissibilityType == rightTriangle)
+        // at least one face on boundary!
+        else
+        {
+            for (int elemIdx = 0; elemIdx < 2 * dim; elemIdx++)
+            {
+                bool isOutside = false;
+                for (int faceIdx = 0; faceIdx < dim; faceIdx++)
                 {
-                    u[0] = potW[1];
-                    u[1] = potW[2];
-                    u[2] = potW[0];
-
-                    T.mv(u, Tu);
-
-                    fluxW[0] = Tu[1];
-                    potentialDiffW12 = Tu[1];
-
-                    u[0] = potNw[1];
-                    u[1] = potNw[2];
-                    u[2] = potNw[0];
-
-                    T.mv(u, Tu);
-
-                    fluxNw[0] = Tu[1];
-                    potentialDiffNw12 = Tu[1];
+                    int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
+                    if (interactionVolume.isOutsideFace(intVolFaceIdx))
+                    {
+                        isOutside = true;
+                        break;
+                    }
                 }
-                else if (transmissibilityType == leftTriangle)
+                if (isOutside)
                 {
-                    u[0] = potW[0];
-                    u[1] = potW[3];
-                    u[2] = potW[1];
-
-                    T.mv(u, Tu);
-
-                    fluxW[0] = Tu[1];
-                    potentialDiffW12 = Tu[1];
-
-                    u[0] = potNw[0];
-                    u[1] = potNw[3];
-                    u[2] = potNw[1];
-
-                    T.mv(u, Tu);
-
-                    fluxNw[0] = Tu[1];
-                    potentialDiffNw12 = Tu[1];
+                    continue;
                 }
+                ElementPointer & elementPointer = interactionVolume.getSubVolumeElement(elemIdx);
 
-                transmissibilityType = this->calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
-
-                if  (transmissibilityType == rightTriangle)
-                {
-                    u[0] = potW[2];
-                    u[1] = potW[3];
-                    u[2] = potW[1];
-
-                    T.mv(u, Tu);
+                // cell index
+                int globalIdx = problem_.variables().index(*elementPointer);
+                //get the cell Data
+                CellData& cellData = problem_.variables().cellData(globalIdx);
 
-                    fluxW[1] = Tu[1];
-                    potentialDiffW32 = -Tu[1];
+                velocity_.calculateBoundaryInteractionVolumeVelocity(interactionVolume, cellData, elemIdx);
+            }
 
-                    u[0] = potNw[2];
-                    u[1] = potNw[3];
-                    u[2] = potNw[1];
+        } // end boundaries
 
-                    T.mv(u, Tu);
+    } // end vertex iterator
+    return;
+} // end method calcTotalVelocity
 
-                    fluxNw[1] = Tu[1];
-                    potentialDiffNw32 = -Tu[1];
-                }
-                else if (transmissibilityType == leftTriangle)
-                {
-                    u[0] = potW[1];
-                    u[1] = potW[0];
-                    u[2] = potW[2];
+template<class TypeTag>
+void FvMpfaL2dPressureVelocity2pAdaptive<TypeTag>::calculateVelocity(const Intersection& intersection, CellData& cellData)
+{
+    int numVertices = intersection.geometry().corners();
 
-                    T.mv(u, Tu);
+    ElementPointer elementPtrI = intersection.inside();
+    ElementPointer elementPtrJ = intersection.outside();
 
-                    fluxW[1] = Tu[1];
-                    potentialDiffW32 = -Tu[1];
+    int levelI = elementPtrI->level();
+    int levelJ = elementPtrJ->level();
 
-                    u[0] = potNw[1];
-                    u[1] = potNw[0];
-                    u[2] = potNw[2];
+    int globalIdxI = problem_.variables().index(*elementPtrI);
+    int globalIdxJ = problem_.variables().index(*elementPtrJ);
 
-                    T.mv(u, Tu);
+    CellData& cellDataJ = problem_.variables().cellData(globalIdxJ);
 
-                    fluxNw[1] = Tu[1];
-                    potentialDiffNw32 = -Tu[1];
-                }
+    const ReferenceElement& referenceElement = ReferenceElements::general(elementPtrI->geometry().type());
 
-                transmissibilityType = this->calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
+    int indexInInside = intersection.indexInInside();
+    int indexInOutside = intersection.indexInOutside();
 
-                if  (transmissibilityType == rightTriangle)
-                {
-                    u[0] = potW[3];
-                    u[1] = potW[0];
-                    u[2] = potW[2];
+    int faceIdx = indexInInside;
 
-                    T.mv(u, Tu);
+    if (levelI < levelJ)
+        faceIdx = indexInOutside;
 
-                    fluxW[2] = Tu[1];
-                    potentialDiffW34 = Tu[1];
+    std::vector<CellData> cellDataTemp(0);
 
-                    u[0] = potNw[3];
-                    u[1] = potNw[0];
-                    u[2] = potNw[2];
+    if (levelI != levelJ)
+    {
+        DimVector vel(0);
+        cellData.fluxData().setVelocity(wPhaseIdx, indexInInside, vel);
+        cellData.fluxData().setVelocity(nPhaseIdx, indexInInside, vel);
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside, 0);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside, 0);
+
+        cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside, vel);
+        cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside, vel);
+        cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside, 0);
+        cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside, 0);
+    }
 
-                    T.mv(u, Tu);
+    for (int vIdx = 0; vIdx < numVertices; vIdx++)
+    {
+        int localVertIdx = referenceElement.subEntity(faceIdx, dim - 1, vIdx, dim);
 
-                    fluxNw[2] = Tu[1];
-                    potentialDiffNw34 = Tu[1];
-                }
-                else if (transmissibilityType == leftTriangle)
+        int globalVertIdx = 0;
+                if (levelI >= levelJ)
                 {
-                    u[0] = potW[2];
-                    u[1] = potW[1];
-                    u[2] = potW[3];
-
-                    T.mv(u, Tu);
-
-                    fluxW[2] = Tu[1];
-                    potentialDiffW34 = Tu[1];
-
-                    u[0] = potNw[2];
-                    u[1] = potNw[1];
-                    u[2] = potNw[3];
-
-                    T.mv(u, Tu);
-
-                    fluxNw[2] = Tu[1];
-                    potentialDiffNw34 = Tu[1];
+                    globalVertIdx = problem_.variables().index(
+                            *((*elementPtrI).template subEntity < dim > (localVertIdx)));
                 }
-
-                transmissibilityType = this->calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
-
-                if  (transmissibilityType == rightTriangle)
+                else
                 {
-                    u[0] = potW[0];
-                    u[1] = potW[1];
-                    u[2] = potW[3];
-
-                    T.mv(u, Tu);
-
-                    fluxW[3] = Tu[1];
-                    potentialDiffW14 = -Tu[1];
-
-                    u[0] = potNw[0];
-                    u[1] = potNw[1];
-                    u[2] = potNw[3];
-
-                    T.mv(u, Tu);
-
-                    fluxNw[3] = Tu[1];
-                    potentialDiffNw14 = -Tu[1];
+                    globalVertIdx = problem_.variables().index(
+                            *((*elementPtrJ).template subEntity < dim > (localVertIdx)));
                 }
-                else if (transmissibilityType == leftTriangle)
-                {
-                    u[0] = potW[3];
-                    u[1] = potW[2];
-                    u[2] = potW[0];
 
-                    T.mv(u, Tu);
-
-                    fluxW[3] = Tu[1];
-                    potentialDiffW14 = -Tu[1];
-
-                    u[0] = potNw[3];
-                    u[1] = potNw[2];
-                    u[2] = potNw[0];
+        InteractionVolume& interactionVolume = this->interactionVolumes_[globalVertIdx];
 
-                    T.mv(u, Tu);
+        if (interactionVolume.isInnerVolume())
+        {
+            // cell index vector
+            std::vector<int> globalIdx(0);
 
-                    fluxNw[3] = Tu[1];
-                    potentialDiffNw14 = -Tu[1];
-                }
+            if (interactionVolume.getElementNumber() == 4)
+            {
+                ElementPointer & elementPointer1 = interactionVolume.getSubVolumeElement(0);
+                ElementPointer & elementPointer2 = interactionVolume.getSubVolumeElement(1);
+                ElementPointer & elementPointer3 = interactionVolume.getSubVolumeElement(2);
+                ElementPointer & elementPointer4 = interactionVolume.getSubVolumeElement(3);
 
-                //store potentials for further calculations (saturation, ...)
-                cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffW12);
-                cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffNw12);
-                cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffW14);
-                cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffNw14);
-                cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 0), -potentialDiffW32);
-                cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 0), -potentialDiffNw32);
-                cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffW12);
-                cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffNw12);
-                cellData3.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(2, 0), potentialDiffW34);
-                cellData3.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(2, 0), potentialDiffNw34);
-                cellData3.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(2, 1), potentialDiffW32);
-                cellData3.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(2, 1), potentialDiffNw32);
-                cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffW14);
-                cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffNw14);
-                cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffW34);
-                cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffNw34);
-
-                //compute mobilities of face 1
-                Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
-                lambda12Upw[wPhaseIdx] = (potentialDiffW12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
-                lambda12Upw[nPhaseIdx] = (potentialDiffNw12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
-
-                //compute mobilities of face 4
-                Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
-                lambda14Upw[wPhaseIdx] = (potentialDiffW14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
-                lambda14Upw[nPhaseIdx] = (potentialDiffNw14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
-
-                //compute mobilities of face 2
-                Dune::FieldVector<Scalar, numPhases> lambda32Upw(0.0);
-                lambda32Upw[wPhaseIdx] = (potentialDiffW32 >= 0) ? lambda3[wPhaseIdx] : lambda2[wPhaseIdx];
-                lambda32Upw[nPhaseIdx] = (potentialDiffNw32 >= 0) ? lambda3[nPhaseIdx] : lambda2[nPhaseIdx];
-
-                //compute mobilities of face 3
-                Dune::FieldVector<Scalar, numPhases> lambda34Upw(0.0);
-                lambda34Upw[wPhaseIdx] = (potentialDiffW34 >= 0) ? lambda3[wPhaseIdx] : lambda4[wPhaseIdx];
-                lambda34Upw[nPhaseIdx] = (potentialDiffNw34 >= 0) ? lambda3[nPhaseIdx] : lambda4[nPhaseIdx];
-
-                for (int i = 0; i < numPhases; i++)
-                {
-                    // evaluate parts of velocity --> always take the normal for which the flux is calculated!
-                    DimVector vel12 = interactionVolume.getNormal(0, 0);
-                    DimVector vel14 = interactionVolume.getNormal(3, 0);
-                    DimVector vel23 = interactionVolume.getNormal(1, 0);
-                    DimVector vel21 = interactionVolume.getNormal(0, 0);
-                    DimVector vel34 = interactionVolume.getNormal(2, 0);
-                    DimVector vel32 = interactionVolume.getNormal(1, 0);
-                    DimVector vel41 = interactionVolume.getNormal(3, 0);
-                    DimVector vel43 = interactionVolume.getNormal(2, 0);
-
-                    Dune::FieldVector<Scalar, 2 * dim> flux(0);
-                    switch (i)
-                    {
-                    case wPhaseIdx:
-                    {
-                        flux = fluxW;
-                        break;
-                    }
-                    case nPhaseIdx:
-                    {
-                        flux = fluxNw;
-                        break;
-                    }
-                    }
+                globalIdx.resize(4);
 
-                    vel12 *= flux[0] / (2 * interactionVolume.getFaceArea(0, 0)); //divide by 2 because the flux is related to the half face!
-                    vel14 *= flux[3] / (2 * interactionVolume.getFaceArea(0, 1));
-                    vel23 *= flux[1] / (2 * interactionVolume.getFaceArea(1, 0));
-                    vel21 *= flux[0] / (2 * interactionVolume.getFaceArea(1, 1));
-                    vel34 *= flux[2] / (2 * interactionVolume.getFaceArea(2, 0));
-                    vel32 *= flux[1] / (2 * interactionVolume.getFaceArea(2, 1));
-                    vel41 *= flux[3] / (2 * interactionVolume.getFaceArea(3, 0));
-                    vel43 *= flux[2] / (2 * interactionVolume.getFaceArea(3, 1));
+                globalIdx[0] = problem_.variables().index(*elementPointer1);
+                globalIdx[1] = problem_.variables().index(*elementPointer2);
+                globalIdx[2] = problem_.variables().index(*elementPointer3);
+                globalIdx[3] = problem_.variables().index(*elementPointer4);
 
-                    if (level1 < level2)
-                    {
-                        vel12 *= 0.5;
-                    }
-                    else if (level2 < level1)
-                    {
-                        vel21 *= 0.5;
-                    }
-                    if (level2 < level3)
-                    {
-                        vel23 *= 0.5;
-                    }
-                    else if (level3 < level2)
-                    {
-                        vel32 *= 0.5;
-                    }
-                    if (level3 < level4)
-                    {
-                        vel34 *= 0.5;
-                    }
-                    else if (level4 < level3)
-                    {
-                        vel43 *= 0.5;
-                    }
-                    if (level4 < level1)
-                    {
-                        vel41 *= 0.5;
-                    }
-                    else if (level1 < level4)
-                    {
-                        vel14 *= 0.5;
-                    }
+                //cell Data vector
+                cellDataTemp.resize(4);
 
-                    Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
-                    Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
-                    Scalar lambdaT32 = lambda32Upw[wPhaseIdx] + lambda32Upw[nPhaseIdx];
-                    Scalar lambdaT34 = lambda34Upw[wPhaseIdx] + lambda34Upw[nPhaseIdx];
-                    Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
-                    Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
-                    Scalar fracFlow32 = (lambdaT32 > threshold_) ? lambda32Upw[i] / (lambdaT32) : 0.0;
-                    Scalar fracFlow34 = (lambdaT34 > threshold_) ? lambda34Upw[i] / (lambdaT34) : 0.0;
-
-                    vel12 *= fracFlow12;
-                    vel14 *= fracFlow14;
-                    vel23 *= fracFlow32;
-                    vel21 *= fracFlow12;
-                    vel34 *= fracFlow34;
-                    vel32 *= fracFlow32;
-                    vel41 *= fracFlow14;
-                    vel43 *= fracFlow34;
-
-                    if (this->innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
-                    {
-                        vel12 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 1)])
-                    {
-                        vel14 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
-                    {
-                        vel23 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 1)])
-                    {
-                        vel21 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx3][interactionVolume.getIndexOnElement(2, 0)])
-                    {
-                        vel34 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx3][interactionVolume.getIndexOnElement(2, 1)])
-                    {
-                        vel32 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx4][interactionVolume.getIndexOnElement(3, 0)])
-                    {
-                        vel41 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx4][interactionVolume.getIndexOnElement(3, 1)])
-                    {
-                        vel43 *= 2;
-                    }
+                cellDataTemp[0] = problem_.variables().cellData(globalIdx[0]);
+                cellDataTemp[1] = problem_.variables().cellData(globalIdx[1]);
+                cellDataTemp[2] = problem_.variables().cellData(globalIdx[2]);
+                cellDataTemp[3] = problem_.variables().cellData(globalIdx[3]);
 
-                    //store velocities
-                    cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 0), vel12);
-                    cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 1), vel14);
-                    cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 0), vel23);
-                    cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 1), vel21);
-                    cellData3.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(2, 0), vel34);
-                    cellData3.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(2, 1), vel32);
-                    cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 0), vel41);
-                    cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 1), vel43);
-                }
-                //set velocity marker
-                cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 0));
-                cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 1));
-                cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 0));
-                cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 1));
-                cellData3.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(2, 0));
-                cellData3.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(2, 1));
-                cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 0));
-                cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 1));
+                velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume, cellDataTemp[0], cellDataTemp[1], cellDataTemp[2], cellDataTemp[3], this->innerBoundaryVolumeFaces_);
             }
             else if (interactionVolume.getElementNumber() == 3)
             {
@@ -800,501 +429,262 @@ void FvMpfaL2dPressureVelocity2pAdaptive<TypeTag>::calculateVelocity()
                 ElementPointer & elementPointer2 = interactionVolume.getSubVolumeElement(1);
                 ElementPointer & elementPointer4 = interactionVolume.getSubVolumeElement(3);
 
-                // cell index
-                int globalIdx1 = problem_.variables().index(*elementPointer1);
-                int globalIdx2 = problem_.variables().index(*elementPointer2);
-                int globalIdx4 = problem_.variables().index(*elementPointer4);
-
-                //get the cell Data
-                CellData& cellData1 = problem_.variables().cellData(globalIdx1);
-                CellData& cellData2 = problem_.variables().cellData(globalIdx2);
-                CellData& cellData4 = problem_.variables().cellData(globalIdx4);
-
-                // get pressure values
-                Dune::FieldVector < Scalar, 2 * dim > potW(0);
-                Dune::FieldVector < Scalar, 2 * dim > potNw(0);
-
-                potW[0] = cellData1.potential(wPhaseIdx);
-                potW[1] = cellData2.potential(wPhaseIdx);
-                potW[2] = cellData4.potential(wPhaseIdx);
+                globalIdx.resize(3);
 
-                potNw[0] = cellData1.potential(nPhaseIdx);
-                potNw[1] = cellData2.potential(nPhaseIdx);
-                potNw[2] = cellData4.potential(nPhaseIdx);
+                globalIdx[0] = problem_.variables().index(*elementPointer1);
+                globalIdx[1] = problem_.variables().index(*elementPointer2);
+                globalIdx[2] = problem_.variables().index(*elementPointer4);
 
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
-                lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
+                //cell Data vector
+                cellDataTemp.resize(3);
 
-                //compute total mobility of cell 1
-                Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
+                cellDataTemp[0] = problem_.variables().cellData(globalIdx[0]);
+                cellDataTemp[1] = problem_.variables().cellData(globalIdx[1]);
+                cellDataTemp[2] = problem_.variables().cellData(globalIdx[2]);
 
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
-                lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
 
-                //compute total mobility of cell 1
-                Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
-
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
-                lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
-
-                //compute total mobility of cell 1
-                Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
-
-                std::vector < DimVector > lambda(4);
-
-                lambda[0][0] = lambdaTotal1;
-                lambda[0][1] = lambdaTotal1;
-                lambda[1][0] = lambdaTotal2;
-                lambda[1][1] = lambdaTotal2;
-                lambda[3][0] = lambdaTotal4;
-                lambda[3][1] = lambdaTotal4;
-
-                Scalar potentialDiffW12 = 0;
-                Scalar potentialDiffW14 = 0;
-                Scalar potentialDiffW24 = 0;
+                velocity_.calculateHangingNodeInteractionVolumeVelocity(interactionVolume, cellDataTemp[0], cellDataTemp[1], cellDataTemp[2], this->innerBoundaryVolumeFaces_);
+            }
+            else
+            {
+                DUNE_THROW(Dune::NotImplemented, "Unknown interactionvolume type!");
+            }
 
-                Scalar potentialDiffNw12 = 0;
-                Scalar potentialDiffNw14 = 0;
-                Scalar potentialDiffNw24 = 0;
+            int size = cellDataTemp.size();
+        for (int i = 0; i < size; i++)
+        {
+            if (globalIdx[i] == globalIdxI)
+            {
+                if (levelI >= levelJ)
+                {
+                 cellData.fluxData().setVelocity(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInInside));
+                 cellData.fluxData().setVelocity(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInInside));
+                 cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInInside));
+                 cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInInside));
+
+                 if (levelI > levelJ)
+                 {
+                     cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInInside));
+                     cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInInside));
+                     cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInInside));
+                     cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInInside));
+
+                 }
+                }
 
-                //flux vector
-                Dune::FieldVector<Scalar, 3> fluxW(0);
-                Dune::FieldVector<Scalar, 3> fluxNw(0);
+            }
+            else if (globalIdx[i] == globalIdxJ)
+            {
+                if (levelJ >= levelI)
+                {
+                cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInOutside));
 
-                Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
-                DimVector Tu(0);
-                Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
+                if (levelJ > levelI)
+                {
+                    cellData.fluxData().setVelocity(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInOutside));
+                    cellData.fluxData().setVelocity(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInOutside));
+                    cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInOutside));
+                    cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInOutside));
 
-                int transmissibilityType = this->calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 3, 3);
+                }
+                }
+            }
+        }
+    }
+    }
+    if (levelI == levelJ)
+    {
+        cellData.fluxData().setVelocityMarker(indexInInside);
+        cellDataJ.fluxData().setVelocityMarker(indexInOutside);
+    }
+}
 
-                if (transmissibilityType == rightTriangle)
-                {
-                    u[0] = potW[1];
-                    u[1] = potW[2];
-                    u[2] = potW[0];
+template<class TypeTag>
+void FvMpfaL2dPressureVelocity2pAdaptive<TypeTag>::calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData)
+{
+    ElementPointer element = intersection.inside();
 
-                    T.mv(u, Tu);
+    //get face index
+    int isIndex = intersection.indexInInside();
 
-                    fluxW[0] = Tu[1];
-                    potentialDiffW12 = Tu[1];
+    //get face normal
+    const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
 
-                    u[0] = potNw[1];
-                    u[1] = potNw[2];
-                    u[2] = potNw[0];
+    BoundaryTypes bcType;
+    //get boundary type
+    problem_.boundaryTypes(bcType, intersection);
+    PrimaryVariables boundValues(0.0);
 
-                    T.mv(u, Tu);
+    if (bcType.isDirichlet(pressEqIdx))
+    {
+        problem_.dirichlet(boundValues, intersection);
 
-                    fluxNw[0] = Tu[1];
-                    potentialDiffNw12 = Tu[1];
-                }
-                else if (transmissibilityType == leftTriangle)
-                {
-                    u[0] = potW[0];
-                    u[1] = potW[2];
-                    u[2] = potW[1];
+        // get global coordinates of cell centers
+        const GlobalPosition& globalPosI = element->geometry().center();
 
-                    T.mv(u, Tu);
+        // center of face in global coordinates
+        const GlobalPosition& globalPosJ = intersection.geometry().center();
 
-                    fluxW[0] = Tu[1];
-                    potentialDiffW12 = Tu[1];
+        // get mobilities and fractional flow factors
+        Scalar lambdaWI = cellData.mobility(wPhaseIdx);
+        Scalar lambdaNwI = cellData.mobility(nPhaseIdx);
 
-                    u[0] = potNw[0];
-                    u[1] = potNw[2];
-                    u[2] = potNw[1];
+        // get capillary pressure
+        Scalar pcI = cellData.capillaryPressure();
 
-                    T.mv(u, Tu);
+        // distance vector between barycenters
+        GlobalPosition distVec = globalPosJ - globalPosI;
 
-                    fluxNw[0] = Tu[1];
-                    potentialDiffNw12 = Tu[1];
-                }
+        // compute distance between cell centers
+        Scalar dist = distVec.two_norm();
 
-                transmissibilityType = this->calculateLeftHNTransmissibility(T, interactionVolume, lambda, 1, 3, 0);
+        //permeability vector at boundary
+        // compute vectorized permeabilities
+        DimMatrix meanPermeability(0);
 
-                if (transmissibilityType == leftTriangle)
-                {
-                    u[0] = potW[1];
-                    u[1] = potW[0];
-                    u[2] = potW[2];
+        problem_.spatialParams().meanK(meanPermeability, problem_.spatialParams().intrinsicPermeability(*element));
 
-                    T.mv(u, Tu);
+        Dune::FieldVector<Scalar, dim> permeability(0);
+        meanPermeability.mv(unitOuterNormal, permeability);
 
-                    fluxW[1] = Tu[1];
-                    potentialDiffW24 = Tu[1];
+        //determine saturation at the boundary -> if no saturation is known directly at the boundary use the cell saturation
+        Scalar satW = 0;
+        Scalar satNw = 0;
+        if (bcType.isDirichlet(satEqIdx))
+        {
+            switch (saturationType_)
+            {
+            case sw:
+            {
+                satW = boundValues[saturationIdx];
+                satNw = 1 - boundValues[saturationIdx];
+                break;
+            }
+            case sn:
+            {
+                satW = 1 - boundValues[saturationIdx];
+                satNw = boundValues[saturationIdx];
+                break;
+            }
+            }
+        }
+        else
+        {
+            satW = cellData.saturation(wPhaseIdx);
+            satNw = cellData.saturation(nPhaseIdx);
+        }
 
-                    u[0] = potNw[1];
-                    u[1] = potNw[0];
-                    u[2] = potNw[2];
+        Scalar pressBound = boundValues[pressureIdx];
+        Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(*element), satW);
 
-                    T.mv(u, Tu);
+        //determine phase pressures from primary pressure variable
+        Scalar pressWBound = 0;
+        Scalar pressNwBound = 0;
+        if (pressureType_ == pw)
+        {
+            pressWBound = pressBound;
+            pressNwBound = pressBound + pcBound;
+        }
+        else if (pressureType_ == pn)
+        {
+            pressWBound = pressBound - pcBound;
+            pressNwBound = pressBound;
+        }
 
-                    fluxNw[1] = Tu[1];
-                    potentialDiffNw24 = Tu[1];
-                }
+        Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(*element), satW)
+                / viscosity_[wPhaseIdx];
+        Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(*element), satW)
+                / viscosity_[nPhaseIdx];
 
-                transmissibilityType = this->calculateRightHNTransmissibility(T, interactionVolume, lambda, 3, 0, 1);
+        Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex);
+        Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex);
 
-                if (transmissibilityType == rightTriangle)
-                {
-                    u[0] = potW[0];
-                    u[1] = potW[1];
-                    u[2] = potW[2];
+        //calculate potential gradient
+        potentialDiffW = (cellData.pressure(wPhaseIdx) - pressWBound);
+        potentialDiffNw = (cellData.pressure(nPhaseIdx) - pressNwBound);
 
-                    T.mv(u, Tu);
+        potentialDiffW += density_[wPhaseIdx] * (distVec * problem_.gravity());
+        potentialDiffNw += density_[nPhaseIdx] * (distVec * problem_.gravity());
 
-                    fluxW[2] = Tu[1];
-                    potentialDiffW14 = -Tu[1];
+        //store potential gradients for further calculations
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, potentialDiffW);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, potentialDiffNw);
 
-                    u[0] = potNw[0];
-                    u[1] = potNw[1];
-                    u[2] = potNw[2];
+        //do the upwinding of the mobility depending on the phase potentials
+        Scalar lambdaW = (potentialDiffW > 0.) ? lambdaWI : lambdaWBound;
+        lambdaW = (potentialDiffW == 0) ? 0.5 * (lambdaWI + lambdaWBound) : lambdaW;
+        Scalar lambdaNw = (potentialDiffNw > 0.) ? lambdaNwI : lambdaNwBound;
+        lambdaNw = (potentialDiffNw == 0) ? 0.5 * (lambdaNwI + lambdaNwBound) : lambdaNw;
 
-                    T.mv(u, Tu);
 
-                    fluxNw[2] = Tu[1];
-                    potentialDiffNw14 = -Tu[1];
-                }
+        Scalar scalarPerm = permeability.two_norm();
 
-                //store potentials for further calculations (saturation, ...) -> maybe add new potential to old one!!
-                cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffW12);
-                cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffNw12);
-                cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffW14);
-                cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffNw14);
-                cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 0), potentialDiffW24);
-                cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 0), potentialDiffNw24);
-                cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffW12);
-                cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffNw12);
-                cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffW14);
-                cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffNw14);
-                cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffW24);
-                cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffNw24);
-
-                //compute mobilities of face 1
-                Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
-                lambda12Upw[wPhaseIdx] = (potentialDiffW12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
-                lambda12Upw[nPhaseIdx] = (potentialDiffNw12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
-
-                //compute mobilities of face 4
-                Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
-                lambda14Upw[wPhaseIdx] = (potentialDiffW14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
-                lambda14Upw[nPhaseIdx] = (potentialDiffNw14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
-
-                //compute mobilities of face 2
-                Dune::FieldVector<Scalar, numPhases> lambda24Upw(0.0);
-                lambda24Upw[wPhaseIdx] = (potentialDiffW24 >= 0) ? lambda2[wPhaseIdx] : lambda4[wPhaseIdx];
-                lambda24Upw[nPhaseIdx] = (potentialDiffNw24 >= 0) ? lambda2[nPhaseIdx] : lambda4[nPhaseIdx];
-
-                for (int i = 0; i < numPhases; i++)
-                {
-                    // evaluate parts of velocity --> always take the normal for which the flux is calculated!
-                    DimVector vel12 = interactionVolume.getNormal(0, 0);
-                    DimVector vel14 = interactionVolume.getNormal(3, 0);
-                    DimVector vel24 = interactionVolume.getNormal(1, 0);
-                    DimVector vel21 = interactionVolume.getNormal(0, 0);
-                    DimVector vel41 = interactionVolume.getNormal(3, 0);
-                    DimVector vel42 = interactionVolume.getNormal(1, 0);
-
-                    Dune::FieldVector<Scalar, 3> flux(0);
-                    switch (i)
-                    {
-                    case wPhaseIdx:
-                    {
-                        flux = fluxW;
-                        break;
-                    }
-                    case nPhaseIdx:
-                    {
-                        flux = fluxNw;
-                        break;
-                    }
-                    }
+        //calculate the gravity term
+        Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
+        Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
 
-                    vel12 *= flux[0] / (2 * interactionVolume.getFaceArea(0, 0)); //divide by 2 because the flux is related to the half face!
-                    vel14 *= flux[2] / (2 * interactionVolume.getFaceArea(3, 0));
-                    vel24 *= flux[1] / (2 * interactionVolume.getFaceArea(1, 0));
-                    vel21 *= flux[0] / (2 * interactionVolume.getFaceArea(0, 0));
-                    vel41 *= flux[2] / (4 * interactionVolume.getFaceArea(3, 0));
-                    vel42 *= flux[1] / (4 * interactionVolume.getFaceArea(1, 0));
-
-                    Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
-                    Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
-                    Scalar lambdaT24 = lambda24Upw[wPhaseIdx] + lambda24Upw[nPhaseIdx];
-                    Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
-                    Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
-                    Scalar fracFlow24 = (lambdaT24 > threshold_) ? lambda24Upw[i] / (lambdaT24) : 0.0;
-
-                    vel12 *= fracFlow12;
-                    vel14 *= fracFlow14;
-                    vel24 *= fracFlow24;
-                    vel21 *= fracFlow12;
-                    vel41 *= fracFlow14;
-                    vel42 *= fracFlow24;
-
-                    if (this->innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
-                    {
-                        vel12 *= 2;
-                        vel21 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx1][interactionVolume.getIndexOnElement(0, 1)])
-                    {
-                        vel14 *= 2;
-                        vel41 *= 2;
-                    }
-                    if (this->innerBoundaryVolumeFaces_[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
-                    {
-                        vel24 *= 2;
-                        vel42 *= 2;
-                    }
+        //calculate unit distVec
+        distVec /= dist;
+        Scalar areaScaling = (unitOuterNormal * distVec);
+        //this treatment of g allows to account for gravity flux through faces where the face normal has no z component (e.g. parallelepiped grids)
+        Scalar gravityTermW = (problem_.gravity() * distVec) * density_[wPhaseIdx] * areaScaling;
+        Scalar gravityTermNw = (problem_.gravity() * distVec) * density_[nPhaseIdx] * areaScaling;
 
-                    //store velocities
-                    //set velocity
-                    cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 0), vel12);
-                    cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 1), vel14);
-                    cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 0), vel24);
-                    cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 1), vel21);
-                    cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 0), vel41);
-                    cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 1), vel42);
-                }
-                //set velocity marker
-                cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 0));
-                cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 1));
-                cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 0));
-                cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 1));
-                cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 0));
-                cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 1));
-            }
-            else
-            {
-                DUNE_THROW(Dune::NotImplemented, "Unknown interactionvolume type!");
-            }
+        //calculate velocity depending on the pressure used -> use pc = pn - pw
+        switch (pressureType_)
+        {
+        case pw:
+        {
+            velocityW *= lambdaW * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermW);
+            velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermNw)
+                    + 0.5 * (lambdaNwI + lambdaNwBound) * scalarPerm * (pcI - pcBound) / dist;
+            break;
         }
-
-        // at least one face on boundary!
-        else
+        case pn:
         {
-            for (int elemIdx = 0; elemIdx < 2 * dim; elemIdx++)
-            {
-                bool isOutside = false;
-                for (int faceIdx = 0; faceIdx < dim; faceIdx++)
-                {
-                    int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
-                    if (interactionVolume.isOutsideFace(intVolFaceIdx))
-                    {
-                        isOutside = true;
-                        break;
-                    }
-                }
-                if (isOutside)
-                {
-                    continue;
-                }
-
-                ElementPointer & elementPointer = interactionVolume.getSubVolumeElement(elemIdx);
-
-                // get global coordinate of cell centers
-                const GlobalPosition& globalPos = elementPointer->geometry().center();
+            velocityW *= lambdaW * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermW)
+                    - 0.5 * (lambdaWI + lambdaWBound) * scalarPerm * (pcI - pcBound) / dist;
+            velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermNw);
+            break;
+        }
+        }
 
-                // cell index
-                int globalIdx = problem_.variables().index(*elementPointer);
+        //store velocities
+        cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
+        cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
+        cellData.fluxData().setVelocityMarker(isIndex);
 
-                //get the cell Data
-                CellData& cellData = problem_.variables().cellData(globalIdx);
+    } //end dirichlet boundary
 
-                //permeability vector at boundary
-                DimMatrix permeability(problem_.spatialParams().intrinsicPermeability(*elementPointer));
+    else if (bcType.isNeumann(pressEqIdx))
+    {
+        problem_.neumann(boundValues, intersection);
 
-                //get mobilities of the phases
-                Dune::FieldVector<Scalar, numPhases> lambda(cellData.mobility(wPhaseIdx));
-                lambda[nPhaseIdx] = cellData.mobility(nPhaseIdx);
+        Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
+        Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
 
-                for (int faceIdx = 0; faceIdx < dim; faceIdx++)
-                {
-                    int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
+        velocityW *= boundValues[wPhaseIdx];
+        velocityNw *= boundValues[nPhaseIdx];
 
-                    if (interactionVolume.isBoundaryFace(intVolFaceIdx))
-                    {
-                        if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(pressEqIdx))
-                        {
-                            int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, faceIdx);
-
-                            const ReferenceElement& referenceElement = ReferenceElements::general(
-                                    elementPointer->geometry().type());
-
-                            const LocalPosition& localPos = referenceElement.position(boundaryFaceIdx, 1);
-
-                            const GlobalPosition& globalPosFace = elementPointer->geometry().global(localPos);
-
-                            DimVector distVec(globalPosFace - globalPos);
-                            Scalar dist = distVec.two_norm();
-                            DimVector unitDistVec(distVec);
-                            unitDistVec /= dist;
-
-                            // get pc and lambda at the boundary
-                            Scalar satWBound = cellData.saturation(wPhaseIdx);
-                            //check boundary sat at face 1
-                            if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(satEqIdx))
-                            {
-                                Scalar satBound = interactionVolume.getDirichletValues(intVolFaceIdx)[saturationIdx];
-                                switch (saturationType_)
-                                {
-                                case sw:
-                                {
-                                    satWBound = satBound;
-                                      break;
-                                }
-                                case sn:
-                                {
-                                    satWBound = 1 - satBound;
-                                    break;
-                                }
-                                }
-
-                            }
-
-                            Scalar pcBound = MaterialLaw::pc(
-                                    problem_.spatialParams().materialLawParams(*elementPointer), satWBound);
-
-                            Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * problem_.gravity()
-                                    * (density_[nPhaseIdx] - density_[wPhaseIdx]);
-
-                            pcBound += gravityDiffBound;
-
-                            Dune::FieldVector<Scalar, numPhases> lambdaBound(
-                                    MaterialLaw::krw(problem_.spatialParams().materialLawParams(*elementPointer),
-                                            satWBound));
-                            lambdaBound[nPhaseIdx] = MaterialLaw::krn(
-                                    problem_.spatialParams().materialLawParams(*elementPointer), satWBound);
-                            lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx];
-                            lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx];
-
-                            Scalar gdeltaZ = (problem_.bBoxMax()-globalPosFace) * gravity_;
-                            Scalar potentialBoundW = interactionVolume.getDirichletValues(intVolFaceIdx)[pressureIdx] + density_[wPhaseIdx]*gdeltaZ;
-                            Scalar potentialBoundNw = potentialBoundW;
-
-                            //calculate potential gradients
-                            switch (pressureType_)
-                            {
-                            case pw:
-                            {
-                                potentialBoundNw += pcBound;
-                                break;
-                            }
-                            case pn:
-                            {
-                                //calculate potential gradients
-                                potentialBoundW -= pcBound;
-                                break;
-                            }
-                            }
-
-
-                            Scalar potentialDiffW = (cellData.potential(wPhaseIdx) - potentialBoundW) / dist;
-                            Scalar  potentialDiffNw = (cellData.potential(nPhaseIdx) - potentialBoundNw) / dist;
-
-                            //store potentials for further calculations (saturation, ...)
-                            cellData.fluxData().addUpwindPotential(wPhaseIdx, boundaryFaceIdx, potentialDiffW);
-                            cellData.fluxData().addUpwindPotential(nPhaseIdx, boundaryFaceIdx, potentialDiffNw);
-
-                            //calculated phase velocities from advective velocities -> capillary pressure velocity already added in pressure part!
-                            DimVector velocityW(0);
-                            DimVector velocityNw(0);
-
-                            // calculate capillary pressure gradient
-                            DimVector pressGradient = unitDistVec;
-                            pressGradient *= (cellData.potential(wPhaseIdx) - potentialBoundW) / dist;
-                            permeability.mv(pressGradient, velocityW);
-
-                            pressGradient = unitDistVec;
-                            pressGradient *= (cellData.potential(nPhaseIdx) - potentialBoundNw) / dist;
-                            permeability.mv(pressGradient, velocityNw);
-
-                            velocityW *= (potentialDiffW >= 0.) ? lambda[wPhaseIdx] : lambdaBound[wPhaseIdx];
-                            velocityNw *= (potentialDiffNw >= 0.) ? lambda[nPhaseIdx] : lambdaBound[nPhaseIdx];
-
-                            //velocity is calculated from two vertices of one intersection!
-                            velocityW *= 0.5;
-                            velocityNw *= 0.5;
-
-                            //store velocities
-                                cellData.fluxData().addVelocity(wPhaseIdx, boundaryFaceIdx, velocityW);
-                                cellData.fluxData().addVelocity(nPhaseIdx, boundaryFaceIdx, velocityNw);
-                                cellData.fluxData().setVelocityMarker(boundaryFaceIdx);
-
-                        }
-                        else if (interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressEqIdx))
-                        {
-                            int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, faceIdx);
-
-                            const ReferenceElement& referenceElement = ReferenceElements::general(
-                                    elementPointer->geometry().type());
-
-                            const LocalPosition& localPos = referenceElement.position(boundaryFaceIdx, 1);
-
-                            const GlobalPosition& globalPosFace = elementPointer->geometry().global(localPos);
-
-                            DimVector distVec(globalPosFace - globalPos);
-                            Scalar dist = distVec.two_norm();
-                            DimVector unitDistVec(distVec);
-                            unitDistVec /= dist;
-
-                            // get neumann boundary value
-                            PrimaryVariables boundValues(interactionVolume.getNeumannValues(intVolFaceIdx));
-
-                            boundValues[wPhaseIdx] /= density_[wPhaseIdx];
-                            boundValues[nPhaseIdx] /= density_[nPhaseIdx];
-
-                            DimVector velocityW(unitDistVec);
-                            DimVector velocityNw(unitDistVec);
-
-                            velocityW *= boundValues[wPhaseIdx] / (2 * interactionVolume.getFaceArea(elemIdx, faceIdx));
-                            velocityNw *= boundValues[nPhaseIdx]
-                                    / (2 * interactionVolume.getFaceArea(elemIdx, faceIdx));
-
-                            //store potentials for further calculations (saturation, ...)
-                            cellData.fluxData().addUpwindPotential(wPhaseIdx, boundaryFaceIdx, boundValues[wPhaseIdx]);
-                            cellData.fluxData().addUpwindPotential(nPhaseIdx, boundaryFaceIdx, boundValues[nPhaseIdx]);
-
-                            //store velocities
-                            cellData.fluxData().addVelocity(wPhaseIdx, boundaryFaceIdx, velocityW);
-                            cellData.fluxData().addVelocity(nPhaseIdx, boundaryFaceIdx, velocityNw);
-                            cellData.fluxData().setVelocityMarker(boundaryFaceIdx);
-                        }
-                        else
-                        {
-                            DUNE_THROW(Dune::NotImplemented,
-                                    "No valid boundary condition type defined for pressure equation!");
-                        }
-                    }
-                }
-            }
+            velocityW /= density_[wPhaseIdx];
+            velocityNw /= density_[nPhaseIdx];
 
-        } // end boundaries
+        //store potential gradients for further calculations
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, boundValues[wPhaseIdx]);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, boundValues[nPhaseIdx]);
 
-    } // end vertex iterator
-//        std::cout<<"velocityW = \n";
-//        for  (int i = 0; i<problem_.gridView().size(0);i++)
-//        {
-//            std::cout<<i<<": ";
-//            for (int j=0; j<4; j++)
-//            {
-//                std::cout<<"    ("<<j<<") "<<problem_.variables().cellData(i).fluxData().velocity(wPhaseIdx, j);
-//            }
-//            std::cout<<"\n";
-//        }
-//        std::cout<<"velocityNw = \n";
-//        for  (int i = 0; i<problem_.gridView().size(0);i++)
-//        {
-//            std::cout<<i<<": ";
-//            for (int j=0; j<4; j++)
-//            {
-//                std::cout<<"    ("<<j<<") "<<problem_.variables().cellData(i).fluxData().velocity(nPhaseIdx, j);
-//            }
-//            std::cout<<"\n";
-//        }
-    return;
-} // end method calcTotalVelocity
+        cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
+        cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
+        cellData.fluxData().setVelocityMarker(isIndex);
+    } //end neumann boundary
+    else
+    {
+        DUNE_THROW(Dune::NotImplemented, "No valid boundary condition type defined for pressure equation!");
+    }
+}
 
 }
 // end of Dune namespace
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dtransmissibilitycalculator.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dtransmissibilitycalculator.hh
new file mode 100644
index 0000000000000000000000000000000000000000..70bbffb27f14eae738f34c2b5ecb96a7e9c655c3
--- /dev/null
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dtransmissibilitycalculator.hh
@@ -0,0 +1,646 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_FVMPFAL2D_TRANSMISSIBILITYCALCULATOR_HH
+#define DUMUX_FVMPFAL2D_TRANSMISSIBILITYCALCULATOR_HH
+
+// dumux environment
+#include <dumux/decoupled/common/pressureproperties.hh>
+#include <dumux/decoupled/common/fv/mpfa/fvmpfaproperties.hh>
+#include <dumux/decoupled/common/fv/mpfa/mpfalinteractionvolume.hh>
+
+/**
+ * @file
+ * @brief Provides methods for transmissibility calculation
+ */
+
+namespace Dumux
+{
+//! \ingroup FVPressure2p
+/*! Provides methods for transmissibility calculation.
+ */
+template<class TypeTag>
+class FvMpfaL2dTransmissibilityCalculator
+{
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    enum
+        {
+            dim = GridView::dimension, dimWorld = GridView::dimensionworld
+        };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+
+    typedef typename GridView::template Codim<0>::EntityPointer ElementPointer;
+
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+    typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
+
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+    typedef typename Dumux::FVMPFALInteractionVolume<TypeTag> InteractionVolume;
+
+public:
+    typedef Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> TransmissibilityType;
+
+    enum
+    {
+        leftTriangle = -1,
+        noTransmissibility = 0,
+        rightTriangle = 1
+    };
+
+    // Calculates tranmissibility matrix
+    int calculateTransmissibility(
+            TransmissibilityType& transmissibility,
+            InteractionVolume& interactionVolume,
+            std::vector<DimVector >& lambda,
+            int idx1, int idx2, int idx3, int idx4);
+
+    // Calculates tranmissibility matrix of left L-shape
+    int calculateLeftHNTransmissibility(TransmissibilityType& transmissibility,
+    InteractionVolume& interactionVolume,
+    std::vector<DimVector >& lambda,
+    int idx1, int idx2, int idx3);
+
+    // Calculates tranmissibility matrix of right L-shape
+    int calculateRightHNTransmissibility(TransmissibilityType& transmissibility,
+    InteractionVolume& interactionVolume,
+    std::vector<DimVector >& lambda,
+    int idx1, int idx2, int idx3);
+
+
+    FvMpfaL2dTransmissibilityCalculator(Problem& problem) :
+        problem_(problem), R_(0)
+    {
+        if (dim != 2)
+        {
+            DUNE_THROW(Dune::NotImplemented, "Dimension not supported!");
+        }
+
+        // evaluate matrix R
+        if (dim == 2)
+        {
+            R_[0][1] = 1;
+            R_[1][0] = -1;
+        }
+    }
+
+private:
+    Problem& problem_;
+    DimMatrix R_;
+};
+
+/*! \brief Calculates tranmissibility matrix
+ *
+ * Calculates tranmissibility matrix of an L-shape for a certain flux face.
+ * Automatically selects one of the two possible L-shape (left, or right).
+ *
+ * \param transmissibility Matrix for the resulting transmissibility
+ * \param interactionVolume The interaction volume object (includes geometric information)
+ * \param lambda Mobilities of cells 1-4
+ * \param idx1 Index of cell 1 of the L-stencil
+ * \param idx2 Index of cell 2 of the L-stencil
+ * \param idx3 Index of cell 3 of the L-stencil
+ * \param idx4 Index of cell 4 of the L-stencil
+ */
+template<class TypeTag>
+int FvMpfaL2dTransmissibilityCalculator<TypeTag>::calculateTransmissibility(
+        TransmissibilityType& transmissibility,
+        InteractionVolume& interactionVolume,
+        std::vector<DimVector >& lambda,
+        int idx1, int idx2, int idx3, int idx4)
+{
+    ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(idx1);
+    ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(idx2);
+    ElementPointer& elementPointer3 = interactionVolume.getSubVolumeElement(idx3);
+    ElementPointer& elementPointer4 = interactionVolume.getSubVolumeElement(idx4);
+
+    if (elementPointer3 == elementPointer4 && elementPointer1->level() != elementPointer2->level())
+    {
+        return noTransmissibility;
+    }
+
+    // get global coordinate of cell centers
+    const GlobalPosition& globalPos1 = elementPointer1->geometry().center();
+    const GlobalPosition& globalPos2 = elementPointer2->geometry().center();
+    const GlobalPosition& globalPos3 = elementPointer3->geometry().center();
+    const GlobalPosition& globalPos4 = elementPointer4->geometry().center();
+
+    const GlobalPosition& globalPosCenter = interactionVolume.getCenterPosition();
+
+    const DimMatrix& K1 = problem_.spatialParams().intrinsicPermeability(*elementPointer1);
+    const DimMatrix& K2 = problem_.spatialParams().intrinsicPermeability(*elementPointer2);
+    const DimMatrix& K3 = problem_.spatialParams().intrinsicPermeability(*elementPointer3);
+    const DimMatrix& K4 = problem_.spatialParams().intrinsicPermeability(*elementPointer4);
+
+    const GlobalPosition& globalPosFace12 = interactionVolume.getFacePosition(idx1, 0);
+    const GlobalPosition& globalPosFace23 = interactionVolume.getFacePosition(idx2, 0);
+
+    // compute normal vectors nu1-nu7 in triangle R for first half edge
+    DimVector nu1R1(0);
+    R_.mv(globalPosFace12 - globalPos2, nu1R1);
+
+    DimVector nu2R1(0);
+    R_.mv(globalPos2 - globalPosFace23, nu2R1);
+
+    DimVector nu3R1(0);
+    R_.mv(globalPosFace23 - globalPos3, nu3R1);
+
+    DimVector nu4R1(0);
+    R_.mv(globalPos3 - globalPosCenter, nu4R1);
+
+    DimVector nu5R1(0);
+    R_.mv(globalPosCenter - globalPos1, nu5R1);
+
+    DimVector nu6R1(0);
+    R_.mv(globalPos1 - globalPosFace12, nu6R1);
+
+    DimVector nu7R1(0);
+    R_.mv(globalPosCenter - globalPos2, nu7R1);
+
+    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
+    DimVector Rnu2R1(0);
+    R_.mv(nu2R1, Rnu2R1);
+    Scalar T1R1 = nu1R1 * Rnu2R1;
+
+    DimVector Rnu4R1(0);
+    R_.mv(nu4R1, Rnu4R1);
+    Scalar T2R1 = nu3R1 * Rnu4R1;
+
+    DimVector Rnu6R1(0);
+    R_.mv(nu6R1, Rnu6R1);
+    Scalar T3R1 = nu5R1 * Rnu6R1;
+
+    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
+    DimVector K2nu1R1(0);
+    K2.mv(nu1R1, K2nu1R1);
+    DimVector K2nu2R1(0);
+    K2.mv(nu2R1, K2nu2R1);
+    DimVector K4nu3R1(0);
+    K3.mv(nu3R1, K4nu3R1);
+    DimVector K4nu4R1(0);
+    K3.mv(nu4R1, K4nu4R1);
+    DimVector K1nu5R1(0);
+    K1.mv(nu5R1, K1nu5R1);
+    DimVector K1nu6R1(0);
+    K1.mv(nu6R1, K1nu6R1);
+
+    DimVector Rnu1R1(0);
+    R_.mv(nu1R1, Rnu1R1);
+
+    DimVector &outerNormaln1R1 = interactionVolume.getNormal(idx2, 0);
+    DimVector &outerNormaln2 = interactionVolume.getNormal(idx1, 0);
+
+    Scalar omega111R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 0) / T1R1;
+    Scalar omega112R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 0) / T1R1;
+    Scalar omega211R1 = lambda[idx2][1] * (outerNormaln2 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 1) / T1R1;
+    Scalar omega212R1 = lambda[idx2][1] * (outerNormaln2 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 1) / T1R1;
+    Scalar omega123R1 = lambda[idx3][1] * (outerNormaln1R1 * K4nu3R1) * interactionVolume.getFaceArea(idx3, 1) / T2R1;
+    Scalar omega124R1 = lambda[idx3][1] * (outerNormaln1R1 * K4nu4R1) * interactionVolume.getFaceArea(idx3, 1) / T2R1;
+    Scalar omega235R1 = lambda[idx1][0] * (outerNormaln2 * K1nu5R1) * interactionVolume.getFaceArea(idx1, 0) / T3R1;
+    Scalar omega236R1 = lambda[idx1][0] * (outerNormaln2 * K1nu6R1) * interactionVolume.getFaceArea(idx1, 0) / T3R1;
+    Scalar chi711R1 = (nu7R1 * Rnu1R1) / T1R1;
+    Scalar chi712R1 = (nu7R1 * Rnu2R1) / T1R1;
+
+    // compute transmissibility matrix TR1 = CA^{-1}B+D
+    DimMatrix C(0), A(0);
+    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> D(0), B(0);
+
+    // evaluate matrix C, D, A, B
+    C[0][0] = -omega111R1;
+    C[0][1] = -omega112R1;
+    C[1][0] = -omega211R1;
+    C[1][1] = -omega212R1;
+
+    D[0][0] = omega111R1 + omega112R1;
+    D[1][0] = omega211R1 + omega212R1;
+
+    A[0][0] = omega111R1 - omega124R1 - omega123R1 * chi711R1;
+    A[0][1] = omega112R1 - omega123R1 * chi712R1;
+    A[1][0] = omega211R1 - omega236R1 * chi711R1;
+    A[1][1] = omega212R1 - omega235R1 - omega236R1 * chi712R1;
+
+    B[0][0] = omega111R1 + omega112R1 + omega123R1 * (1.0 - chi711R1 - chi712R1);
+    B[0][1] = -omega123R1 - omega124R1;
+    B[1][0] = omega211R1 + omega212R1 + omega236R1 * (1.0 - chi711R1 - chi712R1);
+    B[1][2] = -omega235R1 - omega236R1;
+
+    // compute TR1
+    A.invert();
+    D += B.leftmultiply(C.rightmultiply(A));
+    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> TR1(D);
+
+    // 2.use triangle L to compute the transmissibility of half edge
+    const GlobalPosition& globalPosFace14 = interactionVolume.getFacePosition(idx1, 1);
+
+    // compute normal vectors nu1-nu7 in triangle L for first half edge
+    DimVector nu1L1(0);
+    R_.mv(globalPosFace12 - globalPos1, nu1L1);
+
+    DimVector nu2L1(0);
+    R_.mv(globalPos1 - globalPosFace14, nu2L1);
+
+    DimVector nu3L1(0);
+    R_.mv(globalPosFace14 - globalPos4, nu3L1);
+
+    DimVector nu4L1(0);
+    R_.mv(globalPos4 - globalPosCenter, nu4L1);
+
+    DimVector nu5L1(0);
+    R_.mv(globalPosCenter - globalPos2, nu5L1);
+
+    DimVector nu6L1(0);
+    R_.mv(globalPos2 - globalPosFace12, nu6L1);
+
+    DimVector nu7L1(0);
+    R_.mv(globalPosCenter - globalPos1, nu7L1);
+
+    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
+    DimVector Rnu2L1(0);
+    R_.mv(nu2L1, Rnu2L1);
+    Scalar T1L1 = nu1L1 * Rnu2L1;
+
+    DimVector Rnu4L1(0);
+    R_.mv(nu4L1, Rnu4L1);
+    Scalar T2L1 = nu3L1 * Rnu4L1;
+
+    DimVector Rnu6L1(0);
+    R_.mv(nu6L1, Rnu6L1);
+    Scalar T3L1 = nu5L1 * Rnu6L1;
+
+    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
+    DimVector K1nu1L1(0);
+    K1.mv(nu1L1, K1nu1L1);
+    DimVector K1nu2L1(0);
+    K1.mv(nu2L1, K1nu2L1);
+    DimVector K3nu3L1(0);
+    K4.mv(nu3L1, K3nu3L1);
+    DimVector K3nu4L1(0);
+    K4.mv(nu4L1, K3nu4L1);
+    DimVector K2nu5L1(0);
+    K2.mv(nu5L1, K2nu5L1);
+    DimVector K2nu6L1(0);
+    K2.mv(nu6L1, K2nu6L1);
+
+    DimVector Rnu1L1(0);
+    R_.mv(nu1L1, Rnu1L1);
+
+    DimVector &outerNormaln1L1 = interactionVolume.getNormal(idx1, 1);
+
+    Scalar omega111L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu1L1) * interactionVolume.getFaceArea(idx1, 1) / T1L1;
+    Scalar omega112L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu2L1) * interactionVolume.getFaceArea(idx1, 1) / T1L1;
+    Scalar omega211L1 = lambda[idx1][0] * (outerNormaln2 * K1nu1L1) * interactionVolume.getFaceArea(idx1, 0) / T1L1;
+    Scalar omega212L1 = lambda[idx1][0] * (outerNormaln2 * K1nu2L1) * interactionVolume.getFaceArea(idx1, 0) / T1L1;
+    Scalar omega123L1 = lambda[idx4][0] * (outerNormaln1L1 * K3nu3L1) * interactionVolume.getFaceArea(idx4, 0) / T2L1;
+    Scalar omega124L1 = lambda[idx4][0] * (outerNormaln1L1 * K3nu4L1) * interactionVolume.getFaceArea(idx4, 0) / T2L1;
+    Scalar omega235L1 = lambda[idx2][1] * (outerNormaln2 * K2nu5L1) * interactionVolume.getFaceArea(idx2, 1) / T3L1;
+    Scalar omega236L1 = lambda[idx2][1] * (outerNormaln2 * K2nu6L1) * interactionVolume.getFaceArea(idx2, 1) / T3L1;
+    Scalar chi711L1 = (nu7L1 * Rnu1L1) / T1L1;
+    Scalar chi712L1 = (nu7L1 * Rnu2L1) / T1L1;
+
+    // compute transmissibility matrix TL1 = CA^{-1}B+D
+    C = 0;
+    A = 0;
+    D = 0;
+    B = 0;
+
+    // evaluate matrix C, D, A, B
+    C[0][0] = -omega111L1;
+    C[0][1] = -omega112L1;
+    C[1][0] = -omega211L1;
+    C[1][1] = -omega212L1;
+
+    D[0][0] = omega111L1 + omega112L1;
+    D[1][0] = omega211L1 + omega212L1;
+
+    A[0][0] = omega111L1 - omega124L1 - omega123L1 * chi711L1;
+    A[0][1] = omega112L1 - omega123L1 * chi712L1;
+    A[1][0] = omega211L1 - omega236L1 * chi711L1;
+    A[1][1] = omega212L1 - omega235L1 - omega236L1 * chi712L1;
+
+    B[0][0] = omega111L1 + omega112L1 + omega123L1 * (1.0 - chi711L1 - chi712L1);
+    B[0][1] = -omega123L1 - omega124L1;
+    B[1][0] = omega211L1 + omega212L1 + omega236L1 * (1.0 - chi711L1 - chi712L1);
+    B[1][2] = -omega235L1 - omega236L1;
+
+    // compute TL1
+    A.invert();
+    D += B.leftmultiply(C.rightmultiply(A));
+    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> TL1(D);
+
+    //selection criterion
+    Scalar sR = std::abs(TR1[1][2] - TR1[1][0]);
+    Scalar sL = std::abs(TL1[1][0] - TL1[1][2]);
+
+    // 3.decide which triangle (which transmissibility coefficients) to use
+    if (sR <= sL)
+    {
+        transmissibility = TR1;
+        return rightTriangle;
+    }
+    else
+    {
+        transmissibility = TL1;
+        return leftTriangle;
+    }
+}
+
+/*! \brief Calculates tranmissibility matrix
+ *
+ * Calculates tranmissibility matrix of an L-shape for a certain flux face.
+ * Calculates only the transmissibility of the left L-shape (needed at hanging nodes HN).
+ *
+ * \param transmissibilityLeft Matrix for the resulting transmissibility
+ * \param interactionVolume The interaction volume object (includes geometric information)
+ * \param lambda Mobilities of cells 1-3
+ * \param idx1 Index of cell 1 of the L-stencil
+ * \param idx2 Index of cell 2 of the L-stencil
+ * \param idx3 Index of cell 3 of the L-stencil
+ */
+template<class TypeTag>
+int FvMpfaL2dTransmissibilityCalculator<TypeTag>::calculateLeftHNTransmissibility(
+        TransmissibilityType& transmissibilityLeft,
+        InteractionVolume& interactionVolume,
+        std::vector<DimVector >& lambda,
+        int idx1, int idx2, int idx3)
+{
+    ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(idx1);
+    ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(idx2);
+    ElementPointer& elementPointer3 = interactionVolume.getSubVolumeElement(idx3);
+
+    if (elementPointer1->level() != elementPointer3->level())
+    {
+        return noTransmissibility;
+    }
+
+    // get global coordinate of cell centers
+    const GlobalPosition& globalPos1 = elementPointer1->geometry().center();
+    const GlobalPosition& globalPos2 = elementPointer2->geometry().center();
+    const GlobalPosition& globalPos3 = elementPointer3->geometry().center();
+
+    const GlobalPosition& globalPosCenter = interactionVolume.getCenterPosition();
+
+    const DimMatrix& K1 = problem_.spatialParams().intrinsicPermeability(*elementPointer1);
+    const DimMatrix& K2 = problem_.spatialParams().intrinsicPermeability(*elementPointer2);
+    const DimMatrix& K3 = problem_.spatialParams().intrinsicPermeability(*elementPointer3);
+
+    const GlobalPosition& globalPosFace12 = interactionVolume.getFacePosition(idx1, 0);
+    DimVector &outerNormaln2 = interactionVolume.getNormal(idx1, 0);
+
+    // compute transmissibility matrix TR1 = CA^{-1}B+D
+    DimMatrix C(0), A(0);
+    TransmissibilityType D(0), B(0);
+
+    // 2.use triangle L to compute the transmissibility of half edge
+    const GlobalPosition& globalPosFace14 = interactionVolume.getFacePosition(idx1, 1);
+
+    // compute normal vectors nu1-nu7 in triangle L for first half edge
+    DimVector nu1L1(0);
+    R_.mv(globalPosFace12 - globalPos1, nu1L1);
+
+    DimVector nu2L1(0);
+    R_.mv(globalPos1 - globalPosFace14, nu2L1);
+
+    DimVector nu3L1(0);
+    R_.mv(globalPosFace14 - globalPos3, nu3L1);
+
+    DimVector nu4L1(0);
+    R_.mv(globalPos3 - globalPosCenter, nu4L1);
+
+    DimVector nu5L1(0);
+    R_.mv(globalPosCenter - globalPos2, nu5L1);
+
+    DimVector nu6L1(0);
+    R_.mv(globalPos2 - globalPosFace12, nu6L1);
+
+    DimVector nu7L1(0);
+    R_.mv(globalPosCenter - globalPos1, nu7L1);
+
+    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
+    DimVector Rnu2L1(0);
+    R_.mv(nu2L1, Rnu2L1);
+    Scalar T1L1 = nu1L1 * Rnu2L1;
+
+    DimVector Rnu4L1(0);
+    R_.mv(nu4L1, Rnu4L1);
+    Scalar T2L1 = nu3L1 * Rnu4L1;
+
+    DimVector Rnu6L1(0);
+    R_.mv(nu6L1, Rnu6L1);
+    Scalar T3L1 = nu5L1 * Rnu6L1;
+
+    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
+    DimVector K1nu1L1(0);
+    K1.mv(nu1L1, K1nu1L1);
+    DimVector K1nu2L1(0);
+    K1.mv(nu2L1, K1nu2L1);
+    DimVector K3nu3L1(0);
+    K3.mv(nu3L1, K3nu3L1);
+    DimVector K3nu4L1(0);
+    K3.mv(nu4L1, K3nu4L1);
+    DimVector K2nu5L1(0);
+    K2.mv(nu5L1, K2nu5L1);
+    DimVector K2nu6L1(0);
+    K2.mv(nu6L1, K2nu6L1);
+
+    DimVector Rnu1L1(0);
+    R_.mv(nu1L1, Rnu1L1);
+
+    DimVector &outerNormaln1L1 = interactionVolume.getNormal(idx1, 1);
+
+    Scalar omega111L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu1L1) * interactionVolume.getFaceArea(idx1, 1) / T1L1;
+    Scalar omega112L1 = lambda[idx1][1] * (outerNormaln1L1 * K1nu2L1) * interactionVolume.getFaceArea(idx1, 1) / T1L1;
+    Scalar omega211L1 = lambda[idx1][0] * (outerNormaln2 * K1nu1L1) * interactionVolume.getFaceArea(idx1, 0) / T1L1;
+    Scalar omega212L1 = lambda[idx1][0] * (outerNormaln2 * K1nu2L1) * interactionVolume.getFaceArea(idx1, 0) / T1L1;
+    Scalar omega123L1 = lambda[idx3][0] * (outerNormaln1L1 * K3nu3L1) * interactionVolume.getFaceArea(idx3, 0) / T2L1;
+    Scalar omega124L1 = lambda[idx3][0] * (outerNormaln1L1 * K3nu4L1) * interactionVolume.getFaceArea(idx3, 0) / T2L1;
+    Scalar omega235L1 = lambda[idx2][1] * (outerNormaln2 * K2nu5L1) * interactionVolume.getFaceArea(idx2, 1) / T3L1;
+    Scalar omega236L1 = lambda[idx2][1] * (outerNormaln2 * K2nu6L1) * interactionVolume.getFaceArea(idx2, 1) / T3L1;
+    Scalar chi711L1 = (nu7L1 * Rnu1L1) / T1L1;
+    Scalar chi712L1 = (nu7L1 * Rnu2L1) / T1L1;
+
+    // compute transmissibility matrix TL1 = CA^{-1}B+D
+    // evaluate matrix C, D, A, B
+    C[0][0] = -omega111L1;
+    C[0][1] = -omega112L1;
+    C[1][0] = -omega211L1;
+    C[1][1] = -omega212L1;
+
+    D[0][0] = omega111L1 + omega112L1;
+    D[1][0] = omega211L1 + omega212L1;
+
+    A[0][0] = omega111L1 - omega124L1 - omega123L1 * chi711L1;
+    A[0][1] = omega112L1 - omega123L1 * chi712L1;
+    A[1][0] = omega211L1 - omega236L1 * chi711L1;
+    A[1][1] = omega212L1 - omega235L1 - omega236L1 * chi712L1;
+
+    B[0][0] = omega111L1 + omega112L1 + omega123L1 * (1.0 - chi711L1 - chi712L1);
+    B[0][1] = -omega123L1 - omega124L1;
+    B[1][0] = omega211L1 + omega212L1 + omega236L1 * (1.0 - chi711L1 - chi712L1);
+    B[1][2] = -omega235L1 - omega236L1;
+
+    // compute TL1
+    A.invert();
+    D += B.leftmultiply(C.rightmultiply(A));
+
+    // 3.decide which triangle (which transmissibility coefficients) to use
+    transmissibilityLeft = D;
+    return leftTriangle;
+}
+
+/*! \brief Calculates tranmissibility matrix
+ *
+ * Calculates tranmissibility matrix of an L-shape for a certain flux face.
+ * Calculates only the transmissibility of the right L-shape (needed at hanging nodes HN).
+ *
+ * \param transmissibilityRight Matrix for the resulting transmissibility
+ * \param interactionVolume The interaction volume object (includes geometric information)
+ * \param lambda Mobilities of cells 1-3
+ * \param idx1 Index of cell 1 of the L-stencil
+ * \param idx2 Index of cell 2 of the L-stencil
+ * \param idx3 Index of cell 3 of the L-stencil
+ */
+template<class TypeTag>
+int FvMpfaL2dTransmissibilityCalculator<TypeTag>::calculateRightHNTransmissibility(
+        TransmissibilityType& transmissibilityRight,
+        InteractionVolume& interactionVolume,
+        std::vector<DimVector >& lambda,
+        int idx1, int idx2, int idx3)
+{
+    ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(idx1);
+    ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(idx2);
+    ElementPointer& elementPointer3 = interactionVolume.getSubVolumeElement(idx3);
+
+    if (elementPointer2->level() != elementPointer3->level())
+    {
+        return noTransmissibility;
+    }
+
+    // get global coordinate of cell centers
+    const GlobalPosition& globalPos1 = elementPointer1->geometry().center();
+    const GlobalPosition& globalPos2 = elementPointer2->geometry().center();
+    const GlobalPosition& globalPos3 = elementPointer3->geometry().center();
+
+    const GlobalPosition& globalPosCenter = interactionVolume.getCenterPosition();
+
+    const DimMatrix& K1 = problem_.spatialParams().intrinsicPermeability(*elementPointer1);
+    const DimMatrix& K2 = problem_.spatialParams().intrinsicPermeability(*elementPointer2);
+    const DimMatrix& K3 = problem_.spatialParams().intrinsicPermeability(*elementPointer3);
+
+    const GlobalPosition& globalPosFace12 = interactionVolume.getFacePosition(idx1, 0);
+    const GlobalPosition& globalPosFace23 = interactionVolume.getFacePosition(idx2, 0);
+
+    // compute normal vectors nu1-nu7 in triangle R for first half edge
+    DimVector nu1R1(0);
+    R_.mv(globalPosFace12 - globalPos2, nu1R1);
+
+    DimVector nu2R1(0);
+    R_.mv(globalPos2 - globalPosFace23, nu2R1);
+
+    DimVector nu3R1(0);
+    R_.mv(globalPosFace23 - globalPos3, nu3R1);
+
+    DimVector nu4R1(0);
+    R_.mv(globalPos3 - globalPosCenter, nu4R1);
+
+    DimVector nu5R1(0);
+    R_.mv(globalPosCenter - globalPos1, nu5R1);
+
+    DimVector nu6R1(0);
+    R_.mv(globalPos1 - globalPosFace12, nu6R1);
+
+    DimVector nu7R1(0);
+    R_.mv(globalPosCenter - globalPos2, nu7R1);
+
+    // compute T, i.e., the area of quadrilateral made by normal vectors 'nu'
+    DimVector Rnu2R1(0);
+    R_.mv(nu2R1, Rnu2R1);
+    Scalar T1R1 = nu1R1 * Rnu2R1;
+
+    DimVector Rnu4R1(0);
+    R_.mv(nu4R1, Rnu4R1);
+    Scalar T2R1 = nu3R1 * Rnu4R1;
+
+    DimVector Rnu6R1(0);
+    R_.mv(nu6R1, Rnu6R1);
+    Scalar T3R1 = nu5R1 * Rnu6R1;
+
+    // compute components needed for flux calculation, denoted as 'omega' and 'chi'
+    DimVector K2nu1R1(0);
+    K2.mv(nu1R1, K2nu1R1);
+    DimVector K2nu2R1(0);
+    K2.mv(nu2R1, K2nu2R1);
+    DimVector K3nu3R1(0);
+    K3.mv(nu3R1, K3nu3R1);
+    DimVector K3nu4R1(0);
+    K3.mv(nu4R1, K3nu4R1);
+    DimVector K1nu5R1(0);
+    K1.mv(nu5R1, K1nu5R1);
+    DimVector K1nu6R1(0);
+    K1.mv(nu6R1, K1nu6R1);
+
+    DimVector Rnu1R1(0);
+    R_.mv(nu1R1, Rnu1R1);
+
+    DimVector &outerNormaln1R1 = interactionVolume.getNormal(idx2, 0);
+    DimVector &outerNormaln2 = interactionVolume.getNormal(idx1, 0);
+
+    Scalar omega111R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 0) / T1R1;
+    Scalar omega112R1 = lambda[idx2][0] * (outerNormaln1R1 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 0) / T1R1;
+    Scalar omega211R1 = lambda[idx2][1] * (outerNormaln2 * K2nu1R1) * interactionVolume.getFaceArea(idx2, 1) / T1R1;
+    Scalar omega212R1 = lambda[idx2][1] * (outerNormaln2 * K2nu2R1) * interactionVolume.getFaceArea(idx2, 1) / T1R1;
+    Scalar omega123R1 = lambda[idx3][1] * (outerNormaln1R1 * K3nu3R1) * interactionVolume.getFaceArea(idx3, 1) / T2R1;
+    Scalar omega124R1 = lambda[idx3][1] * (outerNormaln1R1 * K3nu4R1) * interactionVolume.getFaceArea(idx3, 1) / T2R1;
+    Scalar omega235R1 = lambda[idx1][0] * (outerNormaln2 * K1nu5R1) * interactionVolume.getFaceArea(idx1, 0) / T3R1;
+    Scalar omega236R1 = lambda[idx1][0] * (outerNormaln2 * K1nu6R1) * interactionVolume.getFaceArea(idx1, 0) / T3R1;
+    Scalar chi711R1 = (nu7R1 * Rnu1R1) / T1R1;
+    Scalar chi712R1 = (nu7R1 * Rnu2R1) / T1R1;
+
+    // compute transmissibility matrix TR1 = CA^{-1}B+D
+    DimMatrix C(0), A(0);
+    TransmissibilityType D(0), B(0);
+
+    // evaluate matrix C, D, A, B
+    C[0][0] = -omega111R1;
+    C[0][1] = -omega112R1;
+    C[1][0] = -omega211R1;
+    C[1][1] = -omega212R1;
+
+    D[0][0] = omega111R1 + omega112R1;
+    D[1][0] = omega211R1 + omega212R1;
+
+    A[0][0] = omega111R1 - omega124R1 - omega123R1 * chi711R1;
+    A[0][1] = omega112R1 - omega123R1 * chi712R1;
+    A[1][0] = omega211R1 - omega236R1 * chi711R1;
+    A[1][1] = omega212R1 - omega235R1 - omega236R1 * chi712R1;
+
+    B[0][0] = omega111R1 + omega112R1 + omega123R1 * (1.0 - chi711R1 - chi712R1);
+    B[0][1] = -omega123R1 - omega124R1;
+    B[1][0] = omega211R1 + omega212R1 + omega236R1 * (1.0 - chi711R1 - chi712R1);
+    B[1][2] = -omega235R1 - omega236R1;
+
+    // compute TR1
+    A.invert();
+    D += B.leftmultiply(C.rightmultiply(A));
+
+    transmissibilityRight = D;
+    return rightTriangle;
+}
+}// end of Dune namespace
+#endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dvelocity2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dvelocity2p.hh
new file mode 100644
index 0000000000000000000000000000000000000000..d6241a583c0c900f98cdc83b57cf0e41e49fc75e
--- /dev/null
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dvelocity2p.hh
@@ -0,0 +1,862 @@
+// -*- 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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_FVMPFAL2DVELOCITY2P_HH
+#define DUMUX_FVMPFAL2DVELOCITY2P_HH
+
+
+#include <dune/grid/common/gridenums.hh>
+#include <dumux/decoupled/2p/diffusion/diffusionproperties2p.hh>
+#include <dumux/decoupled/common/fv/mpfa/fvmpfaproperties.hh>
+#include <dumux/decoupled/common/fv/mpfa/mpfalinteractionvolume.hh>
+#include "fvmpfal2dtransmissibilitycalculator.hh"
+
+/**
+ * @file
+ * @brief  Velocity calculation using a 2-d MPFA L-method
+ */
+
+namespace Dumux
+{
+template<class TypeTag> class FvMpfaL2dVelocity2p
+{
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum
+        {
+            dim = GridView::dimension, dimWorld = GridView::dimensionworld
+        };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+
+#if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
+    typedef typename Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::ReferenceElement<Scalar, dim> ReferenceElement;
+#else
+    typedef typename Dune::GenericReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<Scalar, dim> ReferenceElement;
+#endif
+
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename SpatialParams::MaterialLaw MaterialLaw;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes;
+    typedef typename SolutionTypes::PrimaryVariables PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData;
+
+    typedef typename GridView::Traits::template Codim<0>::Entity Element;
+    typedef typename GridView::Grid Grid;
+    typedef typename GridView::IndexSet IndexSet;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+    typedef typename Grid::template Codim<0>::EntityPointer ElementPointer;
+
+    typedef typename Element::Geometry Geometry;
+    #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
+        typedef typename Geometry::JacobianTransposed JacobianTransposed;
+    #else
+        typedef typename Geometry::Jacobian JacobianTransposed;
+    #endif
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridTypeIndices) GridTypeIndices;
+
+    typedef typename Dumux::FVMPFALInteractionVolume<TypeTag> InteractionVolume;
+    typedef Dumux::FvMpfaL2dTransmissibilityCalculator<TypeTag> TransmissibilityCalculator;
+    typedef std::vector<Dune::FieldVector<bool, 2 * dim> > InnerBoundaryVolumeFaces;
+
+    enum
+        {
+            pw = Indices::pressureW,
+            pn = Indices::pressureNw,
+            pglobal = Indices::pressureGlobal,
+            sw = Indices::saturationW,
+            sn = Indices::saturationNw,
+            vw = Indices::velocityW,
+            vn = Indices::velocityNw,
+            vt = Indices::velocityTotal
+        };
+    enum
+        {
+            wPhaseIdx = Indices::wPhaseIdx,
+            nPhaseIdx = Indices::nPhaseIdx,
+            pressureIdx = Indices::pressureIdx,
+            saturationIdx = Indices::saturationIdx,
+            pressureEqIdx = Indices::pressureEqIdx,
+            satEqIdx = Indices::satEqIdx,
+            numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+        };
+
+    typedef Dune::FieldVector<Scalar, dim> LocalPosition;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+    typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+public:
+    FvMpfaL2dVelocity2p(Problem& problem) :
+        problem_(problem), transmissibilityCalculator_(problem), gravity_(problem.gravity())
+    {
+        density_[wPhaseIdx] = 0.;
+        density_[nPhaseIdx] = 0.;
+        viscosity_[wPhaseIdx] = 0.;
+        viscosity_[nPhaseIdx] = 0.;
+
+        vtkOutputLevel_ = GET_PARAM_FROM_GROUP(TypeTag, int, Vtk, OutputLevel);
+    }
+
+    void calculateInnerInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData1, CellData& cellData2, CellData& cellData3, CellData& cellData4, InnerBoundaryVolumeFaces& innerBoundaryVolumeFaces);
+    void calculateBoundaryInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData, int elemIdx);
+
+    void initialize()
+    {
+        ElementIterator element = problem_.gridView().template begin<0>();
+        FluidState fluidState;
+        fluidState.setPressure(wPhaseIdx, problem_.referencePressure(*element));
+        fluidState.setPressure(nPhaseIdx, problem_.referencePressure(*element));
+        fluidState.setTemperature(problem_.temperature(*element));
+        fluidState.setSaturation(wPhaseIdx, 1.);
+        fluidState.setSaturation(nPhaseIdx, 0.);
+        density_[wPhaseIdx] = FluidSystem::density(fluidState, wPhaseIdx);
+        density_[nPhaseIdx] = FluidSystem::density(fluidState, nPhaseIdx);
+        viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
+        viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
+
+        return;
+    }
+
+    //! \brief Write data files
+    /*  \param name file name */
+    template<class MultiWriter>
+    void addOutputVtkFields(MultiWriter &writer)
+    {
+        if (vtkOutputLevel_ > 0)
+        {
+            Dune::BlockVector < DimVector > &velocityWetting = *(writer.template allocateManagedBuffer<Scalar, dim>(
+                                                                                                                    problem_.gridView().size(0)));
+            Dune::BlockVector < DimVector > &velocityNonwetting = *(writer.template allocateManagedBuffer<Scalar, dim>(
+                                                                                                                       problem_.gridView().size(0)));
+
+            // compute update vector
+            ElementIterator eEndIt = problem_.gridView().template end<0>();
+            for (ElementIterator eIt = problem_.gridView().template begin<0>(); eIt != eEndIt; ++eIt)
+            {
+                // cell index
+                int globalIdx = problem_.variables().index(*eIt);
+
+                CellData & cellData = problem_.variables().cellData(globalIdx);
+
+                Dune::FieldVector < Scalar, 2 * dim > fluxW(0);
+                Dune::FieldVector < Scalar, 2 * dim > fluxNw(0);
+
+                // run through all intersections with neighbors and boundary
+                IntersectionIterator isEndIt = problem_.gridView().iend(*eIt);
+                for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isEndIt; ++isIt)
+                {
+                    int isIndex = isIt->indexInInside();
+
+                    fluxW[isIndex] += isIt->geometry().volume()
+                        * (isIt->centerUnitOuterNormal() * cellData.fluxData().velocity(wPhaseIdx, isIndex));
+                    fluxNw[isIndex] += isIt->geometry().volume()
+                        * (isIt->centerUnitOuterNormal() * cellData.fluxData().velocity(nPhaseIdx, isIndex));
+                }
+
+                DimVector refVelocity(0);
+                refVelocity[0] = 0.5 * (fluxW[1] - fluxW[0]);
+                refVelocity[1] = 0.5 * (fluxW[3] - fluxW[2]);
+
+                const DimVector& localPos = ReferenceElements::general(eIt->geometry().type()).position(0, 0);
+
+                // get the transposed Jacobian of the element mapping
+                const JacobianTransposed jacobianT = eIt->geometry().jacobianTransposed(localPos);
+
+                // calculate the element velocity by the Piola transformation
+                DimVector elementVelocity(0);
+                jacobianT.umtv(refVelocity, elementVelocity);
+                elementVelocity /= eIt->geometry().integrationElement(localPos);
+
+                velocityWetting[globalIdx] = elementVelocity;
+
+                refVelocity = 0;
+                refVelocity[0] = 0.5 * (fluxNw[1] - fluxNw[0]);
+                refVelocity[1] = 0.5 * (fluxNw[3] - fluxNw[2]);
+
+                // calculate the element velocity by the Piola transformation
+                elementVelocity = 0;
+                jacobianT.umtv(refVelocity, elementVelocity);
+                elementVelocity /= eIt->geometry().integrationElement(localPos);
+
+                velocityNonwetting[globalIdx] = elementVelocity;
+            }
+
+            writer.attachCellData(velocityWetting, "wetting-velocity", dim);
+            writer.attachCellData(velocityNonwetting, "non-wetting-velocity", dim);
+        }
+
+        return;
+    }
+
+private:
+    Problem& problem_;
+protected:
+    TransmissibilityCalculator transmissibilityCalculator_;
+
+    const GlobalPosition& gravity_; //!< vector including the gravity constant
+
+    Scalar density_[numPhases];
+    Scalar viscosity_[numPhases];
+
+    int vtkOutputLevel_;
+
+    static constexpr Scalar threshold_ = 1e-15;
+    static const int velocityType_ = GET_PROP_VALUE(TypeTag, VelocityFormulation);//!< gives kind of velocity used (\f$ 0 = v_w\f$, \f$ 1 = v_n\f$, \f$ 2 = v_t\f$)
+    static const int pressureType_ = GET_PROP_VALUE(TypeTag, PressureFormulation);//!< gives kind of pressure used (\f$ 0 = p_w\f$, \f$ 1 = p_n\f$, \f$ 2 = p_{global}\f$)
+    static const int saturationType_ = GET_PROP_VALUE(TypeTag, SaturationFormulation);//!< gives kind of saturation used (\f$ 0 = S_w\f$, \f$ 1 = S_n\f$)
+};
+// end of template
+
+template<class TypeTag>
+void FvMpfaL2dVelocity2p<TypeTag>::calculateInnerInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData1, CellData& cellData2, CellData& cellData3, CellData& cellData4, InnerBoundaryVolumeFaces& innerBoundaryVolumeFaces)
+{
+    ElementPointer & elementPointer1 = interactionVolume.getSubVolumeElement(0);
+    ElementPointer & elementPointer2 = interactionVolume.getSubVolumeElement(1);
+    ElementPointer & elementPointer3 = interactionVolume.getSubVolumeElement(2);
+    ElementPointer & elementPointer4 = interactionVolume.getSubVolumeElement(3);
+
+    int level1 = elementPointer1->level();
+    int level2 = elementPointer2->level();
+    int level3 = elementPointer3->level();
+    int level4 = elementPointer4->level();
+
+    // cell index
+    int globalIdx1 = problem_.variables().index(*elementPointer1);
+    int globalIdx2 = problem_.variables().index(*elementPointer2);
+    int globalIdx3 = problem_.variables().index(*elementPointer3);
+    int globalIdx4 = problem_.variables().index(*elementPointer4);
+
+    // get pressure values
+    Dune::FieldVector < Scalar, 2 * dim > potW(0);
+    Dune::FieldVector < Scalar, 2 * dim > potNw(0);
+
+    potW[0] = cellData1.potential(wPhaseIdx);
+    potW[1] = cellData2.potential(wPhaseIdx);
+    potW[2] = cellData3.potential(wPhaseIdx);
+    potW[3] = cellData4.potential(wPhaseIdx);
+
+    potNw[0] = cellData1.potential(nPhaseIdx);
+    potNw[1] = cellData2.potential(nPhaseIdx);
+    potNw[2] = cellData3.potential(nPhaseIdx);
+    potNw[3] = cellData4.potential(nPhaseIdx);
+
+    //get mobilities of the phases
+    Dune::FieldVector < Scalar, numPhases > lambda1(cellData1.mobility(wPhaseIdx));
+    lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
+
+    //compute total mobility of cell 1
+    Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
+
+    //get mobilities of the phases
+    Dune::FieldVector < Scalar, numPhases > lambda2(cellData2.mobility(wPhaseIdx));
+    lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
+
+    //compute total mobility of cell 1
+    Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
+
+    //get mobilities of the phases
+    Dune::FieldVector < Scalar, numPhases > lambda3(cellData3.mobility(wPhaseIdx));
+    lambda3[nPhaseIdx] = cellData3.mobility(nPhaseIdx);
+
+    //compute total mobility of cell 1
+    Scalar lambdaTotal3 = lambda3[wPhaseIdx] + lambda3[nPhaseIdx];
+
+    //get mobilities of the phases
+    Dune::FieldVector < Scalar, numPhases > lambda4(cellData4.mobility(wPhaseIdx));
+    lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
+
+    //compute total mobility of cell 1
+    Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
+
+
+    std::vector < DimVector > lambda(2 * dim);
+
+    lambda[0][0] = lambdaTotal1;
+    lambda[0][1] = lambdaTotal1;
+    lambda[1][0] = lambdaTotal2;
+    lambda[1][1] = lambdaTotal2;
+    lambda[2][0] = lambdaTotal3;
+    lambda[2][1] = lambdaTotal3;
+    lambda[3][0] = lambdaTotal4;
+    lambda[3][1] = lambdaTotal4;
+
+    Scalar potentialDiffW12 = 0;
+    Scalar potentialDiffW14 = 0;
+    Scalar potentialDiffW32 = 0;
+    Scalar potentialDiffW34 = 0;
+
+    Scalar potentialDiffNw12 = 0;
+    Scalar potentialDiffNw14 = 0;
+    Scalar potentialDiffNw32 = 0;
+    Scalar potentialDiffNw34 = 0;
+
+    //flux vector
+    Dune::FieldVector < Scalar, 2 * dim > fluxW(0);
+    Dune::FieldVector < Scalar, 2 * dim > fluxNw(0);
+
+    Dune::FieldMatrix < Scalar, dim, 2 * dim - dim + 1 > T(0);
+    DimVector Tu(0);
+    Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
+
+    int lType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
+
+    if (lType == TransmissibilityCalculator::rightTriangle)
+    {
+        u[0] = potW[1];
+        u[1] = potW[2];
+        u[2] = potW[0];
+
+        T.mv(u, Tu);
+
+        fluxW[0] = Tu[1];
+        potentialDiffW12 = Tu[1];
+
+        u[0] = potNw[1];
+        u[1] = potNw[2];
+        u[2] = potNw[0];
+
+        T.mv(u, Tu);
+
+        fluxNw[0] = Tu[1];
+        potentialDiffNw12 = Tu[1];
+    }
+    else
+    {
+        u[0] = potW[0];
+        u[1] = potW[3];
+        u[2] = potW[1];
+
+        T.mv(u, Tu);
+
+        fluxW[0] = Tu[1];
+        potentialDiffW12 = Tu[1];
+
+        u[0] = potNw[0];
+        u[1] = potNw[3];
+        u[2] = potNw[1];
+
+        T.mv(u, Tu);
+
+        fluxNw[0] = Tu[1];
+        potentialDiffNw12 = Tu[1];
+    }
+
+    lType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
+
+    if (lType == TransmissibilityCalculator::rightTriangle)
+    {
+        u[0] = potW[2];
+        u[1] = potW[3];
+        u[2] = potW[1];
+
+        T.mv(u, Tu);
+
+        fluxW[1] = Tu[1];
+        potentialDiffW32 = -Tu[1];
+
+        u[0] = potNw[2];
+        u[1] = potNw[3];
+        u[2] = potNw[1];
+
+        T.mv(u, Tu);
+
+        fluxNw[1] = Tu[1];
+        potentialDiffNw32 = -Tu[1];
+    }
+    else
+    {
+        u[0] = potW[1];
+        u[1] = potW[0];
+        u[2] = potW[2];
+
+        T.mv(u, Tu);
+
+        fluxW[1] = Tu[1];
+        potentialDiffW32 = -Tu[1];
+
+        u[0] = potNw[1];
+        u[1] = potNw[0];
+        u[2] = potNw[2];
+
+        T.mv(u, Tu);
+
+        fluxNw[1] = Tu[1];
+        potentialDiffNw32 = -Tu[1];
+    }
+
+    lType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
+
+    if (lType == TransmissibilityCalculator::rightTriangle)
+    {
+        u[0] = potW[3];
+        u[1] = potW[0];
+        u[2] = potW[2];
+
+        T.mv(u, Tu);
+
+        fluxW[2] = Tu[1];
+        potentialDiffW34 = Tu[1];
+
+        u[0] = potNw[3];
+        u[1] = potNw[0];
+        u[2] = potNw[2];
+
+        T.mv(u, Tu);
+
+        fluxNw[2] = Tu[1];
+        potentialDiffNw34 = Tu[1];
+    }
+    else
+    {
+        u[0] = potW[2];
+        u[1] = potW[1];
+        u[2] = potW[3];
+
+        T.mv(u, Tu);
+
+        fluxW[2] = Tu[1];
+        potentialDiffW34 = Tu[1];
+
+        u[0] = potNw[2];
+        u[1] = potNw[1];
+        u[2] = potNw[3];
+
+        T.mv(u, Tu);
+
+        fluxNw[2] = Tu[1];
+        potentialDiffNw34 = Tu[1];
+    }
+
+    lType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
+
+    if (lType == TransmissibilityCalculator::rightTriangle)
+    {
+        u[0] = potW[0];
+        u[1] = potW[1];
+        u[2] = potW[3];
+
+        T.mv(u, Tu);
+
+        fluxW[3] = Tu[1];
+        potentialDiffW14 = -Tu[1];
+
+        u[0] = potNw[0];
+        u[1] = potNw[1];
+        u[2] = potNw[3];
+
+        T.mv(u, Tu);
+
+        fluxNw[3] = Tu[1];
+        potentialDiffNw14 = -Tu[1];
+    }
+    else
+    {
+        u[0] = potW[3];
+        u[1] = potW[2];
+        u[2] = potW[0];
+
+        T.mv(u, Tu);
+
+        fluxW[3] = Tu[1];
+        potentialDiffW14 = -Tu[1];
+
+        u[0] = potNw[3];
+        u[1] = potNw[2];
+        u[2] = potNw[0];
+
+        T.mv(u, Tu);
+
+        fluxNw[3] = Tu[1];
+        potentialDiffNw14 = -Tu[1];
+    }
+
+    //store potentials for further calculations (saturation, ...)
+    cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffW12);
+    cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffNw12);
+    cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffW14);
+    cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffNw14);
+    cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 0), -potentialDiffW32);
+    cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 0), -potentialDiffNw32);
+    cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffW12);
+    cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffNw12);
+    cellData3.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(2, 0), potentialDiffW34);
+    cellData3.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(2, 0), potentialDiffNw34);
+    cellData3.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(2, 1), potentialDiffW32);
+    cellData3.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(2, 1), potentialDiffNw32);
+    cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffW14);
+    cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffNw14);
+    cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffW34);
+    cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffNw34);
+
+    //compute mobilities of face 1
+    Dune::FieldVector < Scalar, numPhases > lambda12Upw(0.0);
+    lambda12Upw[wPhaseIdx] = (potentialDiffW12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
+    lambda12Upw[nPhaseIdx] = (potentialDiffNw12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
+
+    //compute mobilities of face 4
+    Dune::FieldVector < Scalar, numPhases > lambda14Upw(0.0);
+    lambda14Upw[wPhaseIdx] = (potentialDiffW14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
+    lambda14Upw[nPhaseIdx] = (potentialDiffNw14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
+
+    //compute mobilities of face 2
+    Dune::FieldVector < Scalar, numPhases > lambda32Upw(0.0);
+    lambda32Upw[wPhaseIdx] = (potentialDiffW32 >= 0) ? lambda3[wPhaseIdx] : lambda2[wPhaseIdx];
+    lambda32Upw[nPhaseIdx] = (potentialDiffNw32 >= 0) ? lambda3[nPhaseIdx] : lambda2[nPhaseIdx];
+
+    //compute mobilities of face 3
+    Dune::FieldVector < Scalar, numPhases > lambda34Upw(0.0);
+    lambda34Upw[wPhaseIdx] = (potentialDiffW34 >= 0) ? lambda3[wPhaseIdx] : lambda4[wPhaseIdx];
+    lambda34Upw[nPhaseIdx] = (potentialDiffNw34 >= 0) ? lambda3[nPhaseIdx] : lambda4[nPhaseIdx];
+
+    for (int i = 0; i < numPhases; i++)
+    {
+        // evaluate parts of velocity
+        DimVector vel12 = interactionVolume.getNormal(0, 0);
+        DimVector vel14 = interactionVolume.getNormal(3, 0);
+        DimVector vel23 = interactionVolume.getNormal(1, 0);
+        DimVector vel21 = interactionVolume.getNormal(0, 0);
+        DimVector vel34 = interactionVolume.getNormal(2, 0);
+        DimVector vel32 = interactionVolume.getNormal(1, 0);
+        DimVector vel41 = interactionVolume.getNormal(3, 0);
+        DimVector vel43 = interactionVolume.getNormal(2, 0);
+
+        Dune::FieldVector < Scalar, 2 * dim > flux(0);
+        switch (i)
+        {
+        case wPhaseIdx:
+        {
+            flux = fluxW;
+            break;
+        }
+        case nPhaseIdx:
+        {
+            flux = fluxNw;
+            break;
+        }
+        }
+
+        vel12 *= flux[0] / (2 * interactionVolume.getFaceArea(0, 0)); //divide by 2 because the flux is related to the half face!
+        vel14 *= flux[3] / (2 * interactionVolume.getFaceArea(0, 1));
+        vel23 *= flux[1] / (2 * interactionVolume.getFaceArea(1, 0));
+        vel21 *= flux[0] / (2 * interactionVolume.getFaceArea(1, 1));
+        vel34 *= flux[2] / (2 * interactionVolume.getFaceArea(2, 0));
+        vel32 *= flux[1] / (2 * interactionVolume.getFaceArea(2, 1));
+        vel41 *= flux[3] / (2 * interactionVolume.getFaceArea(3, 0));
+        vel43 *= flux[2] / (2 * interactionVolume.getFaceArea(3, 1));
+
+        if (level1 < level2)
+        {
+            vel12 *= 0.5;
+        }
+        else if (level2 < level1)
+        {
+            vel21 *= 0.5;
+        }
+        if (level2 < level3)
+        {
+            vel23 *= 0.5;
+        }
+        else if (level3 < level2)
+        {
+            vel32 *= 0.5;
+        }
+        if (level3 < level4)
+        {
+            vel34 *= 0.5;
+        }
+        else if (level4 < level3)
+        {
+            vel43 *= 0.5;
+        }
+        if (level4 < level1)
+        {
+            vel41 *= 0.5;
+        }
+        else if (level1 < level4)
+        {
+            vel14 *= 0.5;
+        }
+
+        Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
+        Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
+        Scalar lambdaT32 = lambda32Upw[wPhaseIdx] + lambda32Upw[nPhaseIdx];
+        Scalar lambdaT34 = lambda34Upw[wPhaseIdx] + lambda34Upw[nPhaseIdx];
+        Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
+        Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
+        Scalar fracFlow32 = (lambdaT32 > threshold_) ? lambda32Upw[i] / (lambdaT32) : 0.0;
+        Scalar fracFlow34 = (lambdaT34 > threshold_) ? lambda34Upw[i] / (lambdaT34) : 0.0;
+
+        vel12 *= fracFlow12;
+        vel14 *= fracFlow14;
+        vel23 *= fracFlow32;
+        vel21 *= fracFlow12;
+        vel34 *= fracFlow34;
+        vel32 *= fracFlow32;
+        vel41 *= fracFlow14;
+        vel43 *= fracFlow34;
+
+        if (innerBoundaryVolumeFaces[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
+        {
+            vel12 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx1][interactionVolume.getIndexOnElement(0, 1)])
+        {
+            vel14 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
+        {
+            vel23 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx2][interactionVolume.getIndexOnElement(1, 1)])
+        {
+            vel21 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx3][interactionVolume.getIndexOnElement(2, 0)])
+        {
+            vel34 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx3][interactionVolume.getIndexOnElement(2, 1)])
+        {
+            vel32 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx4][interactionVolume.getIndexOnElement(3, 0)])
+        {
+            vel41 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx4][interactionVolume.getIndexOnElement(3, 1)])
+        {
+            vel43 *= 2;
+        }
+
+        //store velocities
+        cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 0), vel12);
+        cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 1), vel14);
+        cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 0), vel23);
+        cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 1), vel21);
+        cellData3.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(2, 0), vel34);
+        cellData3.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(2, 1), vel32);
+        cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 0), vel41);
+        cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 1), vel43);
+    }
+    //set velocity marker
+    cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 0));
+    cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 1));
+    cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 0));
+    cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 1));
+    cellData3.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(2, 0));
+    cellData3.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(2, 1));
+    cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 0));
+    cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 1));
+}
+
+template<class TypeTag>
+void FvMpfaL2dVelocity2p<TypeTag>::calculateBoundaryInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData, int elemIdx)
+{
+        ElementPointer & elementPointer = interactionVolume.getSubVolumeElement(elemIdx);
+
+        // get global coordinate of cell centers
+        const GlobalPosition& globalPos = elementPointer->geometry().center();
+
+        //permeability vector at boundary
+        DimMatrix permeability(problem_.spatialParams().intrinsicPermeability(*elementPointer));
+
+        //get mobilities of the phases
+        Dune::FieldVector < Scalar, numPhases > lambda(cellData.mobility(wPhaseIdx));
+        lambda[nPhaseIdx] = cellData.mobility(nPhaseIdx);
+
+        for (int faceIdx = 0; faceIdx < dim; faceIdx++)
+        {
+            int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
+
+            if (interactionVolume.isBoundaryFace(intVolFaceIdx))
+            {
+                if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(pressureEqIdx))
+                {
+                    int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, faceIdx);
+
+                    const ReferenceElement& referenceElement = ReferenceElements::general(
+                            elementPointer->geometry().type());
+
+                    const LocalPosition& localPos = referenceElement.position(boundaryFaceIdx, 1);
+
+                    const GlobalPosition& globalPosFace = elementPointer->geometry().global(localPos);
+
+                    DimVector distVec(globalPosFace - globalPos);
+                    Scalar dist = distVec.two_norm();
+                    DimVector unitDistVec(distVec);
+                    unitDistVec /= dist;
+
+                    // get pc and lambda at the boundary
+                    Scalar satWBound = cellData.saturation(wPhaseIdx);
+                    //check boundary sat at face 1
+                    if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(satEqIdx))
+                    {
+                        Scalar satBound = interactionVolume.getDirichletValues(intVolFaceIdx)[saturationIdx];
+                        switch (saturationType_)
+                        {
+                        case sw:
+                        {
+                            satWBound = satBound;
+                              break;
+                        }
+                        case sn:
+                        {
+                            satWBound = 1 - satBound;
+                            break;
+                        }
+                        }
+
+                    }
+
+                    Scalar pcBound = MaterialLaw::pc(
+                            problem_.spatialParams().materialLawParams(*elementPointer), satWBound);
+
+                    Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_
+                            * (density_[nPhaseIdx] - density_[wPhaseIdx]);
+
+                    pcBound += gravityDiffBound;
+
+                    Dune::FieldVector < Scalar, numPhases
+                            > lambdaBound(
+                                    MaterialLaw::krw(
+                                            problem_.spatialParams().materialLawParams(*elementPointer),
+                                            satWBound));
+                    lambdaBound[nPhaseIdx] = MaterialLaw::krn(
+                            problem_.spatialParams().materialLawParams(*elementPointer), satWBound);
+                    lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx];
+                    lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx];
+
+                    Scalar gdeltaZ = (problem_.bBoxMax()-globalPosFace) * gravity_;
+                    Scalar potentialBoundW = interactionVolume.getDirichletValues(intVolFaceIdx)[pressureIdx] + density_[wPhaseIdx]*gdeltaZ;
+                    Scalar potentialBoundNw = potentialBoundW;
+
+                    //calculate potential gradients
+                    switch (pressureType_)
+                    {
+                    case pw:
+                    {
+                        potentialBoundNw += pcBound;
+                        break;
+                    }
+                    case pn:
+                    {
+                        //calculate potential gradients
+                        potentialBoundW -= pcBound;
+                        break;
+                    }
+                    }
+
+                    Scalar potentialDiffW = (cellData.potential(wPhaseIdx) - potentialBoundW) / dist;
+                    Scalar  potentialDiffNw = (cellData.potential(nPhaseIdx) - potentialBoundNw) / dist;
+
+                    //store potentials for further calculations (saturation, ...)
+                    cellData.fluxData().addUpwindPotential(wPhaseIdx, boundaryFaceIdx, potentialDiffW);
+                    cellData.fluxData().addUpwindPotential(nPhaseIdx, boundaryFaceIdx, potentialDiffNw);
+
+                    //calculated phase velocities from advective velocities -> capillary pressure velocity already added in pressure part!
+                    DimVector velocityW(0);
+                    DimVector velocityNw(0);
+
+                    // calculate capillary pressure gradient
+                    DimVector pressGradient = unitDistVec;
+                    pressGradient *= (cellData.potential(wPhaseIdx) - potentialBoundW) / dist;
+                    permeability.mv(pressGradient, velocityW);
+
+                    pressGradient = unitDistVec;
+                    pressGradient *= (cellData.potential(nPhaseIdx) - potentialBoundNw) / dist;
+                    permeability.mv(pressGradient, velocityNw);
+
+                    velocityW *= (potentialDiffW >= 0.) ? lambda[wPhaseIdx] : lambdaBound[wPhaseIdx];
+                    velocityNw *= (potentialDiffNw >= 0.) ? lambda[nPhaseIdx] : lambdaBound[nPhaseIdx];
+
+                    //velocity is calculated from two vertices of one intersection!
+                    velocityW *= 0.5;
+                    velocityNw *= 0.5;
+
+                    //store velocities
+                        velocityW += cellData.fluxData().velocity(wPhaseIdx, boundaryFaceIdx);
+                        velocityNw += cellData.fluxData().velocity(nPhaseIdx, boundaryFaceIdx);
+                        cellData.fluxData().setVelocity(wPhaseIdx, boundaryFaceIdx, velocityW);
+                        cellData.fluxData().setVelocity(nPhaseIdx, boundaryFaceIdx, velocityNw);
+                        cellData.fluxData().setVelocityMarker(boundaryFaceIdx);
+                }
+                else if (interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressureEqIdx))
+                {
+                    int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, faceIdx);
+
+                    const ReferenceElement& referenceElement = ReferenceElements::general(
+                            elementPointer->geometry().type());
+
+                    const LocalPosition& localPos = referenceElement.position(boundaryFaceIdx, 1);
+
+                    const GlobalPosition& globalPosFace = elementPointer->geometry().global(localPos);
+
+                    DimVector distVec(globalPosFace - globalPos);
+                    Scalar dist = distVec.two_norm();
+                    DimVector unitDistVec(distVec);
+                    unitDistVec /= dist;
+
+                    // get neumann boundary value
+                    PrimaryVariables boundValues(interactionVolume.getNeumannValues(intVolFaceIdx));
+
+                    boundValues[wPhaseIdx] /= density_[wPhaseIdx];
+                    boundValues[nPhaseIdx] /= density_[nPhaseIdx];
+
+                    DimVector velocityW(unitDistVec);
+                    DimVector velocityNw(unitDistVec);
+
+                    velocityW *= boundValues[wPhaseIdx] / (2 * interactionVolume.getFaceArea(elemIdx, faceIdx));
+                    velocityNw *= boundValues[nPhaseIdx]
+                            / (2 * interactionVolume.getFaceArea(elemIdx, faceIdx));
+
+                    //store potentials for further calculations (saturation, ...)
+                    cellData.fluxData().addUpwindPotential(wPhaseIdx, boundaryFaceIdx, boundValues[wPhaseIdx]);
+                    cellData.fluxData().addUpwindPotential(nPhaseIdx, boundaryFaceIdx, boundValues[nPhaseIdx]);
+
+                    //store velocities
+                    velocityW += cellData.fluxData().velocity(wPhaseIdx, boundaryFaceIdx);
+                    velocityNw += cellData.fluxData().velocity(nPhaseIdx, boundaryFaceIdx);
+                    cellData.fluxData().setVelocity(wPhaseIdx, boundaryFaceIdx, velocityW);
+                    cellData.fluxData().setVelocity(nPhaseIdx, boundaryFaceIdx, velocityNw);
+                    cellData.fluxData().setVelocityMarker(boundaryFaceIdx);
+                }
+                else
+                {
+                    DUNE_THROW(Dune::NotImplemented,
+                            "No valid boundary condition type defined for pressure equation!");
+                }
+        }
+    }
+}
+
+}
+// end of Dune namespace
+#endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dvelocity2padaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dvelocity2padaptive.hh
new file mode 100644
index 0000000000000000000000000000000000000000..eb6059d73a5cd837df88bf4992c549b307afb0d0
--- /dev/null
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dvelocity2padaptive.hh
@@ -0,0 +1,395 @@
+// -*- 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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_FVMPFAL2DVELOCITY2P_ADAPTIVE_HH
+#define DUMUX_FVMPFAL2DVELOCITY2P_ADAPTIVE_HH
+
+
+#include "fvmpfal2dvelocity2p.hh"
+
+/**
+ * @file
+ * @brief  Velocity calculation using a 2-d MPFA L-method
+ */
+
+namespace Dumux
+{
+template<class TypeTag> class FvMpfaL2dVelocity2pAdaptive : public FvMpfaL2dVelocity2p<TypeTag>
+{
+    typedef FvMpfaL2dVelocity2p<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    enum
+        {
+            dim = GridView::dimension, dimWorld = GridView::dimensionworld
+        };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+
+#if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
+    typedef typename Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::ReferenceElement<Scalar, dim> ReferenceElement;
+#else
+    typedef typename Dune::GenericReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<Scalar, dim> ReferenceElement;
+#endif
+
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename SpatialParams::MaterialLaw MaterialLaw;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes;
+    typedef typename SolutionTypes::PrimaryVariables PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData;
+
+    typedef typename GridView::Traits::template Codim<0>::Entity Element;
+    typedef typename GridView::Grid Grid;
+    typedef typename GridView::IndexSet IndexSet;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+    typedef typename Grid::template Codim<0>::EntityPointer ElementPointer;
+
+    typedef typename Element::Geometry Geometry;
+    #if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
+        typedef typename Geometry::JacobianTransposed JacobianTransposed;
+    #else
+        typedef typename Geometry::Jacobian JacobianTransposed;
+    #endif
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridTypeIndices) GridTypeIndices;
+
+    typedef typename Dumux::FVMPFALInteractionVolume<TypeTag> InteractionVolume;
+    typedef std::vector<Dune::FieldVector<bool, 2 * dim> > InnerBoundaryVolumeFaces;
+    typedef Dumux::FvMpfaL2dTransmissibilityCalculator<TypeTag> TransmissibilityCalculator;
+
+    enum
+        {
+            pw = Indices::pressureW,
+            pn = Indices::pressureNw,
+            pglobal = Indices::pressureGlobal,
+            sw = Indices::saturationW,
+            sn = Indices::saturationNw,
+            vw = Indices::velocityW,
+            vn = Indices::velocityNw,
+            vt = Indices::velocityTotal
+        };
+    enum
+        {
+            wPhaseIdx = Indices::wPhaseIdx,
+            nPhaseIdx = Indices::nPhaseIdx,
+            pressureIdx = Indices::pressureIdx,
+            saturationIdx = Indices::saturationIdx,
+            pressureEqIdx = Indices::pressureEqIdx,
+            satEqIdx = Indices::satEqIdx,
+            numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+        };
+
+    typedef Dune::FieldVector<Scalar, dim> LocalPosition;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+    typedef Dune::FieldMatrix<Scalar, dim, dim> DimMatrix;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
+
+public:
+    FvMpfaL2dVelocity2pAdaptive(Problem& problem) :
+        ParentType(problem), problem_(problem)
+    {}
+
+    void calculateHangingNodeInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData1, CellData& cellData2, CellData& cellData4, InnerBoundaryVolumeFaces& innerBoundaryVolumeFaces);
+
+private:
+    Problem& problem_;
+};
+// end of template
+
+template<class TypeTag>
+void FvMpfaL2dVelocity2pAdaptive<TypeTag>::calculateHangingNodeInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData1, CellData& cellData2, CellData& cellData4, InnerBoundaryVolumeFaces& innerBoundaryVolumeFaces)
+{
+    ElementPointer & elementPointer1 = interactionVolume.getSubVolumeElement(0);
+    ElementPointer & elementPointer2 = interactionVolume.getSubVolumeElement(1);
+    ElementPointer & elementPointer4 = interactionVolume.getSubVolumeElement(3);
+
+    // cell index
+    int globalIdx1 = problem_.variables().index(*elementPointer1);
+    int globalIdx2 = problem_.variables().index(*elementPointer2);
+    int globalIdx4 = problem_.variables().index(*elementPointer4);
+
+    // get pressure values
+    Dune::FieldVector < Scalar, 2 * dim > potW(0);
+    Dune::FieldVector < Scalar, 2 * dim > potNw(0);
+
+    potW[0] = cellData1.potential(wPhaseIdx);
+    potW[1] = cellData2.potential(wPhaseIdx);
+    potW[2] = cellData4.potential(wPhaseIdx);
+
+    potNw[0] = cellData1.potential(nPhaseIdx);
+    potNw[1] = cellData2.potential(nPhaseIdx);
+    potNw[2] = cellData4.potential(nPhaseIdx);
+
+    //get mobilities of the phases
+    Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
+    lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
+
+    //compute total mobility of cell 1
+    Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
+
+    //get mobilities of the phases
+    Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
+    lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
+
+    //compute total mobility of cell 1
+    Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
+
+    //get mobilities of the phases
+    Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
+    lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
+
+    //compute total mobility of cell 1
+    Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
+
+    std::vector < DimVector > lambda(4);
+
+    lambda[0][0] = lambdaTotal1;
+    lambda[0][1] = lambdaTotal1;
+    lambda[1][0] = lambdaTotal2;
+    lambda[1][1] = lambdaTotal2;
+    lambda[3][0] = lambdaTotal4;
+    lambda[3][1] = lambdaTotal4;
+
+    Scalar potentialDiffW12 = 0;
+    Scalar potentialDiffW14 = 0;
+    Scalar potentialDiffW24 = 0;
+
+    Scalar potentialDiffNw12 = 0;
+    Scalar potentialDiffNw14 = 0;
+    Scalar potentialDiffNw24 = 0;
+
+    //flux vector
+    Dune::FieldVector<Scalar, 3> fluxW(0);
+    Dune::FieldVector<Scalar, 3> fluxNw(0);
+
+    Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
+    DimVector Tu(0);
+    Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
+
+    int transmissibilityType = this->transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 3, 3);
+
+    if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
+    {
+        u[0] = potW[1];
+        u[1] = potW[2];
+        u[2] = potW[0];
+
+        T.mv(u, Tu);
+
+        fluxW[0] = Tu[1];
+        potentialDiffW12 = Tu[1];
+
+        u[0] = potNw[1];
+        u[1] = potNw[2];
+        u[2] = potNw[0];
+
+        T.mv(u, Tu);
+
+        fluxNw[0] = Tu[1];
+        potentialDiffNw12 = Tu[1];
+    }
+    else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
+    {
+        u[0] = potW[0];
+        u[1] = potW[2];
+        u[2] = potW[1];
+
+        T.mv(u, Tu);
+
+        fluxW[0] = Tu[1];
+        potentialDiffW12 = Tu[1];
+
+        u[0] = potNw[0];
+        u[1] = potNw[2];
+        u[2] = potNw[1];
+
+        T.mv(u, Tu);
+
+        fluxNw[0] = Tu[1];
+        potentialDiffNw12 = Tu[1];
+    }
+
+    transmissibilityType = this->transmissibilityCalculator_.calculateLeftHNTransmissibility(T, interactionVolume, lambda, 1, 3, 0);
+
+    if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
+    {
+        u[0] = potW[1];
+        u[1] = potW[0];
+        u[2] = potW[2];
+
+        T.mv(u, Tu);
+
+        fluxW[1] = Tu[1];
+        potentialDiffW24 = Tu[1];
+
+        u[0] = potNw[1];
+        u[1] = potNw[0];
+        u[2] = potNw[2];
+
+        T.mv(u, Tu);
+
+        fluxNw[1] = Tu[1];
+        potentialDiffNw24 = Tu[1];
+    }
+
+    transmissibilityType = this->transmissibilityCalculator_.calculateRightHNTransmissibility(T, interactionVolume, lambda, 3, 0, 1);
+
+    if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
+    {
+        u[0] = potW[0];
+        u[1] = potW[1];
+        u[2] = potW[2];
+
+        T.mv(u, Tu);
+
+        fluxW[2] = Tu[1];
+        potentialDiffW14 = -Tu[1];
+
+        u[0] = potNw[0];
+        u[1] = potNw[1];
+        u[2] = potNw[2];
+
+        T.mv(u, Tu);
+
+        fluxNw[2] = Tu[1];
+        potentialDiffNw14 = -Tu[1];
+    }
+
+    //store potentials for further calculations (saturation, ...) -> maybe add new potential to old one!!
+    cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffW12);
+    cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 0), potentialDiffNw12);
+    cellData1.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffW14);
+    cellData1.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(0, 1), potentialDiffNw14);
+    cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 0), potentialDiffW24);
+    cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 0), potentialDiffNw24);
+    cellData2.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffW12);
+    cellData2.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(1, 1), -potentialDiffNw12);
+    cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffW14);
+    cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 0), -potentialDiffNw14);
+    cellData4.fluxData().addUpwindPotential(wPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffW24);
+    cellData4.fluxData().addUpwindPotential(nPhaseIdx, interactionVolume.getIndexOnElement(3, 1), -potentialDiffNw24);
+
+    //compute mobilities of face 1
+    Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
+    lambda12Upw[wPhaseIdx] = (potentialDiffW12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
+    lambda12Upw[nPhaseIdx] = (potentialDiffNw12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
+
+    //compute mobilities of face 4
+    Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
+    lambda14Upw[wPhaseIdx] = (potentialDiffW14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
+    lambda14Upw[nPhaseIdx] = (potentialDiffNw14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
+
+    //compute mobilities of face 2
+    Dune::FieldVector<Scalar, numPhases> lambda24Upw(0.0);
+    lambda24Upw[wPhaseIdx] = (potentialDiffW24 >= 0) ? lambda2[wPhaseIdx] : lambda4[wPhaseIdx];
+    lambda24Upw[nPhaseIdx] = (potentialDiffNw24 >= 0) ? lambda2[nPhaseIdx] : lambda4[nPhaseIdx];
+
+    for (int i = 0; i < numPhases; i++)
+    {
+        // evaluate parts of velocity --> always take the normal for which the flux is calculated!
+        DimVector vel12 = interactionVolume.getNormal(0, 0);
+        DimVector vel14 = interactionVolume.getNormal(3, 0);
+        DimVector vel24 = interactionVolume.getNormal(1, 0);
+        DimVector vel21 = interactionVolume.getNormal(0, 0);
+        DimVector vel41 = interactionVolume.getNormal(3, 0);
+        DimVector vel42 = interactionVolume.getNormal(1, 0);
+
+        Dune::FieldVector<Scalar, 3> flux(0);
+        switch (i)
+        {
+        case wPhaseIdx:
+        {
+            flux = fluxW;
+            break;
+        }
+        case nPhaseIdx:
+        {
+            flux = fluxNw;
+            break;
+        }
+        }
+
+        vel12 *= flux[0] / (2 * interactionVolume.getFaceArea(0, 0)); //divide by 2 because the flux is related to the half face!
+        vel14 *= flux[2] / (2 * interactionVolume.getFaceArea(3, 0));
+        vel24 *= flux[1] / (2 * interactionVolume.getFaceArea(1, 0));
+        vel21 *= flux[0] / (2 * interactionVolume.getFaceArea(0, 0));
+        vel41 *= flux[2] / (4 * interactionVolume.getFaceArea(3, 0));
+        vel42 *= flux[1] / (4 * interactionVolume.getFaceArea(1, 0));
+
+        Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
+        Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
+        Scalar lambdaT24 = lambda24Upw[wPhaseIdx] + lambda24Upw[nPhaseIdx];
+        Scalar fracFlow12 = (lambdaT12 > this->threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
+        Scalar fracFlow14 = (lambdaT14 > this->threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
+        Scalar fracFlow24 = (lambdaT24 > this->threshold_) ? lambda24Upw[i] / (lambdaT24) : 0.0;
+
+        vel12 *= fracFlow12;
+        vel14 *= fracFlow14;
+        vel24 *= fracFlow24;
+        vel21 *= fracFlow12;
+        vel41 *= fracFlow14;
+        vel42 *= fracFlow24;
+
+        if (innerBoundaryVolumeFaces[globalIdx1][interactionVolume.getIndexOnElement(0, 0)])
+        {
+            vel12 *= 2;
+            vel21 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx1][interactionVolume.getIndexOnElement(0, 1)])
+        {
+            vel14 *= 2;
+            vel41 *= 2;
+        }
+        if (innerBoundaryVolumeFaces[globalIdx2][interactionVolume.getIndexOnElement(1, 0)])
+        {
+            vel24 *= 2;
+            vel42 *= 2;
+        }
+
+        //store velocities
+        //set velocity
+        cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 0), vel12);
+        cellData1.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(0, 1), vel14);
+        cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 0), vel24);
+        cellData2.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(1, 1), vel21);
+        cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 0), vel41);
+        cellData4.fluxData().addVelocity(i, interactionVolume.getIndexOnElement(3, 1), vel42);
+    }
+    //set velocity marker
+    cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 0));
+    cellData1.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(0, 1));
+    cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 0));
+    cellData2.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(1, 1));
+    cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 0));
+    cellData4.fluxData().setVelocityMarker(interactionVolume.getIndexOnElement(3, 1));
+}
+
+}
+// end of Dune namespace
+#endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dinteractionvolumecontaineradaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dinteractionvolumecontaineradaptive.hh
index 2be63d5d34b685163c74363d773334f0843027f2..3ae9911121a40c9f857a946ce1004225082ec0e3 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dinteractionvolumecontaineradaptive.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dinteractionvolumecontaineradaptive.hh
@@ -76,7 +76,7 @@ class FvMpfaL3dInteractionVolumeContainerAdaptive: public FvMpfaL3dInteractionVo
 
     enum
         {
-            pressEqIdx = Indices::pressEqIdx,
+            pressEqIdx = Indices::pressureEqIdx,
         };
 
     typedef IndexTranslatorAdaptive IndexTranslator;
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressure2padaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressure2padaptive.hh
index f173e080a7bb2175d057815e4c9114df684c517d..73917e647f809e26c27a6715da46ea1d602822d3 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressure2padaptive.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressure2padaptive.hh
@@ -103,7 +103,7 @@ class FvMpfaL3dPressure2pAdaptive: public FvMpfaL3dPressure2p<TypeTag>
             nPhaseIdx = Indices::nPhaseIdx,
             pressureIdx = Indices::pressureIdx,
             saturationIdx = Indices::saturationIdx,
-            pressEqIdx = Indices::pressEqIdx,
+            pressEqIdx = Indices::pressureEqIdx,
             satEqIdx = Indices::satEqIdx,
             numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
         };
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressureproperties2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressureproperties2p.hh
index 4c6a7b49885a89c888569fda6bdb215c34e251f9..576ff9fcbf041859f445591e8972847a71fa2fac 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressureproperties2p.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressureproperties2p.hh
@@ -39,6 +39,7 @@ NEW_TYPE_TAG(FvMpfaL3dPressureTwoP, INHERITS_FROM(PressureTwoP, MPFAProperties))
 }
 
 #include <dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2p.hh>
+#include <dumux/decoupled/common/fv/mpfa/fvmpfavelocityintransport.hh>
 
 namespace Dumux
 {
@@ -47,6 +48,7 @@ namespace Properties
 SET_TYPE_PROP(FvMpfaL3dPressureTwoP, MPFAInteractionVolume, Dumux::FvMpfaL3dInteractionVolume<TypeTag>);
 SET_TYPE_PROP(FvMpfaL3dPressureTwoP, MPFAInteractionVolumeContainer, Dumux::FvMpfaL3dInteractionVolumeContainer<TypeTag>);
 SET_TYPE_PROP(FvMpfaL3dPressureTwoP, PressureModel, Dumux::FvMpfaL3dPressureVelocity2p<TypeTag>);
+SET_TYPE_PROP( FvMpfaL3dPressureTwoP, Velocity, Dumux::FvMpfaVelocityInTransport<TypeTag> );
 }
 }// end of Dune namespace
 #endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressureproperties2padaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressureproperties2padaptive.hh
index b376cacd3beb9d30c325f17ae454c24fbfbef8f7..967cf7295b5960ff05193dbd755ebba1beeeeb1a 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressureproperties2padaptive.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressureproperties2padaptive.hh
@@ -40,6 +40,7 @@ NEW_TYPE_TAG(FvMpfaL3dPressureTwoPAdaptive, INHERITS_FROM(PressureTwoP, MPFAProp
 }
 
 #include <dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2padaptive.hh>
+#include <dumux/decoupled/common/fv/mpfa/fvmpfavelocityintransport.hh>
 
 namespace Dumux
 {
@@ -48,6 +49,7 @@ namespace Properties
 SET_TYPE_PROP(FvMpfaL3dPressureTwoPAdaptive, MPFAInteractionVolume, Dumux::FvMpfaL3dInteractionVolumeAdaptive<TypeTag>);
 SET_TYPE_PROP(FvMpfaL3dPressureTwoPAdaptive, MPFAInteractionVolumeContainer, Dumux::FvMpfaL3dInteractionVolumeContainerAdaptive<TypeTag>);
 SET_TYPE_PROP(FvMpfaL3dPressureTwoPAdaptive, PressureModel, Dumux::FvMpfaL3dPressureVelocity2pAdaptive<TypeTag>);
+SET_TYPE_PROP( FvMpfaL3dPressureTwoPAdaptive, Velocity, Dumux::FvMpfaVelocityInTransport<TypeTag> );
 }
 }// end of Dune namespace
 #endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2p.hh
index fcf548d45d05188626a3f922cdf0af33dc78a3f5..fb71e1f8b30575bbfafe349d4c41726152188af3 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2p.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2p.hh
@@ -34,46 +34,106 @@ template<class TypeTag> class FvMpfaL3dPressureVelocity2p: public FvMpfaL3dPress
     typedef FvMpfaL3dPressure2p<TypeTag> ParentType;
 
     typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
 
     enum
         {
             dim = GridView::dimension, dimWorld = GridView::dimensionworld
         };
 
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum
+    {
+        pw = Indices::pressureW,
+        pn = Indices::pressureNw,
+        sw = Indices::saturationW,
+        sn = Indices::saturationNw,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        pressureIdx = Indices::pressureIdx,
+        saturationIdx = Indices::saturationIdx,
+        pressEqIdx = Indices::pressureEqIdx,
+        satEqIdx = Indices::satEqIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+    };
+
     typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
     typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes;
+    typedef typename SolutionTypes::PrimaryVariables PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename SpatialParams::MaterialLaw MaterialLaw;
 
+#if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
+    typedef typename Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::ReferenceElement<Scalar, dim> ReferenceElement;
+#else
+    typedef typename Dune::GenericReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<Scalar, dim> ReferenceElement;
+#endif
+
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
     typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
     typedef typename GET_PROP_TYPE(TypeTag, MPFAInteractionVolume) InteractionVolume;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+    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> DimMatrix;
 
 public:
     FvMpfaL3dPressureVelocity2p(Problem& problem) :
         ParentType(problem), problem_(problem), velocity_(problem)
-    {}
+    {
+        density_[wPhaseIdx] = 0.;
+        density_[nPhaseIdx] = 0.;
+        viscosity_[wPhaseIdx] = 0.;
+        viscosity_[nPhaseIdx] = 0.;
+
+        calcVelocityInTransport_ = GET_PARAM_FROM_GROUP(TypeTag, bool, MPFA, CalcVelocityInTransport);
+    }
 
     void calculateVelocity();
 
 public:
 
+    // Calculates the velocity at a cell-cell interface.
+    void calculateVelocity(const Intersection&, CellData&);
+    void calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData);
+
     void updateVelocity()
     {
         this->updateMaterialLaws();
 
-        //reset velocities
-        int size = problem_.gridView().size(0);
-        for (int i = 0; i < size; i++)
-        {
-            CellData& cellData = problem_.variables().cellData(i);
-            cellData.fluxData().resetVelocity();
-        }
+        this->storePressureSolution();
 
+        if (!calculateVelocityInTransport())
         calculateVelocity();
     }
 
     void initialize(bool solveTwice = true)
     {
+        ElementIterator element = problem_.gridView().template begin<0>();
+        FluidState fluidState;
+        fluidState.setPressure(wPhaseIdx, problem_.referencePressure(*element));
+        fluidState.setPressure(nPhaseIdx, problem_.referencePressure(*element));
+        fluidState.setTemperature(problem_.temperature(*element));
+        fluidState.setSaturation(wPhaseIdx, 1.);
+        fluidState.setSaturation(nPhaseIdx, 0.);
+        density_[wPhaseIdx] = FluidSystem::density(fluidState, wPhaseIdx);
+        density_[nPhaseIdx] = FluidSystem::density(fluidState, nPhaseIdx);
+        viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
+        viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
+
         ParentType::initialize();
         velocity_.initialize();
+
+        if (!calculateVelocityInTransport())
         calculateVelocity();
 
         return;
@@ -82,9 +142,20 @@ public:
     void update()
     {
         ParentType::update();
+
+        if (!calculateVelocityInTransport())
         calculateVelocity();
     }
 
+    /*! \brief Indicates if velocity is reconstructed in the pressure step or in the transport step
+     *
+     * Returns true (In the standard finite volume discretization the velocity is calculated during the saturation transport.)
+     */
+    bool calculateVelocityInTransport()
+    {
+        return calcVelocityInTransport_;
+    }
+
     //! \brief Write data files
     /*  \param name file name */
     template<class MultiWriter>
@@ -97,6 +168,13 @@ public:
 private:
     Problem& problem_;
     FvMpfaL3dVelocity2p<TypeTag> velocity_;
+
+    Scalar density_[numPhases];
+    Scalar viscosity_[numPhases];
+    bool calcVelocityInTransport_;
+
+    static const int pressureType_ = GET_PROP_VALUE(TypeTag, PressureFormulation); //!< gives kind of pressure used (\f$ 0 = p_w\f$, \f$ 1 = p_n\f$, \f$ 2 = p_{global}\f$)
+    static const int saturationType_ = GET_PROP_VALUE(TypeTag, SaturationFormulation); //!< gives kind of saturation used (\f$ 0 = S_w\f$, \f$ 1 = S_n\f$)
 };
 // end of template
 
@@ -115,12 +193,61 @@ void FvMpfaL3dPressureVelocity2p<TypeTag>::calculateVelocity()
         // inner interactionvolume
         if (interactionVolume.isInnerVolume())
         {
-            velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume, this->interactionVolumes_, this->transmissibilityCalculator_);
+            // cell index
+            int globalIdx[8];
+            for (int i = 0; i < 8; i++)
+            {
+                globalIdx[i] = problem_.variables().index(*(interactionVolume.getSubVolumeElement(i)));
+            }
+
+            //get the cell Data
+            CellData & cellData1 = problem_.variables().cellData(globalIdx[0]);
+            CellData & cellData2 = problem_.variables().cellData(globalIdx[1]);
+            CellData & cellData3 = problem_.variables().cellData(globalIdx[2]);
+            CellData & cellData4 = problem_.variables().cellData(globalIdx[3]);
+            CellData & cellData5 = problem_.variables().cellData(globalIdx[4]);
+            CellData & cellData6 = problem_.variables().cellData(globalIdx[5]);
+            CellData & cellData7 = problem_.variables().cellData(globalIdx[6]);
+            CellData & cellData8 = problem_.variables().cellData(globalIdx[7]);
+
+            velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume,
+                    cellData1, cellData2, cellData3, cellData4,
+                    cellData5, cellData6, cellData7, cellData8,
+                    this->interactionVolumes_, this->transmissibilityCalculator_);
         }
         // at least one face on boundary! (boundary interactionvolume)
         else
         {
-            velocity_.calculateBoundaryInteractionVolumeVelocity(interactionVolume, this->interactionVolumes_, this->transmissibilityCalculator_);
+            for (int elemIdx = 0; elemIdx < 8; elemIdx++)
+            {
+                if (!interactionVolume.hasSubVolumeElement(elemIdx))
+                {
+                    continue;
+                }
+                bool isOutside = false;
+                for (int faceIdx = 0; faceIdx < dim; faceIdx++)
+                {
+                    int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
+                    if (interactionVolume.isOutsideFace(intVolFaceIdx))
+                    {
+                        isOutside = true;
+                        break;
+                    }
+                }
+                if (isOutside)
+                {
+                    continue;
+                }
+
+                ElementPointer & elementPointer = interactionVolume.getSubVolumeElement(elemIdx);
+
+                // cell index
+                int globalIdx = problem_.variables().index(*elementPointer);
+                //get the cell Data
+                CellData& cellData = problem_.variables().cellData(globalIdx);
+
+                velocity_.calculateBoundaryInteractionVolumeVelocity(interactionVolume, cellData, elemIdx);
+            }
         } // end boundaries
 
     } // end vertex iterator
@@ -128,6 +255,257 @@ void FvMpfaL3dPressureVelocity2p<TypeTag>::calculateVelocity()
     return;
 }
 
+template<class TypeTag>
+void FvMpfaL3dPressureVelocity2p<TypeTag>::calculateVelocity(const Intersection& intersection, CellData& cellData)
+{
+    int numVertices = intersection.geometry().corners();
+
+    ElementPointer elementPtrI = intersection.inside();
+    ElementPointer elementPtrJ = intersection.outside();
+
+    int globalIdxI = problem_.variables().index(*elementPtrI);
+    int globalIdxJ = problem_.variables().index(*elementPtrJ);
+
+    CellData& cellDataJ = problem_.variables().cellData(globalIdxJ);
+
+    const ReferenceElement& referenceElement = ReferenceElements::general(elementPtrI->geometry().type());
+
+    int indexInInside = intersection.indexInInside();
+    int indexInOutside = intersection.indexInOutside();
+
+    Dune::FieldVector<CellData, 8> cellDataTemp;
+
+    for (int vIdx = 0; vIdx < numVertices; vIdx++)
+    {
+        int localVertIdx = referenceElement.subEntity(indexInInside, 1, vIdx, dim);
+
+        int globalVertIdx = problem_.variables().index(
+                *((*elementPtrI).template subEntity < dim > (localVertIdx)));
+
+        InteractionVolume& interactionVolume = this->interactionVolumes_.interactionVolume(globalVertIdx);
+
+        if (interactionVolume.isInnerVolume())
+        {
+        // cell index
+        int globalIdx[8];
+        for (int i = 0; i < 8; i++)
+        {
+            globalIdx[i] = problem_.variables().index(*(interactionVolume.getSubVolumeElement(i)));
+            cellDataTemp[i] = problem_.variables().cellData(globalIdx[i]);
+        }
+
+        velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume,
+                cellDataTemp[0], cellDataTemp[1], cellDataTemp[2], cellDataTemp[3],
+                cellDataTemp[4], cellDataTemp[5], cellDataTemp[6], cellDataTemp[7],
+                this->interactionVolumes_, this->transmissibilityCalculator_);
+
+        for (int i = 0; i < 8; i++)
+        {
+            if (globalIdx[i] == globalIdxI)
+            {
+                 cellData.fluxData().setVelocity(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInInside));
+                 cellData.fluxData().setVelocity(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInInside));
+                 cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInInside));
+                 cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInInside));
+            }
+            else if (globalIdx[i] == globalIdxJ)
+            {
+                cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInOutside));
+            }
+        }
+    }
+    }
+    cellData.fluxData().setVelocityMarker(indexInInside);
+    cellDataJ.fluxData().setVelocityMarker(indexInOutside);
+}
+
+template<class TypeTag>
+void FvMpfaL3dPressureVelocity2p<TypeTag>::calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData)
+{
+    ElementPointer element = intersection.inside();
+
+    //get face index
+    int isIndex = intersection.indexInInside();
+
+    //get face normal
+    const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
+
+    BoundaryTypes bcType;
+    //get boundary type
+    problem_.boundaryTypes(bcType, intersection);
+    PrimaryVariables boundValues(0.0);
+
+    if (bcType.isDirichlet(pressEqIdx))
+    {
+        problem_.dirichlet(boundValues, intersection);
+
+        // get global coordinates of cell centers
+        const GlobalPosition& globalPosI = element->geometry().center();
+
+        // center of face in global coordinates
+        const GlobalPosition& globalPosJ = intersection.geometry().center();
+
+        // get mobilities and fractional flow factors
+        Scalar lambdaWI = cellData.mobility(wPhaseIdx);
+        Scalar lambdaNwI = cellData.mobility(nPhaseIdx);
+
+        // get capillary pressure
+        Scalar pcI = cellData.capillaryPressure();
+
+        // distance vector between barycenters
+        GlobalPosition distVec = globalPosJ - globalPosI;
+
+        // compute distance between cell centers
+        Scalar dist = distVec.two_norm();
+
+        //permeability vector at boundary
+        // compute vectorized permeabilities
+        DimMatrix meanPermeability(0);
+
+        problem_.spatialParams().meanK(meanPermeability, problem_.spatialParams().intrinsicPermeability(*element));
+
+        Dune::FieldVector<Scalar, dim> permeability(0);
+        meanPermeability.mv(unitOuterNormal, permeability);
+
+        //determine saturation at the boundary -> if no saturation is known directly at the boundary use the cell saturation
+        Scalar satW = 0;
+        Scalar satNw = 0;
+        if (bcType.isDirichlet(satEqIdx))
+        {
+            switch (saturationType_)
+            {
+            case sw:
+            {
+                satW = boundValues[saturationIdx];
+                satNw = 1 - boundValues[saturationIdx];
+                break;
+            }
+            case sn:
+            {
+                satW = 1 - boundValues[saturationIdx];
+                satNw = boundValues[saturationIdx];
+                break;
+            }
+            }
+        }
+        else
+        {
+            satW = cellData.saturation(wPhaseIdx);
+            satNw = cellData.saturation(nPhaseIdx);
+        }
+
+        Scalar pressBound = boundValues[pressureIdx];
+        Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(*element), satW);
+
+        //determine phase pressures from primary pressure variable
+        Scalar pressWBound = 0;
+        Scalar pressNwBound = 0;
+        if (pressureType_ == pw)
+        {
+            pressWBound = pressBound;
+            pressNwBound = pressBound + pcBound;
+        }
+        else if (pressureType_ == pn)
+        {
+            pressWBound = pressBound - pcBound;
+            pressNwBound = pressBound;
+        }
+
+        Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(*element), satW)
+                / viscosity_[wPhaseIdx];
+        Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(*element), satW)
+                / viscosity_[nPhaseIdx];
+
+        Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex);
+        Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex);
+
+        //calculate potential gradient
+        potentialDiffW = (cellData.pressure(wPhaseIdx) - pressWBound);
+        potentialDiffNw = (cellData.pressure(nPhaseIdx) - pressNwBound);
+
+        potentialDiffW += density_[wPhaseIdx] * (distVec * problem_.gravity());
+        potentialDiffNw += density_[nPhaseIdx] * (distVec * problem_.gravity());
+
+        //store potential gradients for further calculations
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, potentialDiffW);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, potentialDiffNw);
+
+        //do the upwinding of the mobility depending on the phase potentials
+        Scalar lambdaW = (potentialDiffW > 0.) ? lambdaWI : lambdaWBound;
+        lambdaW = (potentialDiffW == 0) ? 0.5 * (lambdaWI + lambdaWBound) : lambdaW;
+        Scalar lambdaNw = (potentialDiffNw > 0.) ? lambdaNwI : lambdaNwBound;
+        lambdaNw = (potentialDiffNw == 0) ? 0.5 * (lambdaNwI + lambdaNwBound) : lambdaNw;
+
+
+        Scalar scalarPerm = permeability.two_norm();
+
+        //calculate the gravity term
+        Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
+        Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
+
+        //calculate unit distVec
+        distVec /= dist;
+        Scalar areaScaling = (unitOuterNormal * distVec);
+        //this treatment of g allows to account for gravity flux through faces where the face normal has no z component (e.g. parallelepiped grids)
+        Scalar gravityTermW = (problem_.gravity() * distVec) * density_[wPhaseIdx] * areaScaling;
+        Scalar gravityTermNw = (problem_.gravity() * distVec) * density_[nPhaseIdx] * areaScaling;
+
+        //calculate velocity depending on the pressure used -> use pc = pn - pw
+        switch (pressureType_)
+        {
+        case pw:
+        {
+            velocityW *= lambdaW * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermW);
+            velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermNw)
+                    + 0.5 * (lambdaNwI + lambdaNwBound) * scalarPerm * (pcI - pcBound) / dist;
+            break;
+        }
+        case pn:
+        {
+            velocityW *= lambdaW * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermW)
+                    - 0.5 * (lambdaWI + lambdaWBound) * scalarPerm * (pcI - pcBound) / dist;
+            velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermNw);
+            break;
+        }
+        }
+
+        //store velocities
+        cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
+        cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
+        cellData.fluxData().setVelocityMarker(isIndex);
+
+    } //end dirichlet boundary
+
+    else if (bcType.isNeumann(pressEqIdx))
+    {
+        problem_.neumann(boundValues, intersection);
+
+        Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
+        Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
+
+        velocityW *= boundValues[wPhaseIdx];
+        velocityNw *= boundValues[nPhaseIdx];
+
+            velocityW /= density_[wPhaseIdx];
+            velocityNw /= density_[nPhaseIdx];
+
+        //store potential gradients for further calculations
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, boundValues[wPhaseIdx]);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, boundValues[nPhaseIdx]);
+
+        cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
+        cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
+        cellData.fluxData().setVelocityMarker(isIndex);
+    } //end neumann boundary
+    else
+    {
+        DUNE_THROW(Dune::NotImplemented, "No valid boundary condition type defined for pressure equation!");
+    }
+}
+
 }
 // end of Dune namespace
 #endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2padaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2padaptive.hh
index 31a8f8a6fca6ca4cf94346920fd1dc538bcfb04c..04a11ce5fbf957967118b8b1db61496ae2ca3d99 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2padaptive.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dpressurevelocity2padaptive.hh
@@ -31,6 +31,7 @@ namespace Dumux
 template<class TypeTag> class FvMpfaL3dPressureVelocity2pAdaptive: public FvMpfaL3dPressure2pAdaptive<TypeTag>
 {
     typedef FvMpfaL3dPressure2pAdaptive<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
 
     typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
 
@@ -39,40 +40,101 @@ template<class TypeTag> class FvMpfaL3dPressureVelocity2pAdaptive: public FvMpfa
             dim = GridView::dimension, dimWorld = GridView::dimensionworld
         };
 
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum
+    {
+        pw = Indices::pressureW,
+        pn = Indices::pressureNw,
+        sw = Indices::saturationW,
+        sn = Indices::saturationNw,
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+        pressureIdx = Indices::pressureIdx,
+        saturationIdx = Indices::saturationIdx,
+        pressEqIdx = Indices::pressureEqIdx,
+        satEqIdx = Indices::satEqIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
+    };
+
     typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
     typedef typename GET_PROP_TYPE(TypeTag, CellData) CellData;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP(TypeTag, SolutionTypes) SolutionTypes;
+    typedef typename SolutionTypes::PrimaryVariables PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename SpatialParams::MaterialLaw MaterialLaw;
 
+#if DUNE_VERSION_NEWER(DUNE_GRID, 2, 3)
+    typedef typename Dune::ReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::ReferenceElement<Scalar, dim> ReferenceElement;
+#else
+    typedef typename Dune::GenericReferenceElements<Scalar, dim> ReferenceElements;
+    typedef typename Dune::GenericReferenceElement<Scalar, dim> ReferenceElement;
+#endif
+
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
     typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
     typedef typename GET_PROP_TYPE(TypeTag, MPFAInteractionVolume) InteractionVolume;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+    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> DimMatrix;
+    typedef Dune::FieldVector<Scalar, dim> DimVector;
 
 public:
     FvMpfaL3dPressureVelocity2pAdaptive(Problem& problem) :
         ParentType(problem), problem_(problem), velocity_(problem)
-    {}
+    {
+        density_[wPhaseIdx] = 0.;
+        density_[nPhaseIdx] = 0.;
+        viscosity_[wPhaseIdx] = 0.;
+        viscosity_[nPhaseIdx] = 0.;
+
+        calcVelocityInTransport_ = GET_PARAM_FROM_GROUP(TypeTag, bool, MPFA, CalcVelocityInTransport);
+    }
 
     void calculateVelocity();
 
 public:
 
+    // Calculates the velocity at a cell-cell interface.
+    void calculateVelocity(const Intersection&, CellData&);
+    void calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData);
+
+
     void updateVelocity()
     {
         this->updateMaterialLaws();
 
-        //reset velocities
-        int size = problem_.gridView().size(0);
-        for (int i = 0; i < size; i++)
-        {
-            CellData& cellData = problem_.variables().cellData(i);
-            cellData.fluxData().resetVelocity();
-        }
+        this->storePressureSolution();
 
+        if (!calculateVelocityInTransport())
         calculateVelocity();
     }
 
     void initialize(bool solveTwice = true)
     {
+        ElementIterator element = problem_.gridView().template begin<0>();
+        FluidState fluidState;
+        fluidState.setPressure(wPhaseIdx, problem_.referencePressure(*element));
+        fluidState.setPressure(nPhaseIdx, problem_.referencePressure(*element));
+        fluidState.setTemperature(problem_.temperature(*element));
+        fluidState.setSaturation(wPhaseIdx, 1.);
+        fluidState.setSaturation(nPhaseIdx, 0.);
+        density_[wPhaseIdx] = FluidSystem::density(fluidState, wPhaseIdx);
+        density_[nPhaseIdx] = FluidSystem::density(fluidState, nPhaseIdx);
+        viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
+        viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
+
         ParentType::initialize();
         velocity_.initialize();
+
+        if (!calculateVelocityInTransport())
         calculateVelocity();
 
         return;
@@ -81,9 +143,20 @@ public:
     void update()
     {
         ParentType::update();
+
+        if (!calculateVelocityInTransport())
         calculateVelocity();
     }
 
+    /*! \brief Indicates if velocity is reconstructed in the pressure step or in the transport step
+     *
+     * Returns true (In the standard finite volume discretization the velocity is calculated during the saturation transport.)
+     */
+    bool calculateVelocityInTransport()
+    {
+        return calcVelocityInTransport_;
+    }
+
     //! \brief Write data files
     /*  \param name file name */
     template<class MultiWriter>
@@ -96,6 +169,13 @@ public:
 private:
     Problem& problem_;
     FvMpfaL3dVelocity2pAdaptive<TypeTag> velocity_;
+
+    Scalar density_[numPhases];
+    Scalar viscosity_[numPhases];
+    bool calcVelocityInTransport_;
+
+    static const int pressureType_ = GET_PROP_VALUE(TypeTag, PressureFormulation); //!< gives kind of pressure used (\f$ 0 = p_w\f$, \f$ 1 = p_n\f$, \f$ 2 = p_{global}\f$)
+    static const int saturationType_ = GET_PROP_VALUE(TypeTag, SaturationFormulation); //!< gives kind of saturation used (\f$ 0 = S_w\f$, \f$ 1 = S_n\f$)
 };
 // end of template
 
@@ -114,19 +194,70 @@ void FvMpfaL3dPressureVelocity2pAdaptive<TypeTag>::calculateVelocity()
         // inner interactionvolume
         if (interactionVolume.isInnerVolume())
         {
+            // cell index
+            int globalIdx[8];
+            for (int i = 0; i < 8; i++)
+            {
+                globalIdx[i] = problem_.variables().index(*(interactionVolume.getSubVolumeElement(i)));
+            }
+
+            //get the cell Data
+            CellData & cellData1 = problem_.variables().cellData(globalIdx[0]);
+            CellData & cellData2 = problem_.variables().cellData(globalIdx[1]);
+            CellData & cellData3 = problem_.variables().cellData(globalIdx[2]);
+            CellData & cellData4 = problem_.variables().cellData(globalIdx[3]);
+            CellData & cellData5 = problem_.variables().cellData(globalIdx[4]);
+            CellData & cellData6 = problem_.variables().cellData(globalIdx[5]);
+            CellData & cellData7 = problem_.variables().cellData(globalIdx[6]);
+            CellData & cellData8 = problem_.variables().cellData(globalIdx[7]);
+
             if (!interactionVolume.isHangingNodeVolume())
             {
-                velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume, this->interactionVolumes_, this->transmissibilityCalculator_);
+                velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume,
+                        cellData1, cellData2, cellData3, cellData4,
+                        cellData5, cellData6, cellData7, cellData8,
+                        this->interactionVolumes_, this->transmissibilityCalculator_);
             }
             else
             {
-                velocity_.calculateHangingNodeInteractionVolumeVelocity(interactionVolume);
+                velocity_.calculateHangingNodeInteractionVolumeVelocity(interactionVolume,
+                        cellData1, cellData2, cellData3, cellData4,
+                        cellData5, cellData6, cellData7, cellData8);
             }
         }
         // at least one face on boundary! (boundary interactionvolume)
         else
         {
-            velocity_.calculateBoundaryInteractionVolumeVelocity(interactionVolume, this->interactionVolumes_, this->transmissibilityCalculator_);
+            for (int elemIdx = 0; elemIdx < 8; elemIdx++)
+            {
+                if (!interactionVolume.hasSubVolumeElement(elemIdx))
+                {
+                    continue;
+                }
+                bool isOutside = false;
+                for (int faceIdx = 0; faceIdx < dim; faceIdx++)
+                {
+                    int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
+                    if (interactionVolume.isOutsideFace(intVolFaceIdx))
+                    {
+                        isOutside = true;
+                        break;
+                    }
+                }
+                if (isOutside)
+                {
+                    continue;
+                }
+
+                ElementPointer & elementPointer = interactionVolume.getSubVolumeElement(elemIdx);
+
+                // cell index
+                int globalIdx = problem_.variables().index(*elementPointer);
+                //get the cell Data
+                CellData& cellData = problem_.variables().cellData(globalIdx);
+
+                velocity_.calculateBoundaryInteractionVolumeVelocity(interactionVolume, cellData, elemIdx);
+            }
         } // end boundaries
 
     } // end vertex iterator
@@ -134,6 +265,325 @@ void FvMpfaL3dPressureVelocity2pAdaptive<TypeTag>::calculateVelocity()
     return;
 }
 
+template<class TypeTag>
+void FvMpfaL3dPressureVelocity2pAdaptive<TypeTag>::calculateVelocity(const Intersection& intersection, CellData& cellData)
+{
+    int numVertices = intersection.geometry().corners();
+
+    ElementPointer elementPtrI = intersection.inside();
+    ElementPointer elementPtrJ = intersection.outside();
+
+    int levelI = elementPtrI->level();
+    int levelJ = elementPtrJ->level();
+
+    int globalIdxI = problem_.variables().index(*elementPtrI);
+    int globalIdxJ = problem_.variables().index(*elementPtrJ);
+
+    CellData& cellDataJ = problem_.variables().cellData(globalIdxJ);
+
+    const ReferenceElement& referenceElement = ReferenceElements::general(elementPtrI->geometry().type());
+
+    int indexInInside = intersection.indexInInside();
+    int indexInOutside = intersection.indexInOutside();
+
+    int faceIdx = indexInInside;
+
+    if (levelI < levelJ)
+        faceIdx = indexInOutside;
+
+    Dune::FieldVector<CellData, 8> cellDataTemp;
+
+    if (levelI != levelJ)
+    {
+        DimVector vel(0);
+        cellData.fluxData().setVelocity(wPhaseIdx, indexInInside, vel);
+        cellData.fluxData().setVelocity(nPhaseIdx, indexInInside, vel);
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside, 0);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside, 0);
+
+        cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside, vel);
+        cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside, vel);
+        cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside, 0);
+        cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside, 0);
+    }
+
+    for (int vIdx = 0; vIdx < numVertices; vIdx++)
+    {
+        int localVertIdx = referenceElement.subEntity(faceIdx, 1, vIdx, dim);
+
+        int globalVertIdx = 0;
+                if (levelI >= levelJ)
+                {
+                    globalVertIdx = problem_.variables().index(
+                            *((*elementPtrI).template subEntity < dim > (localVertIdx)));
+                }
+                else
+                {
+                    globalVertIdx = problem_.variables().index(
+                            *((*elementPtrJ).template subEntity < dim > (localVertIdx)));
+                }
+
+        InteractionVolume& interactionVolume = this->interactionVolumes_.interactionVolume(globalVertIdx);
+
+        if (interactionVolume.isInnerVolume())
+        {
+        // cell index
+        int globalIdx[8];
+        for (int i = 0; i < 8; i++)
+        {
+            globalIdx[i] = problem_.variables().index(*(interactionVolume.getSubVolumeElement(i)));
+            cellDataTemp[i] = problem_.variables().cellData(globalIdx[i]);
+        }
+
+        if (!interactionVolume.isHangingNodeVolume())
+        {
+        velocity_.calculateInnerInteractionVolumeVelocity(interactionVolume,
+                cellDataTemp[0], cellDataTemp[1], cellDataTemp[2], cellDataTemp[3],
+                cellDataTemp[4], cellDataTemp[5], cellDataTemp[6], cellDataTemp[7],
+                this->interactionVolumes_, this->transmissibilityCalculator_);
+        }
+        else
+        {
+            velocity_.calculateHangingNodeInteractionVolumeVelocity(interactionVolume,
+                    cellDataTemp[0], cellDataTemp[1], cellDataTemp[2], cellDataTemp[3],
+                    cellDataTemp[4], cellDataTemp[5], cellDataTemp[6], cellDataTemp[7]);
+        }
+
+
+        for (int i = 0; i < 8; i++)
+        {
+            if (globalIdx[i] == globalIdxI)
+            {
+                if (levelI >= levelJ)
+                {
+                 cellData.fluxData().setVelocity(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInInside));
+                 cellData.fluxData().setVelocity(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInInside));
+                 cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInInside));
+                 cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInInside));
+
+                 if (levelI > levelJ)
+                 {
+                     cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInInside));
+                     cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInInside));
+                     cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInInside));
+                     cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInInside));
+
+                 }
+                }
+            }
+            else if (globalIdx[i] == globalIdxJ)
+            {
+                if (levelJ >= levelI)
+                {
+                cellDataJ.fluxData().setVelocity(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setVelocity(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setUpwindPotential(wPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInOutside));
+                cellDataJ.fluxData().setUpwindPotential(nPhaseIdx, indexInOutside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInOutside));
+
+                if (levelJ > levelI)
+                {
+                    cellData.fluxData().setVelocity(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(wPhaseIdx, indexInOutside));
+                    cellData.fluxData().setVelocity(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().velocity(nPhaseIdx, indexInOutside));
+                    cellData.fluxData().setUpwindPotential(wPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(wPhaseIdx, indexInOutside));
+                    cellData.fluxData().setUpwindPotential(nPhaseIdx, indexInInside, cellDataTemp[i].fluxData().upwindPotential(nPhaseIdx, indexInOutside));
+
+                }
+                }
+            }
+        }
+    }
+    }
+    if (levelI == levelJ)
+    {
+        cellData.fluxData().setVelocityMarker(indexInInside);
+        cellDataJ.fluxData().setVelocityMarker(indexInOutside);
+    }
+}
+
+template<class TypeTag>
+void FvMpfaL3dPressureVelocity2pAdaptive<TypeTag>::calculateVelocityOnBoundary(const Intersection& intersection, CellData& cellData)
+{
+    ElementPointer element = intersection.inside();
+
+    //get face index
+    int isIndex = intersection.indexInInside();
+
+    //get face normal
+    const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
+
+    BoundaryTypes bcType;
+    //get boundary type
+    problem_.boundaryTypes(bcType, intersection);
+    PrimaryVariables boundValues(0.0);
+
+    if (bcType.isDirichlet(pressEqIdx))
+    {
+        problem_.dirichlet(boundValues, intersection);
+
+        // get global coordinates of cell centers
+        const GlobalPosition& globalPosI = element->geometry().center();
+
+        // center of face in global coordinates
+        const GlobalPosition& globalPosJ = intersection.geometry().center();
+
+        // get mobilities and fractional flow factors
+        Scalar lambdaWI = cellData.mobility(wPhaseIdx);
+        Scalar lambdaNwI = cellData.mobility(nPhaseIdx);
+
+        // get capillary pressure
+        Scalar pcI = cellData.capillaryPressure();
+
+        // distance vector between barycenters
+        GlobalPosition distVec = globalPosJ - globalPosI;
+
+        // compute distance between cell centers
+        Scalar dist = distVec.two_norm();
+
+        //permeability vector at boundary
+        // compute vectorized permeabilities
+        DimMatrix meanPermeability(0);
+
+        problem_.spatialParams().meanK(meanPermeability, problem_.spatialParams().intrinsicPermeability(*element));
+
+        Dune::FieldVector<Scalar, dim> permeability(0);
+        meanPermeability.mv(unitOuterNormal, permeability);
+
+        //determine saturation at the boundary -> if no saturation is known directly at the boundary use the cell saturation
+        Scalar satW = 0;
+        Scalar satNw = 0;
+        if (bcType.isDirichlet(satEqIdx))
+        {
+            switch (saturationType_)
+            {
+            case sw:
+            {
+                satW = boundValues[saturationIdx];
+                satNw = 1 - boundValues[saturationIdx];
+                break;
+            }
+            case sn:
+            {
+                satW = 1 - boundValues[saturationIdx];
+                satNw = boundValues[saturationIdx];
+                break;
+            }
+            }
+        }
+        else
+        {
+            satW = cellData.saturation(wPhaseIdx);
+            satNw = cellData.saturation(nPhaseIdx);
+        }
+
+        Scalar pressBound = boundValues[pressureIdx];
+        Scalar pcBound = MaterialLaw::pc(problem_.spatialParams().materialLawParams(*element), satW);
+
+        //determine phase pressures from primary pressure variable
+        Scalar pressWBound = 0;
+        Scalar pressNwBound = 0;
+        if (pressureType_ == pw)
+        {
+            pressWBound = pressBound;
+            pressNwBound = pressBound + pcBound;
+        }
+        else if (pressureType_ == pn)
+        {
+            pressWBound = pressBound - pcBound;
+            pressNwBound = pressBound;
+        }
+
+        Scalar lambdaWBound = MaterialLaw::krw(problem_.spatialParams().materialLawParams(*element), satW)
+                / viscosity_[wPhaseIdx];
+        Scalar lambdaNwBound = MaterialLaw::krn(problem_.spatialParams().materialLawParams(*element), satW)
+                / viscosity_[nPhaseIdx];
+
+        Scalar potentialDiffW = cellData.fluxData().upwindPotential(wPhaseIdx, isIndex);
+        Scalar potentialDiffNw = cellData.fluxData().upwindPotential(nPhaseIdx, isIndex);
+
+        //calculate potential gradient
+        potentialDiffW = (cellData.pressure(wPhaseIdx) - pressWBound);
+        potentialDiffNw = (cellData.pressure(nPhaseIdx) - pressNwBound);
+
+        potentialDiffW += density_[wPhaseIdx] * (distVec * problem_.gravity());
+        potentialDiffNw += density_[nPhaseIdx] * (distVec * problem_.gravity());
+
+        //store potential gradients for further calculations
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, potentialDiffW);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, potentialDiffNw);
+
+        //do the upwinding of the mobility depending on the phase potentials
+        Scalar lambdaW = (potentialDiffW > 0.) ? lambdaWI : lambdaWBound;
+        lambdaW = (potentialDiffW == 0) ? 0.5 * (lambdaWI + lambdaWBound) : lambdaW;
+        Scalar lambdaNw = (potentialDiffNw > 0.) ? lambdaNwI : lambdaNwBound;
+        lambdaNw = (potentialDiffNw == 0) ? 0.5 * (lambdaNwI + lambdaNwBound) : lambdaNw;
+
+
+        Scalar scalarPerm = permeability.two_norm();
+
+        //calculate the gravity term
+        Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
+        Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
+
+        //calculate unit distVec
+        distVec /= dist;
+        Scalar areaScaling = (unitOuterNormal * distVec);
+        //this treatment of g allows to account for gravity flux through faces where the face normal has no z component (e.g. parallelepiped grids)
+        Scalar gravityTermW = (problem_.gravity() * distVec) * density_[wPhaseIdx] * areaScaling;
+        Scalar gravityTermNw = (problem_.gravity() * distVec) * density_[nPhaseIdx] * areaScaling;
+
+        //calculate velocity depending on the pressure used -> use pc = pn - pw
+        switch (pressureType_)
+        {
+        case pw:
+        {
+            velocityW *= lambdaW * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermW);
+            velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(wPhaseIdx) - pressBound) / dist + gravityTermNw)
+                    + 0.5 * (lambdaNwI + lambdaNwBound) * scalarPerm * (pcI - pcBound) / dist;
+            break;
+        }
+        case pn:
+        {
+            velocityW *= lambdaW * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermW)
+                    - 0.5 * (lambdaWI + lambdaWBound) * scalarPerm * (pcI - pcBound) / dist;
+            velocityNw *= lambdaNw * scalarPerm * ((cellData.pressure(nPhaseIdx) - pressBound) / dist + gravityTermNw);
+            break;
+        }
+        }
+
+        //store velocities
+        cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
+        cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
+        cellData.fluxData().setVelocityMarker(isIndex);
+
+    } //end dirichlet boundary
+
+    else if (bcType.isNeumann(pressEqIdx))
+    {
+        problem_.neumann(boundValues, intersection);
+
+        Dune::FieldVector<Scalar, dimWorld> velocityW(unitOuterNormal);
+        Dune::FieldVector<Scalar, dimWorld> velocityNw(unitOuterNormal);
+
+        velocityW *= boundValues[wPhaseIdx];
+        velocityNw *= boundValues[nPhaseIdx];
+
+            velocityW /= density_[wPhaseIdx];
+            velocityNw /= density_[nPhaseIdx];
+
+        //store potential gradients for further calculations
+        cellData.fluxData().setUpwindPotential(wPhaseIdx, isIndex, boundValues[wPhaseIdx]);
+        cellData.fluxData().setUpwindPotential(nPhaseIdx, isIndex, boundValues[nPhaseIdx]);
+
+        cellData.fluxData().setVelocity(wPhaseIdx, isIndex, velocityW);
+        cellData.fluxData().setVelocity(nPhaseIdx, isIndex, velocityNw);
+        cellData.fluxData().setVelocityMarker(isIndex);
+    } //end neumann boundary
+    else
+    {
+        DUNE_THROW(Dune::NotImplemented, "No valid boundary condition type defined for pressure equation!");
+    }
+}
+
 }
 // end of Dune namespace
 #endif
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dvelocity2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dvelocity2p.hh
index c6344b5efb9e2b4c672248fb898c06ea23e946b6..c2740d4dc5947eccde91dd02037059777772d30c 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dvelocity2p.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dvelocity2p.hh
@@ -140,8 +140,11 @@ public:
         vtkOutputLevel_ = GET_PARAM_FROM_GROUP(TypeTag, int, Vtk, OutputLevel);
     }
 
-    void calculateInnerInteractionVolumeVelocity(InteractionVolume& interactionVolume, InteractionVolumeContainer& interactionVolumes, TransmissibilityCalculator& transmissibilityCalculator);
-    void calculateBoundaryInteractionVolumeVelocity(InteractionVolume& interactionVolume, InteractionVolumeContainer& interactionVolumes, TransmissibilityCalculator& transmissibilityCalculator);
+    void calculateInnerInteractionVolumeVelocity(InteractionVolume& interactionVolume,
+            CellData & cellData1,  CellData & cellData2, CellData & cellData3, CellData & cellData4,
+            CellData & cellData5, CellData & cellData6, CellData & cellData7, CellData & cellData8,
+            InteractionVolumeContainer& interactionVolumes, TransmissibilityCalculator& transmissibilityCalculator);
+    void calculateBoundaryInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData, int elemIdx);
 
     void initialize(bool solveTwice = true)
     {
@@ -250,7 +253,10 @@ private:
 // end of template
 
 template<class TypeTag>
-void FvMpfaL3dVelocity2p<TypeTag>::calculateInnerInteractionVolumeVelocity(InteractionVolume& interactionVolume, InteractionVolumeContainer& interactionVolumes, TransmissibilityCalculator& transmissibilityCalculator)
+void FvMpfaL3dVelocity2p<TypeTag>::calculateInnerInteractionVolumeVelocity(InteractionVolume& interactionVolume,
+        CellData & cellData1,  CellData & cellData2, CellData & cellData3, CellData & cellData4,
+        CellData & cellData5, CellData & cellData6, CellData & cellData7, CellData & cellData8,
+        InteractionVolumeContainer& interactionVolumes, TransmissibilityCalculator& transmissibilityCalculator)
 {
     ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(0);
     ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(1);
@@ -271,16 +277,6 @@ void FvMpfaL3dVelocity2p<TypeTag>::calculateInnerInteractionVolumeVelocity(Inter
     int globalIdx7 = problem_.variables().index(*elementPointer7);
     int globalIdx8 = problem_.variables().index(*elementPointer8);
 
-    //get the cell Data
-    CellData & cellData1 = problem_.variables().cellData(globalIdx1);
-    CellData & cellData2 = problem_.variables().cellData(globalIdx2);
-    CellData & cellData3 = problem_.variables().cellData(globalIdx3);
-    CellData & cellData4 = problem_.variables().cellData(globalIdx4);
-    CellData & cellData5 = problem_.variables().cellData(globalIdx5);
-    CellData & cellData6 = problem_.variables().cellData(globalIdx6);
-    CellData & cellData7 = problem_.variables().cellData(globalIdx7);
-    CellData & cellData8 = problem_.variables().cellData(globalIdx8);
-
     // pressures flux calculation
     Dune::FieldVector<Scalar, 8> potW(0);
     Dune::FieldVector<Scalar, 8> potNw(0);
@@ -1837,40 +1833,13 @@ void FvMpfaL3dVelocity2p<TypeTag>::calculateInnerInteractionVolumeVelocity(Inter
 }
 
 template<class TypeTag>
-void FvMpfaL3dVelocity2p<TypeTag>::calculateBoundaryInteractionVolumeVelocity(InteractionVolume& interactionVolume, InteractionVolumeContainer& interactionVolumes, TransmissibilityCalculator& transmissibilityCalculator)
+void FvMpfaL3dVelocity2p<TypeTag>::calculateBoundaryInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData, int elemIdx)
 {
-    for (int elemIdx = 0; elemIdx < 8; elemIdx++)
-    {
-        if (!interactionVolume.hasSubVolumeElement(elemIdx))
-        {
-            continue;
-        }
-        bool isOutside = false;
-        for (int faceIdx = 0; faceIdx < dim; faceIdx++)
-        {
-            int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, faceIdx);
-            if (interactionVolume.isOutsideFace(intVolFaceIdx))
-            {
-                isOutside = true;
-                break;
-            }
-        }
-        if (isOutside)
-        {
-            continue;
-        }
-
         ElementPointer& elementPointer = interactionVolume.getSubVolumeElement(elemIdx);
 
         // get global coordinate of cell centers
         const GlobalPosition& globalPos = elementPointer->geometry().center();
 
-        // cell index
-        int globalIdx = problem_.variables().index(*elementPointer);
-
-        //get the cell Data
-        CellData & cellData = problem_.variables().cellData(globalIdx);
-
         // permeability vector at boundary
         DimMatrix permeability(problem_.spatialParams().intrinsicPermeability(*elementPointer));
 
@@ -2023,7 +1992,6 @@ void FvMpfaL3dVelocity2p<TypeTag>::calculateBoundaryInteractionVolumeVelocity(In
                                "No valid boundary condition type defined for pressure equation!");
                 }
             }
-        }
     }
 }
 
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dvelocity2padaptive.hh b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dvelocity2padaptive.hh
index 15674fa2f3b7ec257f75d6f2c166b55e4cd4fdce..dfea523223ba721246f30357293c19f5c024ffe9 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dvelocity2padaptive.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal3dvelocity2padaptive.hh
@@ -100,7 +100,7 @@ template<class TypeTag> class FvMpfaL3dVelocity2pAdaptive: public FvMpfaL3dVeloc
             nPhaseIdx = Indices::nPhaseIdx,
             pressureIdx = Indices::pressureIdx,
             saturationIdx = Indices::saturationIdx,
-            pressEqIdx = Indices::pressEqIdx,
+            pressEqIdx = Indices::pressureEqIdx,
             satEqIdx = Indices::satEqIdx,
             numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
         };
@@ -143,7 +143,9 @@ public:
         viscosity_[nPhaseIdx] = 0.;
     }
 
-    void calculateHangingNodeInteractionVolumeVelocity(InteractionVolume& interactionVolume);
+    void calculateHangingNodeInteractionVolumeVelocity(InteractionVolume& interactionVolume,
+            CellData & cellData1,  CellData & cellData2, CellData & cellData3, CellData & cellData4,
+            CellData & cellData5, CellData & cellData6, CellData & cellData7, CellData & cellData8);
 
 
     void initialize()
@@ -181,7 +183,9 @@ private:
 
 // only for 3-D general hexahedron
 template<class TypeTag>
-void FvMpfaL3dVelocity2pAdaptive<TypeTag>::calculateHangingNodeInteractionVolumeVelocity(InteractionVolume& interactionVolume)
+void FvMpfaL3dVelocity2pAdaptive<TypeTag>::calculateHangingNodeInteractionVolumeVelocity(InteractionVolume& interactionVolume,
+        CellData & cellData1,  CellData & cellData2, CellData & cellData3, CellData & cellData4,
+        CellData & cellData5, CellData & cellData6, CellData & cellData7, CellData & cellData8)
 {
     ElementPointer& elementPointer1 = interactionVolume.getSubVolumeElement(0);
     ElementPointer& elementPointer2 = interactionVolume.getSubVolumeElement(1);
@@ -202,16 +206,6 @@ void FvMpfaL3dVelocity2pAdaptive<TypeTag>::calculateHangingNodeInteractionVolume
     int globalIdx7 = problem_.variables().index(*elementPointer7);
     int globalIdx8 = problem_.variables().index(*elementPointer8);
 
-    //get the cell Data
-    CellData & cellData1 = problem_.variables().cellData(globalIdx1);
-    CellData & cellData2 = problem_.variables().cellData(globalIdx2);
-    CellData & cellData3 = problem_.variables().cellData(globalIdx3);
-    CellData & cellData4 = problem_.variables().cellData(globalIdx4);
-    CellData & cellData5 = problem_.variables().cellData(globalIdx5);
-    CellData & cellData6 = problem_.variables().cellData(globalIdx6);
-    CellData & cellData7 = problem_.variables().cellData(globalIdx7);
-    CellData & cellData8 = problem_.variables().cellData(globalIdx8);
-
     // pressures flux calculation
     Dune::FieldVector<Scalar, 8> potW(0);
     Dune::FieldVector<Scalar, 8> potNw(0);
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/omethod/fvmpfao2dpressurevelocity2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/omethod/fvmpfao2dpressurevelocity2p.hh
index 505be6f4c53ee9b1743b6f41bcf62086e94d9c39..27156a2b8b3ca5e97426e45061fa77f96254039e 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/omethod/fvmpfao2dpressurevelocity2p.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/omethod/fvmpfao2dpressurevelocity2p.hh
@@ -103,8 +103,8 @@ template<class TypeTag> class FvMpfaO2dPressureVelocity2p: public FvMpfaO2dPress
             sn = Indices::saturationNw,
             pressureIdx = Indices::pressureIdx,
             saturationIdx = Indices::saturationIdx,
-            eqIdxPress = Indices::pressureEqIdx,
-            eqIdxSat = Indices::satEqIdx,
+            pressEqIdx = Indices::pressureEqIdx,
+            satEqIdx = Indices::satEqIdx,
             numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
         };
 
@@ -138,13 +138,7 @@ public:
     {
         this->updateMaterialLaws();
 
-        //reset velocities
-        int size = problem_.gridView().size(0);
-        for (int i = 0; i < size; i++)
-        {
-            CellData& cellData = problem_.variables().cellData(i);
-            cellData.fluxData().resetVelocity();
-        }
+        this->storePressureSolution();
 
         if (!calculateVelocityInTransport())
             calculateVelocity();
@@ -388,7 +382,7 @@ void FvMpfaO2dPressureVelocity2p<TypeTag>::calculateVelocityOnBoundary(const Int
     problem_.boundaryTypes(bcType, intersection);
     PrimaryVariables boundValues(0.0);
 
-    if (bcType.isDirichlet(eqIdxPress))
+    if (bcType.isDirichlet(pressEqIdx))
     {
         problem_.dirichlet(boundValues, intersection);
 
@@ -423,7 +417,7 @@ void FvMpfaO2dPressureVelocity2p<TypeTag>::calculateVelocityOnBoundary(const Int
         //determine saturation at the boundary -> if no saturation is known directly at the boundary use the cell saturation
         Scalar satW = 0;
         Scalar satNw = 0;
-        if (bcType.isDirichlet(eqIdxSat))
+        if (bcType.isDirichlet(satEqIdx))
         {
             switch (saturationType_)
             {
@@ -529,7 +523,7 @@ void FvMpfaO2dPressureVelocity2p<TypeTag>::calculateVelocityOnBoundary(const Int
 
     } //end dirichlet boundary
 
-    else if (bcType.isNeumann(eqIdxPress))
+    else if (bcType.isNeumann(pressEqIdx))
     {
         problem_.neumann(boundValues, intersection);
 
diff --git a/dumux/decoupled/2p/diffusion/fvmpfa/omethod/fvmpfao2dvelocity2p.hh b/dumux/decoupled/2p/diffusion/fvmpfa/omethod/fvmpfao2dvelocity2p.hh
index c532e653cb34cde9edf3142300f7906261033dbc..914fff2d425eed268c56cdc9fe8ad9c63268e9bd 100644
--- a/dumux/decoupled/2p/diffusion/fvmpfa/omethod/fvmpfao2dvelocity2p.hh
+++ b/dumux/decoupled/2p/diffusion/fvmpfa/omethod/fvmpfao2dvelocity2p.hh
@@ -126,7 +126,7 @@ public:
     void calculateInnerInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData1, CellData& cellData2, CellData& cellData3, CellData& cellData4, InnerBoundaryVolumeFaces& innerBoundaryVolumeFaces);
     void calculateBoundaryInteractionVolumeVelocity(InteractionVolume& interactionVolume, CellData& cellData, int elemIdx);
 
-    void initialize(bool solveTwice = true)
+    void initialize()
     {
         ElementIterator element = problem_.gridView().template begin<0>();
         FluidState fluidState;
diff --git a/dumux/decoupled/2p2c/fvpressure2p2cadaptive.hh b/dumux/decoupled/2p2c/fvpressure2p2cadaptive.hh
index a810aef384345e1af81edb76317c1d6526c0cfc7..2b571156b33c8258533d2f9329381e45e44ba1a1 100644
--- a/dumux/decoupled/2p2c/fvpressure2p2cadaptive.hh
+++ b/dumux/decoupled/2p2c/fvpressure2p2cadaptive.hh
@@ -27,8 +27,7 @@
 
 // dumux environment
 // include 2p mpfa pressure model
-#include <dumux/decoupled/common/fv/mpfa/fvmpfaproperties.hh>
-#include <dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dpressure2padaptive.hh>
+#include <dumux/decoupled/2p/diffusion/fvmpfa/lmethod/fvmpfal2dtransmissibilitycalculator.hh>
 
 #include <dumux/decoupled/2p2c/fvpressure2p2c.hh>
 #include <dumux/common/math.hh>
@@ -122,6 +121,7 @@ template<class TypeTag> class FVPressure2P2CAdaptive
     // the typenames used for the stiffness matrix and solution vector
     typedef typename GET_PROP_TYPE(TypeTag, PressureCoefficientMatrix) Matrix;
 
+    typedef Dumux::FvMpfaL2dTransmissibilityCalculator<TypeTag> TransmissibilityCalculator;
 protected:
     Problem& problem()
     {
@@ -166,7 +166,7 @@ public:
      * \param problem a problem class object
      */
     FVPressure2P2CAdaptive(Problem& problem) : FVPressure2P2C<TypeTag>(problem),
-            problem_(problem)
+            problem_(problem), transmissibilityCalculator_(problem)
     {
         enableVolumeIntegral = GET_PARAM_FROM_GROUP(TypeTag,bool, Impet, EnableVolumeIntegral);
         enableMPFA= GET_PARAM_FROM_GROUP(TypeTag,bool, GridAdapt, EnableMultiPointFluxApproximation);
@@ -206,7 +206,7 @@ protected:
     bool enableMPFA; //!< Enables mpfa method to calculate the fluxes near hanging nodes
     bool enableSecondHalfEdge; //!< If possible, 2 interaction volumes are used for the mpfa method near hanging nodes
     //! The 2p Mpfa pressure module, that is only used for the calulation of transmissibility of the second interaction volumes
-    Dune::shared_ptr<FvMpfaL2dPressure2pAdaptive<TypeTag> > pressureModelAdaptive2p_;
+    TransmissibilityCalculator transmissibilityCalculator_;
 };
 
 
@@ -1181,9 +1181,6 @@ int FVPressure2P2CAdaptive<TypeTag>::transmissibilityAdapter_(const Intersection
     }
     /**** end find 4 faces **/
 
-
-    if(!pressureModelAdaptive2p_)
-        pressureModelAdaptive2p_= Dune::make_shared<FvMpfaL2dPressure2pAdaptive<TypeTag> >(problem()) ;
     // create Interaction Volume object
     Dumux::FVMPFALInteractionVolume<TypeTag> interactionVolume;
 
@@ -1275,12 +1272,12 @@ int FVPressure2P2CAdaptive<TypeTag>::transmissibilityAdapter_(const Intersection
     std::vector<Dune::FieldVector<Scalar, dim> > lambda(4, unity);
 
     Dune::FieldMatrix<Scalar,dim,2*dim-dim+1> T;
-    int triangleType = pressureModelAdaptive2p_->calculateTransmissibility(
+    int triangleType = transmissibilityCalculator_.calculateTransmissibility(
             T, interactionVolume, lambda,
             0, 1, 2, 3);
 
     // 3.decide which triangle (which transmissibility coefficients) to use
-    if (triangleType == pressureModelAdaptive2p_->rightTriangle)
+    if (triangleType == TransmissibilityCalculator::rightTriangle)
     {
         additionalIntersectionIt = isIt23;
         // Translate flux from 2p mpfa-l local indexing to
@@ -1290,7 +1287,7 @@ int FVPressure2P2CAdaptive<TypeTag>::transmissibilityAdapter_(const Intersection
         additionalT[1] = -T[1][1];
         additionalT[2] = -T[1][0];
     }
-    else if (triangleType == pressureModelAdaptive2p_->leftTriangle)
+    else if (triangleType == TransmissibilityCalculator::leftTriangle)
     {
         additionalIntersectionIt = isIt14;
         // Translate flux from 2p mpfa-l local indexing to