diff --git a/dumux/porousmediumflow/2p1c/implicit/indices.hh b/dumux/porousmediumflow/2p1c/implicit/indices.hh
index 49a07a06e8fea6035c1e9e8d98799e83212b734b..6bd3e53b970df39299c7cdc9e88174b6d1474dd3 100644
--- a/dumux/porousmediumflow/2p1c/implicit/indices.hh
+++ b/dumux/porousmediumflow/2p1c/implicit/indices.hh
@@ -25,11 +25,22 @@
 #ifndef DUMUX_2P1C_INDICES_HH
 #define DUMUX_2P1C_INDICES_HH
 
-#include "properties.hh"
-
 namespace Dumux
 {
 
+/*!
+ * \ingroup TwoPNCModel
+ * \ingroup ImplicitIndices
+ * \brief Enumerates the formulations which the two-phase n-component model accepts.
+ */
+struct TwoPOneCFormulation
+{
+    enum {
+        pnsw,
+        pwsn
+        };
+};
+
 /*!
  * \ingroup TwoPOneCModel
  * \ingroup ImplicitIndices
@@ -46,12 +57,12 @@ class TwoPOneCIndices
 public:
     // Phase indices
     static const int wPhaseIdx = FluidSystem::wPhaseIdx; //!< index of the wetting liquid phase
-    static const int gPhaseIdx = FluidSystem::nPhaseIdx; //!< index of the gas phase
+    static const int nPhaseIdx = FluidSystem::nPhaseIdx; //!< index of the gas phase
 
     // present phases (-> 'pseudo' primary variable)
     static const int twoPhases = 1; //!< All three phases are present
     static const int wPhaseOnly = 2; //!< Only the water phase is present
-    static const int gPhaseOnly = 3; //!< Only gas phase is present
+    static const int nPhaseOnly = 3; //!< Only gas phase is present
 
     // Primary variable indices
     static const int pressureIdx = PVOffset + 0; //!< Index for phase pressure in a solution vector
diff --git a/dumux/porousmediumflow/2p1c/implicit/localresidual.hh b/dumux/porousmediumflow/2p1c/implicit/localresidual.hh
deleted file mode 100644
index 51a772df81669f7b9b2821a65cf12b2256e535fe..0000000000000000000000000000000000000000
--- a/dumux/porousmediumflow/2p1c/implicit/localresidual.hh
+++ /dev/null
@@ -1,272 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- *
- * \brief Element-wise calculation of the Jacobian matrix for problems
- *        using the two-phase one-component fully implicit model.
- *
- * Important note: The 2p1c model requires the use of the non-isothermal extension found in dumux/porousmediumflow/nonisothermal/implicit/
- */
-#ifndef DUMUX_2P1C_LOCAL_RESIDUAL_HH
-#define DUMUX_2P1C_LOCAL_RESIDUAL_HH
-
-#include "properties.hh"
-
-namespace Dumux
-{
-/*!
- * \ingroup TwoPOneCModel
- * \ingroup ImplicitLocalResidual
- * \brief Element-wise calculation of the Jacobian matrix for problems
- *        using the two-phase one-component fully implicit model.
- *
- * This class depends on the non-isothermal model.
- *
- */
-template<class TypeTag>
-class TwoPOneCLocalResidual: public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
-{
-protected:
-    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
-
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
-
-
-    enum {
-        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
-        numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
-
-        conti0EqIdx = Indices::conti0EqIdx, //!< Index of the mass conservation equation for the water component
-        energyEqIdx = Indices::energyEqIdx, //!< Index of the energy conservation equation
-        wPhaseIdx = Indices::wPhaseIdx,
-        gPhaseIdx = Indices::gPhaseIdx,
-    };
-
-    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
-
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-    typedef typename GridView::template Codim<0>::Entity Element;
-
-    static const bool useBlockingOfSpuriousFlow = GET_PROP_VALUE(TypeTag, UseBlockingOfSpuriousFlow);
-
-public:
-
-    /*!
-     * \brief Evaluate the amount all conservation quantities
-     *        (e.g. phase mass) within a sub-control volume.
-     *
-     * The result should be averaged over the volume (e.g. phase mass
-     * inside a sub control volume divided by the volume)
-     *
-     *  \param storage The mass of the component within the sub-control volume
-     *  \param scvIdx The SCV (sub-control-volume) index
-     *  \param usePrevSol Evaluate function with solution of current or previous time step
-     */
-    void computeStorage(PrimaryVariables &storage, const int scvIdx, bool usePrevSol) const
-    {
-        // if flag usePrevSol is set, the solution from the previous
-        // time step is used, otherwise the current solution is
-        // used. The secondary variables are used accordingly.  This
-        // is required to compute the derivative of the storage term
-        // using the implicit euler method.
-        const ElementVolumeVariables &elemVolVars = usePrevSol ? this->prevVolVars_() : this->curVolVars_();
-        const VolumeVariables &volVars = elemVolVars[scvIdx];
-
-        // compute storage term of all components within all phases
-        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
-        {
-            storage[conti0EqIdx] +=
-                volVars.porosity()
-                * volVars.saturation(phaseIdx) * volVars.density(phaseIdx);
-        }
-    }
-
-    /*!
-     * \brief Evaluates the total flux of all conservation quantities
-     *        over a face of a sub-control volume.
-     *
-     * \param flux The flux over the SCV (sub-control-volume) face for each component
-     * \param faceIdx The index of the SCV face
-     * \param onBoundary A boolean variable to specify whether the flux variables
-     *        are calculated for interior SCV faces or boundary faces, default=false
-     */
-    void computeFlux(PrimaryVariables &flux, const int faceIdx, const bool onBoundary=false) const
-    {
-        FluxVariables fluxVars;
-        fluxVars.update(this->problem_(),
-                           this->element_(),
-                           this->fvGeometry_(),
-                           faceIdx,
-                           this->curVolVars_(),
-                           onBoundary);
-
-        flux = 0;
-        computeAdvectiveFlux(flux, fluxVars);
-        asImp_()->computeDiffusiveFlux(flux, fluxVars);
-    }
-
-    /*!
-     * \brief Evaluates the advective mass flux of all components over
-     *        a face of a subcontrol volume.
-     *
-     * \param flux The advective flux over the sub-control-volume face for each component
-     * \param fluxVars The flux variables at the current SCV
-     */
-
-    void computeAdvectiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
-    {
-        Scalar massUpwindWeight = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
-
-        // loop over all phases
-        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
-        {
-            // data attached to upstream and the downstream vertices
-            // of the current phase
-            const VolumeVariables &up = this->curVolVars_(fluxVars.upstreamIdx(phaseIdx));
-            const VolumeVariables &dn = this->curVolVars_(fluxVars.downstreamIdx(phaseIdx));
-
-            Scalar factor = 1.0;
-
-            // factor for the blocking of spurious cold water fluxes into the steam zone (Gudbjerg, 2004)
-            if(useBlockingOfSpuriousFlow)
-            { factor = factor_(up, dn, phaseIdx); }
-
-
-            // advective mass flux
-            flux[conti0EqIdx] +=  fluxVars.volumeFlux(phaseIdx)
-                                  * (massUpwindWeight
-                                  * up.fluidState().density(phaseIdx)
-                                  + (1.0 - massUpwindWeight)
-                                  * dn.fluidState().density(phaseIdx))
-                                  * factor ;
-
-            // advective heat flux
-            flux[energyEqIdx] += fluxVars.volumeFlux(phaseIdx)
-                                 *  (massUpwindWeight
-                                 *  up.density(phaseIdx)
-                                 *  up.enthalpy(phaseIdx)
-                                 +  (1.0 - massUpwindWeight)
-                                 *  dn.density(phaseIdx)
-                                 *  dn.enthalpy(phaseIdx))
-                                 *  factor ;
-        }
-    }
-
-    /*!
-     * \brief Adds the diffusive mass flux of all components over
-     *        a face of a subcontrol volume.
-     *
-     * \param flux The diffusive flux over the sub-control-volume face for each component
-     * \param fluxVars The flux variables at the current SCV
-     */
-    void computeDiffusiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
-    {}
-
-    /*!
-     * \brief Returns true if a spurious flow has been detected
-     *
-     */
-    bool spuriousFlowDetected() const
-    {
-        return spuriousFlowDetected_;
-    }
-
-    /*!
-     * \brief Used to reset the respective flag
-     *
-     */
-    void resetSpuriousFlowDetected()
-    {
-        spuriousFlowDetected_ = false;
-    }
-
-protected:
-
-    /*!
-     * \brief Calculate the blocking factor which prevents spurious cold water fluxes into the steam zone (Gudbjerg et al., 2005) \cite gudbjerg2004 <BR>
-     *
-     * \param up The upstream volume variables
-     * \param dn The downstream volume variables
-     * \param phaseIdx The index of the fluid phase
-     */
-    Scalar factor_(const VolumeVariables &up, const VolumeVariables &dn,const  int phaseIdx) const {
-
-        Scalar factor = 1.0;
-
-        Scalar tDn = dn.temperature(); //temperature of the downstream SCV (where the cold water is potentially intruding into a steam zone)
-        Scalar tUp = up.temperature(); //temperature of the upstream SCV
-
-        Scalar sgDn = dn.saturation(gPhaseIdx); //gas phase saturation of the downstream SCV
-        Scalar sgUp = up.saturation(gPhaseIdx); //gas phase saturation of the upstream SCV
-
-        bool upIsNotSteam = false;
-        bool downIsSteam = false;
-        bool spuriousFlow = false;
-
-        if(sgUp <= 1e-5)
-        {upIsNotSteam = true;}
-
-        if(sgDn > 1e-5)
-        {downIsSteam = true;}
-
-        if(upIsNotSteam && downIsSteam  && tDn > tUp && phaseIdx == wPhaseIdx)
-        {
-          spuriousFlow = true;
-          spuriousFlowDetected_ = true;
-        }
-
-        if(spuriousFlow)
-        {
-          Scalar deltaT = tDn - tUp;
-
-          if((deltaT) > 15 )
-          {factor = 0.0 ;}
-
-          else
-          { factor = 1-(deltaT/15); }
-
-        }
-        return factor;
-    }
-
-    Implementation *asImp_()
-    {
-        return static_cast<Implementation *> (this);
-    }
-
-    const Implementation *asImp_() const
-    {
-        return static_cast<const Implementation *> (this);
-    }
-
-private:
-    mutable bool spuriousFlowDetected_;// true if spurious cold-water flow into a steam zone is happening
-};
-
-} // end namespace
-
-#endif
diff --git a/dumux/porousmediumflow/2p1c/implicit/model.hh b/dumux/porousmediumflow/2p1c/implicit/model.hh
index 0ec78078c25bc6ad6d20375d57715ea7fcff2146..b66da7eaf00d865092e572b9a06b007799c94c79 100644
--- a/dumux/porousmediumflow/2p1c/implicit/model.hh
+++ b/dumux/porousmediumflow/2p1c/implicit/model.hh
@@ -25,8 +25,24 @@
 #ifndef DUMUX_2P1C_MODEL_HH
 #define DUMUX_2P1C_MODEL_HH
 
-#include <dumux/porousmediumflow/implicit/velocityoutput.hh>
-#include "properties.hh"
+#include <dumux/common/properties.hh>
+
+#include <dumux/material/spatialparams/implicit.hh>
+#include <dumux/material/fluidmatrixinteractions/diffusivitymillingtonquirk.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/thermalconductivitysomerton.hh>
+#include <dumux/material/fluidstates/immiscible.hh>
+#include <dumux/material/fluidstates/compositional.hh>
+
+#include <dumux/porousmediumflow/properties.hh>
+#include <dumux/porousmediumflow/immiscible/localresidual.hh>
+#include <dumux/porousmediumflow/compositional/switchableprimaryvariables.hh>
+#include <dumux/porousmediumflow/nonisothermal/implicit/properties.hh>
+
+#include <dumux/porousmediumflow/2p/implicit/vtkoutputfields.hh>
+
+#include "indices.hh"
+#include "volumevariables.hh"
+#include "primaryvariableswitch.hh"
 
 namespace Dumux
 {
@@ -66,559 +82,114 @@ namespace Dumux
  * If only one phase is present, \f$p_g\f$ and \f$T\f$ are the primary variables.
  * In the presence of two phases, \f$p_g\f$ and \f$S_w\f$ become the new primary variables.
  */
-template<class TypeTag>
-class TwoPOneCModel: public GET_PROP_TYPE(TypeTag, BaseModel)
-{
-    typedef typename GET_PROP_TYPE(TypeTag, BaseModel) ParentType;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
-
-    enum {
-        dim = GridView::dimension,
-        dimWorld = GridView::dimensionworld,
-
-        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
-        numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
-
-        pressureIdx = Indices::pressureIdx,
-        switch1Idx = Indices::switch1Idx,
-
-        wPhaseIdx = Indices::wPhaseIdx,
-        gPhaseIdx = Indices::gPhaseIdx,
-
-        twoPhases = Indices::twoPhases,
-        wPhaseOnly  = Indices::wPhaseOnly,
-        gPhaseOnly  = Indices::gPhaseOnly,
-    };
-
-    typedef typename GridView::template Codim<dim>::Entity Vertex;
-    typedef typename GridView::template Codim<0>::Entity Element;
-    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
-    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
-    typedef Dune::FieldMatrix<Scalar,dim,dim> FieldMatrix;
-
-    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
-
-
-    enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) };
-    enum { dofCodim = isBox ? dim : 0 };
-
-public:
-    /*!
-     * \brief Initialize the static data with the initial solution.
-     *
-     * \param problem The problem to be solved
-     */
-    void init(Problem &problem)
-    {
-        ParentType::init(problem);
-
-        staticDat_.resize(this->numDofs());
-
-        setSwitched_(false);
-
-        if (isBox)
-        {
-            for(const auto& vertex: vertices(this->gridView_()))
-            {
-                int globalIdx = this->dofMapper().index(vertex);
-                const GlobalPosition &globalPos = vertex.geometry().corner(0);
-
-                // initialize phase presence
-                staticDat_[globalIdx].phasePresence
-                    = this->problem_().initialPhasePresence(vertex, globalIdx,
-                                                        globalPos);
-                staticDat_[globalIdx].wasSwitched = false;
-
-                staticDat_[globalIdx].oldPhasePresence
-                    = staticDat_[globalIdx].phasePresence;
-            }
-        }
-        else
-        {
-            for (const auto& element : elements(this->gridView_()))
-            {
-                int globalIdx = this->dofMapper().index(element);
-                const GlobalPosition &globalPos = element.geometry().center();
-
-                // initialize phase presence
-                staticDat_[globalIdx].phasePresence
-                    = this->problem_().initialPhasePresence(*this->gridView_().template begin<dim> (),
-                                                            globalIdx, globalPos);
-                staticDat_[globalIdx].wasSwitched = false;
-
-                staticDat_[globalIdx].oldPhasePresence
-                    = staticDat_[globalIdx].phasePresence;
-            }
-        }
-    }
-
-    /*!
-     * \brief Called by the update() method if applying the newton
-     *         method was unsuccessful.
-     */
-    void updateFailed()
-    {
-        ParentType::updateFailed();
-
-        setSwitched_(false);
-        resetPhasePresence_();
-    };
-
-    /*!
-     * \brief Called by the problem if a time integration was
-     *        successful, post processing of the solution is done and the
-     *        result has been written to disk.
-     *
-     * This should prepare the model for the next time integration.
-     */
-    void advanceTimeLevel()
-    {
-        ParentType::advanceTimeLevel();
-
-        // update the phase state
-        updateOldPhasePresence_();
-        setSwitched_(false);
-    }
-
-    /*!
-     * \brief Return true if the primary variables were switched for
-     *        at least one vertex after the last timestep.
-     */
-    bool switched() const
-    {
-        return switchFlag_;
-    }
-
-    /*!
-     * \brief Returns the phase presence of the current or the old solution of a degree of freedom.
-     *
-     * \param globalIdx The global index of the degree of freedom
-     * \param oldSol Evaluate function with solution of current or previous time step
-     */
-    int phasePresence(int globalIdx, bool oldSol) const
-    {
-        return
-            oldSol
-            ? staticDat_[globalIdx].oldPhasePresence
-            : staticDat_[globalIdx].phasePresence;
-    }
-
-    /*!
-     * \brief Append all quantities of interest which can be derived
-     *        from the solution of the current time step to the VTK
-     *        writer.
-     *
-     * \param sol The solution vector
-     * \param writer The writer for multi-file VTK datasets
-     */
-    template<class MultiWriter>
-    void addOutputVtkFields(const SolutionVector &sol,
-                            MultiWriter &writer)
-    {
-        typedef Dune::BlockVector<Dune::FieldVector<double, 1> > ScalarField;
-        typedef Dune::BlockVector<Dune::FieldVector<double, dim> > VectorField;
-
-        // get the number of degrees of freedom
-        unsigned numDofs = this->numDofs();
-
-        // create the required scalar fields
-        ScalarField *saturation[numPhases];
-        ScalarField *pressure[numPhases];
-        ScalarField *density[numPhases];
-
-        ScalarField *mobility[numPhases];
-        ScalarField *viscosity[numPhases];
-
-
-        for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
-            saturation[phaseIdx] = writer.allocateManagedBuffer(numDofs);
-            pressure[phaseIdx] = writer.allocateManagedBuffer(numDofs);
-            density[phaseIdx] = writer.allocateManagedBuffer(numDofs);
-
-            mobility[phaseIdx] = writer.allocateManagedBuffer(numDofs);
-            viscosity[phaseIdx] = writer.allocateManagedBuffer(numDofs);
-        }
-
-        ScalarField *phasePresence = writer.allocateManagedBuffer (numDofs);
-        ScalarField *poro = writer.allocateManagedBuffer(numDofs);
-        ScalarField *permXX = writer.allocateManagedBuffer(numDofs);
-        ScalarField *permYY = writer.allocateManagedBuffer(numDofs);
-        ScalarField *permZZ = writer.allocateManagedBuffer(numDofs);
-        VectorField *velocityW = writer.template allocateManagedBuffer<double, dim>(numDofs);
-        VectorField *velocityG = writer.template allocateManagedBuffer<double, dim>(numDofs);
-        ImplicitVelocityOutput<TypeTag> velocityOutput(this->problem_());
-
-        if (velocityOutput.enableOutput()) // check if velocity output is demanded
-        {
-            // initialize velocity fields
-            for (unsigned int i = 0; i < numDofs; ++i)
-            {
-                (*velocityW)[i] = Scalar(0);
-                (*velocityG)[i] = Scalar(0);
-            }
-        }
-
-        unsigned numElements = this->gridView_().size(0);
-        ScalarField *rank = writer.allocateManagedBuffer (numElements);
-
-        for (const auto& element : elements(this->gridView_(), Dune::Partitions::interior))
-        {
-            int eIdx = this->elementMapper().index(element);
-            (*rank)[eIdx] = this->gridView_().comm().rank();
-
-            FVElementGeometry fvGeometry;
-            fvGeometry.update(this->gridView_(), element);
-
-
-            ElementVolumeVariables elemVolVars;
-            elemVolVars.update(this->problem_(),
-                            element,
-                            fvGeometry,
-                            false /* oldSol? */);
-
-            for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
-            {
-                int globalIdx = this->dofMapper().subIndex(element, scvIdx, dofCodim);
-
-                for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
-                    (*saturation[phaseIdx])[globalIdx] = elemVolVars[scvIdx].fluidState().saturation(phaseIdx);
-                    (*pressure[phaseIdx])[globalIdx] = elemVolVars[scvIdx].fluidState().pressure(phaseIdx);
-                    (*density[phaseIdx])[globalIdx] = elemVolVars[scvIdx].fluidState().density(phaseIdx);
-
-                    (*mobility[phaseIdx])[globalIdx] = elemVolVars[scvIdx].mobility(phaseIdx);
-                    (*viscosity[phaseIdx])[globalIdx] = elemVolVars[scvIdx].fluidState().viscosity(phaseIdx);
-                }
-
-                (*poro)[globalIdx] = elemVolVars[scvIdx].porosity();
-                (*phasePresence)[globalIdx] = staticDat_[globalIdx].phasePresence;
-
-                FieldMatrix K = this->problem_().spatialParams().intrinsicPermeability(element,
-                                                                                    fvGeometry,
-                                                                                    scvIdx);
-                (*permXX)[globalIdx] = K[0][0];
-                if(dimWorld > 1)
-                    (*permYY)[globalIdx] = K[1][1];
-                if(dimWorld > 2)
-                    (*permZZ)[globalIdx] = K[2][2];
-            }
-
-            // velocity output
-            velocityOutput.calculateVelocity(*velocityW, elemVolVars, fvGeometry, element, wPhaseIdx);
-            velocityOutput.calculateVelocity(*velocityG, elemVolVars, fvGeometry, element, gPhaseIdx);
-        }
-
-        writer.attachDofData(*saturation[wPhaseIdx], "sw", isBox);
-        writer.attachDofData(*saturation[gPhaseIdx], "sg", isBox);
-        writer.attachDofData(*pressure[wPhaseIdx], "pw", isBox);
-        writer.attachDofData(*pressure[gPhaseIdx], "pg", isBox);
-        writer.attachDofData(*density[wPhaseIdx], "rhow", isBox);
-        writer.attachDofData(*density[gPhaseIdx], "rhog", isBox);
 
-        writer.attachDofData(*mobility[wPhaseIdx], "MobW", isBox);
-        writer.attachDofData(*mobility[gPhaseIdx], "MobG", isBox);
-
-        writer.attachDofData(*viscosity[wPhaseIdx], "ViscosW", isBox);
-        writer.attachDofData(*viscosity[gPhaseIdx], "ViscosG", isBox);
-
-        writer.attachDofData(*poro, "porosity", isBox);
-        writer.attachDofData(*permXX, "permeabilityXX", isBox);
-        if(dimWorld > 1)
-            writer.attachDofData(*permYY, "permeabilityYY", isBox);
-        if(dimWorld > 2)
-            writer.attachDofData(*permZZ, "permeabilityZZ", isBox);
-        writer.attachDofData(*phasePresence, "phase presence", isBox);
-
-        if (velocityOutput.enableOutput()) // check if velocity output is demanded
-        {
-            writer.attachDofData(*velocityW,  "velocityW", isBox, dim);
-            writer.attachDofData(*velocityG,  "velocityG", isBox, dim);
-        }
-
-        writer.attachCellData(*rank, "process rank");
-    }
-
-    /*!
-     * \brief Write the current solution to a restart file.
-     *
-     * \param outStream The output stream of one vertex for the restart file
-     * \param entity The entity, either a vertex or an element
-     */
-    template<class Entity>
-    void serializeEntity(std::ostream &outStream, const Entity &entity)
-    {
-        // write primary variables
-        ParentType::serializeEntity(outStream, entity);
-
-        int dofIdxGlobal = this->dofMapper().index(entity);
-
-        if (!outStream.good())
-            DUNE_THROW(Dune::IOError, "Could not serialize entity " << dofIdxGlobal);
-
-        outStream << staticDat_[dofIdxGlobal].phasePresence << " ";
-    }
-
-    /*!
-     * \brief Reads the current solution from a restart file.
-     *
-     * \param inStream The input stream of one vertex from the restart file
-     * \param entity The entity, either a vertex or an element
-     */
-    template<class Entity>
-    void deserializeEntity(std::istream &inStream, const Entity &entity)
-    {
-        // read primary variables
-        ParentType::deserializeEntity(inStream, entity);
-
-        // read phase presence
-        int dofIdxGlobal = this->dofMapper().index(entity);
-
-        if (!inStream.good())
-            DUNE_THROW(Dune::IOError,
-                       "Could not deserialize entity " << dofIdxGlobal);
-
-        inStream >> staticDat_[dofIdxGlobal].phasePresence;
-        staticDat_[dofIdxGlobal].oldPhasePresence
-            = staticDat_[dofIdxGlobal].phasePresence;
-
-    }
-
-    /*!
-     * \brief Update the static data of all vertices in the grid.
-     *
-     * \param curGlobalSol The current global solution
-     * \param oldGlobalSol The previous global solution
-     */
-    void updateStaticData(SolutionVector &curGlobalSol,
-                          const SolutionVector &oldGlobalSol)
-    {
-        bool wasSwitched = false;
-        int succeeded;
-        try {
-        for (unsigned i = 0; i < staticDat_.size(); ++i)
-            staticDat_[i].visited = false;
-
-        FVElementGeometry fvGeometry;
-        static VolumeVariables volVars;
-        for (const auto& element : elements(this->gridView_()))
-        {
-            fvGeometry.update(this->gridView_(), element);
-            for (int scvIdx = 0; scvIdx < fvGeometry.numScv; ++scvIdx)
-            {
-                int globalIdx = this->dofMapper().subIndex(element, scvIdx, dofCodim);
-
-                if (staticDat_[globalIdx].visited)
-                    continue;
-
-                staticDat_[globalIdx].visited = true;
-                volVars.update(curGlobalSol[globalIdx],
-                               this->problem_(),
-                               element,
-                               fvGeometry,
-                               scvIdx,
-                               false);
-                const GlobalPosition &globalPos = fvGeometry.subContVol[scvIdx].global;
-
-                    if (primaryVarSwitch_(curGlobalSol,
-                                          volVars,
-                                          globalIdx,
-                                          globalPos))
-                    {
-                        this->jacobianAssembler().markDofRed(globalIdx);
-                        wasSwitched = true;
-                    }
-            }
-        }
-         succeeded = 1;
-        }
-
-        catch (Dumux::NumericalProblem &e)
-        {
-            std::cout << "\n"
-                      << "Rank " << this->problem_().gridView().comm().rank()
-                      << " caught an exception while updating the static data." << e.what()
-                      << "\n";
-            succeeded = 0;
-        }
-
-        //make sure that all processes succeeded. If not throw a NumericalProblem to decrease the time step size.
-        if (this->gridView_().comm().size() > 1)
-            succeeded = this->gridView_().comm().min(succeeded);
-
-        if (!succeeded) {
-            updateFailed();
-
-            DUNE_THROW(NumericalProblem,
-                       "A process did not succeed in updating the static data.");
-
-            return;
-        }
-
-        // make sure that if there was a variable switch in an
-        // other partition we will also set the switch flag
-        // for our partition.
-        if (this->gridView_().comm().size() > 1)
-            wasSwitched = this->gridView_().comm().max(wasSwitched);
-
-        setSwitched_(wasSwitched);
-    }
-
-protected:
-    /*!
-     * \brief Data which is attached to each vertex and is not only
-     *        stored locally.
-     */
-    struct StaticVars
-    {
-        int phasePresence;
-        bool wasSwitched;
-
-        int oldPhasePresence;
-        bool visited;
-    };
-
-    /*!
-     * \brief Reset the current phase presence of all vertices to the old one.
-     *
-     * This is done after an update failed.
-     */
-    void resetPhasePresence_()
-    {
-        for (unsigned int i = 0; i < this->numDofs(); ++i)
-        {
-            staticDat_[i].phasePresence
-                = staticDat_[i].oldPhasePresence;
-            staticDat_[i].wasSwitched = false;
-        }
-    }
-
-    /*!
-     * \brief Set the old phase of all verts state to the current one.
-     */
-    void updateOldPhasePresence_()
-    {
-        for (unsigned int i = 0; i < this->numDofs(); ++i)
-        {
-            staticDat_[i].oldPhasePresence
-                = staticDat_[i].phasePresence;
-            staticDat_[i].wasSwitched = false;
-        }
-    }
-
-    /*!
-     * \brief Set whether there was a primary variable switch after in
-     *        the last timestep.
-     */
-    void setSwitched_(bool yesno)
-    {
-        switchFlag_ = yesno;
-    }
-
-    //  perform variable switch at a vertex; Returns true if a
-    //  variable switch was performed.
-    bool primaryVarSwitch_(SolutionVector &globalSol,
-                           const VolumeVariables &volVars,
-                           int globalIdx,
-                           const GlobalPosition &globalPos)
-    {
-        // evaluate primary variable switch
-        bool wouldSwitch = false;
-        int phasePresence = staticDat_[globalIdx].phasePresence;
-        int newPhasePresence = phasePresence;
-
-        globalSol[globalIdx][pressureIdx] = volVars.fluidState().pressure(gPhaseIdx);
-
-        // check if a primary var switch is necessary
-        if (phasePresence == twoPhases)
-        {
-            Scalar Smin = 0;
-            if (staticDat_[globalIdx].wasSwitched)
-                Smin = -0.01;
-
-            if (volVars.saturation(gPhaseIdx) <= Smin)
-            {
-                wouldSwitch = true;
-                // gas phase disappears
-                std::cout << "Gas phase disappears at vertex " << globalIdx
-                          << ", coordinates: " << globalPos << ", sg: "
-                          << volVars.saturation(gPhaseIdx) << std::endl;
-                newPhasePresence = wPhaseOnly;
-
-                globalSol[globalIdx][switch1Idx] = volVars.fluidState().temperature();
-            }
-            else if (volVars.saturation(wPhaseIdx) <= Smin)
-            {
-                wouldSwitch = true;
-                // water phase disappears
-                std::cout << "Wetting phase disappears at vertex " << globalIdx
-                          << ", coordinates: " << globalPos << ", sw: "
-                          << volVars.saturation(wPhaseIdx) << std::endl;
-                newPhasePresence = gPhaseOnly;
-
-                globalSol[globalIdx][switch1Idx] = volVars.fluidState().temperature();
-            }
-
-        }
-        else if (phasePresence == wPhaseOnly)
-        {
-            Scalar temp = volVars.fluidState().temperature();
-            Scalar tempVap = volVars.vaporTemperature();
-
-            // if the the temperature would be larger than
-            // the vapor temperature at the given pressure, gas phase appears
-            if (temp >= tempVap)
-            {
-                wouldSwitch = true;
-                // gas phase appears
-                std::cout << "gas phase appears at vertex " << globalIdx
-                          << ", coordinates: " << globalPos  << std::endl;
-
-               newPhasePresence = twoPhases;
-               globalSol[globalIdx][switch1Idx] = 0.9999; //wetting phase saturation
-            }
-        }
-
-
-        else if (phasePresence == gPhaseOnly)
-        {
-
-            Scalar temp = volVars.fluidState().temperature();
-            Scalar tempVap = volVars.vaporTemperature();
-
-            if (temp < tempVap)
-            {
-                wouldSwitch = true;
-                // wetting phase appears
-                std::cout << "wetting phase appears at vertex " << globalIdx
-                          << ", coordinates: " << globalPos  << std::endl;
-
-
-               newPhasePresence = twoPhases;
-               globalSol[globalIdx][switch1Idx] = 0.0001; //arbitrary small value
-            }
-    }
-        staticDat_[globalIdx].phasePresence = newPhasePresence;
-        staticDat_[globalIdx].wasSwitched = wouldSwitch;
-        return phasePresence != newPhasePresence;
-    }
-
-    // parameters given in constructor
-    std::vector<StaticVars> staticDat_;
-    bool switchFlag_;
-};
-
-}
-
-#include "propertydefaults.hh"
-
-#endif
+namespace Properties
+{
+ //////////////////////////////////////////////////////////////////
+ // Type tags
+ //////////////////////////////////////////////////////////////////
+ NEW_TYPE_TAG(TwoPOneCNI, INHERITS_FROM(PorousMediumFlow, NonIsothermal));
+
+ //////////////////////////////////////////////////////////////////
+ // Property tags
+ //////////////////////////////////////////////////////////////////
+
+ NEW_PROP_TAG(UseBlockingOfSpuriousFlow); //!< Determines whether Blocking ofspurious flow is used
+
+ /*!
+  * \brief Set the property for the number of components.
+  *
+  * We just forward the number from the fluid system and use an static
+  * assert to make sure it is 1.
+  */
+ SET_PROP(TwoPOneCNI, NumComponents)
+ {
+  private:
+     using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
+  public:
+     static constexpr auto value = FluidSystem::numComponents;
+
+     static_assert(value == 1,
+                   "Only fluid systems with 1 component are supported by the 2p1cni model!");
+ };
+
+ /*!
+  * \brief Set the property for the number of fluid phases.
+  *
+  * We just forward the number from the fluid system and use an static
+  * assert to make sure it is 2.
+  */
+ SET_PROP(TwoPOneCNI, NumPhases)
+ {
+  private:
+     using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
+  public:
+     static constexpr auto value = FluidSystem::numPhases;
+     static_assert(value == 2,
+                   "Only fluid systems with 2 phases are supported by the 2p1cni model!");
+ };
+
+SET_TYPE_PROP(TwoPOneCNI, LocalResidual, ImmiscibleLocalResidual<TypeTag>); //! The local residual function
+
+SET_BOOL_PROP(TwoPOneCNI, EnableAdvection, true);                           //! The one-phase model considers advection
+SET_BOOL_PROP(TwoPOneCNI, EnableMolecularDiffusion, false);                 //! The one-phase model has no molecular diffusion
+
+ /*!
+  * \brief The fluid state which is used by the volume variables to
+  *        store the thermodynamic state. This should be chosen
+  *        appropriately for the model ((non-)isothermal, equilibrium, ...).
+  *        This can be done in the problem.
+  */
+ SET_PROP(TwoPOneCNI, FluidState)
+ {
+ private:
+     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+     using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
+ public:
+     using type = CompositionalFluidState<Scalar, FluidSystem>;
+    //  using type = ImmiscibleFluidState<Scalar, FluidSystem>;
+ };
+
+ //! Determines whether Blocking ofspurious flow is used
+ SET_BOOL_PROP(TwoPOneCNI, UseBlockingOfSpuriousFlow, false);
+
+  SET_TYPE_PROP(TwoPOneCNI, VolumeVariables, TwoPOneCVolumeVariables<TypeTag>);
+
+ //! The primary variable switch for the 2p1c model
+ SET_TYPE_PROP(TwoPOneCNI, PrimaryVariableSwitch, TwoPOneCPrimaryVariableSwitch<TypeTag>);
+
+ //! The primary variables vector for the 2p1c model
+ SET_TYPE_PROP(TwoPOneCNI, PrimaryVariables, SwitchablePrimaryVariables<TypeTag, int>);
+
+ //! Somerton is used as default model to compute the effective thermal heat conductivity
+ SET_PROP(NonIsothermal, ThermalConductivityModel)
+ {
+ private:
+     typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+     typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+ public:
+     typedef ThermalConductivitySomerton<Scalar> type;
+ };
+
+ //////////////////////////////////////////////////////////////////
+ // Property values for isothermal model required for the general non-isothermal model
+ //////////////////////////////////////////////////////////////////
+ //set isothermal VolumeVariables
+ SET_TYPE_PROP(TwoPOneCNI, IsothermalVolumeVariables, TwoPOneCVolumeVariables<TypeTag>);
+
+ //set isothermal LocalResidual
+ SET_TYPE_PROP(TwoPOneCNI, IsothermalLocalResidual, ImmiscibleLocalResidual<TypeTag>);
+
+ //set isothermal Indices
+ SET_TYPE_PROP(TwoPOneCNI, IsothermalIndices, TwoPOneCIndices<TypeTag, 0>);
+
+//! the isothermal vtk output fields
+ SET_TYPE_PROP(TwoPOneCNI, IsothermalVtkOutputFields, TwoPVtkOutputFields<TypeTag>);
+
+ //set isothermal NumEq
+ SET_INT_PROP(TwoPOneCNI, IsothermalNumEq, 1);
+
+} // end namespace Properties
+} // end namespace Dumux
+
+#endif // DUMUX_2P1C_MODEL_HH
diff --git a/dumux/porousmediumflow/2p1c/implicit/newtoncontroller.hh b/dumux/porousmediumflow/2p1c/implicit/newtoncontroller.hh
deleted file mode 100644
index bc5c7e32f493186f9dbdb23cdc9e0125f8132d20..0000000000000000000000000000000000000000
--- a/dumux/porousmediumflow/2p1c/implicit/newtoncontroller.hh
+++ /dev/null
@@ -1,86 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \brief A 2p1c specific controller for the newton solver.
- *
- * This controller 'knows' what a 'physically meaningful' solution is
- * which allows the newton method to abort quicker if the solution is
- * way out of bounds.
- */
-#ifndef DUMUX_2P1CNI_NEWTON_CONTROLLER_HH
-#define DUMUX_2P1CNI_NEWTON_CONTROLLER_HH
-
-#include "properties.hh"
-
-#include <dumux/porousmediumflow/2p2c/implicit/newtoncontroller.hh>
-#include <dumux/nonlinear/newtoncontroller.hh>
-
-namespace Dumux {
-/*!
- * \ingroup TwoPOneCModel
- * \brief A 2p1cni specific controller for the newton solver.
- *
- * This controller 'knows' what a 'physically meaningful' solution is
- * which allows the newton method to abort quicker if the solution is
- * way out of bounds.
- */
-template <class TypeTag>
-class TwoPOneCNINewtonController : public TwoPTwoCNewtonController<TypeTag>
-{
-    typedef TwoPTwoCNewtonController<TypeTag> ParentType;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-
-public:
-    TwoPOneCNINewtonController(const Problem &problem)
-        : ParentType(problem)
-    {}
-
-    void newtonBeginStep()
-    {
-        // call the method of the base class
-        ParentType::newtonBeginStep();
-
-        //reset the indicator of spurious cold water fluxes into the steam zone
-        this->model_().localJacobian().localResidual().resetSpuriousFlowDetected();
-    }
-
-
-    /*!
-     * \brief Called after each Newton update
-     *
-     * \param uCurrentIter The current global solution vector
-     * \param uLastIter The previous global solution vector
-     */
-    void newtonEndStep(SolutionVector &uCurrentIter,
-                       const SolutionVector &uLastIter)
-    {
-        // call the method of the base class
-        ParentType::newtonEndStep(uCurrentIter, uLastIter);
-
-        //Output message after each Newton Step if spurious fluxes have been blocked
-        if (this->model_().localJacobian().localResidual().spuriousFlowDetected())
-            std::cout <<"Spurious fluxes blocked!" <<std::endl;
-    }
-
-};
-}
-
-#endif
diff --git a/dumux/porousmediumflow/2p1c/implicit/primaryvariableswitch.hh b/dumux/porousmediumflow/2p1c/implicit/primaryvariableswitch.hh
new file mode 100644
index 0000000000000000000000000000000000000000..1cb87b50f522c25b497199a3501876f37760aeda
--- /dev/null
+++ b/dumux/porousmediumflow/2p1c/implicit/primaryvariableswitch.hh
@@ -0,0 +1,156 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief The primary variable switch for the 2p2c model
+ */
+#ifndef DUMUX_2P1C_PRIMARY_VARIABLE_SWITCH_HH
+#define DUMUX_2P1C_PRIMARY_VARIABLE_SWITCH_HH
+
+#include <dumux/porousmediumflow/compositional/primaryvariableswitch.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPTwoCModel
+ * \brief The primary variable switch controlling the phase presence state variable
+ */
+template<class TypeTag>
+class TwoPOneCPrimaryVariableSwitch : public PrimaryVariableSwitch<TypeTag>
+{
+    friend typename Dumux::PrimaryVariableSwitch<TypeTag>;
+    using ParentType = Dumux::PrimaryVariableSwitch<TypeTag>;
+
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using IndexType = typename GridView::IndexSet::IndexType;
+    using GlobalPosition = Dune::FieldVector<Scalar, GridView::dimensionworld>;
+
+    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
+    using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
+    using Indices = typename GET_PROP_TYPE(TypeTag, Indices);
+
+    enum {
+        switchIdx = Indices::switch1Idx,
+
+        pressureIdx = Indices::pressureIdx,
+
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
+
+        twoPhases = Indices::twoPhases,
+        wPhaseOnly  = Indices::wPhaseOnly,
+        nPhaseOnly  = Indices::nPhaseOnly
+    };
+
+public:
+    using ParentType::ParentType;
+
+protected:
+
+    // perform variable switch at a degree of freedom location
+    bool update_(PrimaryVariables& priVars,
+                 const VolumeVariables& volVars,
+                 IndexType dofIdxGlobal,
+                 const GlobalPosition& globalPos)
+    {
+        // evaluate primary variable switch
+        bool wouldSwitch = false;
+        int phasePresence =  priVars.state();
+        int newPhasePresence = phasePresence;
+
+        // check if a primary var switch is necessary
+        if (phasePresence == twoPhases)
+        {
+            Scalar Smin = 0;
+            if (this->wasSwitched_[dofIdxGlobal])
+                Smin = -0.01;
+
+            if (volVars.saturation(nPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // gas phase disappears
+                std::cout << "Gas phase disappears at vertex " << dofIdxGlobal
+                          << ", coordinates: " << globalPos << ", sg: "
+                          << volVars.saturation(nPhaseIdx) << std::endl;
+                newPhasePresence = wPhaseOnly;
+
+                priVars[switchIdx] = volVars.fluidState().temperature();
+            }
+            else if (volVars.saturation(wPhaseIdx) <= Smin)
+            {
+                wouldSwitch = true;
+                // water phase disappears
+                std::cout << "Wetting phase disappears at vertex " << dofIdxGlobal
+                          << ", coordinates: " << globalPos << ", sw: "
+                          << volVars.saturation(wPhaseIdx) << std::endl;
+                newPhasePresence = nPhaseOnly;
+
+                priVars[switchIdx] = volVars.fluidState().temperature();
+            }
+
+        }
+        else if (phasePresence == wPhaseOnly)
+        {
+            const Scalar temp = volVars.fluidState().temperature();
+            const Scalar tempVap = volVars.vaporTemperature();
+
+            // if the the temperature would be larger than
+            // the vapor temperature at the given pressure, gas phase appears
+            if (temp >= tempVap)
+            {
+                wouldSwitch = true;
+                // gas phase appears
+                std::cout << "gas phase appears at vertex " << dofIdxGlobal
+                          << ", coordinates: " << globalPos  << std::endl;
+
+               newPhasePresence = twoPhases;
+               priVars[switchIdx] = 0.9999; //wetting phase saturation
+            }
+        }
+
+
+        else if (phasePresence == nPhaseOnly)
+        {
+
+            const Scalar temp = volVars.fluidState().temperature();
+            const Scalar tempVap = volVars.vaporTemperature();
+
+            if (temp < tempVap)
+            {
+                wouldSwitch = true;
+                // wetting phase appears
+                std::cout << "wetting phase appears at vertex " << dofIdxGlobal
+                          << ", coordinates: " << globalPos  << std::endl;
+
+
+               newPhasePresence = twoPhases;
+               priVars[switchIdx] = 0.0001; //arbitrary small value
+            }
+    }
+        priVars.setState(newPhasePresence);
+        this->wasSwitched_[dofIdxGlobal] = wouldSwitch;
+        return phasePresence != newPhasePresence;
+    }
+};
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/porousmediumflow/2p1c/implicit/propertydefaults.hh b/dumux/porousmediumflow/2p1c/implicit/propertydefaults.hh
deleted file mode 100644
index 19b589d5ae175bd5d915d437eb15ac8a064782ca..0000000000000000000000000000000000000000
--- a/dumux/porousmediumflow/2p1c/implicit/propertydefaults.hh
+++ /dev/null
@@ -1,171 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \ingroup TwoPOneCModel
- */
-/*!
- * \file
- *
- * \brief Defines default values for most properties required by the
- *        2p1cni fully implicit model.
- *
- *Important note: The 2p1c model requires the use of the non-isothermal extension found in dumux/implicit/nonisothermal
- */
-#ifndef DUMUX_2P1C_PROPERTY_DEFAULTS_HH
-#define DUMUX_2P1C_PROPERTY_DEFAULTS_HH
-
-#include "model.hh"
-#include "indices.hh"
-#include "volumevariables.hh"
-#include "properties.hh"
-#include "newtoncontroller.hh"
-#include "localresidual.hh"
-
-#include <dumux/porousmediumflow/implicit/darcyfluxvariables.hh>
-#include <dumux/porousmediumflow/nonisothermal/implicit/propertydefaults.hh>
-#include <dumux/material/fluidsystems/2pliquidvapor.hh>
-#include <dumux/material/components/constant.hh>
-#include <dumux/material/fluidmatrixinteractions/2p/thermalconductivitysomerton.hh>
-#include <dumux/material/spatialparams/implicit.hh>
-
-namespace Dumux
-{
-
-namespace Properties {
-//////////////////////////////////////////////////////////////////
-// Property values
-//////////////////////////////////////////////////////////////////
-
-/*!
- * \brief Set the property for the number of components.
- *
- * We just forward the number from the fluid system and use an static
- * assert to make sure it is 1.
- */
-SET_PROP(TwoPOneCNI, NumComponents)
-{
- private:
-    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
-
- public:
-    static const int value = FluidSystem::numComponents;
-
-    static_assert(value == 1,
-                  "Only fluid systems with 1 component are supported by the 2p1cni model!");
-};
-
-/*!
- * \brief Set the property for the number of fluid phases.
- *
- * We just forward the number from the fluid system and use an static
- * assert to make sure it is 2.
- */
-SET_PROP(TwoPOneCNI, NumPhases)
-{
- private:
-    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
-
- public:
-    static const int value = FluidSystem::numPhases;
-    static_assert(value == 2,
-                  "Only fluid systems with 2 phases are supported by the 2p1cni model!");
-};
-
-//! Use the 2p2c specific newton controller for dealing with phase switches
-SET_TYPE_PROP(TwoPOneCNI, NewtonController, TwoPOneCNINewtonController<TypeTag>);
-
-//! the FluxVariables property
-// SET_TYPE_PROP(TwoPOneCNI, FluxVariables, ImplicitDarcyFluxVariables<TypeTag>);
-
-//! the upwind factor for the mobility.
-SET_SCALAR_PROP(TwoPOneCNI, ImplicitMassUpwindWeight, 1.0);
-
-//! set default mobility upwind weight to 1.0, i.e. fully upwind
-SET_SCALAR_PROP(TwoPOneCNI, ImplicitMobilityUpwindWeight, 1.0);
-
-//! The fluid system to use by default
-SET_PROP(TwoPOneCNI, FluidSystem)
-{ private:
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-public:
-    typedef FluidSystems::TwoPLiquidVaporFluidsystem<Scalar, Components::Constant<1, Scalar> > type;
-};
-
-//! Determines whether Blocking ofspurious flow is used
-SET_BOOL_PROP(TwoPOneCNI, UseBlockingOfSpuriousFlow, false);
-
-//! The spatial parameters to be employed.
-//! Use ImplicitSpatialParams by default.
-SET_TYPE_PROP(TwoPOneCNI, SpatialParams, ImplicitSpatialParams<TypeTag>);
-
-// disable velocity output by default
-
-// enable gravity by default
-SET_BOOL_PROP(TwoPOneCNI, ProblemEnableGravity, true);
-
-//! default value for the forchheimer coefficient
-// Source: Ward, J.C. 1964 Turbulent flow in porous media. ASCE J. Hydraul. Div 90.
-//        Actually the Forchheimer coefficient is also a function of the dimensions of the
-//        porous medium. Taking it as a constant is only a first approximation
-//        (Nield, Bejan, Convection in porous media, 2006, p. 10)
-SET_SCALAR_PROP(BoxModel, SpatialParamsForchCoeff, 0.55);
-
-
-//! Somerton is used as default model to compute the effective thermal heat conductivity
-SET_PROP(NonIsothermal, ThermalConductivityModel)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
-public:
-    typedef ThermalConductivitySomerton<Scalar> type;
-};
-
-//////////////////////////////////////////////////////////////////
-// Property values for isothermal model required for the general non-isothermal model
-//////////////////////////////////////////////////////////////////
-
-// set isothermal Model
-SET_TYPE_PROP(TwoPOneCNI, IsothermalModel, TwoPOneCModel<TypeTag>);
-
-// set isothermal FluxVariables
-SET_TYPE_PROP(TwoPOneCNI, IsothermalFluxVariables, ImplicitDarcyFluxVariables<TypeTag>);
-
-//set isothermal VolumeVariables
-SET_TYPE_PROP(TwoPOneCNI, IsothermalVolumeVariables, TwoPOneCVolumeVariables<TypeTag>);
-
-//set isothermal LocalResidual
-SET_TYPE_PROP(TwoPOneCNI, IsothermalLocalResidual, TwoPOneCLocalResidual<TypeTag>);
-
-//set isothermal Indices
-SET_PROP(TwoPOneCNI, IsothermalIndices)
-{
-
-public:
-    typedef TwoPOneCIndices<TypeTag, 0> type;
-};
-
-//set isothermal NumEq
-SET_INT_PROP(TwoPOneCNI, IsothermalNumEq, 1);
-
-}
-
-}
-
-#endif
diff --git a/dumux/porousmediumflow/2p1c/implicit/volumevariables.hh b/dumux/porousmediumflow/2p1c/implicit/volumevariables.hh
index cf406f1ff303196525a8db14fbfe9f77f95760e2..019b54ff27e924f1d96a8f87bd11b25beb6f5aa6 100644
--- a/dumux/porousmediumflow/2p1c/implicit/volumevariables.hh
+++ b/dumux/porousmediumflow/2p1c/implicit/volumevariables.hh
@@ -27,9 +27,9 @@
 #ifndef DUMUX_2P1C_VOLUME_VARIABLES_HH
 #define DUMUX_2P1C_VOLUME_VARIABLES_HH
 
-#include <dumux/implicit/volumevariables.hh>
+#include <dumux/discretization/volumevariables.hh>
 #include <dumux/material/fluidstates/compositional.hh>
-#include "properties.hh"
+#include "indices.hh"
 
 namespace Dumux
 {
@@ -43,19 +43,21 @@ namespace Dumux
 template <class TypeTag>
 class TwoPOneCVolumeVariables : public ImplicitVolumeVariables<TypeTag>
 {
-    typedef ImplicitVolumeVariables<TypeTag> ParentType;
-    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) Implementation;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
-    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
-    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw)::Params MaterialLawParams;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    using ParentType = ImplicitVolumeVariables<TypeTag>;
+    using Implementation = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Grid = typename GET_PROP_TYPE(TypeTag, Grid);
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using SpatialParams = typename GET_PROP_TYPE(TypeTag, SpatialParams);
+    using PermeabilityType = typename SpatialParams::PermeabilityType;
+    using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
+    using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
+    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
+    using MaterialLaw = typename GET_PROP_TYPE(TypeTag, MaterialLaw);
+    using MaterialLawParams = typename GET_PROP_TYPE(TypeTag, MaterialLaw)::Params;
+    using Indices = typename GET_PROP_TYPE(TypeTag, Indices);
+
     enum {
         dim = GridView::dimension,
 
@@ -63,7 +65,7 @@ class TwoPOneCVolumeVariables : public ImplicitVolumeVariables<TypeTag>
         numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
 
         wPhaseIdx = Indices::wPhaseIdx,
-        gPhaseIdx = Indices::gPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
 
         switch1Idx = Indices::switch1Idx,
         pressureIdx = Indices::pressureIdx
@@ -73,42 +75,71 @@ class TwoPOneCVolumeVariables : public ImplicitVolumeVariables<TypeTag>
     enum {
         twoPhases = Indices::twoPhases,
         wPhaseOnly  = Indices::wPhaseOnly,
-        gPhaseOnly  = Indices::gPhaseOnly,
+        nPhaseOnly  = Indices::nPhaseOnly,
     };
 
-    typedef typename GridView::template Codim<0>::Entity Element;
-    typedef Dune::FieldMatrix<Scalar,dim,dim> FieldMatrix;
-
-    enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) };
-    enum { dofCodim = isBox ? dim : 0 };
+    using Element = typename GridView::template Codim<0>::Entity;
 
 public:
     //! The type of the object returned by the fluidState() method
-    typedef Dumux::CompositionalFluidState<Scalar, FluidSystem> FluidState;
+    using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState);
 
     /*!
      * \copydoc ImplicitVolumeVariables::update
      */
-    void update(const PrimaryVariables &priVars,
+    void update(const ElementSolutionVector &elemSol,
                 const Problem &problem,
                 const Element &element,
-                const FVElementGeometry &fvGeometry,
-                const int scvIdx,
-                bool isOldSol)
+                const SubControlVolume& scv)
+    {
+        ParentType::update(elemSol, problem, element, scv);
+
+        completeFluidState(elemSol, problem, element, scv, fluidState_);
+
+        /////////////
+        // calculate the remaining quantities
+        /////////////
+        const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol);
+
+        // Second instance of a parameter cache.
+        // Could be avoided if diffusion coefficients also
+        // became part of the fluid state.
+        typename FluidSystem::ParameterCache paramCache;
+        paramCache.updateAll(fluidState_);
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // relative permeabilities
+            Scalar kr;
+            if (phaseIdx == wPhaseIdx)
+                kr = MaterialLaw::krw(materialParams, saturation(wPhaseIdx));
+            else // ATTENTION: krn requires the wetting phase saturation
+                // as parameter!
+                kr = MaterialLaw::krn(materialParams, saturation(wPhaseIdx));
+            relativePermeability_[phaseIdx] = kr;
+            Valgrind::CheckDefined(relativePermeability_[phaseIdx]);
+        }
+
+        // porosity & permeability
+        porosity_ = problem.spatialParams().porosity(element, scv, elemSol);
+        permeability_ = problem.spatialParams().permeability(element, scv, elemSol);
+    }
+
+    /*!
+     * \copydoc ImplicitModel::completeFluidState
+     * \param isOldSol Specifies whether this is the previous solution or the current one
+     */
+    static void completeFluidState(const ElementSolutionVector& elemSol,
+                                   const Problem& problem,
+                                   const Element& element,
+                                   const SubControlVolume& scv,
+                                   FluidState& fluidState)
     {
-        ParentType::update(priVars,
-                           problem,
-                           element,
-                           fvGeometry,
-                           scvIdx,
-                           isOldSol);
 
-        // capillary pressure parameters
-        const MaterialLawParams &materialParams =
-            problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+        // // capillary pressure parameters
+        const auto& materialParams = problem.spatialParams().materialLawParams(element, scv, elemSol);
 
-        int globalIdx = problem.model().dofMapper().subIndex(element, scvIdx, dofCodim);
-        int phasePresence = problem.model().phasePresence(globalIdx, isOldSol);
+        const auto& priVars = ParentType::extractDofPriVars(elemSol, scv);
+        const auto phasePresence = priVars.state();
 
         // get saturations
         Scalar sw(0.0);
@@ -123,7 +154,7 @@ public:
             sw = 1.0;
             sg = 0.0;
         }
-        else if (phasePresence == gPhaseOnly)
+        else if (phasePresence == nPhaseOnly)
         {
             sw = 0.0;
             sg = 1.0;
@@ -131,8 +162,8 @@ public:
         else DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid.");
         Valgrind::CheckDefined(sg);
 
-        fluidState_.setSaturation(wPhaseIdx, sw);
-        fluidState_.setSaturation(gPhaseIdx, sg);
+        fluidState.setSaturation(wPhaseIdx, sw);
+        fluidState.setSaturation(nPhaseIdx, sg);
 
         // get gas phase pressure
         const Scalar pg = priVars[pressureIdx];
@@ -144,64 +175,45 @@ public:
         const Scalar pw = pg - pc;
 
         //set pressures
-        fluidState_.setPressure(wPhaseIdx, pw);
-        fluidState_.setPressure(gPhaseIdx, pg);
+        fluidState.setPressure(wPhaseIdx, pw);
+        fluidState.setPressure(nPhaseIdx, pg);
 
         // get temperature
         Scalar temperature;
-        if (phasePresence == wPhaseOnly || phasePresence == gPhaseOnly)
+        if (phasePresence == wPhaseOnly || phasePresence == nPhaseOnly)
             temperature = priVars[switch1Idx];
         else if (phasePresence == twoPhases)
-            temperature = FluidSystem::vaporTemperature(fluidState_, wPhaseIdx);
+            temperature = FluidSystem::vaporTemperature(fluidState, wPhaseIdx);
         else
             DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid.");
 
         Valgrind::CheckDefined(temperature);
 
-        fluidState_.setTemperature(temperature);
+        fluidState.setTemperature(temperature);
 
         // set the densities
-        const Scalar rhoW = FluidSystem::density(fluidState_, wPhaseIdx);
-        const Scalar rhoG = FluidSystem::density(fluidState_, gPhaseIdx);
+        const Scalar rhoW = FluidSystem::density(fluidState, wPhaseIdx);
+        const Scalar rhoG = FluidSystem::density(fluidState, nPhaseIdx);
 
-        fluidState_.setDensity(wPhaseIdx, rhoW);
-        fluidState_.setDensity(gPhaseIdx, rhoG);
+        fluidState.setDensity(wPhaseIdx, rhoW);
+        fluidState.setDensity(nPhaseIdx, rhoG);
 
         //get the viscosity and mobility
         for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
         {
             // Mobilities
             const Scalar mu =
-                FluidSystem::viscosity(fluidState_,
+                FluidSystem::viscosity(fluidState,
                                        phaseIdx);
-            fluidState_.setViscosity(phaseIdx,mu);
-
-            Scalar kr;
-            if (phaseIdx == wPhaseIdx)
-                kr = MaterialLaw::krw(materialParams, saturation(wPhaseIdx));
-            else // ATTENTION: krn requires the wetting phase saturation
-                // as parameter!
-                kr = MaterialLaw::krn(materialParams, saturation(wPhaseIdx));
-
-            mobility_[phaseIdx] = kr / mu;
-            Valgrind::CheckDefined(mobility_[phaseIdx]);
+            fluidState.setViscosity(phaseIdx,mu);
         }
 
-        // porosity
-        porosity_ = problem.spatialParams().porosity(element,
-                                                         fvGeometry,
-                                                         scvIdx);
-        Valgrind::CheckDefined(porosity_);
-
         // the enthalpies (internal energies are directly calculated in the fluidstate
         for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
         {
-            Scalar h = FluidSystem::enthalpy(fluidState_, phaseIdx);
-            fluidState_.setEnthalpy(phaseIdx, h);
+            const Scalar h = FluidSystem::enthalpy(fluidState, phaseIdx);
+            fluidState.setEnthalpy(phaseIdx, h);
         }
-
-        // energy related quantities not contained in the fluid state
-        asImp_().updateEnergy_(priVars, problem, element, fvGeometry, scvIdx, isOldSol);
     }
 
     /*!
@@ -243,7 +255,7 @@ public:
      *
      * \param phaseIdx The phase index
      */
-    Scalar pressure(const int phaseIdx) const
+    Scalar pressure(const int phaseIdx = 0) const
     { return fluidState_.pressure(phaseIdx); }
 
     /*!
@@ -253,8 +265,8 @@ public:
      * temperatures of the rock matrix and of all fluid phases are
      * identical.
      */
-    Scalar temperature() const
-    { return fluidState_.temperature(/*phaseIdx=*/0); }
+    Scalar temperature(const int phaseIdx = 0) const
+    { return fluidState_.temperature(phaseIdx); }
 
     /*!
      * \brief Returns the effective mobility of a given phase within
@@ -264,14 +276,15 @@ public:
      */
     Scalar mobility(const int phaseIdx) const
     {
-        return mobility_[phaseIdx];
+        return relativePermeability_[phaseIdx]/fluidState_.viscosity(phaseIdx);
     }
 
     /*!
-     * \brief Returns the effective capillary pressure within the control volume.
+     * \brief Returns the effective capillary pressure within the control volume
+     *        in \f$[kg/(m*s^2)=N/m^2=Pa]\f$.
      */
     Scalar capillaryPressure() const
-    { return fluidState_.capillaryPressure(); }
+    { return fluidState_.pressure(nPhaseIdx) - fluidState_.pressure(wPhaseIdx); }
 
     /*!
      * \brief Returns the average porosity within the control volume.
@@ -279,6 +292,12 @@ public:
     Scalar porosity() const
     { return porosity_; }
 
+    /*!
+     * \brief Returns the average permeability within the control volume in \f$[m^2]\f$.
+     */
+    const PermeabilityType& permeability() const
+    { return permeability_; }
+
     /*!
      * \brief Returns the vapor temperature (T_{vap}(p_g) of the fluid within the control volume.
      */
@@ -289,9 +308,9 @@ protected:
     FluidState fluidState_;
 
 private:
-
-    Scalar porosity_;
-    Scalar mobility_[numPhases];
+    Scalar porosity_;               //!< Effective porosity within the control volume
+    PermeabilityType permeability_; //!> Effective permeability within the control volume
+    std::array<Scalar, numPhases> relativePermeability_;
 
     Implementation &asImp_()
     { return *static_cast<Implementation*>(this); }
diff --git a/dumux/porousmediumflow/2p1c/implicit/vtkoutputfields.hh b/dumux/porousmediumflow/2p1c/implicit/vtkoutputfields.hh
new file mode 100644
index 0000000000000000000000000000000000000000..12296f473e9b81ab0b6ca393499cb4672db46f6a
--- /dev/null
+++ b/dumux/porousmediumflow/2p1c/implicit/vtkoutputfields.hh
@@ -0,0 +1,47 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief Adds vtk output fields specific to the onep model
+ */
+#ifndef DUMUX_ONEP_VTK_OUTPUT_FIELDS_HH
+#define DUMUX_ONEP_VTK_OUTPUT_FIELDS_HH
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup OneP, InputOutput
+ * \brief Adds vtk output fields specific to the onep model
+ */
+template<class TypeTag>
+class OnePVtkOutputFields
+{
+    using Indices = typename GET_PROP_TYPE(TypeTag, Indices);
+public:
+    template <class VtkOutputModule>
+    static void init(VtkOutputModule& vtk)
+    {
+        vtk.addVolumeVariable([](const auto& volVars){ return volVars.pressure(); }, "pressure");
+    }
+};
+
+} // end namespace Dumux
+
+#endif
diff --git a/test/porousmediumflow/2p1c/implicit/CMakeLists.txt b/test/porousmediumflow/2p1c/implicit/CMakeLists.txt
index 436aaaac55c891152be6a21e14741cf0a592031a..4bfebfdff9b167714328cf9f013c201314d61cb5 100644
--- a/test/porousmediumflow/2p1c/implicit/CMakeLists.txt
+++ b/test/porousmediumflow/2p1c/implicit/CMakeLists.txt
@@ -1,16 +1,20 @@
 #add links to input files
 add_input_file_links()
 
-add_dumux_test(test_boxsteaminjection test_boxsteaminjection test_boxsteaminjection.cc
-               python ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py
-                 --script fuzzy
-                 --files ${CMAKE_SOURCE_DIR}/test/references/steaminjectionbox-reference.vtu
-                         ${CMAKE_CURRENT_BINARY_DIR}/test_boxsteaminjection-00008.vtu
-                 --command "${CMAKE_CURRENT_BINARY_DIR}/test_boxsteaminjection")
+dune_add_test(NAME test_2p1cni_box
+              SOURCES test_2p1c_fv.cc
+              COMPILE_DEFINITIONS TYPETAG=TwoPOneCNIBoxProblem
+              COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py
+              CMD_ARGS  --script fuzzy
+                        --files ${CMAKE_SOURCE_DIR}/test/references/1p2cniccmpfaconvection-reference.vtu
+                                ${CMAKE_CURRENT_BINARY_DIR}/1p2cni_convectiontest_mpfa-00010.vtu
+                        --command "${CMAKE_CURRENT_BINARY_DIR}/test_2p1cni_box test_boxsteaminjection.input")
 
-add_dumux_test(test_ccsteaminjection test_ccsteaminjection test_ccsteaminjection.cc
-               python ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py
-                 --script fuzzy
-                 --files ${CMAKE_SOURCE_DIR}/test/references/steaminjectioncc-reference.vtu
-                         ${CMAKE_CURRENT_BINARY_DIR}/test_ccsteaminjection-00009.vtu
-                 --command "${CMAKE_CURRENT_BINARY_DIR}/test_ccsteaminjection")
+dune_add_test(NAME test_2p1cni_tpfa
+              SOURCES test_2p1c_fv.cc
+              COMPILE_DEFINITIONS TYPETAG=TwoPOneCNICCTpfaProblem
+              COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py
+              CMD_ARGS  --script fuzzy
+                        --files ${CMAKE_SOURCE_DIR}/test/references/1p2cniccmpfaconvection-reference.vtu
+                                ${CMAKE_CURRENT_BINARY_DIR}/1p2cni_convectiontest_mpfa-00010.vtu
+                        --command "${CMAKE_CURRENT_BINARY_DIR}/test_2p1cni_tpfa test_ccsteaminjection.input")
diff --git a/test/porousmediumflow/2p1c/implicit/steaminjectionproblem.hh b/test/porousmediumflow/2p1c/implicit/steaminjectionproblem.hh
index 97a3347bd0eba5a200f2ec79e9a2983240d388ad..9985d0608d33ce945f216b1fe85543f0e7f4c51b 100644
--- a/test/porousmediumflow/2p1c/implicit/steaminjectionproblem.hh
+++ b/test/porousmediumflow/2p1c/implicit/steaminjectionproblem.hh
@@ -25,13 +25,18 @@
 #ifndef DUMUX_STEAM_INJECTIONPROBLEM_HH
 #define DUMUX_STEAM_INJECTIONPROBLEM_HH
 
+#include <dumux/discretization/cellcentered/tpfa/properties.hh>
+#include <dumux/discretization/box/properties.hh>
 #include <dumux/porousmediumflow/2p1c/implicit/model.hh>
-#include <dumux/porousmediumflow/implicit/problem.hh>
+#include <dumux/porousmediumflow/problem.hh>
+
+#include <dumux/material/fluidsystems/2pliquidvapor.hh>
 
-#include "steaminjectionspatialparams.hh"
 #include <dumux/material/components/tabulatedcomponent.hh>
 #include <dumux/material/components/h2o.hh>
 
+#include "steaminjectionspatialparams.hh"
+
 namespace Dumux
 {
 template <class TypeTag>
@@ -40,32 +45,28 @@ class InjectionProblem;
 namespace Properties
 {
 NEW_TYPE_TAG(InjectionProblem, INHERITS_FROM(TwoPOneCNI, InjectionProblemSpatialParams));
-NEW_TYPE_TAG(InjectionBoxProblem, INHERITS_FROM(BoxModel, InjectionProblem));
-NEW_TYPE_TAG(InjectionCCProblem, INHERITS_FROM(CCModel, InjectionProblem));
+NEW_TYPE_TAG(TwoPOneCNIBoxProblem, INHERITS_FROM(BoxModel, InjectionProblem));
+NEW_TYPE_TAG(TwoPOneCNICCTpfaProblem, INHERITS_FROM(CCTpfaModel, InjectionProblem));
 
 SET_TYPE_PROP(InjectionProblem, Grid, Dune::YaspGrid<2>);
 
 // Set the problem property
-SET_PROP(InjectionProblem, Problem)
-{
-    typedef Dumux::InjectionProblem<TypeTag> type;
-};
+SET_TYPE_PROP(InjectionProblem, Problem, InjectionProblem<TypeTag>);
 
-// Set the fluid system
+
+// Set fluid configuration
 SET_PROP(InjectionProblem, FluidSystem)
 {
 private:
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef Dumux::TabulatedComponent<Scalar, Dumux::H2O<Scalar> >  H2OType ;
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using H2OType = Dumux::TabulatedComponent<Scalar, Dumux::H2O<Scalar> >;
 public:
-    typedef Dumux::FluidSystems::TwoPLiquidVaporFluidsystem<Scalar, H2OType > type;
+    using type = Dumux::FluidSystems::TwoPLiquidVaporFluidsystem<Scalar, H2OType >;
 };
 
-// Enable gravity
-SET_BOOL_PROP(InjectionProblem, ProblemEnableGravity, true);
 
 //Define whether spurious cold-water flow into the steam is blocked
-SET_BOOL_PROP(InjectionProblem, UseBlockingOfSpuriousFlow, true);
+SET_BOOL_PROP(InjectionProblem, UseBlockingOfSpuriousFlow, false);
 }
 
 //TODO: Names
@@ -78,16 +79,29 @@ SET_BOOL_PROP(InjectionProblem, UseBlockingOfSpuriousFlow, true);
  *
  *  */
 template <class TypeTag>
-class InjectionProblem : public ImplicitPorousMediaProblem<TypeTag>
+class InjectionProblem : public PorousMediumFlowProblem<TypeTag>
 {
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-    typedef typename GridView::Grid Grid;
-
-    typedef ImplicitPorousMediaProblem<TypeTag> ParentType;
+    using ParentType = PorousMediumFlowProblem<TypeTag>;
+
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Indices = typename GET_PROP_TYPE(TypeTag, Indices);
+    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
+    using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
+    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
+    using Sources = typename GET_PROP_TYPE(TypeTag, NumEqVector);
+    using ElementVolumeVariables = typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables);
+    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVElementGeometry);
+    using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
+    using SubControlVolumeFace = typename GET_PROP_TYPE(TypeTag, SubControlVolumeFace);
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using Element = typename GridView::template Codim<0>::Entity;
+    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
+    using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
+    using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
+    using ResidualVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
 
     // copy some indices for convenience
-    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
     enum {
         pressureIdx = Indices::pressureIdx,
         switch1Idx = Indices::switch1Idx,
@@ -96,32 +110,20 @@ class InjectionProblem : public ImplicitPorousMediaProblem<TypeTag>
 
         // phase and component indices
         wPhaseIdx = Indices::wPhaseIdx,
-        gPhaseIdx = Indices::gPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx,
 
         // Phase State
         wPhaseOnly = Indices::wPhaseOnly,
-        gPhaseOnly = Indices::gPhaseOnly,
+        nPhaseOnly = Indices::nPhaseOnly,
         twoPhases = Indices::twoPhases,
-
-        // Grid and world dimension
-        dim = GridView::dimension,
-        dimWorld = GridView::dimensionworld
     };
 
-    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
-    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
-    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
-
-    typedef typename GridView::template Codim<0>::Entity Element;
-    typedef typename GridView::template Codim<dim>::Entity Vertex;
-
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
-    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    static constexpr int dim = GridView::dimension;
+    static constexpr int dimWorld = GridView::dimensionworld;
+    static constexpr bool isBox = GET_PROP_VALUE(TypeTag, DiscretizationMethod) == DiscretizationMethods::Box;
+    using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
 
-    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
-
-    enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) };
+    enum { dofCodim = isBox ? dim : 0 };
 
 public:
 
@@ -132,15 +134,9 @@ public:
      * \param gridView The grid view
      */
 
-    InjectionProblem(TimeManager &timeManager, const GridView &gridView)
-        : ParentType(timeManager, gridView)
+    InjectionProblem(std::shared_ptr<const FVGridGeometry> fvGridGeometry)
+    : ParentType(fvGridGeometry)
     {
-
-        name_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag,
-                                             std::string,
-                                             Problem,
-                                             Name);
-
         FluidSystem::init();
     }
 
@@ -149,20 +145,15 @@ public:
      */
     // \{
 
-    /*!
-     * \brief The problem name.
-     *
-     * This is used as a prefix for files generated by the simulation.
-     */
-    const std::string name() const
-    { return name_; }
-
 
-    void sourceAtPos(PrimaryVariables &values,
-                     const GlobalPosition &globalPos) const
-     {
-          values = 0.0;
-     }
+    //! \copydoc Dumux::FVProblem::source()
+    Sources source(const Element &element,
+                   const FVElementGeometry& fvGeometry,
+                   const ElementVolumeVariables& elemVolVars,
+                   const SubControlVolume &scv) const
+    {
+          return Sources(0.0);
+    }
 
     /*!
      * \name Boundary conditions
@@ -171,58 +162,71 @@ public:
 
     /*!
      * \brief Specifies which kind of boundary condition should be
-     *        used for which equation on a given boundary segment.
+     *        used for which equation on a given boundary segment
      *
-     * \param bcTypes The boundary types for the conservation equations
-     * \param globalPos The position for which the bc type should be evaluated
+     * \param globalPos The global position
      */
-   void boundaryTypesAtPos(BoundaryTypes &bcTypes,
-            const GlobalPosition &globalPos) const
+    BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
     {
-        if(globalPos[1] > this->bBoxMax()[1] - eps_ || globalPos[0] > this->bBoxMax()[0] - eps_)
+        BoundaryTypes bcTypes;
+
+        if(globalPos[1] > this->fvGridGeometry().bBoxMax()[1] - eps_ || globalPos[0] > this->fvGridGeometry().bBoxMax()[0] - eps_)
            bcTypes.setAllDirichlet();
         else
            bcTypes.setAllNeumann();
+
+         return bcTypes;
     }
 
     /*!
-     * \brief Evaluate the boundary conditions for a dirichlet
-     *        boundary segment.
+     * \brief Evaluates the boundary conditions for a Dirichlet
+     *        boundary segment
      *
-     * \param values The dirichlet values for the primary variables
-     * \param globalPos The position for which the bc type should be evaluated
-     *
-     * For this method, the \a values parameter stores primary variables.
+     * \param globalPos The global position
      */
-    void dirichletAtPos(PrimaryVariables &values, const GlobalPosition &globalPos) const
+    PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
     {
-       initial_(values, globalPos);
+       return initialAtPos(globalPos);
     }
 
     /*!
      * \brief Evaluate the boundary conditions for a neumann
      *        boundary segment.
      *
-     * \param values The dirichlet values for the primary variables
-     * \param globalPos The position for which the bc type should be evaluated
+     * This is the method for the case where the Neumann condition is
+     * potentially solution dependent and requires some quantities that
+     * are specific to the fully-implicit method.
+     *
+     * \param values The neumann values for the conservation equations in units of
+     *                 \f$ [ \textnormal{unit of conserved quantity} / (m^2 \cdot s )] \f$
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry
+     * \param elemVolVars All volume variables for the element
+     * \param scvf The sub control volume face
      *
-     * For this method, the \a values parameter stores the mass flux
+     * For this method, the \a values parameter stores the flux
      * in normal direction of each phase. Negative values mean influx.
+     * E.g. for the mass balance that would the mass flux in \f$ [ kg / (m^2 \cdot s)] \f$.
      */
-      void neumannAtPos(PrimaryVariables &values,
-                      const GlobalPosition &globalPos) const
+    ResidualVector neumann(const Element& element,
+                           const FVElementGeometry& fvGeometry,
+                           const ElementVolumeVariables& elemVolVars,
+                           const SubControlVolumeFace& scvf) const
     {
-        values = 0.0;
+        ResidualVector values(0.0);
 
-        if (globalPos[0] < eps_)
+        const auto& ipGlobal = scvf.ipGlobal();
+
+        if (ipGlobal[0] < eps_)
         {
-            if(globalPos[1] > 2.0 - eps_ && globalPos[1] < 3.0 + eps_)
+            if(ipGlobal[1] > 2.0 - eps_ && ipGlobal[1] < 3.0 + eps_)
             {
-            Scalar massRate = 1e-1;
-            values[Indices::conti0EqIdx] = -massRate;
-            values[Indices::energyEqIdx] = -massRate * 2690e3;
+                const Scalar massRate = 1e-1;
+                values[Indices::conti0EqIdx] = -massRate;
+                values[Indices::energyEqIdx] = -massRate * 2690e3;
             }
         }
+        return values;
     }
 
     // \}
@@ -233,48 +237,26 @@ public:
     // \{
 
     /*!
-     * \brief Evaluate the initial value for a control volume.
-     *
-     * \param values The initial values for the primary variables
-     * \param globalPos The position for which the initial condition should be evaluated
+     * \brief Evaluates the initial values for a control volume
      *
-     * For this method, the \a values parameter stores primary
-     * variables.
-     */
-    void initialAtPos(PrimaryVariables &values, const GlobalPosition &globalPos) const
-    {
-        initial_(values, globalPos);
-    }
-
-    /*!
-     * \brief Return the initial phase state inside a control volume.
-     *
-     * \param vert The vertex
-     * \param globalIdx The index of the global vertex
      * \param globalPos The global position
      */
-    int initialPhasePresence(const Vertex &vert,
-                             int &globalIdx,
-                             const GlobalPosition &globalPos) const
+    PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
     {
-        return wPhaseOnly;
-    }
+        PrimaryVariables values(0.0);
+
+        const Scalar densityW = 1000.0;
+        values[pressureIdx] = 101300.0 + (this->fvGridGeometry().bBoxMax()[1] - globalPos[1])*densityW*9.81; // hydrostatic pressure
+        values[switch1Idx] = 283.13;
 
+        values.setState(wPhaseOnly);
 
+        return values;
+    }
 
 private:
-    // internal method for the initial condition (reused for the
-    // dirichlet conditions!)
-    void initial_(PrimaryVariables &values,
-                  const GlobalPosition &globalPos) const
-    {
-        Scalar densityW = 1000.0;
-        values[pressureIdx] = 101300.0 + (this->bBoxMax()[1] - globalPos[1])*densityW*9.81; // hydrostatic pressure
-        values[switch1Idx] = 283.13;
-    }
 
     static constexpr Scalar eps_ = 1e-6;
-    std::string name_;
 };
 } //end namespace
 
diff --git a/test/porousmediumflow/2p1c/implicit/steaminjectionspatialparams.hh b/test/porousmediumflow/2p1c/implicit/steaminjectionspatialparams.hh
index 43f02fc690c822b56ef00a58b59f5808f7a0a756..48a00ca88b29986d2095d11a6d8cc7ddcc25478c 100644
--- a/test/porousmediumflow/2p1c/implicit/steaminjectionspatialparams.hh
+++ b/test/porousmediumflow/2p1c/implicit/steaminjectionspatialparams.hh
@@ -64,34 +64,36 @@ SET_PROP(InjectionProblemSpatialParams, MaterialLaw)
 template<class TypeTag>
 class InjectionProblemSpatialParams : public ImplicitSpatialParams<TypeTag>
 {
-    typedef ImplicitSpatialParams<TypeTag> ParentType;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename Grid::ctype CoordScalar;
-    enum {
-        dim=GridView::dimension,
-        dimWorld=GridView::dimensionworld
-    };
-
-    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
-    typedef typename GridView::template Codim<0>::Entity Element;
-
-    typedef Dune::FieldMatrix<Scalar,dim,dim> FieldMatrix;
-
-
+    using ParentType = ImplicitSpatialParams<TypeTag>;
+
+    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
+    using MaterialLaw = typename GET_PROP_TYPE(TypeTag, MaterialLaw);
+
+    using MaterialLawParams = typename MaterialLaw::Params;
+    using CoordScalar = typename GridView::ctype;
+    using Element = typename GridView::template Codim<0>::Entity;
+    using SubControlVolume = typename GET_PROP_TYPE(TypeTag, SubControlVolume);
+    using ElementSolutionVector = typename GET_PROP_TYPE(TypeTag, ElementSolutionVector);
+
+    static constexpr int dim = GridView::dimension;
+    static constexpr int dimWorld = GridView::dimensionworld;
+    static constexpr int wPhaseIdx = FluidSystem::wPhaseIdx;
+
+    using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
+    using DimWorldMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
 public:
-    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
-    typedef typename MaterialLaw::Params MaterialLawParams;
+    using PermeabilityType = DimWorldMatrix;
 
     /*!
      * \brief The constructor
      *
      * \param gridView The grid view
      */
-    InjectionProblemSpatialParams(const GridView &gridView)
-        : ParentType(gridView)
+    InjectionProblemSpatialParams(const Problem& problem)
+    : ParentType(problem)
     {
         // set Van Genuchten Parameters
         materialParams_.setSwr(0.1);
@@ -101,18 +103,13 @@ public:
     }
 
     /*!
-     * \brief Apply the intrinsic permeability tensor to a pressure
-     *        potential gradient.
+     * \brief Returns the hydraulic conductivity \f$[m^2]\f$
      *
-     * \param element The current finite element
-     * \param fvElemGeom The current finite volume geometry of the element
-     * \param scvIdx The index of the sub-control volume
+     * \param globalPos The global position
      */
-    const FieldMatrix intrinsicPermeability(const Element &element,
-                                       const FVElementGeometry &fvElemGeom,
-                                       int scvIdx) const
+    DimWorldMatrix permeabilityAtPos(const GlobalPosition& globalPos) const
     {
-        FieldMatrix permMatrix(0.0);
+        DimWorldMatrix permMatrix(0.0);
 
         // intrinsic permeability
         permMatrix[0][0] = 1e-9;
@@ -124,78 +121,62 @@ public:
     /*!
      * \brief Define the porosity \f$[-]\f$ of the spatial parameters
      *
-     * \param element The finite element
-     * \param fvGeometry The finite volume geometry
-     * \param scvIdx The local index of the sub-control volume where
-     *                    the porosity needs to be defined
+     * \param globalPos The global position
      */
-    double porosity(const Element &element,
-                    const FVElementGeometry &fvGeometry,
-                    const int scvIdx) const
+    Scalar porosityAtPos(const GlobalPosition& globalPos) const
     {
         return 0.4;
     }
 
-
     /*!
-     * \brief return the parameter object for the Brooks-Corey material law which depends on the position
+     * \brief Returns the parameter object for the capillary-pressure/
+     *        saturation material law
      *
-     * \param element The current finite element
-     * \param fvGeometry The current finite volume geometry of the element
-     * \param scvIdx The index of the sub-control volume
+     * \param globalPos The global position
      */
-    const MaterialLawParams& materialLawParams(const Element &element,
-                                               const FVElementGeometry &fvGeometry,
-                                               const int scvIdx) const
+    const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const
     {
         return materialParams_;
     }
-
     /*!
      * \brief Returns the heat capacity \f$[J / (kg K)]\f$ of the rock matrix.
      *
      * This is only required for non-isothermal models.
      *
-     * \param element The finite element
-     * \param fvGeometry The finite volume geometry
-     * \param scvIdx The local index of the sub-control volume
+     * \param element The element
+     * \param scv The sub control volume
+     * \param elemSol The element solution vector
      */
-     Scalar solidHeatCapacity(const Element &element,
-                             const FVElementGeometry &fvGeometry,
-                             const int scvIdx) const
-    {
-        return 850.0; // specific heat capacity of granite [J / (kg K)]
-    }
+    Scalar solidHeatCapacity(const Element &element,
+                             const SubControlVolume& scv,
+                             const ElementSolutionVector& elemSol) const
+    { return 850.0; /*specific heat capacity of granite [J / (kg K)]*/ }
 
     /*!
      * \brief Returns the mass density \f$[kg / m^3]\f$ of the rock matrix.
      *
      * This is only required for non-isothermal models.
      *
-     * \param element The finite element
-     * \param fvGeometry The finite volume geometry
-     * \param scvIdx The local index of the sub-control volume
+     * \param element The element
+     * \param scv The sub control volume
+     * \param elemSol The element solution vector
      */
     Scalar solidDensity(const Element &element,
-                        const FVElementGeometry &fvGeometry,
-                        const int scvIdx) const
-    {
-        return 2650.0; // density of granite [kg/m^3]
-    }
+                        const SubControlVolume& scv,
+                        const ElementSolutionVector& elemSol) const
+    { return 2650; /*density of granite [kg/m^3]*/ }
 
     /*!
-     * \brief Returns the thermal conductivity \f$\mathrm{[W/(m K)]}\f$ of the porous material.
+     * \brief Returns the thermal conductivity \f$\mathrm{[W/(m K)]}\f$ of the solid
      *
-     * \param element The finite element
-     * \param fvGeometry The finite volume geometry
-     * \param scvIdx The local index of the sub-control volume
+     * \param element The element
+     * \param scv The sub control volume
+     * \param elemSol The element solution vector
      */
     Scalar solidThermalConductivity(const Element &element,
-                                    const FVElementGeometry &fvGeometry,
-                                    const int scvIdx) const
-    {
-        return 2.8;
-    }
+                                    const SubControlVolume& scv,
+                                    const ElementSolutionVector& elemSol) const
+    { return 2.8; }
 
 private:
     MaterialLawParams materialParams_;
diff --git a/test/porousmediumflow/2p1c/implicit/test_2p1c_fv.cc b/test/porousmediumflow/2p1c/implicit/test_2p1c_fv.cc
new file mode 100644
index 0000000000000000000000000000000000000000..94aafde415fa6cbe7771fdff0bf8dd5ad5607499
--- /dev/null
+++ b/test/porousmediumflow/2p1c/implicit/test_2p1c_fv.cc
@@ -0,0 +1,218 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief test for the 1pnc model
+ */
+ #include <config.h>
+
+ #include "steaminjectionproblem.hh"
+
+ #include <ctime>
+ #include <iostream>
+
+ #include <dune/common/parallel/mpihelper.hh>
+ #include <dune/common/timer.hh>
+ #include <dune/grid/io/file/dgfparser/dgfexception.hh>
+ #include <dune/grid/io/file/vtk.hh>
+ #include <dune/istl/io.hh>
+
+ #include <dumux/discretization/methods.hh>
+
+ #include <dumux/common/properties.hh>
+ #include <dumux/common/parameters.hh>
+ #include <dumux/common/valgrind.hh>
+ #include <dumux/common/dumuxmessage.hh>
+ #include <dumux/common/defaultusagemessage.hh>
+ #include <dumux/common/parameterparser.hh>
+
+ #include <dumux/porousmediumflow/compositional/privarswitchnewtoncontroller.hh>
+ #include <dumux/linear/seqsolverbackend.hh>
+ #include <dumux/nonlinear/newtonmethod.hh>
+
+ #include <dumux/assembly/fvassembler.hh>
+
+ #include <dumux/io/vtkoutputmodule.hh>
+
+ int main(int argc, char** argv) try
+ {
+     using namespace Dumux;
+
+     // define the type tag for this problem
+     using TypeTag = TTAG(TYPETAG);
+
+     ////////////////////////////////////////////////////////////
+     ////////////////////////////////////////////////////////////
+
+     // initialize MPI, finalize is done automatically on exit
+     const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv);
+
+     // print dumux start message
+     if (mpiHelper.rank() == 0)
+         DumuxMessage::print(/*firstCall=*/true);
+
+     // initialize parameter tree
+     Parameters::init(argc, argv);
+
+     //////////////////////////////////////////////////////////////////////
+     // try to create a grid (from the given grid file or the input file)
+     /////////////////////////////////////////////////////////////////////
+
+     using GridCreator = typename GET_PROP_TYPE(TypeTag, GridCreator);
+     GridCreator::makeGrid();
+     GridCreator::loadBalance();
+
+     ////////////////////////////////////////////////////////////
+     // run instationary non-linear problem on this grid
+     ////////////////////////////////////////////////////////////
+
+     // we compute on the leaf grid view
+     const auto& leafGridView = GridCreator::grid().leafGridView();
+
+     // create the finite volume grid geometry
+     using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+     auto fvGridGeometry = std::make_shared<FVGridGeometry>(leafGridView);
+     fvGridGeometry->update();
+
+     // the problem (initial and boundary conditions)
+     using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+     auto problem = std::make_shared<Problem>(fvGridGeometry);
+
+     // the solution vector
+     using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
+     SolutionVector x(fvGridGeometry->numDofs());
+     problem->applyInitialSolution(x);
+     auto xOld = x;
+
+     // the grid variables
+     using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables);
+     auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry);
+     gridVariables->init(x, xOld);
+
+     // get some time loop parameters
+     using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+     auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
+     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
+     auto maxDivisions = getParam<int>("TimeLoop.MaxTimeStepDivisions");
+     auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
+
+     // intialize the vtk output module
+     VtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name());
+     using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields);
+     VtkOutputFields::init(vtkWriter); //! Add model specific output fields
+     vtkWriter.write(0.0);
+
+     // instantiate time loop
+     auto timeLoop = std::make_shared<TimeLoop<Scalar>>(0.0, dt, tEnd);
+     timeLoop->setMaxTimeStepSize(maxDt);
+
+     // the assembler with time loop for instationary problem
+     using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
+     auto assembler = std::make_shared<Assembler>(problem, fvGridGeometry, gridVariables, timeLoop);
+
+     // the linear solver
+     using LinearSolver = ILU0BiCGSTABBackend<TypeTag>;
+     auto linearSolver = std::make_shared<LinearSolver>();
+
+     // the non-linear solver
+     using NewtonController = Dumux::PriVarSwitchNewtonController<TypeTag>;
+     auto newtonController = std::make_shared<NewtonController>(leafGridView.comm(), timeLoop);
+     NewtonMethod<NewtonController, Assembler, LinearSolver> nonLinearSolver(newtonController, assembler, linearSolver);
+
+     // time loop
+     timeLoop->start(); do
+     {
+         // set previous solution for storage evaluations
+         assembler->setPreviousSolution(xOld);
+
+         // try solving the non-linear system
+         for (int i = 0; i < maxDivisions; ++i)
+         {
+             // linearize & solve
+             auto converged = nonLinearSolver.solve(x);
+
+             if (converged)
+                 break;
+
+             if (!converged && i == maxDivisions-1)
+                 DUNE_THROW(Dune::MathError,
+                            "Newton solver didn't converge after "
+                            << maxDivisions
+                            << " time-step divisions. dt="
+                            << timeLoop->timeStepSize()
+                            << ".\nThe solutions of the current and the previous time steps "
+                            << "have been saved to restart files.");
+         }
+
+         // make the new solution the old solution
+         xOld = x;
+         gridVariables->advanceTimeStep();
+
+         // advance to the time loop to the next step
+         timeLoop->advanceTimeStep();
+
+         // write vtk output
+         vtkWriter.write(timeLoop->time());
+
+         // report statistics of this time step
+         timeLoop->reportTimeStep();
+
+         // set new dt as suggested by newton controller
+         timeLoop->setTimeStepSize(newtonController->suggestTimeStepSize(timeLoop->timeStepSize()));
+
+     } while (!timeLoop->finished());
+
+     timeLoop->finalize(leafGridView.comm());
+
+     ////////////////////////////////////////////////////////////
+     // finalize, print dumux message to say goodbye
+     ////////////////////////////////////////////////////////////
+
+     // print dumux end message
+     if (mpiHelper.rank() == 0)
+         DumuxMessage::print(/*firstCall=*/false);
+
+     return 0;
+
+ }
+ catch (Dumux::ParameterException &e)
+ {
+     std::cerr << std::endl << e << " ---> Abort!" << std::endl;
+     return 1;
+ }
+ catch (Dune::DGFException & e)
+ {
+     std::cerr << "DGF exception thrown (" << e <<
+                  "). Most likely, the DGF file name is wrong "
+                  "or the DGF file is corrupted, "
+                  "e.g. missing hash at end of file or wrong number (dimensions) of entries."
+                  << " ---> Abort!" << std::endl;
+     return 2;
+ }
+ catch (Dune::Exception &e)
+ {
+     std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl;
+     return 3;
+ }
+ catch (...)
+ {
+     std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl;
+     return 4;
+ }
diff --git a/test/porousmediumflow/2p1c/implicit/test_boxsteaminjection.cc b/test/porousmediumflow/2p1c/implicit/test_boxsteaminjection.cc
deleted file mode 100644
index bd83890846bb39f76a3e9233e83fa289156e7bfe..0000000000000000000000000000000000000000
--- a/test/porousmediumflow/2p1c/implicit/test_boxsteaminjection.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- *
- * \brief Test for the 2p1cni box model
- */
-#include "config.h"
-#include "steaminjectionproblem.hh"
-#include <dumux/common/start.hh>
-
-/*!
- * \brief Provides an interface for customizing error messages associated with
- *        reading in parameters.
- *
- * \param progName  The name of the program, that was tried to be started.
- * \param errorMsg  The error message that was issued by the start function.
- *                  Comprises the thing that went wrong and a general help message.
- */
-void usage(const char *progName, const std::string &errorMsg)
-{
-    if (errorMsg.size() > 0) {
-        std::string errorMessageOut = "\nUsage: ";
-        errorMessageOut += progName;
-        errorMessageOut += " [options]\n";
-        errorMessageOut += errorMsg;
-        errorMessageOut += "\n\nThe list of mandatory options for this program is:\n"
-                           "\t-TimeManager.TEnd              End of the simulation [s] \n"
-                           "\t-TimeManager.DtInitial         Initial timestep size [s] \n"
-                           "\t-Grid.UpperRight               coordinates of the upper right corner of the grid [m] \n"
-                           "\t-Grid.Cells                    Number of cells in respective coordinate directions\n"
-                           "\t-Problem.Name                  String for naming of the output files \n"
-                           "\n";
-
-        std::cout << errorMessageOut << std::endl;
-    }
-}
-
-////////////////////////
-// the main function
-////////////////////////
-int main(int argc, char** argv)
-{
-    typedef TTAG(InjectionBoxProblem) TypeTag;
-    return Dumux::start<TypeTag>(argc, argv, usage);
-}
diff --git a/test/porousmediumflow/2p1c/implicit/test_boxsteaminjection.input b/test/porousmediumflow/2p1c/implicit/test_boxsteaminjection.input
index 4696345154e120977b7f4c2d8377e28ec4cdfc07..59aa81a23af877876c9ffba67dd3c141602d507b 100644
--- a/test/porousmediumflow/2p1c/implicit/test_boxsteaminjection.input
+++ b/test/porousmediumflow/2p1c/implicit/test_boxsteaminjection.input
@@ -1,4 +1,4 @@
-[TimeManager]
+[TimeLoop]
 DtInitial = 50 # [s]
 TEnd = 300 # [s]
 
diff --git a/test/porousmediumflow/2p1c/implicit/test_ccsteaminjection.cc b/test/porousmediumflow/2p1c/implicit/test_ccsteaminjection.cc
deleted file mode 100644
index 1273bd90ede4491753202a2f9cfef6b72e669adc..0000000000000000000000000000000000000000
--- a/test/porousmediumflow/2p1c/implicit/test_ccsteaminjection.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- *
- * \brief Test for the 2p1cni cell-centered model
- */
-#include "config.h"
-#include "steaminjectionproblem.hh"
-#include <dumux/common/start.hh>
-
-/*!
- * \brief Provides an interface for customizing error messages associated with
- *        reading in parameters.
- *
- * \param progName  The name of the program, that was tried to be started.
- * \param errorMsg  The error message that was issued by the start function.
- *                  Comprises the thing that went wrong and a general help message.
- */
-void usage(const char *progName, const std::string &errorMsg)
-{
-    if (errorMsg.size() > 0) {
-        std::string errorMessageOut = "\nUsage: ";
-        errorMessageOut += progName;
-        errorMessageOut += " [options]\n";
-        errorMessageOut += errorMsg;
-        errorMessageOut += "\n\nThe list of mandatory options for this program is:\n"
-                           "\t-TimeManager.TEnd              End of the simulation [s] \n"
-                           "\t-TimeManager.DtInitial         Initial timestep size [s] \n"
-                           "\t-Grid.UpperRight               coordinates of the upper right corner of the grid [m] \n"
-                           "\t-Grid.Cells                    Number of cells in respective coordinate directions\n"
-                           "\t-Problem.Name                  String for naming of the output files \n"
-                           "\n";
-
-        std::cout << errorMessageOut << std::endl;
-    }
-}
-
-////////////////////////
-// the main function
-////////////////////////
-int main(int argc, char** argv)
-{
-    typedef TTAG(InjectionCCProblem) TypeTag;
-    return Dumux::start<TypeTag>(argc, argv, usage);
-}
diff --git a/test/porousmediumflow/2p1c/implicit/test_ccsteaminjection.input b/test/porousmediumflow/2p1c/implicit/test_ccsteaminjection.input
index c5b8d8556b1fd4b9c149baa9212b1684d3db858d..fabf21bed2ff303018d5c1d26fc55ec3f9f00e87 100644
--- a/test/porousmediumflow/2p1c/implicit/test_ccsteaminjection.input
+++ b/test/porousmediumflow/2p1c/implicit/test_ccsteaminjection.input
@@ -1,4 +1,4 @@
-[TimeManager]
+[TimeLoop]
 DtInitial = 50 # [s]
 TEnd = 300 # [s]