diff --git a/dumux/boxmodels/common/porousmediaboxproblem.hh b/dumux/boxmodels/common/porousmediaboxproblem.hh
index 63cd95cb08977333ad9fdab9814b3b4b3f695f80..c86c92e6d4a1fcd3c0f5c00a362823a30dbabe59 100644
--- a/dumux/boxmodels/common/porousmediaboxproblem.hh
+++ b/dumux/boxmodels/common/porousmediaboxproblem.hh
@@ -1,7 +1,6 @@
 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 // vi: set et ts=4 sw=4 sts=4:
 /*****************************************************************************
- *                 2012 by Bernd Flemisch                                    *
  *   See the file COPYING for full copying permissions.                      *
  *                                                                           *
  *   This program is free software: you can redistribute it and/or modify    *
diff --git a/dumux/implicit/box/boxlocalresidual.hh b/dumux/implicit/box/boxlocalresidual.hh
index 8c02754133eec4a5cde1c8afdbff9bbc3d93ece1..3b8fb1a63a8578a11a886719f474c48ca09f53e2 100644
--- a/dumux/implicit/box/boxlocalresidual.hh
+++ b/dumux/implicit/box/boxlocalresidual.hh
@@ -27,6 +27,7 @@
 #include <dune/grid/common/geometry.hh>
 
 #include <dumux/common/valgrind.hh>
+#include <dumux/implicit/common/implicitlocalresidual.hh>
 
 #include "boxproperties.hh"
 
@@ -35,18 +36,16 @@ namespace Dumux
 /*!
  * \ingroup BoxModel
  * \ingroup BoxLocalResidual
- * \brief Element-wise calculation of the residual matrix for models
- *        based on the box scheme.
+ * \brief Element-wise calculation of the residual for models
+ *        based on the fully implicit box scheme.
  *
  * \todo Please doc me more!
  */
 template<class TypeTag>
-class BoxLocalResidual
+class BoxLocalResidual : public ImplicitLocalResidual<TypeTag>
 {
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef ImplicitLocalResidual<TypeTag> ParentType;
+    friend class ImplicitLocalResidual<TypeTag>;
     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
     typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
 
@@ -63,273 +62,18 @@ private:
     typedef typename Dune::GenericReferenceElements<CoordScalar, dim> ReferenceElements;
     typedef typename Dune::GenericReferenceElement<CoordScalar, dim> ReferenceElement;
 
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
     typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
     typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
     typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
-    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
 
     // copying the local residual class is not a good idea
     BoxLocalResidual(const BoxLocalResidual &);
 
 public:
-    BoxLocalResidual()
+    BoxLocalResidual() : ParentType()
     { }
 
-    ~BoxLocalResidual()
-    { }
-
-    /*!
-     * \brief Initialize the local residual.
-     *
-     * This assumes that all objects of the simulation have been fully
-     * allocated but not necessarily initialized completely.
-     *
-     * \param problem The representation of the physical problem to be
-     *             solved.
-     */
-    void init(Problem &problem)
-    { problemPtr_ = &problem; }
-
-    /*!
-     * \brief Compute the local residual, i.e. the deviation of the
-     *        equations from zero.
-     *
-     * \param element The DUNE Codim<0> entity for which the residual
-     *                ought to be calculated
-     */
-    void eval(const Element &element)
-    {
-        FVElementGeometry fvGeometry;
-
-        fvGeometry.update(gridView_(), element);
-        fvElemGeomPtr_ = &fvGeometry;
-
-        ElementVolumeVariables volVarsPrev, volVarsCur;
-        // update the hints
-        model_().setHints(element, volVarsPrev, volVarsCur);
-
-        volVarsPrev.update(problem_(),
-                           element,
-                           fvGeometry_(),
-                           true /* oldSol? */);
-        volVarsCur.update(problem_(),
-                          element,
-                          fvGeometry_(),
-                          false /* oldSol? */);
-
-        ElementBoundaryTypes bcTypes;
-        bcTypes.update(problem_(), element, fvGeometry_());
-
-        // this is pretty much a HACK because the internal state of
-        // the problem is not supposed to be changed during the
-        // evaluation of the residual. (Reasons: It is a violation of
-        // abstraction, makes everything more prone to errors and is
-        // not thread save.) The real solution are context objects!
-        problem_().updateCouplingParams(element);
-
-        asImp_().eval(element, fvGeometry_(), volVarsPrev, volVarsCur, bcTypes);
-    }
-
-    /*!
-     * \brief Compute the storage term for the current solution.
-     *
-     * This can be used to figure out how much of each conservation
-     * quantity is inside the element.
-     *
-     * \param element The DUNE Codim<0> entity for which the storage
-     *                term ought to be calculated
-     */
-    void evalStorage(const Element &element)
-    {
-        elemPtr_ = &element;
-
-        FVElementGeometry fvGeometry;
-        fvGeometry.update(gridView_(), element);
-        fvElemGeomPtr_ = &fvGeometry;
-
-        ElementBoundaryTypes bcTypes;
-        bcTypes.update(problem_(), element, fvGeometry_());
-        bcTypesPtr_ = &bcTypes;
-
-        // no previous volume variables!
-        prevVolVarsPtr_ = 0;
-
-        ElementVolumeVariables volVars;
-
-        // update the hints
-        model_().setHints(element, volVars);
-
-        // calculate volume current variables
-        volVars.update(problem_(), element, fvGeometry_(), false);
-        curVolVarsPtr_ = &volVars;
-
-        asImp_().evalStorage_();
-    }
-
-    /*!
-     * \brief Compute the flux term for the current solution.
-     *
-     * \param element The DUNE Codim<0> entity for which the residual
-     *                ought to be calculated
-     * \param curVolVars The volume averaged variables for all
-     *                   sub-contol volumes of the element
-     */
-    void evalFluxes(const Element &element,
-                    const ElementVolumeVariables &curVolVars)
-    {
-        elemPtr_ = &element;
-
-        FVElementGeometry fvGeometry;
-        fvGeometry.update(gridView_(), element);
-        fvElemGeomPtr_ = &fvGeometry;
-
-        ElementBoundaryTypes bcTypes;
-        bcTypes.update(problem_(), element, fvGeometry_());
-
-        residual_.resize(fvGeometry_().numVertices);
-        residual_ = 0;
-
-        bcTypesPtr_ = &bcTypes;
-        prevVolVarsPtr_ = 0;
-        curVolVarsPtr_ = &curVolVars;
-        asImp_().evalFluxes_();
-    }
-
-    /*!
-     * \brief Compute the local residual, i.e. the deviation of the
-     *        equations from zero.
-     *
-     * \param element The DUNE Codim<0> entity for which the residual
-     *                ought to be calculated
-     * \param fvGeometry The finite-volume geometry of the element
-     * \param prevVolVars The volume averaged variables for all
-     *                   sub-control volumes of the element at the previous
-     *                   time level
-     * \param curVolVars The volume averaged variables for all
-     *                   sub-control volumes of the element at the current
-     *                   time level
-     * \param bcTypes The types of the boundary conditions for all
-     *                vertices of the element
-     */
-    void eval(const Element &element,
-              const FVElementGeometry &fvGeometry,
-              const ElementVolumeVariables &prevVolVars,
-              const ElementVolumeVariables &curVolVars,
-              const ElementBoundaryTypes &bcTypes)
-    {
-        Valgrind::CheckDefined(prevVolVars);
-        Valgrind::CheckDefined(curVolVars);
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry.numVertices; i++) {
-            prevVolVars[i].checkDefined();
-            curVolVars[i].checkDefined();
-        }
-#endif // HAVE_VALGRIND
-
-        elemPtr_ = &element;
-        fvElemGeomPtr_ = &fvGeometry;
-        bcTypesPtr_ = &bcTypes;
-        prevVolVarsPtr_ = &prevVolVars;
-        curVolVarsPtr_ = &curVolVars;
-
-        // resize the vectors for all terms
-        int numVerts = fvGeometry_().numVertices;
-        residual_.resize(numVerts);
-        storageTerm_.resize(numVerts);
-
-        residual_ = 0.0;
-        storageTerm_ = 0.0;
-
-        asImp_().evalFluxes_();
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry_().numVertices; i++)
-            Valgrind::CheckDefined(residual_[i]);
-#endif // HAVE_VALGRIND
-
-        asImp_().evalVolumeTerms_();
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry_().numVertices; i++) {
-            Valgrind::CheckDefined(residual_[i]);
-        }
-#endif // HAVE_VALGRIND
-
-        // evaluate the boundary conditions
-        asImp_().evalBoundary_();
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry_().numVertices; i++)
-            Valgrind::CheckDefined(residual_[i]);
-#endif // HAVE_VALGRIND
-    }
-
-    /*!
-     * \brief Returns the local residual for all sub-control
-     *        volumes of the element.
-     */
-    const ElementSolutionVector &residual() const
-    { return residual_; }
-
-    /*!
-     * \brief Returns the local residual for a given sub-control
-     *        volume of the element.
-     *
-     * \param scvIdx The local index of the sub-control volume
-     *               (i.e. the element's local vertex index)
-     */
-    const PrimaryVariables &residual(const int scvIdx) const
-    { return residual_[scvIdx]; }
-
-    /*!
-     * \brief Returns the storage term for all sub-control volumes of the
-     *        element.
-     */
-    const ElementSolutionVector &storageTerm() const
-    { return storageTerm_; }
-
-    /*!
-     * \brief Returns the storage term for a given sub-control volumes
-     *        of the element.
-     */
-    const PrimaryVariables &storageTerm(const int scvIdx) const
-    { return storageTerm_[scvIdx]; }
-
 protected:
-    Implementation &asImp_()
-    {
-        assert(static_cast<Implementation*>(this) != 0);
-        return *static_cast<Implementation*>(this);
-    }
-
-    const Implementation &asImp_() const
-    {
-        assert(static_cast<const Implementation*>(this) != 0);
-        return *static_cast<const Implementation*>(this);
-    }
-
-    /*!
-     * \brief Evaluate the boundary conditions
-     *        of the current element.
-     */
-    void evalBoundary_()
-    {
-        if (bcTypes_().hasNeumann() || bcTypes_().hasOutflow())
-            asImp_().evalBoundaryFluxes_();
-#if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry_().numVertices; i++)
-            Valgrind::CheckDefined(residual_[i]);
-#endif // HAVE_VALGRIND
-
-        if (bcTypes_().hasDirichlet())
-            asImp_().evalDirichlet_();
-    }
-
     /*!
      * \brief Set the values of the Dirichlet boundary control volumes
      *        of the current element.
@@ -337,14 +81,14 @@ protected:
     void evalDirichlet_()
     {
         PrimaryVariables dirichletValues(0);
-        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; ++scvIdx) {
-            const BoundaryTypes &bcTypes = bcTypes_(scvIdx);
+        for (int scvIdx = 0; scvIdx < this->fvGeometry_().numVertices; ++scvIdx) {
+            const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx);
             
             if (bcTypes.hasDirichlet()) {
                 // ask the problem for the dirichlet values
-                const VertexPointer vPtr = element_().template subEntity<dim>(scvIdx);
+                const VertexPointer vPtr = this->element_().template subEntity<dim>(scvIdx);
                 Valgrind::SetUndefined(dirichletValues);
-                asImp_().problem_().dirichlet(dirichletValues, *vPtr);
+                this->asImp_().problem_().dirichlet(dirichletValues, *vPtr);
 
                 // set the dirichlet conditions
                 for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
@@ -353,10 +97,10 @@ protected:
                         assert(0 <= pvIdx && pvIdx < numEq);
                         Valgrind::CheckDefined(dirichletValues[pvIdx]);
 
-                        residual_[scvIdx][eqIdx] =
-                                curPriVar_(scvIdx, pvIdx) - dirichletValues[pvIdx];
+                        this->residual_[scvIdx][eqIdx] =
+                                this->curPriVar_(scvIdx, pvIdx) - dirichletValues[pvIdx];
 
-                        storageTerm_[scvIdx][eqIdx] = 0.0;
+                        this->storageTerm_[scvIdx][eqIdx] = 0.0;
                     }
                 }
             }
@@ -369,11 +113,11 @@ protected:
      */
     void evalBoundaryFluxes_()
     {
-        Dune::GeometryType geoType = element_().geometry().type();
+        Dune::GeometryType geoType = this->element_().geometry().type();
         const ReferenceElement &refElement = ReferenceElements::general(geoType);
 
-        IntersectionIterator isIt = gridView_().ibegin(element_());
-        const IntersectionIterator &endIt = gridView_().iend(element_());
+        IntersectionIterator isIt = this->gridView_().ibegin(this->element_());
+        const IntersectionIterator &endIt = this->gridView_().iend(this->element_());
         for (; isIt != endIt; ++isIt)
         {
             // handle only faces on the boundary
@@ -392,19 +136,17 @@ protected:
                                                         dim);
 
                     int boundaryFaceIdx =
-                        fvGeometry_().boundaryFaceIndex(faceIdx, faceVertIdx);
+                        this->fvGeometry_().boundaryFaceIndex(faceIdx, faceVertIdx);
 
                     // add the residual of all vertices of the boundary
                     // segment
-                    asImp_().evalNeumannSegment_(isIt,
-                                                scvIdx,
-                                                boundaryFaceIdx);
+                    this->asImp_().evalNeumannSegment_(isIt,
+                                                       scvIdx,
+                                                       boundaryFaceIdx);
                     // evaluate the outflow conditions at the boundary face
-                    // ATTENTION: This is so far a beta version that is only for the 2p2c and 2p2cni model
-                    //              available and not thoroughly tested.
-                    asImp_().evalOutflowSegment_(isIt,
-                                                scvIdx,
-                                                boundaryFaceIdx);
+                    this->asImp_().evalOutflowSegment_(isIt,
+                                                       scvIdx,
+                                                       boundaryFaceIdx);
                 }
             }
         }
@@ -420,28 +162,28 @@ protected:
     {
         // temporary vector to store the neumann boundary fluxes
         PrimaryVariables neumannFlux(0.0);
-        const BoundaryTypes &bcTypes = bcTypes_(scvIdx);
+        const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx);
 
         // deal with neumann boundaries
         if (bcTypes.hasNeumann()) {
             Valgrind::SetUndefined(neumannFlux);
-            problem_().boxSDNeumann(neumannFlux,
-                                    element_(),
-                                    fvGeometry_(),
-                                    *isIt,
-                                    scvIdx,
-                                    boundaryFaceIdx,
-                                    curVolVars_());
+            this->problem_().boxSDNeumann(neumannFlux,
+                                          this->element_(),
+                                          this->fvGeometry_(),
+                                          *isIt,
+                                          scvIdx,
+                                          boundaryFaceIdx,
+                                          this->curVolVars_());
             neumannFlux *=
-                fvGeometry_().boundaryFace[boundaryFaceIdx].area
-                * curVolVars_(scvIdx).extrusionFactor();
+                this->fvGeometry_().boundaryFace[boundaryFaceIdx].area
+                * this->curVolVars_(scvIdx).extrusionFactor();
             Valgrind::CheckDefined(neumannFlux);
 
             // set the neumann conditions
             for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
                 if (!bcTypes.isNeumann(eqIdx))
                     continue;
-                residual_[scvIdx][eqIdx] += neumannFlux[eqIdx];
+                this->residual_[scvIdx][eqIdx] += neumannFlux[eqIdx];
             }
         }
     }
@@ -464,7 +206,7 @@ protected:
         {
             //calculate outflow fluxes
             PrimaryVariables values(0.0);
-            asImp_().computeFlux(values, boundaryFaceIdx, true);
+            this->asImp_().computeFlux(values, boundaryFaceIdx, true);
             Valgrind::CheckDefined(values);
             
             for (int equationIdx = 0; equationIdx < numEq; ++equationIdx)
@@ -485,20 +227,20 @@ protected:
     {
         // calculate the mass flux over the faces and subtract
         // it from the local rates
-        for (int scvfIdx = 0; scvfIdx < fvGeometry_().numEdges; scvfIdx++)
+        for (int scvfIdx = 0; scvfIdx < this->fvGeometry_().numEdges; scvfIdx++)
         {
-            int i = fvGeometry_().subContVolFace[scvfIdx].i;
-            int j = fvGeometry_().subContVolFace[scvfIdx].j;
+            int i = this->fvGeometry_().subContVolFace[scvfIdx].i;
+            int j = this->fvGeometry_().subContVolFace[scvfIdx].j;
 
             PrimaryVariables flux;
 
             Valgrind::SetUndefined(flux);
-            asImp_().computeFlux(flux, scvfIdx);
+            this->asImp_().computeFlux(flux, scvfIdx);
             Valgrind::CheckDefined(flux);
 
             Scalar extrusionFactor =
-                (curVolVars_(i).extrusionFactor()
-                 + curVolVars_(j).extrusionFactor())
+                (this->curVolVars_(i).extrusionFactor()
+                 + this->curVolVars_(j).extrusionFactor())
                 / 2;
             flux *= extrusionFactor;
 
@@ -516,225 +258,13 @@ protected:
             // of sub-control volume i and _INTO_ sub-control volume
             // j, we need to add the flux to finite volume i and
             // subtract it from finite volume j
-            residual_[i] += flux;
-            residual_[j] -= flux;
+            this->residual_[i] += flux;
+            this->residual_[j] -= flux;
         }
     }
-
-    /*!
-     * \brief Set the local residual to the storage terms of all
-     *        sub-control volumes of the current element.
-     */
-    void evalStorage_()
-    {
-        storageTerm_.resize(fvGeometry_().numVertices);
-        storageTerm_ = 0;
-
-        // calculate the amount of conservation each quantity inside
-        // all sub control volumes
-        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; scvIdx++) {
-            Valgrind::SetUndefined(storageTerm_[scvIdx]);
-            asImp_().computeStorage(storageTerm_[scvIdx], scvIdx, /*isOldSol=*/false);
-            storageTerm_[scvIdx] *=
-                fvGeometry_().subContVol[scvIdx].volume
-                * curVolVars_(scvIdx).extrusionFactor();
-            Valgrind::CheckDefined(storageTerm_[scvIdx]);
-        }
-    }
-
-    /*!
-     * \brief Add the change in the storage terms and the source term
-     *        to the local residual of all sub-control volumes of the
-     *        current element.
-     */
-    void evalVolumeTerms_()
-    {
-        // evaluate the volume terms (storage + source terms)
-        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; scvIdx++)
-        {
-            Scalar extrusionFactor =
-                curVolVars_(scvIdx).extrusionFactor();
-
-            PrimaryVariables values(0.0);
-
-            // mass balance within the element. this is the
-            // \f$\frac{m}{\partial t}\f$ term if using implicit
-            // euler as time discretization.
-            //
-            // TODO (?): we might need a more explicit way for
-            // doing the time discretization...
-            Valgrind::SetUndefined(storageTerm_[scvIdx]);
-            Valgrind::SetUndefined(values);
-            asImp_().computeStorage(storageTerm_[scvIdx], scvIdx, false);
-            asImp_().computeStorage(values, scvIdx, true);
-            Valgrind::CheckDefined(storageTerm_[scvIdx]);
-            Valgrind::CheckDefined(values);
-
-            storageTerm_[scvIdx] -= values;
-            storageTerm_[scvIdx] *=
-                fvGeometry_().subContVol[scvIdx].volume
-                / problem_().timeManager().timeStepSize()
-                * extrusionFactor;
-            residual_[scvIdx] += storageTerm_[scvIdx];
-
-            // subtract the source term from the local rate
-            Valgrind::SetUndefined(values);
-            asImp_().computeSource(values, scvIdx);
-            Valgrind::CheckDefined(values);
-            values *= fvGeometry_().subContVol[scvIdx].volume * extrusionFactor;
-            residual_[scvIdx] -= values;
-
-            // make sure that only defined quantities were used
-            // to calculate the residual.
-            Valgrind::CheckDefined(residual_[scvIdx]);
-        }
-    }
-
-    /*!
-     * \brief Returns a reference to the problem.
-     */
-    const Problem &problem_() const
-    { return *problemPtr_; };
-
-    /*!
-     * \brief Returns a reference to the model.
-     */
-    const Model &model_() const
-    { return problem_().model(); };
-
-    /*!
-     * \brief Returns a reference to the vertex mapper.
-     */
-    const VertexMapper &vertexMapper_() const
-    { return problem_().vertexMapper(); };
-
-    /*!
-     * \brief Returns a reference to the grid view.
-     */
-    const GridView &gridView_() const
-    { return problem_().gridView(); }
-
-    /*!
-     * \brief Returns a reference to the current element.
-     */
-    const Element &element_() const
-    {
-        Valgrind::CheckDefined(elemPtr_);
-        return *elemPtr_;
-    }
     
-    /*!
-     * \brief Returns a reference to the current element's finite
-     *        volume geometry.
-     */
-    const FVElementGeometry &fvGeometry_() const
-    {
-        Valgrind::CheckDefined(fvElemGeomPtr_);
-        return *fvElemGeomPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the primary variables of
-     *           the last time step of the i'th
-     *        sub-control volume of the current element.
-     */
-    const PrimaryVariables &prevPriVars_(const int i) const
-    {
-        return prevVolVars_(i).priVars();
-    }
-
-    /*!
-     * \brief Returns a reference to the primary variables of the i'th
-     *        sub-control volume of the current element.
-     */
-    const PrimaryVariables &curPriVars_(const int i) const
-    {
-        return curVolVars_(i).priVars();
-    }
-
-    /*!
-     * \brief Returns the j'th primary of the i'th sub-control volume
-     *        of the current element.
-     */
-    Scalar curPriVar_(const int i, const int j) const
-    {
-        return curVolVars_(i).priVar(j);
-    }
-
-    /*!
-     * \brief Returns a reference to the current volume variables of
-     *        all sub-control volumes of the current element.
-     */
-    const ElementVolumeVariables &curVolVars_() const
-    {
-        Valgrind::CheckDefined(curVolVarsPtr_);
-        return *curVolVarsPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the volume variables of the i-th
-     *        sub-control volume of the current element.
-     */
-    const VolumeVariables &curVolVars_(const int i) const
-    {
-        return curVolVars_()[i];
-    }
-
-    /*!
-     * \brief Returns a reference to the previous time step's volume
-     *        variables of all sub-control volumes of the current
-     *        element.
-     */
-    const ElementVolumeVariables &prevVolVars_() const
-    {
-        Valgrind::CheckDefined(prevVolVarsPtr_);
-        return *prevVolVarsPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the previous time step's volume
-     *        variables of the i-th sub-control volume of the current
-     *        element.
-     */
-    const VolumeVariables &prevVolVars_(const int i) const
-    {
-        return prevVolVars_()[i];
-    }
-
-    /*!
-     * \brief Returns a reference to the boundary types of all
-     *        sub-control volumes of the current element.
-     */
-    const ElementBoundaryTypes &bcTypes_() const
-    {
-        Valgrind::CheckDefined(bcTypesPtr_);
-        return *bcTypesPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the boundary types of the i-th
-     *        sub-control volume of the current element.
-     */
-    const BoundaryTypes &bcTypes_(const int i) const
-    {
-        return bcTypes_()[i];
-    }
-
-protected:
-    ElementSolutionVector storageTerm_;
-    ElementSolutionVector residual_;
-
-    // The problem we would like to solve
-    Problem *problemPtr_;
-
-    const Element *elemPtr_;
-    const FVElementGeometry *fvElemGeomPtr_;
-
-    // current and previous secondary variables for the element
-    const ElementVolumeVariables *prevVolVarsPtr_;
-    const ElementVolumeVariables *curVolVarsPtr_;
-
-    const ElementBoundaryTypes *bcTypesPtr_;
+    const VertexMapper &vertexMapper_() const
+    { return this->problem_().vertexMapper(); };
 };
 
 }
diff --git a/dumux/implicit/cellcentered/cclocalresidual.hh b/dumux/implicit/cellcentered/cclocalresidual.hh
index cdc914e8b2d0b9c446f6486eb2e8a92dcfca1881..abe2f9f0b53319fc00e1f2c0c5806eb0672132cc 100644
--- a/dumux/implicit/cellcentered/cclocalresidual.hh
+++ b/dumux/implicit/cellcentered/cclocalresidual.hh
@@ -31,6 +31,7 @@
 #include <dune/grid/common/geometry.hh>
 
 #include <dumux/common/valgrind.hh>
+#include <dumux/implicit/common/implicitlocalresidual.hh>
 
 #include "ccproperties.hh"
 
@@ -39,18 +40,16 @@ namespace Dumux
 /*!
  * \ingroup CCModel
  * \ingroup CCLocalResidual
- * \brief Element-wise calculation of the residual matrix for models
- *        based on the box scheme.
+ * \brief Element-wise calculation of the residual for models
+ *        based on the fully implicit cell-centered scheme.
  *
  * \todo Please doc me more!
  */
 template<class TypeTag>
-class CCLocalResidual
+class CCLocalResidual : public ImplicitLocalResidual<TypeTag>
 {
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef ImplicitLocalResidual<TypeTag> ParentType;
+    friend class ImplicitLocalResidual<TypeTag>;
     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
     typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
 
@@ -62,302 +61,17 @@ private:
     typedef typename GridView::template Codim<0>::Entity Element;
     typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
     typedef typename GridView::IntersectionIterator IntersectionIterator;
-
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
     typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
     typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
-    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
 
     // copying the local residual class is not a good idea
     CCLocalResidual(const CCLocalResidual &);
 
 public:
-    CCLocalResidual()
-    { }
-
-    ~CCLocalResidual()
+    CCLocalResidual() : ParentType()
     { }
 
-    /*!
-     * \brief Initialize the local residual.
-     *
-     * This assumes that all objects of the simulation have been fully
-     * allocated but not necessarily initialized completely.
-     *
-     * \param prob The representation of the physical problem to be
-     *             solved.
-     */
-    void init(Problem &prob)
-    { problemPtr_ = &prob; }
-
-    /*!
-     * \brief Compute the local residual, i.e. the deviation of the
-     *        equations from zero.
-     *
-     * \param element The DUNE Codim<0> entity for which the residual
-     *                ought to be calculated
-     */
-    void eval(const Element &element)
-    {
-        FVElementGeometry fvElemGeom;
-
-        fvElemGeom.update(gridView_(), element);
-        fvElemGeomPtr_ = &fvElemGeom;
-
-        ElementVolumeVariables volVarsPrev, volVarsCur;
-        // update the hints
-        model_().setHints(element, volVarsPrev, volVarsCur);
-
-        volVarsPrev.update(problem_(),
-                           element,
-                           fvGeometry_(),
-                           true /* oldSol? */);
-        volVarsCur.update(problem_(),
-                          element,
-                          fvGeometry_(),
-                          false /* oldSol? */);
-
-        ElementBoundaryTypes bcTypes;
-        bcTypes.update(problem_(), element, fvGeometry_());
-
-        // this is pretty much a HACK because the internal state of
-        // the problem is not supposed to be changed during the
-        // evaluation of the residual. (Reasons: It is a violation of
-        // abstraction, makes everything more prone to errors and is
-        // not thread save.) The real solution are context objects!
-        problem_().updateCouplingParams(element);
-
-        asImp_().eval(element, fvGeometry_(), volVarsPrev, volVarsCur, bcTypes);
-    }
-
-    /*!
-     * \brief Compute the storage term for the current solution.
-     *
-     * This can be used to figure out how much of each conservation
-     * quantity is inside the element.
-     *
-     * \param element The DUNE Codim<0> entity for which the storage
-     *                term ought to be calculated
-     */
-    void evalStorage(const Element &element)
-    {
-        elemPtr_ = &element;
-
-        FVElementGeometry fvElemGeom;
-        fvElemGeom.update(gridView_(), element);
-        fvElemGeomPtr_ = &fvElemGeom;
-
-        ElementBoundaryTypes bcTypes;
-        bcTypes.update(problem_(), element, fvGeometry_());
-        bcTypesPtr_ = &bcTypes;
-
-        // no previous volume variables!
-        prevVolVarsPtr_ = 0;
-
-        ElementVolumeVariables volVars;
-
-        // update the hints
-        model_().setHints(element, volVars);
-
-        // calculate volume current variables
-        volVars.update(problem_(), element, fvGeometry_(), false);
-        curVolVarsPtr_ = &volVars;
-
-        asImp_().evalStorage_();
-    }
-
-    /*!
-     * \brief Compute the flux term for the current solution.
-     *
-     * \param element The DUNE Codim<0> entity for which the residual
-     *                ought to be calculated
-     * \param curVolVars The volume averaged variables for all
-     *                   sub-contol volumes of the element
-     */
-    void evalFluxes(const Element &element,
-                    const ElementVolumeVariables &curVolVars)
-    {
-        elemPtr_ = &element;
-
-        FVElementGeometry fvElemGeom;
-        fvElemGeom.update(gridView_(), element);
-        fvElemGeomPtr_ = &fvElemGeom;
-
-        ElementBoundaryTypes bcTypes;
-        bcTypes.update(problem_(), element, fvGeometry_());
-
-        residual_.resize(1);
-        residual_ = 0;
-
-        bcTypesPtr_ = &bcTypes;
-        prevVolVarsPtr_ = 0;
-        curVolVarsPtr_ = &curVolVars;
-        asImp_().evalFluxes_();
-    }
-
-    /*!
-     * \brief Compute the local residual, i.e. the deviation of the
-     *        equations from zero.
-     *
-     * \param element The DUNE Codim<0> entity for which the residual
-     *                ought to be calculated
-     * \param fvElemGeom The finite-volume geometry of the element
-     * \param prevVolVars The volume averaged variables for all
-     *                   sub-control volumes of the element at the previous
-     *                   time level
-     * \param curVolVars The volume averaged variables for all
-     *                   sub-control volumes of the element at the current
-     *                   time level
-     * \param bcTypes The types of the boundary conditions for all
-     *                vertices of the element
-     */
-    void eval(const Element &element,
-              const FVElementGeometry &fvElemGeom,
-              const ElementVolumeVariables &prevVolVars,
-              const ElementVolumeVariables &curVolVars,
-              const ElementBoundaryTypes &bcTypes)
-    {
-        Valgrind::CheckDefined(prevVolVars);
-        Valgrind::CheckDefined(curVolVars);
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvElemGeom.numNeighbors; i++) {
-            prevVolVars[i].checkDefined();
-            curVolVars[i].checkDefined();
-        }
-#endif // HAVE_VALGRIND
-
-        elemPtr_ = &element;
-        fvElemGeomPtr_ = &fvElemGeom;
-        bcTypesPtr_ = &bcTypes;
-        prevVolVarsPtr_ = &prevVolVars;
-        curVolVarsPtr_ = &curVolVars;
-
-        // resize the vectors for all terms
-        residual_.resize(1);
-        storageTerm_.resize(1);
-
-        residual_ = 0.0;
-        storageTerm_ = 0.0;
-
-        asImp_().evalFluxes_();
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        Valgrind::CheckDefined(residual_[0]);
-#endif // HAVE_VALGRIND
-
-        asImp_().evalVolumeTerms_();
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        Valgrind::CheckDefined(residual_[0]);
-#endif // HAVE_VALGRIND
-
-        // evaluate the boundary conditions
-        asImp_().evalBoundary_();
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        Valgrind::CheckDefined(residual_[0]);
-#endif // HAVE_VALGRIND
-    }
-
-    /*!
-     * \brief Add Outflow boundary conditions for a single sub-control
-     *        volume face to the local residual.
-     *
-     * \note This is so far an empty method doing not more than
-     *       nothing. A beta version is available for the 2p2c and
-     *       2p2cni model. There you can find a sample implementation.
-     */
-    void evalOutflowSegment(const IntersectionIterator &isIt,
-                            int scvIdx,
-                            int boundaryFaceIdx)
-    {}
-
-    /*!
-     * \brief Returns the local residual for all sub-control
-     *        volumes of the element.
-     */
-    const ElementSolutionVector &residual() const
-    { return residual_; }
-
-    /*!
-     * \brief Returns the local residual for a given sub-control
-     *        volume of the element.
-     *
-     * \param scvIdx The local index of the sub-control volume
-     *               (i.e. the element's local vertex index)
-     */
-    const PrimaryVariables &residual(int scvIdx) const
-    { return residual_[scvIdx]; }
-
-    /*!
-     * \brief Returns the storage term for all sub-control volumes of the
-     *        element.
-     */
-    const ElementSolutionVector &storageTerm() const
-    { return storageTerm_; }
-
-    /*!
-     * \brief Returns the storage term for a given sub-control volumes
-     *        of the element.
-     */
-    const PrimaryVariables &storageTerm(int scvIdx) const
-    { return storageTerm_[scvIdx]; }
-
-    void evalOutflowSegment(const IntersectionIterator &isIt)
-    {
-        const BoundaryTypes &bcTypes = this->bcTypes_(0);
-        
-        // deal with outflow boundaries
-        if (bcTypes.hasOutflow())
-        {
-            PrimaryVariables values(0.0);
-            asImp_().computeFlux(values, 
-                                  /*boundaryFaceIdx=*/isIt->indexInInside(), 
-                                  true);
-            Valgrind::CheckDefined(values);
-            
-            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
-            {
-                if (!bcTypes.isOutflow(eqIdx) )
-                    continue;
-                this->residual_[0][eqIdx] += values[eqIdx];
-            }
-        }
-    }
 protected:
-    Implementation &asImp_()
-    {
-        assert(static_cast<Implementation*>(this) != 0);
-        return *static_cast<Implementation*>(this);
-    }
-
-    const Implementation &asImp_() const
-    {
-        assert(static_cast<const Implementation*>(this) != 0);
-        return *static_cast<const Implementation*>(this);
-    }
-
-    /*!
-     * \brief Evaluate the boundary conditions
-     *        of the current element.
-     */
-    void evalBoundary_()
-    {
-        if (bcTypes_().hasNeumann() || bcTypes_().hasOutflow())
-            asImp_().evalBoundaryFluxes_();
-
-#if !defined NDEBUG && HAVE_VALGRIND
-        Valgrind::CheckDefined(residual_[0]);
-#endif // HAVE_VALGRIND
-
-        if (bcTypes_().hasDirichlet())
-            asImp_().evalDirichlet_();
-    }
 
     /*!
      * \brief Set the values of the Dirichlet boundary control volumes
@@ -365,15 +79,15 @@ protected:
      */
     void evalDirichlet_()
     {
-        PrimaryVariables tmp(0);
+        PrimaryVariables dirichletValues(0);
 
-        const BoundaryTypes &bcTypes = bcTypes_(0);
+        const BoundaryTypes &bcTypes = this->bcTypes_(0);
         if (! bcTypes.hasDirichlet())
             return;
 
-        Valgrind::SetUndefined(tmp);
-	// HACK: ask for Dirichlet value at element center
-        asImp_().problem_().dirichletAtPos(tmp, element_().geometry().center());
+        Valgrind::SetUndefined(dirichletValues);
+        // HACK: ask for Dirichlet value at element center
+        this->asImp_().problem_().dirichletAtPos(dirichletValues, this->element_().geometry().center());
 
         // set the dirichlet conditions
         for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
@@ -381,12 +95,12 @@ protected:
                 continue;
             int pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
             assert(0 <= pvIdx && pvIdx < numEq);
-            Valgrind::CheckDefined(tmp[pvIdx]);
+            Valgrind::CheckDefined(dirichletValues[pvIdx]);
 
-            residual_[0][eqIdx] =
-                    (curPriVar_(0, pvIdx) - tmp[pvIdx]);
+            this->residual_[0][eqIdx] =
+                    (this->curPriVar_(0, pvIdx) - dirichletValues[pvIdx]);
 
-            storageTerm_[0][eqIdx] = 0.0;
+            this->storageTerm_[0][eqIdx] = 0.0;
         }
     }
 
@@ -396,8 +110,8 @@ protected:
      */
     void evalBoundaryFluxes_()
     {
-        IntersectionIterator isIt = gridView_().ibegin(element_());
-        const IntersectionIterator &endIt = gridView_().iend(element_());
+        IntersectionIterator isIt = this->gridView_().ibegin(this->element_());
+        const IntersectionIterator &endIt = this->gridView_().iend(this->element_());
         for (; isIt != endIt; ++isIt)
         {
             // handle only faces on the boundary
@@ -406,18 +120,15 @@ protected:
 
             // add the residual of all vertices of the boundary
             // segment
-            asImp_().evalNeumannSegment_(isIt);
-		
+            this->asImp_().evalNeumannSegment_(isIt);
+
             // evaluate the outflow conditions at the boundary face
-            // ATTENTION: This is so far a beta version that is only for the 2p2c and 2p2cni model
-            //              available and not thoroughly tested.
-            asImp_().evalOutflowSegment(isIt);
+            this->asImp_().evalOutflowSegment_(isIt);
         }
     }
 
     /*!
-     * \brief Add Neumann boundary conditions for a single sub-control
-     *        volume face to the local residual.
+     * \brief Add Neumann boundary conditions for a single intersection
      */
     void evalNeumannSegment_(const IntersectionIterator &isIt)
     {
@@ -425,42 +136,66 @@ protected:
         PrimaryVariables values(0.0);
 
         BoundaryTypes bcTypes;
-        problem_().boundaryTypes(bcTypes, *isIt);
+        this->problem_().boundaryTypes(bcTypes, *isIt);
 
         // deal with neumann boundaries
         if (bcTypes.hasNeumann()) {
             Valgrind::SetUndefined(values);
-            problem_().boxSDNeumann(values,
-                                    element_(),
-                                    fvGeometry_(),
-                                    *isIt,
-                                    /*scvIdx=*/0,
-                                    /*boundaryFaceIdx=*/isIt->indexInInside(),
-                                    curVolVars_());
+            this->problem_().boxSDNeumann(values,
+                                          this->element_(),
+                                          this->fvGeometry_(),
+                                          *isIt,
+                                          /*scvIdx=*/0,
+                                          /*boundaryFaceIdx=*/isIt->indexInInside(),
+                                          this->curVolVars_());
             values *= isIt->geometry().volume()
-                * curVolVars_(0).extrusionFactor();
+                * this->curVolVars_(0).extrusionFactor();
             Valgrind::CheckDefined(values);
 
             // set the neumann conditions
             for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
                 if (!bcTypes.isNeumann(eqIdx))
                     continue;
-                residual_[0][eqIdx] += values[eqIdx];
+                this->residual_[0][eqIdx] += values[eqIdx];
+            }
+        }
+    }
+
+    /*!
+     * \brief Add outflow boundary conditions for a single intersection
+     */
+    void evalOutflowSegment_(const IntersectionIterator &isIt)
+    {
+        const BoundaryTypes &bcTypes = this->bcTypes_(0);
+        
+        // deal with outflow boundaries
+        if (bcTypes.hasOutflow())
+        {
+            PrimaryVariables values(0.0);
+            this->asImp_().computeFlux(values, 
+                                       /*boundaryFaceIdx=*/isIt->indexInInside(), 
+                                       true);
+            Valgrind::CheckDefined(values);
+            
+            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
+            {
+                if (!bcTypes.isOutflow(eqIdx) )
+                    continue;
+                this->residual_[0][eqIdx] += values[eqIdx];
             }
         }
     }
 
     /*!
-     * \brief Add the flux terms to the local residual of all
-     *        sub-control volumes of the current element.
+     * \brief Add the flux terms to the local residual of the current element
      */
     void evalFluxes_()
     {
         // calculate the mass flux over the faces and subtract
         // it from the local rates
         int faceIdx = -1;
-        IntersectionIterator isIt = gridView_().ibegin(element_());
-        IntersectionIterator isEndIt = gridView_().iend(element_());
+        IntersectionIterator isIt = this->gridView_().ibegin(this->element_());
+        IntersectionIterator isEndIt = this->gridView_().iend(this->element_());
         for (; isIt != isEndIt; ++isIt) {
             if (!isIt->neighbor())
                 continue;
@@ -469,240 +204,14 @@ protected:
 	    PrimaryVariables flux;
 
             Valgrind::SetUndefined(flux);
-            asImp_().computeFlux(flux, faceIdx);
+            this->asImp_().computeFlux(flux, faceIdx);
             Valgrind::CheckDefined(flux);
 
-            flux *= curVolVars_(0).extrusionFactor();
-
-            // The balance equation for a finite volume is:
-            //
-            // dStorage/dt = Flux + Source
-            //
-            // where the 'Flux' and the 'Source' terms represent the
-            // mass per second which _ENTER_ the finite
-            // volume. Re-arranging this, we get
-            //
-            // dStorage/dt - Source - Flux = 0
-            //
-            // Since the flux calculated by computeFlux() goes _OUT_
-            // of sub-control volume i and _INTO_ sub-control volume
-            // j, we need to add the flux to finite volume i and
-            // subtract it from finite volume j
-            residual_[0] += flux;
-        }
-    }
-
-    /*!
-     * \brief Set the local residual to the storage terms of all
-     *        sub-control volumes of the current element.
-     */
-    void evalStorage_()
-    {
-        storageTerm_.resize(1);
-        storageTerm_ = 0;
-
-        // calculate the amount of conservation each quantity inside
-        // all sub control volumes
-        Valgrind::SetUndefined(storageTerm_[0]);
-        asImp_().computeStorage(storageTerm_[0], 0, /*isOldSol=*/false);
-        storageTerm_[0] *= fvGeometry_().subContVol[0].volume
-                * curVolVars_(0).extrusionFactor();
-        Valgrind::CheckDefined(storageTerm_[0]);
-    }
-
-    /*!
-     * \brief Add the change in the storage terms and the source term
-     *        to the local residual of all sub-control volumes of the
-     *        current element.
-     */
-    void evalVolumeTerms_()
-    {
-        // evaluate the volume terms (storage + source terms)
-        for (int i=0; i < 1; i++)
-        {
-            Scalar extrusionFactor =
-                curVolVars_(i).extrusionFactor();
-
-            PrimaryVariables tmp(0.);
-
-            // mass balance within the element. this is the
-            // \f$\frac{m}{\partial t}\f$ term if using implicit
-            // euler as time discretization.
-            //
-            // TODO (?): we might need a more explicit way for
-            // doing the time discretization...
-            Valgrind::SetUndefined(storageTerm_[i]);
-            Valgrind::SetUndefined(tmp);
-            asImp_().computeStorage(storageTerm_[i], i, false);
-            asImp_().computeStorage(tmp, i, true);
-            Valgrind::CheckDefined(storageTerm_[i]);
-            Valgrind::CheckDefined(tmp);
+            flux *= this->curVolVars_(0).extrusionFactor();
 
-            storageTerm_[i] -= tmp;
-            storageTerm_[i] *=
-                fvGeometry_().subContVol[i].volume
-                / problem_().timeManager().timeStepSize()
-                * extrusionFactor;
-            residual_[i] += storageTerm_[i];
-
-            // subtract the source term from the local rate
-            Valgrind::SetUndefined(tmp);
-            asImp_().computeSource(tmp, i);
-            Valgrind::CheckDefined(tmp);
-            tmp *= fvGeometry_().subContVol[i].volume * extrusionFactor;
-            residual_[i] -= tmp;
-
-            // make sure that only defined quantities were used
-            // to calculate the residual.
-            Valgrind::CheckDefined(residual_[i]);
+            this->residual_[0] += flux;
         }
     }
-
-    /*!
-     * \brief Returns a reference to the problem.
-     */
-    const Problem &problem_() const
-    { return *problemPtr_; };
-
-    /*!
-     * \brief Returns a reference to the model.
-     */
-    const Model &model_() const
-    { return problem_().model(); };
-
-    /*!
-     * \brief Returns a reference to the vertex mapper.
-     */
-    const VertexMapper &vertexMapper_() const
-    { return problem_().vertexMapper(); };
-
-    /*!
-     * \brief Returns a reference to the grid view.
-     */
-    const GridView &gridView_() const
-    { return problem_().gridView(); }
-
-    /*!
-     * \brief Returns a reference to the current element.
-     */
-    const Element &element_() const
-    {
-        Valgrind::CheckDefined(elemPtr_);
-        return *elemPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the current element's finite
-     *        volume geometry.
-     */
-    const FVElementGeometry &fvGeometry_() const
-    {
-        Valgrind::CheckDefined(fvElemGeomPtr_);
-        return *fvElemGeomPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the primary variables of
-     *           the last time step of the i'th
-     *        sub-control volume of the current element.
-     */
-    const PrimaryVariables &prevPriVars_(int i) const
-    {
-        return prevVolVars_(i).priVars();
-    }
-
-    /*!
-     * \brief Returns a reference to the primary variables of the i'th
-     *        sub-control volume of the current element.
-     */
-    const PrimaryVariables &curPriVars_(int i) const
-    {
-        return curVolVars_(i).priVars();
-    }
-
-    /*!
-     * \brief Returns the j'th primary of the i'th sub-control volume
-     *        of the current element.
-     */
-    Scalar curPriVar_(int i, int j) const
-    {
-        return curVolVars_(i).priVar(j);
-    }
-
-    /*!
-     * \brief Returns a reference to the current volume variables of
-     *        all sub-control volumes of the current element.
-     */
-    const ElementVolumeVariables &curVolVars_() const
-    {
-        Valgrind::CheckDefined(curVolVarsPtr_);
-        return *curVolVarsPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the volume variables of the i-th
-     *        sub-control volume of the current element.
-     */
-    const VolumeVariables &curVolVars_(int i) const
-    {
-        return curVolVars_()[i];
-    }
-
-    /*!
-     * \brief Returns a reference to the previous time step's volume
-     *        variables of all sub-control volumes of the current
-     *        element.
-     */
-    const ElementVolumeVariables &prevVolVars_() const
-    {
-        Valgrind::CheckDefined(prevVolVarsPtr_);
-        return *prevVolVarsPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the previous time step's volume
-     *        variables of the i-th sub-control volume of the current
-     *        element.
-     */
-    const VolumeVariables &prevVolVars_(int i) const
-    {
-        return prevVolVars_()[i];
-    }
-
-    /*!
-     * \brief Returns a reference to the boundary types of all
-     *        sub-control volumes of the current element.
-     */
-    const ElementBoundaryTypes &bcTypes_() const
-    {
-        Valgrind::CheckDefined(bcTypesPtr_);
-        return *bcTypesPtr_;
-    }
-
-    /*!
-     * \brief Returns a reference to the boundary types of the i-th
-     *        sub-control volume of the current element.
-     */
-    const BoundaryTypes &bcTypes_(int i) const
-    {
-        return bcTypes_()[i];
-    }
-
-protected:
-    ElementSolutionVector storageTerm_;
-    ElementSolutionVector residual_;
-
-    // The problem we would like to solve
-    Problem *problemPtr_;
-
-    const Element *elemPtr_;
-    const FVElementGeometry *fvElemGeomPtr_;
-
-    // current and previous secondary variables for the element
-    const ElementVolumeVariables *prevVolVarsPtr_;
-    const ElementVolumeVariables *curVolVarsPtr_;
-
-    const ElementBoundaryTypes *bcTypesPtr_;
 };
 
 }
diff --git a/dumux/implicit/common/implicitlocalresidual.hh b/dumux/implicit/common/implicitlocalresidual.hh
index 53eaa0bf554990078effe06e67ccab58387bf4e9..f020e8bbd1a32fd1a387bc4cfda69a1a7a56a0fd 100644
--- a/dumux/implicit/common/implicitlocalresidual.hh
+++ b/dumux/implicit/common/implicitlocalresidual.hh
@@ -20,8 +20,8 @@
  * \file
  * \brief Calculates the residual of models based on the box scheme element-wise.
  */
-#ifndef DUMUX_BOX_LOCAL_RESIDUAL_HH
-#define DUMUX_BOX_LOCAL_RESIDUAL_HH
+#ifndef DUMUX_IMPLICIT_LOCAL_RESIDUAL_HH
+#define DUMUX_IMPLICIT_LOCAL_RESIDUAL_HH
 
 #include <dune/istl/matrix.hh>
 #include <dune/grid/common/geometry.hh>
@@ -33,15 +33,15 @@
 namespace Dumux
 {
 /*!
- * \ingroup BoxModel
- * \ingroup BoxLocalResidual
+ * \ingroup ImplicitModel
+ * \ingroup ImplicitLocalResidual
  * \brief Element-wise calculation of the residual matrix for models
- *        based on the box scheme.
+ *        using a fully implicit discretization.
  *
  * \todo Please doc me more!
  */
 template<class TypeTag>
-class BoxLocalResidual
+class ImplicitLocalResidual
 {
 private:
     typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
@@ -49,22 +49,10 @@ private:
     typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
     typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-
-    enum {
-        numEq = GET_PROP_VALUE(TypeTag, NumEq),
-        dim = GridView::dimension
-    };
-
     typedef typename GridView::template Codim<0>::Entity Element;
-    typedef typename GridView::template Codim<dim>::EntityPointer VertexPointer;
     typedef typename GridView::IntersectionIterator IntersectionIterator;
 
-    typedef typename GridView::Grid::ctype CoordScalar;
-    typedef typename Dune::GenericReferenceElements<CoordScalar, dim> ReferenceElements;
-    typedef typename Dune::GenericReferenceElement<CoordScalar, dim> ReferenceElement;
-
     typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
     typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
     typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
     typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
@@ -73,13 +61,13 @@ private:
     typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
 
     // copying the local residual class is not a good idea
-    BoxLocalResidual(const BoxLocalResidual &);
+    ImplicitLocalResidual(const ImplicitLocalResidual &);
 
 public:
-    BoxLocalResidual()
+    ImplicitLocalResidual()
     { }
 
-    ~BoxLocalResidual()
+    ~ImplicitLocalResidual()
     { }
 
     /*!
@@ -190,7 +178,7 @@ public:
         ElementBoundaryTypes bcTypes;
         bcTypes.update(problem_(), element, fvGeometry_());
 
-        residual_.resize(fvGeometry_().numVertices);
+        residual_.resize(fvGeometry_().numSCV);
         residual_ = 0;
 
         bcTypesPtr_ = &bcTypes;
@@ -225,7 +213,7 @@ public:
         Valgrind::CheckDefined(curVolVars);
 
 #if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry.numVertices; i++) {
+        for (int i = 0; i < prevVolVars.size(); i++) {
             prevVolVars[i].checkDefined();
             curVolVars[i].checkDefined();
         }
@@ -238,9 +226,9 @@ public:
         curVolVarsPtr_ = &curVolVars;
 
         // resize the vectors for all terms
-        int numVerts = fvGeometry_().numVertices;
-        residual_.resize(numVerts);
-        storageTerm_.resize(numVerts);
+        int numSCV = fvGeometry_().numSCV;
+        residual_.resize(numSCV);
+        storageTerm_.resize(numSCV);
 
         residual_ = 0.0;
         storageTerm_ = 0.0;
@@ -248,14 +236,14 @@ public:
         asImp_().evalFluxes_();
 
 #if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry_().numVertices; i++)
+        for (int i=0; i < fvGeometry_().numSCV; i++)
             Valgrind::CheckDefined(residual_[i]);
 #endif // HAVE_VALGRIND
 
         asImp_().evalVolumeTerms_();
 
 #if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry_().numVertices; i++) {
+        for (int i=0; i < fvGeometry_().numSCV; i++) {
             Valgrind::CheckDefined(residual_[i]);
         }
 #endif // HAVE_VALGRIND
@@ -264,7 +252,7 @@ public:
         asImp_().evalBoundary_();
 
 #if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry_().numVertices; i++)
+        for (int i=0; i < fvGeometry_().numSCV; i++)
             Valgrind::CheckDefined(residual_[i]);
 #endif // HAVE_VALGRIND
     }
@@ -322,7 +310,7 @@ protected:
         if (bcTypes_().hasNeumann() || bcTypes_().hasOutflow())
             asImp_().evalBoundaryFluxes_();
 #if !defined NDEBUG && HAVE_VALGRIND
-        for (int i=0; i < fvGeometry_().numVertices; i++)
+        for (int i=0; i < fvGeometry_().numSCV; i++)
             Valgrind::CheckDefined(residual_[i]);
 #endif // HAVE_VALGRIND
 
@@ -330,209 +318,18 @@ protected:
             asImp_().evalDirichlet_();
     }
 
-    /*!
-     * \brief Set the values of the Dirichlet boundary control volumes
-     *        of the current element.
-     */
-    void evalDirichlet_()
-    {
-        PrimaryVariables dirichletValues(0);
-        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; ++scvIdx) {
-            const BoundaryTypes &bcTypes = bcTypes_(scvIdx);
-            
-            if (bcTypes.hasDirichlet()) {
-                // ask the problem for the dirichlet values
-                const VertexPointer vPtr = element_().template subEntity<dim>(scvIdx);
-                Valgrind::SetUndefined(dirichletValues);
-                asImp_().problem_().dirichlet(dirichletValues, *vPtr);
-
-                // set the dirichlet conditions
-                for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
-                    if (bcTypes.isDirichlet(eqIdx)) {
-                        int pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
-                        assert(0 <= pvIdx && pvIdx < numEq);
-                        Valgrind::CheckDefined(dirichletValues[pvIdx]);
-
-                        residual_[scvIdx][eqIdx] =
-                                curPriVar_(scvIdx, pvIdx) - dirichletValues[pvIdx];
-
-                        storageTerm_[scvIdx][eqIdx] = 0.0;
-                    }
-                }
-            }
-        }
-    }
-
-    /*!
-     * \brief Add all Neumann and outflow boundary conditions to the local
-     *        residual.
-     */
-    void evalBoundaryFluxes_()
-    {
-        Dune::GeometryType geoType = element_().geometry().type();
-        const ReferenceElement &refElement = ReferenceElements::general(geoType);
-
-        IntersectionIterator isIt = gridView_().ibegin(element_());
-        const IntersectionIterator &endIt = gridView_().iend(element_());
-        for (; isIt != endIt; ++isIt)
-        {
-            // handle only faces on the boundary
-            if (isIt->boundary()) {
-                // Assemble the boundary for all vertices of the current
-                // face
-                int faceIdx = isIt->indexInInside();
-                int numFaceVerts = refElement.size(faceIdx, 1, dim);
-                for (int faceVertIdx = 0;
-                    faceVertIdx < numFaceVerts;
-                    ++faceVertIdx)
-                {
-                    int scvIdx = refElement.subEntity(faceIdx,
-                                                        1,
-                                                        faceVertIdx,
-                                                        dim);
-
-                    int boundaryFaceIdx =
-                        fvGeometry_().boundaryFaceIndex(faceIdx, faceVertIdx);
-
-                    // add the residual of all vertices of the boundary
-                    // segment
-                    asImp_().evalNeumannSegment_(isIt,
-                                                scvIdx,
-                                                boundaryFaceIdx);
-                    // evaluate the outflow conditions at the boundary face
-                    // ATTENTION: This is so far a beta version that is only for the 2p2c and 2p2cni model
-                    //              available and not thoroughly tested.
-                    asImp_().evalOutflowSegment_(isIt,
-                                                scvIdx,
-                                                boundaryFaceIdx);
-                }
-            }
-        }
-    }
-
-    /*!
-     * \brief Add Neumann boundary conditions for a single sub-control
-     *        volume face to the local residual.
-     */
-    void evalNeumannSegment_(const IntersectionIterator &isIt,
-                             const int scvIdx,
-                             const int boundaryFaceIdx)
-    {
-        // temporary vector to store the neumann boundary fluxes
-        PrimaryVariables neumannFlux(0.0);
-        const BoundaryTypes &bcTypes = bcTypes_(scvIdx);
-
-        // deal with neumann boundaries
-        if (bcTypes.hasNeumann()) {
-            Valgrind::SetUndefined(neumannFlux);
-            problem_().boxSDNeumann(neumannFlux,
-                                    element_(),
-                                    fvGeometry_(),
-                                    *isIt,
-                                    scvIdx,
-                                    boundaryFaceIdx,
-                                    curVolVars_());
-            neumannFlux *=
-                fvGeometry_().boundaryFace[boundaryFaceIdx].area
-                * curVolVars_(scvIdx).extrusionFactor();
-            Valgrind::CheckDefined(neumannFlux);
-
-            // set the neumann conditions
-            for (int eqIdx = 0; eqIdx < numEq; ++eqIdx) {
-                if (!bcTypes.isNeumann(eqIdx))
-                    continue;
-                residual_[scvIdx][eqIdx] += neumannFlux[eqIdx];
-            }
-        }
-    }
-
-    /*!
-    * \brief Add outflow boundary conditions for a single sub-control
-    *        volume face to the local residual.
-    *
-    * \param isIt   The intersection iterator of current element
-    * \param scvIdx The index of the considered face of the sub-control volume
-    * \param boundaryFaceIdx The index of the considered boundary face of the sub control volume
-    */
-    void evalOutflowSegment_(const IntersectionIterator &isIt,
-                            const int scvIdx,
-                            const int boundaryFaceIdx)
-    {
-        const BoundaryTypes &bcTypes = this->bcTypes_(scvIdx);
-        // deal with outflow boundaries
-        if (bcTypes.hasOutflow())
-        {
-            //calculate outflow fluxes
-            PrimaryVariables values(0.0);
-            asImp_().computeFlux(values, boundaryFaceIdx, true);
-            Valgrind::CheckDefined(values);
-            
-            for (int equationIdx = 0; equationIdx < numEq; ++equationIdx)
-            {
-                if (!bcTypes.isOutflow(equationIdx) )
-                    continue;
-                // deduce outflow
-                this->residual_[scvIdx][equationIdx] += values[equationIdx];
-            }
-        }
-    }
-
-    /*!
-     * \brief Add the flux terms to the local residual of all
-     *        sub-control volumes of the current element.
-     */
-    void evalFluxes_()
-    {
-        // calculate the mass flux over the faces and subtract
-        // it from the local rates
-        for (int scvfIdx = 0; scvfIdx < fvGeometry_().numEdges; scvfIdx++)
-        {
-            int i = fvGeometry_().subContVolFace[scvfIdx].i;
-            int j = fvGeometry_().subContVolFace[scvfIdx].j;
-
-            PrimaryVariables flux;
-
-            Valgrind::SetUndefined(flux);
-            asImp_().computeFlux(flux, scvfIdx);
-            Valgrind::CheckDefined(flux);
-
-            Scalar extrusionFactor =
-                (curVolVars_(i).extrusionFactor()
-                 + curVolVars_(j).extrusionFactor())
-                / 2;
-            flux *= extrusionFactor;
-
-            // The balance equation for a finite volume is:
-            //
-            // dStorage/dt = Flux + Source
-            //
-            // where the 'Flux' and the 'Source' terms represent the
-            // mass per second which _ENTER_ the finite
-            // volume. Re-arranging this, we get
-            //
-            // dStorage/dt - Source - Flux = 0
-            //
-            // Since the flux calculated by computeFlux() goes _OUT_
-            // of sub-control volume i and _INTO_ sub-control volume
-            // j, we need to add the flux to finite volume i and
-            // subtract it from finite volume j
-            residual_[i] += flux;
-            residual_[j] -= flux;
-        }
-    }
-
     /*!
      * \brief Set the local residual to the storage terms of all
      *        sub-control volumes of the current element.
      */
     void evalStorage_()
     {
-        storageTerm_.resize(fvGeometry_().numVertices);
+        storageTerm_.resize(fvGeometry_().numSCV);
         storageTerm_ = 0;
 
         // calculate the amount of conservation each quantity inside
         // all sub control volumes
-        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; scvIdx++) {
+        for (int scvIdx = 0; scvIdx < fvGeometry_().numSCV; scvIdx++) {
             Valgrind::SetUndefined(storageTerm_[scvIdx]);
             asImp_().computeStorage(storageTerm_[scvIdx], scvIdx, /*isOldSol=*/false);
             storageTerm_[scvIdx] *=
@@ -550,7 +347,7 @@ protected:
     void evalVolumeTerms_()
     {
         // evaluate the volume terms (storage + source terms)
-        for (int scvIdx = 0; scvIdx < fvGeometry_().numVertices; scvIdx++)
+        for (int scvIdx = 0; scvIdx < fvGeometry_().numSCV; scvIdx++)
         {
             Scalar extrusionFactor =
                 curVolVars_(scvIdx).extrusionFactor();
@@ -602,12 +399,6 @@ protected:
     const Model &model_() const
     { return problem_().model(); };
 
-    /*!
-     * \brief Returns a reference to the vertex mapper.
-     */
-    const VertexMapper &vertexMapper_() const
-    { return problem_().vertexMapper(); };
-
     /*!
      * \brief Returns a reference to the grid view.
      */
diff --git a/dumux/implicit/common/implicitporousmediaproblem.hh b/dumux/implicit/common/implicitporousmediaproblem.hh
index 0fbde7b6edbbef7299712e892a35a8ce6c6128b3..fab231a7b6486b762d62ef2c0ca6cfd9410c0872 100644
--- a/dumux/implicit/common/implicitporousmediaproblem.hh
+++ b/dumux/implicit/common/implicitporousmediaproblem.hh
@@ -1,7 +1,6 @@
 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 // vi: set et ts=4 sw=4 sts=4:
 /*****************************************************************************
- *                 2012 by Bernd Flemisch                                    *
  *   See the file COPYING for full copying permissions.                      *
  *                                                                           *
  *   This program is free software: you can redistribute it and/or modify    *