diff --git a/dumux/assembly/boxlocalassembler.hh b/dumux/assembly/boxlocalassembler.hh
index 62e432f12337a24697157a979101d0e6b8f8f70d..c1f8e14a9365a1ba58796c9c90b777998f10ec45 100644
--- a/dumux/assembly/boxlocalassembler.hh
+++ b/dumux/assembly/boxlocalassembler.hh
@@ -408,959 +408,216 @@ public:
         return origResiduals;
     }
 }; // explicit BoxAssembler with numeric Jacobian
-//
-//
-// /*!
-//  * \ingroup Assembly
-//  * \ingroup BoxDiscretization
-//  * \brief Box local assembler using numeric differentiation and explicit time discretization
-//  */
-// template<class TypeTag>
-// class BoxLocalAssembler<TypeTag,
-//                        DiffMethod::numeric,
-//                        /*implicit=*/false>
-// {
-//     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-//     using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-//     using ResidualVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
-//     using ElementResidualVector = Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, NumEqVector)>;
-//     using ElementBoundaryTypes = typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes);
-//     using Element = typename GET_PROP_TYPE(TypeTag, GridView)::template Codim<0>::Entity;
-//     using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
-//     using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
-//     using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
-//     using GridVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables);
-//     using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
-//     using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
-//     using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix);
-//
-//     enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
-//
-//     static constexpr int dim = GridView::dimension;
-//
-// public:
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix. The element residual is written into the right hand side.
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, JacobianMatrix& jac, SolutionVector& res,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         assemble_(assembler, jac, res, element, curSol);
-//
-//     }
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix.
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, JacobianMatrix& jac,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         auto dummyresidual = curSol;
-//         assemble_(assembler, jac, dummyresidual, element, curSol);
-//     }
-//
-//     /*!
-//      * \brief Assemble the residual only
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, SolutionVector& res,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         assemble_(assembler, res, element, curSol);
-//     }
-//
-//     /*!
-//      * \brief Computes the epsilon used for numeric differentiation
-//      *        for a given value of a primary variable.
-//      *
-//      * \param priVar The value of the primary variable
-//      */
-//     static Scalar numericEpsilon(const Scalar priVar)
-//     {
-//         // define the base epsilon as the geometric mean of 1 and the
-//         // resolution of the scalar type. E.g. for standard 64 bit
-//         // floating point values, the resolution is about 10^-16 and
-//         // the base epsilon is thus approximately 10^-8.
-//         /*
-//         static const Scalar baseEps
-//             = Dumux::geometricMean<Scalar>(std::numeric_limits<Scalar>::epsilon(), 1.0);
-//         */
-//         static const Scalar baseEps = 1e-10;
-//         assert(std::numeric_limits<Scalar>::epsilon()*1e4 < baseEps);
-//         // the epsilon value used for the numeric differentiation is
-//         // now scaled by the absolute value of the primary variable...
-//         return baseEps*(std::abs(priVar) + 1.0);
-//     }
-//
-// private:
-//     /*!
-//      * \brief Computes the residual
-//      *
-//      * \return The element residual at the current solution.
-//      */
-//     template<class Assembler>
-//     static void assemble_(Assembler& assembler, SolutionVector& r,
-//                           const Element& element, const SolutionVector& curSol)
-//     {
-//         // get some references for convenience
-//         const auto& problem = assembler.problem();
-//         auto& localResidual = assembler.localResidual();
-//         auto& gridVariables = assembler.gridVariables();
-//
-//         // using an explicit assembler doesn't make sense for stationary problems
-//         if (localResidual.isStationary())
-//             DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual");
-//
-//         // prepare the local views
-//         auto fvGeometry = localView(assembler.fvGridGeometry());
-//         fvGeometry.bind(element);
-//
-//         auto curElemVolVars = localView(gridVariables.curGridVolVars());
-//         curElemVolVars.bindElement(element, fvGeometry, curSol);
-//
-//         auto prevElemVolVars = localView(gridVariables.prevGridVolVars());
-//         prevElemVolVars.bind(element, fvGeometry, localResidual.prevSol());
-//
-//         auto elemFluxVarsCache = localView(gridVariables.gridFluxVarsCache());
-//         elemFluxVarsCache.bind(element, fvGeometry, prevElemVolVars);
-//
-//         // the element boundary types
-//         ElementBoundaryTypes elemBcTypes;
-//         elemBcTypes.update(problem, element, fvGeometry);
-//
-//         // the actual element's current residual
-//         auto residual = localResidual.eval(problem,
-//                                            element,
-//                                            fvGeometry,
-//                                            prevElemVolVars,
-//                                            elemBcTypes,
-//                                            elemFluxVarsCache);
-//
-//         auto storageResidual = localResidual.evalStorage(problem,
-//                                                          element,
-//                                                          fvGeometry,
-//                                                          prevElemVolVars,
-//                                                          curElemVolVars,
-//                                                          elemBcTypes,
-//                                                          elemFluxVarsCache);
-//         residual += storageResidual;
-//
-//         for (const auto& scv : scvs(fvGeometry))
-//             r[scv.dofIndex()] += residual[scv.indexInElement()];
-//
-//         // enforce Dirichlet boundaries by setting the residual to (privar - dirichletvalue)
-//         if (elemBcTypes.hasDirichlet())
-//         {
-//             for (const auto& scvI : scvs(fvGeometry))
-//             {
-//                 const auto bcTypes = elemBcTypes[scvI.indexInElement()];
-//                 if (bcTypes.hasDirichlet())
-//                 {
-//                     const auto dirichletValues = problem.dirichlet(element, scvI);
-//
-//                     // set the dirichlet conditions in residual and jacobian
-//                     for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
-//                     {
-//                         if (bcTypes.isDirichlet(eqIdx))
-//                         {
-//                             const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
-//                             assert(0 <= pvIdx && pvIdx < numEq);
-//
-//                             const auto& priVars = curElemVolVars[scvI].priVars();
-//                             r[scvI.dofIndex()][eqIdx] = priVars[pvIdx] - dirichletValues[pvIdx];
-//                         }
-//                     }
-//                 }
-//             }
-//         }
-//     }
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix.
-//      *
-//      * \return The element residual at the current solution.
-//      */
-//     template<class Assembler>
-//     static void assemble_(Assembler& assembler, JacobianMatrix& A, SolutionVector& r,
-//                           const Element& element, const SolutionVector& curSol)
-//     {
-//         // get some references for convenience
-//         const auto& problem = assembler.problem();
-//         auto& localResidual = assembler.localResidual();
-//         auto& gridVariables = assembler.gridVariables();
-//
-//         // using an explicit assembler doesn't make sense for stationary problems
-//         if (localResidual.isStationary())
-//             DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual");
-//
-//         // prepare the local views
-//         auto fvGeometry = localView(assembler.fvGridGeometry());
-//         fvGeometry.bind(element);
-//
-//         auto curElemVolVars = localView(gridVariables.curGridVolVars());
-//         curElemVolVars.bindElement(element, fvGeometry, curSol);
-//
-//         auto prevElemVolVars = localView(gridVariables.prevGridVolVars());
-//         prevElemVolVars.bind(element, fvGeometry, localResidual.prevSol());
-//
-//         auto elemFluxVarsCache = localView(gridVariables.gridFluxVarsCache());
-//         elemFluxVarsCache.bind(element, fvGeometry, prevElemVolVars);
-//
-//         // the element boundary types
-//         ElementBoundaryTypes elemBcTypes;
-//         elemBcTypes.update(problem, element, fvGeometry);
-//
-//         // get the element solution
-//         const auto numVert = element.subEntities(dim);
-//         ElementSolutionVector elemSol(numVert);
-//         for (const auto& scv : scvs(fvGeometry))
-//             elemSol[scv.indexInElement()] = localResidual.prevSol()[scv.dofIndex()];
-//
-//         // the actual element's previous time step residual
-//         auto residual = localResidual.eval(problem,
-//                                            element,
-//                                            fvGeometry,
-//                                            prevElemVolVars,
-//                                            elemBcTypes,
-//                                            elemFluxVarsCache);
-//
-//         auto storageResidual = localResidual.evalStorage(problem,
-//                                                          element,
-//                                                          fvGeometry,
-//                                                          prevElemVolVars,
-//                                                          curElemVolVars,
-//                                                          elemBcTypes,
-//                                                          elemFluxVarsCache);
-//
-//         residual += storageResidual;
-//
-//         //////////////////////////////////////////////////////////////////////////////////////////////////
-//         //                                                                                              //
-//         // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
-//         // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
-//         // actual element. In the actual element we evaluate the derivative of the entire residual.     //
-//         //                                                                                              //
-//         //////////////////////////////////////////////////////////////////////////////////////////////////
-//
-//         static const int numericDifferenceMethod = getParamFromGroup<int>(GET_PROP_VALUE(TypeTag, ModelParameterGroup), "Implicit.NumericDifferenceMethod");
-//
-//         // calculation of the derivatives
-//         for (auto&& scv : scvs(fvGeometry))
-//         {
-//             // dof index and corresponding actual pri vars
-//             const auto dofIdx = scv.dofIndex();
-//             auto& volVars = getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
-//             VolumeVariables origVolVars(volVars);
-//
-//             // add precalculated residual for this scv into the global container
-//             r[dofIdx] += residual[scv.indexInElement()];
-//
-//             // calculate derivatives w.r.t to the privars at the dof at hand
-//             for (int pvIdx = 0; pvIdx < numEq; pvIdx++)
-//             {
-//                 ElementSolutionVector partialDeriv(element.subEntities(dim));
-//                 Scalar eps = numericEpsilon(volVars.priVar(pvIdx));
-//                 Scalar delta = 0;
-//
-//                 // calculate the residual with the forward deflected primary variables
-//                 if (numericDifferenceMethod >= 0)
-//                 {
-//                     // we are not using backward differences, i.e. we need to
-//                     // calculate f(x + \epsilon)
-//
-//                     // deflect primary variables
-//                     elemSol[scv.indexInElement()][pvIdx] += eps;
-//                     delta += eps;
-//
-//                     // update the volume variables connected to the dof
-//                     volVars.update(elemSol, problem, element, scv);
-//
-//                     partialDeriv = localResidual.evalStorage(problem, element, fvGeometry,
-//                                                              prevElemVolVars, curElemVolVars,
-//                                                              elemBcTypes, elemFluxVarsCache);
-//                 }
-//                 else
-//                 {
-//                     // we are using backward differences, i.e. we don't need
-//                     // to calculate f(x + \epsilon) and we can recycle the
-//                     // (already calculated) residual f(x)
-//                     partialDeriv = residual;
-//                 }
-//
-//                 if (numericDifferenceMethod <= 0)
-//                 {
-//                     // we are not using forward differences, i.e. we
-//                     // need to calculate f(x - \epsilon)
-//
-//                     // deflect the primary variables
-//                     elemSol[scv.indexInElement()][pvIdx] -= delta + eps;
-//                     delta += eps;
-//
-//                     // update the volume variables connected to the dof
-//                     volVars.update(elemSol, problem, element, scv);
-//
-//                     partialDeriv -= localResidual.evalStorage(problem, element, fvGeometry,
-//                                                               prevElemVolVars, curElemVolVars,
-//                                                               elemBcTypes, elemFluxVarsCache);
-//                 }
-//                 else
-//                 {
-//                     // we are using forward differences, i.e. we don't need to
-//                     // calculate f(x - \epsilon) and we can recycle the
-//                     // (already calculated) residual f(x)
-//                     partialDeriv -= residual;
-//                 }
-//
-//                 // divide difference in residuals by the magnitude of the
-//                 // deflections between the two function evaluation
-//                 partialDeriv /= delta;
-//
-//                 // update the global stiffness matrix with the current partial derivatives
-//                 for (int eqIdx = 0; eqIdx < numEq; eqIdx++)
-//                 {
-//                     // A[i][col][eqIdx][pvIdx] is the rate of change of
-//                     // the residual of equation 'eqIdx' at dof 'i'
-//                     // depending on the primary variable 'pvIdx' at dof
-//                     // 'col'.
-//                     A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDeriv[scv.indexInElement()][eqIdx];
-//                 }
-//
-//                 // restore the original state of the scv's volume variables
-//                 volVars = origVolVars;
-//
-//                 // restore the original element solution
-//                 elemSol[scv.indexInElement()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
-//             }
-//
-//             // TODO additional dof dependencies
-//         }
-//
-//         // enforce Dirichlet boundaries by overwriting partial derivatives with 1 or 0
-//         // and set the residual to (privar - dirichletvalue)
-//         if (elemBcTypes.hasDirichlet())
-//         {
-//             for (const auto& scvI : scvs(fvGeometry))
-//             {
-//                 const auto bcTypes = elemBcTypes[scvI.indexInElement()];
-//                 if (bcTypes.hasDirichlet())
-//                 {
-//                     const auto dirichletValues = problem.dirichlet(element, scvI);
-//
-//                     // set the dirichlet conditions in residual and jacobian
-//                     for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
-//                     {
-//                         if (bcTypes.isDirichlet(eqIdx))
-//                         {
-//                             const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
-//                             assert(0 <= pvIdx && pvIdx < numEq);
-//
-//                             const auto& priVars = curElemVolVars[scvI].priVars();
-//                             r[scvI.dofIndex()][eqIdx] = priVars[pvIdx] - dirichletValues[pvIdx];
-//                             A[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
-//                         }
-//                     }
-//                 }
-//             }
-//         }
-//     }
-// private:
-//     template<class T = TypeTag>
-//     static typename std::enable_if<!GET_PROP_VALUE(T, EnableGridVolumeVariablesCache), VolumeVariables&>::type
-//     getVolVarAccess(GridVolumeVariables& gridVolVars, ElementVolumeVariables& elemVolVars, const SubControlVolume& scv)
-//     { return elemVolVars[scv]; }
-//
-//     template<class T = TypeTag>
-//     static typename std::enable_if<GET_PROP_VALUE(T, EnableGridVolumeVariablesCache), VolumeVariables&>::type
-//     getVolVarAccess(GridVolumeVariables& gridVolVars, ElementVolumeVariables& elemVolVars, const SubControlVolume& scv)
-//     { return gridVolVars.volVars(scv.elementIndex(), scv.indexInElement()); }
-//
-// }; // explicit BoxAssembler with numeric Jacobian
-
-//
-// /*!
-//  * \ingroup Assembly
-//  * \ingroup BoxDiscretization
-//  * \brief Box local assembler using analytic (hard coded) derivatives and implicit time discretization
-//  */
-// template<class TypeTag>
-// class BoxLocalAssembler<TypeTag,
-//                        DiffMethod::analytic,
-//                        /*implicit=*/true>
-// {
-//     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-//     using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-//     using ResidualVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
-//     using ElementResidualVector = Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, NumEqVector)>;
-//     using ElementBoundaryTypes = typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes);
-//     using Element = typename GET_PROP_TYPE(TypeTag, GridView)::template Codim<0>::Entity;
-//     using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
-//     using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
-//     using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
-//     using GridVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables);
-//     using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
-//     using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
-//     using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix);
-//
-//     enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
-//
-//     static constexpr int dim = GridView::dimension;
-//
-// public:
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix. The element residual is written into the right hand side.
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, JacobianMatrix& jac, SolutionVector& res,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         assemble_(assembler, jac, res, element, curSol);
-//
-//     }
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix.
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, JacobianMatrix& jac,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         auto dummyresidual = curSol;
-//         assemble_(assembler, jac, dummyresidual, element, curSol);
-//     }
-//
-//     /*!
-//      * \brief Assemble the residual only
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, SolutionVector& res,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         assemble_(assembler, res, element, curSol);
-//     }
-//
-// private:
-//     /*!
-//      * \brief Computes the residual
-//      *
-//      * \return The element residual at the current solution.
-//      */
-//     template<class Assembler>
-//     static void assemble_(Assembler& assembler, SolutionVector& r,
-//                           const Element& element, const SolutionVector& curSol)
-//     {
-//         // get some references for convenience
-//         const auto& problem = assembler.problem();
-//         auto& localResidual = assembler.localResidual();
-//         auto& gridVariables = assembler.gridVariables();
-//
-//         // prepare the local views
-//         auto fvGeometry = localView(assembler.fvGridGeometry());
-//         fvGeometry.bind(element);
-//
-//         auto curElemVolVars = localView(gridVariables.curGridVolVars());
-//         curElemVolVars.bind(element, fvGeometry, curSol);
-//
-//         auto elemFluxVarsCache = localView(gridVariables.gridFluxVarsCache());
-//         elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars);
-//
-//         const bool isStationary = localResidual.isStationary();
-//         auto prevElemVolVars = localView(gridVariables.prevGridVolVars());
-//         if (!isStationary)
-//             prevElemVolVars.bindElement(element, fvGeometry, localResidual.prevSol());
-//
-//         // the element boundary types
-//         ElementBoundaryTypes elemBcTypes;
-//         elemBcTypes.update(problem, element, fvGeometry);
-//
-//         // the actual element's current residual
-//         ElementResidualVector residual(0.0);
-//         if (isStationary)
-//         {
-//             residual = localResidual.eval(problem,
-//                                           element,
-//                                           fvGeometry,
-//                                           curElemVolVars,
-//                                           elemBcTypes,
-//                                           elemFluxVarsCache);
-//         }
-//         else
-//         {
-//             residual = localResidual.eval(problem,
-//                                           element,
-//                                           fvGeometry,
-//                                           prevElemVolVars,
-//                                           curElemVolVars,
-//                                           elemBcTypes,
-//                                           elemFluxVarsCache);
-//         }
-//
-//         for (const auto& scv : scvs(fvGeometry))
-//             r[scv.dofIndex()] += residual[scv.indexInElement()];
-//
-//         // enforce Dirichlet boundaries by setting the residual to (privar - dirichletvalue)
-//         if (elemBcTypes.hasDirichlet())
-//         {
-//             for (const auto& scvI : scvs(fvGeometry))
-//             {
-//                 const auto bcTypes = elemBcTypes[scvI.indexInElement()];
-//                 if (bcTypes.hasDirichlet())
-//                 {
-//                     const auto dirichletValues = problem.dirichlet(element, scvI);
-//
-//                     // set the dirichlet conditions in residual and jacobian
-//                     for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
-//                     {
-//                         if (bcTypes.isDirichlet(eqIdx))
-//                         {
-//                             const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
-//                             assert(0 <= pvIdx && pvIdx < numEq);
-//
-//                             const auto& priVars = curElemVolVars[scvI].priVars();
-//                             r[scvI.dofIndex()][eqIdx] = priVars[pvIdx] - dirichletValues[pvIdx];
-//                         }
-//                     }
-//                 }
-//             }
-//         }
-//     }
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix.
-//      *
-//      * \return The element residual at the current solution.
-//      */
-//     template<class Assembler>
-//     static void assemble_(Assembler& assembler, JacobianMatrix& A, SolutionVector& r,
-//                           const Element& element, const SolutionVector& curSol)
-//     {
-//         // get some references for convenience
-//         const auto& problem = assembler.problem();
-//         const auto& fvGridGeometry = assembler.fvGridGeometry();
-//         auto& localResidual = assembler.localResidual();
-//         auto& gridVariables = assembler.gridVariables();
-//
-//         // prepare the local views
-//         auto fvGeometry = localView(fvGridGeometry);
-//         fvGeometry.bind(element);
-//
-//         auto curElemVolVars = localView(gridVariables.curGridVolVars());
-//         curElemVolVars.bind(element, fvGeometry, curSol);
-//
-//         auto elemFluxVarsCache = localView(gridVariables.gridFluxVarsCache());
-//         elemFluxVarsCache.bind(element, fvGeometry, curElemVolVars);
-//
-//         const bool isStationary = localResidual.isStationary();
-//         auto prevElemVolVars = localView(gridVariables.prevGridVolVars());
-//         if (!isStationary)
-//             prevElemVolVars.bindElement(element, fvGeometry, localResidual.prevSol());
-//
-//         // check for boundaries on the element
-//         ElementBoundaryTypes elemBcTypes;
-//         elemBcTypes.update(problem, element, fvGeometry);
-//
-//         // the actual element's current residual
-//         ElementResidualVector residual(0.0);
-//         if (isStationary)
-//         {
-//             residual = localResidual.eval(problem,
-//                                           element,
-//                                           fvGeometry,
-//                                           curElemVolVars,
-//                                           elemBcTypes,
-//                                           elemFluxVarsCache);
-//         }
-//         else
-//         {
-//             residual = localResidual.eval(problem,
-//                                           element,
-//                                           fvGeometry,
-//                                           prevElemVolVars,
-//                                           curElemVolVars,
-//                                           elemBcTypes,
-//                                           elemFluxVarsCache);
-//         }
-//
-//         for (auto&& scv : scvs(fvGeometry))
-//             r[scv.dofIndex()] += residual[scv.indexInElement()];
-//
-//         //////////////////////////////////////////////////////////////////////////////////////////////////
-//         //                                                                                              //
-//         // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
-//         // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
-//         // actual element. In the actual element we evaluate the derivative of the entire residual.     //
-//         //                                                                                              //
-//         //////////////////////////////////////////////////////////////////////////////////////////////////
-//
-//         // calculation of the source and storage derivatives
-//         for (const auto& scv : scvs(fvGeometry))
-//         {
-//             // dof index and corresponding actual pri vars
-//             const auto dofIdx = scv.dofIndex();
-//             const auto& volVars = curElemVolVars[scv];
-//
-//             // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
-//             // only if the problem is instationary we add derivative of storage term
-//             if (!isStationary)
-//                 localResidual.addStorageDerivatives(A[dofIdx][dofIdx],
-//                                                     problem,
-//                                                     element,
-//                                                     fvGeometry,
-//                                                     volVars,
-//                                                     scv);
-//
-//             // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
-//             // add source term derivatives
-//             localResidual.addSourceDerivatives(A[dofIdx][dofIdx],
-//                                                problem,
-//                                                element,
-//                                                fvGeometry,
-//                                                volVars,
-//                                                scv);
-//         }
-//
-//         // localJacobian[scvIdx][otherScvIdx][eqIdx][priVarIdx] of the fluxes
-//         for (const auto& scvf : scvfs(fvGeometry))
-//         {
-//             if (!scvf.boundary())
-//             {
-//                 // add flux term derivatives
-//                 localResidual.addFluxDerivatives(A,
-//                                                  problem,
-//                                                  element,
-//                                                  fvGeometry,
-//                                                  curElemVolVars,
-//                                                  elemFluxVarsCache,
-//                                                  scvf);
-//             }
-//
-//             // the boundary gets special treatment to simplify
-//             // for the user
-//             else
-//             {
-//                 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
-//                 if (elemBcTypes[insideScv.indexInElement()].hasNeumann())
-//                 {
-//                     // add flux term derivatives
-//                     localResidual.addRobinFluxDerivatives(A[insideScv.dofIndex()],
-//                                                           problem,
-//                                                           element,
-//                                                           fvGeometry,
-//                                                           curElemVolVars,
-//                                                           elemFluxVarsCache,
-//                                                           scvf);
-//                 }
-//             }
-//         }
-//
-//         // enforce Dirichlet boundaries by overwriting partial derivatives with 1 or 0
-//         // and set the residual to (privar - dirichletvalue)
-//         if (elemBcTypes.hasDirichlet())
-//         {
-//             for (const auto& scvI : scvs(fvGeometry))
-//             {
-//                 const auto bcTypes = elemBcTypes[scvI.indexInElement()];
-//                 if (bcTypes.hasDirichlet())
-//                 {
-//                     const auto dirichletValues = problem.dirichlet(element, scvI);
-//
-//                     // set the dirichlet conditions in residual and jacobian
-//                     for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
-//                     {
-//                         if (bcTypes.isDirichlet(eqIdx))
-//                         {
-//                             const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
-//                             assert(0 <= pvIdx && pvIdx < numEq);
-//
-//                             const auto& priVars = curElemVolVars[scvI].priVars();
-//                             r[scvI.dofIndex()][eqIdx] = priVars[pvIdx] - dirichletValues[pvIdx];
-//                             for (const auto& scvJ : scvs(fvGeometry))
-//                             {
-//                                 A[scvI.dofIndex()][scvJ.dofIndex()][eqIdx] = 0.0;
-//                                 if (scvI.indexInElement() == scvJ.indexInElement())
-//                                     A[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
-//                             }
-//                         }
-//                     }
-//                 }
-//             }
-//         }
-//
-//         // TODO additional dof dependencies
-//     }
-//
-// }; // implicit BoxAssembler with analytic Jacobian
-//
-//
-// /*!
-//  * \ingroup Assembly
-//  * \ingroup BoxDiscretization
-//  * \brief Box local assembler using analytic (hard coded) derivatives and explicit time discretization
-//  */
-// template<class TypeTag>
-// class BoxLocalAssembler<TypeTag,
-//                        DiffMethod::analytic,
-//                        /*implicit=*/false>
-// {
-//     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-//     using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-//     using ResidualVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
-//     using ElementResidualVector = Dune::BlockVector<typename GET_PROP_TYPE(TypeTag, NumEqVector)>;
-//     using ElementBoundaryTypes = typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes);
-//     using Element = typename GET_PROP_TYPE(TypeTag, GridView)::template Codim<0>::Entity;
-//     using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
-//     using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
-//     using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
-//     using GridVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables);
-//     using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
-//     using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
-//     using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix);
-//
-//     enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
-//
-//     static constexpr int dim = GridView::dimension;
-//
-// public:
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix. The element residual is written into the right hand side.
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, JacobianMatrix& jac, SolutionVector& res,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         assemble_(assembler, jac, res, element, curSol);
-//
-//     }
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix.
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, JacobianMatrix& jac,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         auto dummyresidual = curSol;
-//         assemble_(assembler, jac, dummyresidual, element, curSol);
-//     }
-//
-//     /*!
-//      * \brief Assemble the residual only
-//      */
-//     template<class Assembler>
-//     static void assemble(Assembler& assembler, SolutionVector& res,
-//                          const Element& element, const SolutionVector& curSol)
-//     {
-//         assemble_(assembler, res, element, curSol);
-//     }
-//
-// private:
-//     /*!
-//      * \brief Computes the residual
-//      *
-//      * \return The element residual at the current solution.
-//      */
-//     template<class Assembler>
-//     static void assemble_(Assembler& assembler, SolutionVector& r,
-//                           const Element& element, const SolutionVector& curSol)
-//     {
-//         // get some references for convenience
-//         const auto& problem = assembler.problem();
-//         auto& localResidual = assembler.localResidual();
-//         auto& gridVariables = assembler.gridVariables();
-//
-//         // using an explicit assembler doesn't make sense for stationary problems
-//         if (localResidual.isStationary())
-//             DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual");
-//
-//         // prepare the local views
-//         auto fvGeometry = localView(assembler.fvGridGeometry());
-//         fvGeometry.bind(element);
-//
-//         auto curElemVolVars = localView(gridVariables.curGridVolVars());
-//         curElemVolVars.bindElement(element, fvGeometry, curSol);
-//
-//         auto prevElemVolVars = localView(gridVariables.prevGridVolVars());
-//         prevElemVolVars.bind(element, fvGeometry, localResidual.prevSol());
-//
-//         auto elemFluxVarsCache = localView(gridVariables.gridFluxVarsCache());
-//         elemFluxVarsCache.bind(element, fvGeometry, prevElemVolVars);
-//
-//         // the element boundary types
-//         ElementBoundaryTypes elemBcTypes;
-//         elemBcTypes.update(problem, element, fvGeometry);
-//
-//         // the actual element's current residual
-//         auto residual = localResidual.eval(problem,
-//                                            element,
-//                                            fvGeometry,
-//                                            prevElemVolVars,
-//                                            elemBcTypes,
-//                                            elemFluxVarsCache);
-//
-//         auto storageResidual = localResidual.evalStorage(problem,
-//                                                          element,
-//                                                          fvGeometry,
-//                                                          prevElemVolVars,
-//                                                          curElemVolVars,
-//                                                          elemBcTypes,
-//                                                          elemFluxVarsCache);
-//         residual += storageResidual;
-//
-//         for (const auto& scv : scvs(fvGeometry))
-//             r[scv.dofIndex()] += residual[scv.indexInElement()];
-//
-//         // enforce Dirichlet boundaries by setting the residual to (privar - dirichletvalue)
-//         if (elemBcTypes.hasDirichlet())
-//         {
-//             for (const auto& scvI : scvs(fvGeometry))
-//             {
-//                 const auto bcTypes = elemBcTypes[scvI.indexInElement()];
-//                 if (bcTypes.hasDirichlet())
-//                 {
-//                     const auto dirichletValues = problem.dirichlet(element, scvI);
-//
-//                     // set the dirichlet conditions in residual and jacobian
-//                     for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
-//                     {
-//                         if (bcTypes.isDirichlet(eqIdx))
-//                         {
-//                             const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
-//                             assert(0 <= pvIdx && pvIdx < numEq);
-//
-//                             const auto& priVars = curElemVolVars[scvI].priVars();
-//                             r[scvI.dofIndex()][eqIdx] = priVars[pvIdx] - dirichletValues[pvIdx];
-//                         }
-//                     }
-//                 }
-//             }
-//         }
-//     }
-//
-//     /*!
-//      * \brief Computes the derivatives with respect to the given element and adds them
-//      *        to the global matrix.
-//      *
-//      * \return The element residual at the current solution.
-//      */
-//     template<class Assembler>
-//     static void assemble_(Assembler& assembler, JacobianMatrix& A, SolutionVector& r,
-//                           const Element& element, const SolutionVector& curSol)
-//     {
-//         // get some references for convenience
-//         const auto& problem = assembler.problem();
-//         auto& localResidual = assembler.localResidual();
-//         auto& gridVariables = assembler.gridVariables();
-//
-//         // using an explicit assembler doesn't make sense for stationary problems
-//         if (localResidual.isStationary())
-//             DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual");
-//
-//         // prepare the local views
-//         auto fvGeometry = localView(assembler.fvGridGeometry());
-//         fvGeometry.bind(element);
-//
-//         auto curElemVolVars = localView(gridVariables.curGridVolVars());
-//         curElemVolVars.bindElement(element, fvGeometry, curSol);
-//
-//         auto prevElemVolVars = localView(gridVariables.prevGridVolVars());
-//         prevElemVolVars.bind(element, fvGeometry, localResidual.prevSol());
-//
-//         auto elemFluxVarsCache = localView(gridVariables.gridFluxVarsCache());
-//         elemFluxVarsCache.bind(element, fvGeometry, prevElemVolVars);
-//
-//         // the element boundary types
-//         ElementBoundaryTypes elemBcTypes;
-//         elemBcTypes.update(problem, element, fvGeometry);
-//
-//         // the actual element's current residual
-//         auto residual = localResidual.eval(problem,
-//                                            element,
-//                                            fvGeometry,
-//                                            prevElemVolVars,
-//                                            elemBcTypes,
-//                                            elemFluxVarsCache);
-//
-//         auto storageResidual = localResidual.evalStorage(problem,
-//                                                          element,
-//                                                          fvGeometry,
-//                                                          prevElemVolVars,
-//                                                          curElemVolVars,
-//                                                          elemBcTypes,
-//                                                          elemFluxVarsCache);
-//         residual += storageResidual;
-//
-//         for (const auto& scv : scvs(fvGeometry))
-//             r[scv.dofIndex()] += residual[scv.indexInElement()];
-//
-//         //////////////////////////////////////////////////////////////////////////////////////////////////
-//         //                                                                                              //
-//         // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
-//         // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
-//         // actual element. In the actual element we evaluate the derivative of the entire residual.     //
-//         //                                                                                              //
-//         //////////////////////////////////////////////////////////////////////////////////////////////////
-//
-//         // calculation of the source and storage derivatives
-//         for (const auto& scv : scvs(fvGeometry))
-//         {
-//             // dof index and corresponding actual pri vars
-//             const auto dofIdx = scv.dofIndex();
-//             const auto& volVars = curElemVolVars[scv];
-//
-//             // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
-//             // only if the problem is instationary we add derivative of storage term
-//             localResidual.addStorageDerivatives(A[dofIdx][dofIdx],
-//                                                 problem,
-//                                                 element,
-//                                                 fvGeometry,
-//                                                 volVars,
-//                                                 scv);
-//         }
-//
-//         // enforce Dirichlet boundaries by overwriting partial derivatives with 1 or 0
-//         // and set the residual to (privar - dirichletvalue)
-//         if (elemBcTypes.hasDirichlet())
-//         {
-//             for (const auto& scvI : scvs(fvGeometry))
-//             {
-//                 const auto bcTypes = elemBcTypes[scvI.indexInElement()];
-//                 if (bcTypes.hasDirichlet())
-//                 {
-//                     const auto dirichletValues = problem.dirichlet(element, scvI);
-//
-//                     // set the dirichlet conditions in residual and jacobian
-//                     for (int eqIdx = 0; eqIdx < numEq; ++eqIdx)
-//                     {
-//                         if (bcTypes.isDirichlet(eqIdx))
-//                         {
-//                             const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
-//                             assert(0 <= pvIdx && pvIdx < numEq);
-//
-//                             const auto& priVars = curElemVolVars[scvI].priVars();
-//                             r[scvI.dofIndex()][eqIdx] = priVars[pvIdx] - dirichletValues[pvIdx];
-//                             A[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
-//                         }
-//                     }
-//                 }
-//             }
-//         }
-//
-//         // TODO additional dof dependencies
-//     }
-//
-// }; // explicit BoxAssembler with analytic Jacobian
+
+/*!
+ * \ingroup Assembly
+ * \ingroup BoxDiscretization
+ * \brief Box local assembler using analytic differentiation and implicit time discretization
+ */
+template<class TypeTag, class Assembler>
+class BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, /*implicit=*/true>
+: public BoxLocalAssemblerBase<TypeTag, Assembler,
+                              BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true>, true>
+{
+    using ThisType = BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true>;
+    using ParentType = BoxLocalAssemblerBase<TypeTag, Assembler, ThisType, true>;
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Element = typename GET_PROP_TYPE(TypeTag, GridView)::template Codim<0>::Entity;
+    using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
+    using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
+    using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
+    using GridVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables);
+    using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables);
+    using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
+    using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix);
+
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    enum { dim = GET_PROP_TYPE(TypeTag, GridView)::dimension };
+
+    static constexpr bool enableGridFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableGridFluxVariablesCache);
+    static constexpr int maxNeighbors = 4*(2*dim);
+
+public:
+
+    using ParentType::ParentType;
+
+    /*!
+     * \brief Computes the derivatives with respect to the given element and adds them
+     *        to the global matrix.
+     *
+     * \return The element residual at the current solution.
+     */
+    auto assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables)
+    {
+        // get some aliases for convenience
+        const auto& element = this->element();
+        const auto& fvGeometry = this->fvGeometry();
+        const auto& curSol = this->curSol();
+        const auto& problem = this->problem();
+        auto&& curElemVolVars = this->curElemVolVars();
+        auto&& elemFluxVarsCache = this->elemFluxVarsCache();
+
+        // get the vecor of the acutal element residuals
+        const auto origResiduals = this->evalLocalResidual();
+
+        //////////////////////////////////////////////////////////////////////////////////////////////////
+        //                                                                                              //
+        // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
+        // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
+        // actual element. In the actual element we evaluate the derivative of the entire residual.     //
+        //                                                                                              //
+        //////////////////////////////////////////////////////////////////////////////////////////////////
+
+        // calculation of the source and storage derivatives
+        for (const auto& scv : scvs(fvGeometry))
+        {
+            // dof index and corresponding actual pri vars
+            const auto dofIdx = scv.dofIndex();
+            const auto& volVars = curElemVolVars[scv];
+
+            // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
+            // only if the problem is instationary we add derivative of storage term
+            if (!this->assembler().isStationaryProblem())
+                this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
+                                                            problem,
+                                                            element,
+                                                            fvGeometry,
+                                                            volVars,
+                                                            scv);
+
+            // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
+            // add source term derivatives
+            this->localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
+                                                       problem,
+                                                       element,
+                                                       fvGeometry,
+                                                       volVars,
+                                                       scv);
+        }
+
+        // localJacobian[scvIdx][otherScvIdx][eqIdx][priVarIdx] of the fluxes
+        for (const auto& scvf : scvfs(fvGeometry))
+        {
+            if (!scvf.boundary())
+            {
+                // add flux term derivatives
+                this->localResidual().addFluxDerivatives(A,
+                                                         problem,
+                                                         element,
+                                                         fvGeometry,
+                                                         curElemVolVars,
+                                                         elemFluxVarsCache,
+                                                         scvf);
+            }
+
+            // the boundary gets special treatment to simplify
+            // for the user
+            else
+            {
+                const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
+                if (this->elemBcTypes()[insideScv.indexInElement()].hasNeumann())
+                {
+                    // add flux term derivatives
+                    this->localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
+                                                                  problem,
+                                                                  element,
+                                                                  fvGeometry,
+                                                                  curElemVolVars,
+                                                                  elemFluxVarsCache,
+                                                                  scvf);
+                }
+            }
+        }
+
+        return origResiduals;
+    }
+
+}; // implicit BoxAssembler with analytic Jacobian
+
+/*!
+ * \ingroup Assembly
+ * \ingroup BoxDiscretization
+ * \brief Box local assembler using analytic differentiation and explicit time discretization
+ */
+template<class TypeTag, class Assembler>
+class BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, /*implicit=*/false>
+: public BoxLocalAssemblerBase<TypeTag, Assembler,
+                              BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false>, false>
+{
+    using ThisType = BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false>;
+    using ParentType = BoxLocalAssemblerBase<TypeTag, Assembler, ThisType, false>;
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Element = typename GET_PROP_TYPE(TypeTag, GridView)::template Codim<0>::Entity;
+    using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
+    using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
+    using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
+    using GridVolumeVariables = typename GET_PROP_TYPE(TypeTag, GridVolumeVariables);
+    using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables);
+    using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
+    using JacobianMatrix = typename GET_PROP_TYPE(TypeTag, JacobianMatrix);
+
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    enum { dim = GET_PROP_TYPE(TypeTag, GridView)::dimension };
+
+    static constexpr bool enableGridFluxVarsCache = GET_PROP_VALUE(TypeTag, EnableGridFluxVariablesCache);
+    static constexpr int maxNeighbors = 4*(2*dim);
+
+public:
+
+    using ParentType::ParentType;
+
+    /*!
+     * \brief Computes the derivatives with respect to the given element and adds them
+     *        to the global matrix.
+     *
+     * \return The element residual at the current solution.
+     */
+    auto assembleJacobianAndResidualImpl(JacobianMatrix& A, GridVariables& gridVariables)
+    {
+        // get some aliases for convenience
+        const auto& element = this->element();
+        const auto& fvGeometry = this->fvGeometry();
+        const auto& curSol = this->curSol();
+        const auto& problem = this->problem();
+        auto&& curElemVolVars = this->curElemVolVars();
+        auto&& elemFluxVarsCache = this->elemFluxVarsCache();
+
+        // get the vecor of the acutal element residuals
+        const auto origResiduals = this->evalLocalResidual();
+
+        //////////////////////////////////////////////////////////////////////////////////////////////////
+        //                                                                                              //
+        // Calculate derivatives of all dofs in stencil with respect to the dofs in the element. In the //
+        // neighboring elements we do so by computing the derivatives of the fluxes which depend on the //
+        // actual element. In the actual element we evaluate the derivative of the entire residual.     //
+        //                                                                                              //
+        //////////////////////////////////////////////////////////////////////////////////////////////////
+
+        // calculation of the source and storage derivatives
+        for (const auto& scv : scvs(fvGeometry))
+        {
+            // dof index and corresponding actual pri vars
+            const auto dofIdx = scv.dofIndex();
+            const auto& volVars = curElemVolVars[scv];
+
+            // derivative of this scv residual w.r.t the d.o.f. of the same scv (because of mass lumping)
+            // only if the problem is instationary we add derivative of storage term
+            if (!this->assembler().isStationaryProblem())
+                this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
+                                                            problem,
+                                                            element,
+                                                            fvGeometry,
+                                                            volVars,
+                                                            scv);
+            else
+                DUNE_THROW(Dune::InvalidStateException, "Using explicit jacobian assembler with stationary local residual");
+
+        }
+
+        return origResiduals;
+    }
+
+}; // explicit BoxAssembler with analytic Jacobian
 
 } // end namespace Dumux