diff --git a/dumux/implicit/adaptive/adaptionhelper.hh b/dumux/implicit/adaptive/adaptionhelper.hh
index 36ddbb7eec79deb3f05c5bb718fdd4b24df7f679..21eba4e4772484066df388c6ccbaa650e5bbfa4c 100644
--- a/dumux/implicit/adaptive/adaptionhelper.hh
+++ b/dumux/implicit/adaptive/adaptionhelper.hh
@@ -47,21 +47,7 @@ template<class TypeTag>
 class ImplicitAdaptionHelper
 {
 private:
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-    typedef typename GridView::Grid Grid;
-
-    enum {
-        // Grid and world dimension
-        dim = GridView::dimension,
-        dimWorld = GridView::dimensionworld,
-    };
-
-    enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) };
-    enum { dofCodim = isBox ? dim : 0 };
-
-    typedef typename GridView::Traits::template Codim<0>::Entity Element;
-    typedef typename GridView::Traits::template Codim<dofCodim>::Entity DofEntity;
+    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
 
 public:
     //! Constructs an adaptive helper object
@@ -113,23 +99,8 @@ public:
                    "a reconstructPrimVars method.");
     }
 
-protected:
-
-    int dofIndex(const Problem& problem, const DofEntity& entity) const
-    {
-                return problem.model().dofMapper().index(entity);
-    }
-
-    int dofIndex(const Problem& problem, const Element& element, const int scvIdx) const
-    {
-                return problem.model().dofMapper().subIndex(element, scvIdx, dofCodim);
-    }
+};
 
-    int elementIndex(const Problem& problem, const Element& element) const
-    {
-                return problem.elementMapper().index(element);
-    }
+} // end namespace Dumux
 
-};
-}
 #endif
diff --git a/dumux/implicit/adaptive/gridadapt.hh b/dumux/implicit/adaptive/gridadapt.hh
index 015369d71731d6ed1a5ecda031f4fb5942c6d83b..17c1af7ff4e54df10a20ca28f416aae1374e0fa1 100644
--- a/dumux/implicit/adaptive/gridadapt.hh
+++ b/dumux/implicit/adaptive/gridadapt.hh
@@ -74,8 +74,8 @@ public:
         : problem_(problem),
           adaptionHelper_(problem),
           adaptionIndicator_(problem),
-          marked_(0),
-          coarsened_(0)
+          sumRefine_(0),
+          sumCoarsen_(0)
     {
             levelMin_ = GET_PARAM_FROM_GROUP(TypeTag, int, GridAdapt, MinLevel);
             levelMax_ = GET_PARAM_FROM_GROUP(TypeTag, int, GridAdapt, MaxLevel);
@@ -149,10 +149,7 @@ public:
      */
     bool wasAdapted() const
     {
-        int sumMarked = problem_.grid().comm().sum(marked_);
-        int sumCoarsened = problem_.grid().comm().sum(coarsened_);
-
-        return (sumMarked != 0 || sumCoarsened != 0);
+        return (sumRefine_ != 0 || sumCoarsen_ != 0);
     }
 
     /*!
@@ -222,9 +219,6 @@ private:
     template<class Indicator>
     void adaptGrid(Indicator& indicator)
     {
-        // reset internal counter for marked elements
-        marked_ = coarsened_ = 0;
-
         // check for adaption interval: Adapt only at certain time step indices
         if (problem_.timeManager().timeStepIndex() % adaptionInterval_ != 0)
             return;
@@ -235,16 +229,17 @@ private:
         indicator.calculateIndicator();
 
         /**** 2) mark elements according to indicator     *********/
-        markElements(indicator);
+        int refine, coarsen;
+        std::tie(refine, coarsen) = markElements(indicator);
 
         // abort if nothing in grid is marked
-        int sumMarked = problem_.grid().comm().sum(marked_);
-        int sumCoarsened = problem_.grid().comm().sum(coarsened_);
-        if (sumMarked == 0 && sumCoarsened == 0)
+        sumRefine_ = problem_.grid().comm().sum(refine);
+        sumCoarsen_ = problem_.grid().comm().sum(coarsen);
+        if (sumRefine_ == 0 && sumCoarsen_ == 0)
             return;
-        else
-            Dune::dinfo << marked_ << " cells have been marked_ to be refined, "
-                        << coarsened_ << " to be coarsened." << std::endl;
+        else if (problem_.grid().comm().rank() == 0)
+            Dune::dinfo << sumRefine_ << " cells have been marked to be refined, "
+                        << sumCoarsen_ << " to be coarsened." << std::endl;
 
         /****  2b) Do pre-adaption step    *****/
         problem_.grid().preAdapt();
@@ -280,11 +275,10 @@ private:
      * @param indicator The refinement indicator that is applied
      */
     template<class Indicator>
-    void markElements(Indicator& indicator)
+    std::pair<int, int> markElements(Indicator& indicator)
     {
-        typedef std::unordered_map<int, int> CoarsenMarkerType;
-        CoarsenMarkerType coarsenMarker;
-
+        int refine = 0;
+        int coarsen = 0;
         for (const auto& element : elements(problem_.gridView()))
         {
             // only mark non-ghost elements
@@ -294,18 +288,19 @@ private:
                 if (indicator.refine(element) && element.level() < levelMax_)
                 {
                     problem_.grid().mark( 1,  element);
-                    ++marked_;
+                    ++refine;
 
                     // this also refines the neighbor elements
-                    checkNeighborsRefine_(element);
+                    refine += checkNeighborsRefine_(element);
                 }
                 if (indicator.coarsen(element) && element.hasFather())
                 {
                     problem_.grid().mark( -1, element );
-                    ++coarsened_;
+                    ++coarsen;
                 }
             }
         }
+        return std::make_pair(refine, coarsen);
     }
 
     /*!
@@ -320,9 +315,10 @@ private:
      * @param level level of the refined element: it is at least 1
      * @return true if everything was successful
      */
-    bool checkNeighborsRefine_(const Element &element, int level = 1)
+    int checkNeighborsRefine_(const Element &element, int level = 1)
     {
         // this also refines the neighbor elements
+        int refine = 0;
         for(const auto& intersection : intersections(problem_.gridView(), element))
         {
             if(!intersection.neighbor())
@@ -338,13 +334,13 @@ private:
                 && (outside.level() < element.level()))
             {
                 problem_.grid().mark(1, outside);
-                ++marked_;
+                ++refine;
 
                 if(level != levelMax_)
-                    checkNeighborsRefine_(outside, ++level);
+                    refine += checkNeighborsRefine_(outside, ++level);
             }
         }
-        return true;
+        return refine;
     }
 
 
@@ -359,7 +355,7 @@ private:
      */
     void forceRefineRatio(int maxLevelDelta = 1)
     {
-        LeafGridView leafGridView = problem_.gridView();
+        auto leafGridView = problem_.gridView();
         // delete all existing marks
         problem_.grid().postAdapt();
         bool done;
@@ -394,7 +390,7 @@ private:
                 problem_.grid().postAdapt();
             }
         }
-        while (done!=true);
+        while (!done);
     }
 
     // private Variables
@@ -402,8 +398,8 @@ private:
     AdaptionHelper adaptionHelper_;
     AdaptionIndicator adaptionIndicator_;
 
-    int marked_;
-    int coarsened_;
+    int sumRefine_;
+    int sumCoarsen_;
 
     int levelMin_;
     int levelMax_;
@@ -444,4 +440,4 @@ public:
 };
 
 }
-#endif /* DUMUX_IMPLICIT_GRIDADAPT_HH */
\ No newline at end of file
+#endif /* DUMUX_IMPLICIT_GRIDADAPT_HH */
diff --git a/dumux/implicit/adaptive/gridadaptinitializationindicator.hh b/dumux/implicit/adaptive/gridadaptinitializationindicator.hh
index b106447be6b16703bc81d256bcdbc208fb543e24..55c3db2bf2a0e90be0b2e3fe8177b5fe09a4a9b0 100644
--- a/dumux/implicit/adaptive/gridadaptinitializationindicator.hh
+++ b/dumux/implicit/adaptive/gridadaptinitializationindicator.hh
@@ -20,7 +20,6 @@
 #define DUMUX_IMPLICIT_GRIDADAPTINITIALIZATIONINDICATOR_HH
 
 #include <dune/geometry/type.hh>
-#include <dune/common/dynvector.hh>
 #include "gridadaptproperties.hh"
 
 /**
@@ -53,9 +52,9 @@ template<class TypeTag>
 class ImplicitGridAdaptInitializationIndicator
 {
 private:
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
 
     enum
     {
@@ -64,28 +63,23 @@ private:
         numEq = GET_PROP_VALUE(TypeTag, NumEq),
     };
 
-    typedef typename GridView::Traits::template Codim<0>::Entity Element;
-    typedef typename GridView::Traits::template Codim<dim>::Entity Vertex;
-    typedef typename GridView::Intersection Intersection;
-    typedef typename GridView::Grid::ctype CoordScalar;
-    typedef typename Dune::ReferenceElement<CoordScalar, dim> ReferenceElement;
-    typedef typename Dune::ReferenceElements<CoordScalar, dim> ReferenceElements;
-
-    typedef typename GET_PROP_TYPE(TypeTag, AdaptionIndicator) AdaptionIndicator;
-
-    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
-    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    using Element = typename GridView::Traits::template Codim<0>::Entity;
+    using Vertex = typename GridView::Traits::template Codim<dim>::Entity;
+    using CoordScalar = typename GridView::Grid::ctype;
+    using ReferenceElement = typename Dune::ReferenceElement<CoordScalar, dim>;
+    using ReferenceElements = typename Dune::ReferenceElements<CoordScalar, dim>;
+    using AdaptionIndicator = typename GET_PROP_TYPE(TypeTag, AdaptionIndicator);
+    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
+    using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
+    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
+    using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
+    using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
+    using ElementBoundaryTypes = typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes);
+    using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
 
     enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) };
-
     enum { refineCell = 1 };
 
-
-
-
     /*! \brief Search for a source term
      *
      *  For every element we check if the element center or the element corners
@@ -97,10 +91,9 @@ private:
                     const FVElementGeometry& fvGeometry,
                     const ElementVolumeVariables& elemVolVars)
     {
-        PrimaryVariables source(0.0);
-        for (int scvIdx = 0; scvIdx < fvGeometry.numScv; scvIdx++)
+        for (auto&& scv : scvs(fvGeometry))
         {
-            problem_.solDependentSource(source, element, fvGeometry, scvIdx, elemVolVars);
+            auto source = problem_.source(element, fvGeometry, elemVolVars, scv);
             if (source.infinity_norm() > eps_)
                 return true;
         }
@@ -118,57 +111,53 @@ private:
      *  \param element A grid element
      *  \param intersection The boundary intersection
      */
-    bool hasRefineBC_(ElementBoundaryTypes &elemBcTypes,
-                      const Element& element,
-                      const Intersection& intersection,
+    bool hasRefineBC_(const Element& element,
                       const FVElementGeometry& fvGeometry,
-                      const ElementVolumeVariables& elemVolVars)
+                      const ElementVolumeVariables& elemVolVars,
+                      const SubControlVolumeFace& scvf,
+                      const ElementBoundaryTypes &elemBcTypes)
     {
         // Check for boundary conditions
         if(isBox)
         {
-            Dune::GeometryType geoType = element.geometry().type();
-            const ReferenceElement &refElement = ReferenceElements::general(geoType);
-            int fIdx = intersection.indexInInside();
-            int numFaceVerts = refElement.size(fIdx, 1, dim);
-            for (int faceVertexIdx = 0; faceVertexIdx < numFaceVerts; ++faceVertexIdx)
-            {
-                int scvIdx = refElement.subEntity(fIdx, 1, faceVertexIdx, dim);
-                BoundaryTypes bcTypes = elemBcTypes[scvIdx];
-                problemBoundaryTypes_(bcTypes, element.template subEntity<dim>(scvIdx));
-                int bfIdx = fvGeometry.boundaryFaceIndex(fIdx, faceVertexIdx);
-                for (int i = 0; i < numEq; i++)
-                {
-                    if(bcTypes.isDirichlet(i) && refineAtDirichletBC_)
-                        return true;
-                    if(bcTypes.isNeumann(i) && refineAtFluxBC_)
-                    {
-                        PrimaryVariables fluxes(0.0);
-                        problem_.solDependentNeumann(fluxes, element, fvGeometry,
-                                                 intersection, scvIdx, bfIdx,
-                                                 elemVolVars);
-                        if (fluxes.infinity_norm() > eps_)
-                            return true;
-                    }
-                }
-            }
-
+            // Dune::GeometryType geoType = element.geometry().type();
+            // const ReferenceElement &refElement = ReferenceElements::general(geoType);
+            // int fIdx = intersection.indexInInside();
+            // int numFaceVerts = refElement.size(fIdx, 1, dim);
+            // for (int faceVertexIdx = 0; faceVertexIdx < numFaceVerts; ++faceVertexIdx)
+            // {
+            //     int scvIdx = refElement.subEntity(fIdx, 1, faceVertexIdx, dim);
+            //     BoundaryTypes bcTypes = elemBcTypes[scvIdx];
+            //     problemBoundaryTypes_(bcTypes, element.template subEntity<dim>(scvIdx));
+            //     int bfIdx = fvGeometry.boundaryFaceIndex(fIdx, faceVertexIdx);
+            //     for (int i = 0; i < numEq; i++)
+            //     {
+            //         if(bcTypes.isDirichlet(i) && refineAtDirichletBC_)
+            //             return true;
+            //         if(bcTypes.isNeumann(i) && refineAtFluxBC_)
+            //         {
+            //             PrimaryVariables fluxes(0.0);
+            //             problem_.solDependentNeumann(fluxes, element, fvGeometry,
+            //                                      intersection, scvIdx, bfIdx,
+            //                                      elemVolVars);
+            //             if (fluxes.infinity_norm() > eps_)
+            //                 return true;
+            //         }
+            //     }
+            // }
+            return false;
         }
         else
         {
-            BoundaryTypes bcTypes = elemBcTypes[0];
-            problem_.boundaryTypes(bcTypes, intersection);
-            int bfIdx = intersection.indexInInside();
+            auto bcTypes = problem_.boundaryTypes(element, scvf);
             for (int i = 0; i < numEq; i++)
             {
                 if(bcTypes.isDirichlet(i) && refineAtDirichletBC_)
                     return true;
-                if(bcTypes.isNeumann(i) && refineAtFluxBC_)
+
+                else if(bcTypes.isNeumann(i) && refineAtFluxBC_)
                 {
-                    PrimaryVariables fluxes(0.0);
-                    problem_.solDependentNeumann(fluxes, element, fvGeometry,
-                                                 intersection, 0, bfIdx,
-                                                 elemVolVars);
+                    auto fluxes = problem_.neumann(element, fvGeometry, elemVolVars, scvf);
                     if (fluxes.infinity_norm() > eps_)
                         return true;
                 }
@@ -179,16 +168,19 @@ private:
 
     // only actually call the problem method when it exists
     template <class T = TypeTag>
-    void problemBoundaryTypes_(BoundaryTypes& bcTypes,
-                              const typename std::enable_if<GET_PROP_VALUE(T, ImplicitIsBox), Vertex>::type& v) const
+    BoundaryTypes problemBoundaryTypes_(const Element &element,
+                                        const typename std::enable_if<GET_PROP_VALUE(T, ImplicitIsBox),
+                                        SubControlVolume>::type& scv) const
     {
-        problem_.boundaryTypes(bcTypes, v);
+        return problem_.boundaryTypes(element, scv);
     }
     template <class T = TypeTag>
-    void problemBoundaryTypes_(BoundaryTypes& bcTypes,
-                              const typename std::enable_if<!GET_PROP_VALUE(T, ImplicitIsBox), Vertex>::type& v) const
-    {}
-
+    BoundaryTypes problemBoundaryTypes_(const Element &element,
+                                        const typename std::enable_if<!GET_PROP_VALUE(T, ImplicitIsBox),
+                                        SubControlVolume>::type& scv) const
+    {
+        return BoundaryTypes();
+    }
 
 public:
     /*! \brief Calculates the indicator used for refinement/coarsening for each grid cell.
@@ -199,19 +191,17 @@ public:
         if (!enableInitializationIndicator_)
             return;
 
-        //First adapt for boundary conditions and sources to get a good initial solution
+        // first adapt for boundary conditions and sources to get a good initial solution
         if (nextMaxLevel_ == maxAllowedLevel_)
             adaptionIndicator_.calculateIndicator();
 
         // prepare an indicator for refinement
-        indicatorVector_.resize(problem_.gridView().size(0));
-        indicatorVector_ = 0;
+        indicatorVector_.resize(problem_.gridView().size(0), 0);
 
         // 1) calculate Indicator -> min, maxvalues
         // loop over all leaf elements
         for (const auto& element : elements(problem_.gridView()))
         {
-
             int globalIdxI = problem_.elementMapper().index(element);
             int level = element.level();
             using std::max;
@@ -229,10 +219,11 @@ public:
                 continue;
 
             // get the fvGeometry and elementVolVars needed for the bc and source interfaces
-            FVElementGeometry fvGeometry;
-            ElementVolumeVariables elemVolVars;
-            fvGeometry.update(problem_.gridView(), element);
-            elemVolVars.update(problem_, element, fvGeometry, false /* oldSol? */);
+            auto fvGeometry = localView(problem_.model().globalFvGeometry());
+            fvGeometry.bindElement(element);
+
+            auto elemVolVars = localView(problem_.model().curGlobalVolVars());
+            elemVolVars.bindElement(element, fvGeometry, problem_.model().curSol());
 
             // Check if we have to refine around a source term
             if (indicatorVector_[globalIdxI] != refineCell && refineAtSource_)
@@ -246,18 +237,18 @@ public:
             }
 
             // get the element boundary types
-            ElementBoundaryTypes bcTypes;
-            bcTypes.update(problem_, element, fvGeometry);
+            ElementBoundaryTypes elemBcTypes;
+            elemBcTypes.update(problem_, element, fvGeometry);
 
             // Check if we have to refine at the boundary
             if (indicatorVector_[globalIdxI] != refineCell && (refineAtDirichletBC_ || refineAtFluxBC_))
             {
                 // Calculate the boundary indicator for all boundary intersections
-                for (const auto& intersection : intersections(problem_.gridView(), element))
+                for (auto&& scvf : scvfs(fvGeometry))
                 {
-                    if (intersection.boundary())
+                    if (scvf.boundary())
                     {
-                        if(hasRefineBC_(bcTypes, element, intersection, fvGeometry, elemVolVars))
+                        if(hasRefineBC_(element, fvGeometry, elemVolVars, scvf, elemBcTypes))
                         {
                             nextMaxLevel_ = min(max(level + 1, nextMaxLevel_), maxAllowedLevel_);
                             indicatorVector_[globalIdxI] = refineCell;
@@ -275,7 +266,7 @@ public:
      *
      *  \param element A grid element
      */
-    bool refine(const Element& element)
+    bool refine(const Element& element) const
     {
         int idx = problem_.elementMapper().index(element);
 
@@ -293,28 +284,21 @@ public:
      *
      *  \param element A grid element
      */
-    bool coarsen(const Element& element)
-    {
-        return false;
-    }
+    bool coarsen(const Element& element) const
+    { return false; }
 
-    int maxLevel()
-    {
-        return maxLevel_;
-    }
+    int maxLevel() const
+    { return maxLevel_; }
 
     /*! \brief Initializes the adaption indicator class */
-    void init()
-    {};
+    void init() {}
 
     /*! \brief If the model needs to be initialized after adaption.
      *         We always need to initialize since the hasRefineBC_ method needs information from
                an up-to-date model.
      */
-    bool initializeModel()
-    {
-        return true;
-    }
+    constexpr bool initializeModel() const
+    { return true; }
 
     /*! \brief Constructs a GridAdaptionIndicator instance
      *
@@ -346,7 +330,7 @@ public:
 private:
     Problem& problem_;
     AdaptionIndicator& adaptionIndicator_;
-    Dune::DynamicVector<int> indicatorVector_;
+    std::vector<int> indicatorVector_;
     int maxLevel_;
     int nextMaxLevel_;
     int minAllowedLevel_;
@@ -388,7 +372,7 @@ public:
      *
      *  \param element A grid element
      */
-    bool refine(const Element& element)
+    bool refine(const Element& element) const
     {
         return false;
     }
@@ -399,19 +383,18 @@ public:
      *
      *  \param element A grid element
      */
-    bool coarsen(const Element& element)
+    bool coarsen(const Element& element) const
     {
         return false;
     }
 
-    bool initializeModel()
+    constexpr bool initializeModel() const
     {
         return false;
     }
 
     /*! \brief Initializes the adaption indicator class*/
-    void init()
-    {};
+    void init() {}
 
     /*! \brief Constructs a GridAdaptionIndicator for initialization of an adaptive grid
      *
diff --git a/dumux/porousmediumflow/2p/implicit/adaptionhelper.hh b/dumux/porousmediumflow/2p/implicit/adaptionhelper.hh
index 9f21d22dcd4673d4fe9f29cacd4d3333f9bb4833..80dc9e334f37cbc23f8e21f81728cb77179518e8 100644
--- a/dumux/porousmediumflow/2p/implicit/adaptionhelper.hh
+++ b/dumux/porousmediumflow/2p/implicit/adaptionhelper.hh
@@ -31,15 +31,17 @@ template<class TypeTag>
 class TwoPAdaptionHelper : public ImplicitAdaptionHelper<TypeTag>
 {
 private:
-    typedef ImplicitAdaptionHelper<TypeTag> ParentType;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
-    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    using ParentType = ImplicitAdaptionHelper<TypeTag>;
+    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using Indices = typename GET_PROP_TYPE(TypeTag, Indices);
+    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
+    using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
+    using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
+    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
+    using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
+    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
 
     enum {
         // Grid and world dimension
@@ -59,29 +61,25 @@ private:
     enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) };
     enum { dofCodim = isBox ? dim : 0 };
 
-    typedef typename GridView::Grid Grid;
-    typedef typename Grid::LevelGridView LevelGridView;
-    typedef typename GridView::Traits::template Codim<0>::Entity Element;
+    using Grid = typename GridView::Grid;
+    using Element = typename GridView::Traits::template Codim<0>::Entity;
 
-    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
-    typedef typename GridView::ctype CoordScalar;
-    typedef Dune::FieldVector<CoordScalar, dim> LocalPosition;
+    using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
+    using CoordScalar = typename GridView::ctype;
+    using LocalPosition = Dune::FieldVector<CoordScalar, dim>;
 
-    typedef Dune::PQkLocalFiniteElementCache<CoordScalar, Scalar, dim, 1> LocalFiniteElementCache;
-    typedef typename LocalFiniteElementCache::FiniteElementType LocalFiniteElement;
+    using LocalFiniteElementCache = Dune::PQkLocalFiniteElementCache<CoordScalar, Scalar, dim, 1>;
+    using LocalFiniteElement = typename LocalFiniteElementCache::FiniteElementType;
 
     struct AdaptedValues
     {
-        std::vector<PrimaryVariables> u;
+        ElementSolutionVector u;
         int count;
         PrimaryVariables associatedMass;
-        AdaptedValues(): associatedMass(0)
-        {
-            count = 0;
-        }
+        AdaptedValues(): count(0), associatedMass(0.0) {}
     };
 
-    typedef Dune::PersistentContainer<Grid, AdaptedValues> PersistentContainer;
+    using PersistentContainer = Dune::PersistentContainer<Grid, AdaptedValues>;
     PersistentContainer adaptionMap_;
 
 public:
@@ -92,7 +90,7 @@ public:
     TwoPAdaptionHelper(Problem& problem) : ParentType(problem), adaptionMap_(problem.grid(), 0)
     {
         if(FluidSystem::isCompressible(wPhaseIdx) || FluidSystem::isCompressible(nPhaseIdx))
-            DUNE_THROW(Dune::InvalidStateException, "Adaptionhelper is only for incompressible fluids mass-conservative!");
+            DUNE_THROW(Dune::InvalidStateException, "This adaption helper is only mass conservative for incompressible fluids!");
     }
 
     /*!
@@ -113,53 +111,43 @@ public:
         // loop over all levels of the grid
         for (int level = problem.grid().maxLevel(); level >= 0; level--)
         {
-            //get grid view on level grid
-            LevelGridView levelView = problem.grid().levelGridView(level);
+            // get grid view on level grid
+            auto levelView = problem.grid().levelGridView(level);
 
             for (const auto& element : elements(levelView))
             {
                 //get your map entry
-                AdaptedValues &adaptedValues = adaptionMap_[element];
+                auto& adaptedValues = adaptionMap_[element];
 
                 // put values in the map
                 if (element.isLeaf())
                 {
-                    FVElementGeometry fvGeometry;
-                    fvGeometry.update(problem.gridView(), element);
+                    auto fvGeometry = localView(problem.model().globalFvGeometry());
+                    fvGeometry.bindElement(element);
 
-                    for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
-                    {
-                        // get index
-                        int dofIdx = this->dofIndex(problem, element, scvIdx);
+                    auto elemVolVars = localView(problem.model().curGlobalVolVars());
+                    elemVolVars.bindElement(element, fvGeometry, problem.model().curSol());
 
-                        adaptedValues.u.push_back(problem.model().curSol()[dofIdx]);
+                    for (auto&& scv : scvs(fvGeometry))
+                    {
+                        adaptedValues.u = problem.model().elementSolution(element, problem.model().curSol());
 
                         VolumeVariables volVars;
-                        volVars.update(adaptedValues.u[scvIdx],
-                                      problem,
-                                      element,
-                                      fvGeometry,
-                                      scvIdx,
-                                      false);
-
-                        Scalar volume = fvGeometry.subContVol[scvIdx].volume;
-
-                        adaptedValues.associatedMass[nPhaseIdx] += volume*volVars.density(nPhaseIdx)
-                                            * volVars.porosity() * volVars.saturation(nPhaseIdx);
-                        adaptedValues.associatedMass[wPhaseIdx] += volume*volVars.density(wPhaseIdx)
-                                            * volVars.porosity() * volVars.saturation(wPhaseIdx);
+                        volVars.update(adaptedValues.u, problem, element, scv);
+
+                        adaptedValues.associatedMass[nPhaseIdx] += scv.volume() * volVars.density(nPhaseIdx)
+                                                                   * volVars.porosity() * volVars.saturation(nPhaseIdx);
+                        adaptedValues.associatedMass[wPhaseIdx] += scv.volume() * volVars.density(wPhaseIdx)
+                                                                   * volVars.porosity() * volVars.saturation(wPhaseIdx);
                     }
                     adaptedValues.count = 1;
                 }
-                //Average in father
+                // Average in father
                 if (element.level() > 0)
                 {
-                    if(!element.hasFather())
-                        DUNE_THROW(Dune::InvalidStateException, "Element on level > 0 has no father element!");
-
-                    AdaptedValues& adaptedValuesFather = adaptionMap_[element.father()];
-                    //For some grids the father element is identical to the son element.
-                    //For that case averaging is not necessary.
+                    auto& adaptedValuesFather = adaptionMap_[element.father()];
+                    // For some grids the father element is identical to the son element.
+                    // For that case averaging is not necessary.
                     if(&adaptedValues != &adaptedValuesFather)
                     {
                         adaptedValuesFather.count += 1;
@@ -169,17 +157,8 @@ public:
 
                 if(isBox && !element.isLeaf())
                 {
-                    FVElementGeometry fvGeometry;
-                    fvGeometry.update(problem.gridView(), element);
-
-                    for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
-                    {
-                        int dofIdx = this->dofIndex(problem, element, scvIdx);
-
-                        adaptedValues.u.push_back(problem.model().curSol()[dofIdx]);
-                    }
+                    adaptedValues.u = problem.model().elementSolution(element, problem.model().curSol());
                 }
-
             }
         }
     }
@@ -200,19 +179,19 @@ public:
     void reconstructPrimVars(Problem& problem)
     {
         adaptionMap_.resize();
-        //vectors storing the mass associated with each vertex, when using the box method
+        // vectors storing the mass associated with each vertex, when using the box method
         std::vector<Scalar> massCoeff;
         std::vector<Scalar> associatedMass;
 
         if(isBox)
         {
-            massCoeff.resize(problem.model().numDofs(),0.0);
-            associatedMass.resize(problem.model().numDofs(),0.0);
+            massCoeff.resize(problem.model().numDofs(), 0.0);
+            associatedMass.resize(problem.model().numDofs(), 0.0);
         }
 
         for (int level = 0; level <= problem.grid().maxLevel(); level++)
         {
-            LevelGridView levelView = problem.grid().levelGridView(level);
+            auto levelView = problem.grid().levelGridView(level);
 
             for (const auto& element : elements(levelView))
             {
@@ -222,54 +201,45 @@ public:
 
                 if (!element.isNew() || element.level() == 0)
                 {
-                    //entry is in map, write in leaf
+                    // entry is in map, write in leaf
                     if (element.isLeaf())
                     {
-                        AdaptedValues &adaptedValues = adaptionMap_[element];
+                        auto& adaptedValues = adaptionMap_[element];
 
-                        FVElementGeometry fvGeometry;
-                        fvGeometry.update(problem.gridView(), element);
+                        auto fvGeometry = localView(problem.model().globalFvGeometry());
+                        fvGeometry.bindElement(element);
 
-                        for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
-                        {
-                            // get index
-                            int dofIdx = this->dofIndex(problem, element, scvIdx);
+                        auto elementVolume = element.geometry().volume();
 
+                        for (auto&& scv : scvs(fvGeometry))
+                        {
                             VolumeVariables volVars;
-                            volVars.update(adaptedValues.u[scvIdx],
-                                          problem,
-                                          element,
-                                          fvGeometry,
-                                          scvIdx,
-                                          false);
-
-                            Scalar volumeElement = fvGeometry.elementVolume;
+                            volVars.update(adaptedValues.u, problem, element, scv);
 
-                            this->setAdaptionValues(adaptedValues, problem.model().curSol()[dofIdx],scvIdx);
+                            problem.model().curSol()[scv.dofIndex()] = getPriVars(adaptedValues, scv);
 
-                            if (int(formulation) == pwsn)
+                            if (formulation == pwsn)
                             {
-                                problem.model().curSol()[dofIdx][saturationIdx] = adaptedValues.associatedMass[nPhaseIdx];
-                                problem.model().curSol()[dofIdx][saturationIdx] /= volumeElement * volVars.density(nPhaseIdx) * volVars.porosity();
+                                problem.model().curSol()[scv.dofIndex()][saturationIdx] = adaptedValues.associatedMass[nPhaseIdx];
+                                problem.model().curSol()[scv.dofIndex()][saturationIdx] /= elementVolume * volVars.density(nPhaseIdx) * volVars.porosity();
                             }
-                            else if (int(formulation) == pnsw)
+                            else if (formulation == pnsw)
                             {
-                                problem.model().curSol()[dofIdx][saturationIdx] = adaptedValues.associatedMass[wPhaseIdx];
-                                problem.model().curSol()[dofIdx][saturationIdx] /= volumeElement * volVars.density(wPhaseIdx) * volVars.porosity();
+                                problem.model().curSol()[scv.dofIndex()][saturationIdx] = adaptedValues.associatedMass[wPhaseIdx];
+                                problem.model().curSol()[scv.dofIndex()][saturationIdx] /= elementVolume * volVars.density(wPhaseIdx) * volVars.porosity();
                             }
 
                             if(isBox)
                             {
-                                Scalar volume = fvGeometry.subContVol[scvIdx].volume;
                                 if (int(formulation) == pwsn)
                                 {
-                                    massCoeff[dofIdx] += volume * volVars.density(nPhaseIdx) * volVars.porosity();
-                                    associatedMass[dofIdx] += volume/volumeElement*adaptedValues.associatedMass[nPhaseIdx];
+                                    massCoeff[scv.dofIndex()] += scv.volume() * volVars.density(nPhaseIdx) * volVars.porosity();
+                                    associatedMass[scv.dofIndex()] += scv.volume() / elementVolume * adaptedValues.associatedMass[nPhaseIdx];
                                 }
                                 else if (int(formulation) == pnsw)
                                 {
-                                    massCoeff[dofIdx] += volume * volVars.density(wPhaseIdx) * volVars.porosity();
-                                    associatedMass[dofIdx] += volume/volumeElement*adaptedValues.associatedMass[wPhaseIdx];
+                                    massCoeff[scv.dofIndex()] += scv.volume() * volVars.density(wPhaseIdx) * volVars.porosity();
+                                    associatedMass[scv.dofIndex()] += scv.volume() / elementVolume * adaptedValues.associatedMass[wPhaseIdx];
                                 }
                             }
 
@@ -282,127 +252,118 @@ public:
                     // value is not in map, interpolate from father element
                     if (element.hasFather())
                     {
-                        auto eFather = element.father();
-                        while(eFather.isNew() && eFather.level() > 0)
-                            eFather = eFather.father();
+                        auto fatherElement = element.father();
+                        while(fatherElement.isNew() && fatherElement.level() > 0)
+                            fatherElement = fatherElement.father();
 
                         Scalar massFather = 0.0;
 
                         if(!isBox)
                         {
-                            AdaptedValues& adaptedValuesFather = adaptionMap_[eFather];
+                            auto& adaptedValuesFather = adaptionMap_[fatherElement];
 
-                            if (int(formulation) == pwsn)
-                            {
+                            if (formulation == pwsn)
                                 massFather = adaptedValuesFather.associatedMass[nPhaseIdx];
-                            }
-                            else if (int(formulation) == pnsw)
-                            {
+
+                            else if (formulation == pnsw)
                                 massFather = adaptedValuesFather.associatedMass[wPhaseIdx];
-                            }
 
                             // access new son
-                            AdaptedValues& adaptedValues = adaptionMap_[element];
+                            auto& adaptedValues = adaptionMap_[element];
                             adaptedValues.count = 1;
 
-                            FVElementGeometry fvGeometry;
-                            fvGeometry.update(problem.gridView(), element);
+                            auto fvGeometry = localView(problem.model().globalFvGeometry());
+                            fvGeometry.bindElement(element);
 
-                            adaptedValues.u.push_back(adaptedValuesFather.u[0]);
+                            adaptedValues.u = adaptedValuesFather.u;
 
-                            VolumeVariables volVars;
-                            volVars.update(adaptedValues.u[0],
-                                          problem,
-                                          element,
-                                          fvGeometry,
-                                          /*scvIdx=*/0,
-                                          false);
-
-                            Scalar volume = fvGeometry.subContVol[0].volume;
-                            Scalar massCoeffSon = 0.0;
-                            if (int(formulation) == pwsn)
-                            {
-                                massCoeffSon = volume * volVars.density(nPhaseIdx) * volVars.porosity();
-                            }
-                            else if (int(formulation) == pnsw)
+                            for (auto&& scv : scvs(fvGeometry))
                             {
-                                massCoeffSon = volume * volVars.density(wPhaseIdx) * volVars.porosity();
+                                VolumeVariables volVars;
+                                volVars.update(adaptedValues.u, problem, element, scv);
+
+                                Scalar massCoeffSon = 0.0;
+                                if (int(formulation) == pwsn)
+                                    massCoeffSon = scv.volume() * volVars.density(nPhaseIdx) * volVars.porosity();
+
+                                else if (int(formulation) == pnsw)
+                                    massCoeffSon = scv.volume() * volVars.density(wPhaseIdx) * volVars.porosity();
+
+                                auto fatherElementVolume = fatherElement.geometry().volume();
+                                adaptedValues.u[0][saturationIdx] = (scv.volume() / fatherElementVolume * massFather)/massCoeffSon;
                             }
-                            Scalar volumeFather = eFather.geometry().volume();
-                            adaptedValues.u[0][saturationIdx] = (volume/volumeFather*massFather)/massCoeffSon;
 
                             // if we are on leaf, store reconstructed values of son in CellData object
                             if (element.isLeaf())
                             {
                                 // access new CellData object
-                                int newIdxI = this->elementIndex(problem, element);
-
-                                this->setAdaptionValues(adaptedValues, problem.model().curSol()[newIdxI],0);
+                                auto newIdxI = problem.elementMapper().index(element);
+                                problem.model().curSol()[newIdxI] = adaptedValues.u[0];
                             }
                         }
                         else
                         {
-                            AdaptedValues& adaptedValuesFather = adaptionMap_[eFather];
-                            // access new son
-                            AdaptedValues& adaptedValues = adaptionMap_[element];
-                            adaptedValues.u.clear();
-                            adaptedValues.count = 1;
-
-                            const auto geometryI = element.geometry();
-
-                            FVElementGeometry fvGeometry;
-                            fvGeometry.update(problem.gridView(), element);
-
-                            for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
-                            {
-                                auto subEntity = element.template subEntity <dofCodim>(scvIdx);
-
-                                LocalPosition dofCenterPos = geometryI.local(subEntity.geometry().center());
-                                const LocalFiniteElementCache feCache;
-                                Dune::GeometryType geomType = eFather.geometry().type();
-
-                                // Interpolate values from father element by using ansatz functions
-                                const LocalFiniteElement &localFiniteElement = feCache.get(geomType);
-                                std::vector<Dune::FieldVector<Scalar, 1> > shapeVal;
-                                localFiniteElement.localBasis().evaluateFunction(dofCenterPos, shapeVal);
-                                PrimaryVariables u(0);
-                                for (int j = 0; j < shapeVal.size(); ++j)
-                                {
-                                    u.axpy(shapeVal[j], adaptedValuesFather.u[j]);
-                                }
-
-                                adaptedValues.u.push_back(u);
-                                adaptedValues.count = 1;
-
-                                if (element.isLeaf())
-                                {
-                                    VolumeVariables volVars;
-                                    volVars.update(adaptedValues.u[scvIdx],
-                                                  problem,
-                                                  element,
-                                                  fvGeometry,
-                                                  scvIdx,
-                                                  false);
-
-                                    Scalar volume = fvGeometry.subContVol[scvIdx].volume;
-                                    Scalar volumeFather = eFather.geometry().volume();
-
-                                    int dofIdx = this->dofIndex(problem, element, scvIdx);
-                                    if (int(formulation) == pwsn)
-                                    {
-                                        massCoeff[dofIdx] += volume * volVars.density(nPhaseIdx) * volVars.porosity();
-                                        associatedMass[dofIdx] += volume/volumeFather*adaptedValuesFather.associatedMass[nPhaseIdx];
-                                    }
-                                    else if (int(formulation) == pnsw)
-                                    {
-                                        massCoeff[dofIdx] += volume * volVars.density(wPhaseIdx) * volVars.porosity();
-                                        associatedMass[dofIdx] += volume/volumeFather*adaptedValuesFather.associatedMass[wPhaseIdx];
-                                    }
-
-                                    this->setAdaptionValues(adaptedValues, problem.model().curSol()[dofIdx],scvIdx);
-                                }
-
-                            }
+                            // auto& adaptedValuesFather = adaptionMap_[fatherElement];
+                            // // access new son
+                            // auto& adaptedValues = adaptionMap_[element];
+                            // adaptedValues.u.clear();
+                            // adaptedValues.count = 1;
+                            //
+                            // const auto geometryI = element.geometry();
+                            //
+                            // FVElementGeometry fvGeometry;
+                            // fvGeometry.update(problem.gridView(), element);
+                            //
+                            // for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
+                            // {
+                            //     auto subEntity = element.template subEntity <dofCodim>(scvIdx);
+                            //
+                            //     LocalPosition dofCenterPos = geometryI.local(subEntity.geometry().center());
+                            //     const LocalFiniteElementCache feCache;
+                            //     Dune::GeometryType geomType = fatherElement.geometry().type();
+                            //
+                            //     // Interpolate values from father element by using ansatz functions
+                            //     const LocalFiniteElement &localFiniteElement = feCache.get(geomType);
+                            //     std::vector<Dune::FieldVector<Scalar, 1> > shapeVal;
+                            //     localFiniteElement.localBasis().evaluateFunction(dofCenterPos, shapeVal);
+                            //     PrimaryVariables u(0);
+                            //     for (int j = 0; j < shapeVal.size(); ++j)
+                            //     {
+                            //         u.axpy(shapeVal[j], adaptedValuesFather.u[j]);
+                            //     }
+                            //
+                            //     adaptedValues.u.push_back(u);
+                            //     adaptedValues.count = 1;
+                            //
+                            //     if (element.isLeaf())
+                            //     {
+                            //         VolumeVariables volVars;
+                            //         volVars.update(adaptedValues.u[scvIdx],
+                            //                       problem,
+                            //                       element,
+                            //                       fvGeometry,
+                            //                       scvIdx,
+                            //                       false);
+                            //
+                            //         Scalar volume = fvGeometry.subContVol[scvIdx].volume;
+                            //         Scalar fatherElementVolume = fatherElement.geometry().volume();
+                            //
+                            //         int dofIdxGlobal = this->dofIndex(problem, element, scvIdx);
+                            //         if (int(formulation) == pwsn)
+                            //         {
+                            //             massCoeff[dofIdxGlobal] += volume * volVars.density(nPhaseIdx) * volVars.porosity();
+                            //             associatedMass[dofIdxGlobal] += volume/fatherElementVolume*adaptedValuesFather.associatedMass[nPhaseIdx];
+                            //         }
+                            //         else if (int(formulation) == pnsw)
+                            //         {
+                            //             massCoeff[dofIdxGlobal] += volume * volVars.density(wPhaseIdx) * volVars.porosity();
+                            //             associatedMass[dofIdxGlobal] += volume/fatherElementVolume*adaptedValuesFather.associatedMass[wPhaseIdx];
+                            //         }
+                            //
+                            //         this->setAdaptionValues(adaptedValues, problem.model().curSol()[dofIdxGlobal],scvIdx);
+                            //     }
+                            //
+                            // }
                         }
                     }
                     else
@@ -417,10 +378,8 @@ public:
 
         if(isBox)
         {
-            for(int dofIdx = 0; dofIdx < problem.model().numDofs(); dofIdx++)
-            {
-                problem.model().curSol()[dofIdx][saturationIdx] = associatedMass[dofIdx]/massCoeff[dofIdx];
-            }
+            for(int dofIdxGlobal = 0; dofIdxGlobal < problem.model().numDofs(); dofIdxGlobal++)
+                problem.model().curSol()[dofIdxGlobal][saturationIdx] = associatedMass[dofIdxGlobal] / massCoeff[dofIdxGlobal];
         }
 
         // reset entries in restrictionmap
@@ -454,9 +413,6 @@ public:
     {
         if(!isBox)
         {
-            if(adaptedValuesFather.u.size() == 0)
-                adaptedValuesFather.u.resize(1);
-
             adaptedValuesFather.u[0] += adaptedValues.u[0];
             adaptedValuesFather.u[0] /= adaptedValues.count;
             adaptedValuesFather.associatedMass += adaptedValues.associatedMass;
@@ -475,21 +431,21 @@ public:
      * \param adaptedValues Container for model-specific values to be adapted
      * \param u The variables to be stored
      */
-    static void setAdaptionValues(AdaptedValues& adaptedValues, PrimaryVariables& u, int scvIdx)
+    static PrimaryVariables getPriVars(const AdaptedValues& adaptedValues, const SubControlVolume& scv)
     {
-        PrimaryVariables uNew(0);
         if(!isBox)
         {
-            uNew = adaptedValues.u[scvIdx];
+            auto uNew = adaptedValues.u[0];
             uNew /= adaptedValues.count;
+            return uNew;
         }
         else
         {
-            uNew = adaptedValues.u[scvIdx];
+            return adaptedValues.u[scv.index()];
         }
-
-        u = uNew;
     }
 };
-}
+
+} // end namespace Dumux
+
 #endif