diff --git a/dumux/implicit/2pnc/2pncfluxvariables.hh b/dumux/implicit/2pnc/2pncfluxvariables.hh
new file mode 100644
index 0000000000000000000000000000000000000000..165dc8857d7537c259d4416e693764efe256e86e
--- /dev/null
+++ b/dumux/implicit/2pnc/2pncfluxvariables.hh
@@ -0,0 +1,415 @@
+// -*- 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 Contains the data which is required to calculate
+ *        all fluxes of components over a face of a finite volume for
+ *        the two-phase two-component model fully implicit model.
+ */
+#ifndef DUMUX_2PNC_FLUX_VARIABLES_HH
+#define DUMUX_2PNC_FLUX_VARIABLES_HH
+
+#include <dumux/common/math.hh>
+#include <dumux/common/spline.hh>
+
+#include "2pncproperties.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPNCModel
+ * \ingroup ImplicitFluxVariables
+ * \brief Contains the data which is required to calculate
+ *        all fluxes of components over a face of a finite volume for
+ *        the two-phase n-component fully implicit model.
+ *
+ * This means pressure and concentration gradients, phase densities at
+ * the integration point, etc.
+ */
+
+template <class TypeTag>
+class TwoPNCFluxVariables : public GET_PROP_TYPE(TypeTag, BaseFluxVariables)
+{
+	typedef typename GET_PROP_TYPE(TypeTag, BaseFluxVariables) BaseFluxVariables;
+    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, VolumeVariables) VolumeVariables;
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    enum {
+            dim = GridView::dimension,
+            dimWorld = GridView::dimensionworld,
+            numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+            numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
+          };
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+//     typedef typename FVElementGeometry::SubControlVolume SCV;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+    typedef Dune::FieldVector<CoordScalar, dimWorld> DimVector;
+    typedef Dune::FieldMatrix<CoordScalar, dim, dim> DimMatrix;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+            wPhaseIdx = FluidSystem::wPhaseIdx,
+            nPhaseIdx = FluidSystem::nPhaseIdx,
+            wCompIdx  = FluidSystem::wCompIdx,
+         };
+
+public:
+    /*!
+     * \brief The constructor
+     *
+     * \param problem The problem
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry in the fully implicit scheme
+     * \param fIdx The local index of the sub-control-volume face
+     * \param elemVolVars The volume variables of the current element
+     * \param onBoundary Evaluate flux at inner sub-control-volume face or on a boundary face
+     */
+    TwoPNCFluxVariables(const Problem &problem,
+                     const Element &element,
+                     const FVElementGeometry &fvGeometry,
+                     const int fIdx,
+                     const ElementVolumeVariables &elemVolVars,
+                     const bool onBoundary = false)
+    : BaseFluxVariables(problem, element, fvGeometry, fIdx, elemVolVars, onBoundary)
+    {
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            density_[phaseIdx] = Scalar(0);
+            molarDensity_[phaseIdx] = Scalar(0);
+            potentialGrad_[phaseIdx] = Scalar(0);
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            {
+            	massFractionGrad_[phaseIdx][compIdx] = Scalar(0);
+            	moleFractionGrad_[phaseIdx][compIdx] = Scalar(0);
+            }
+        }
+        calculateGradients_(problem, element, elemVolVars);
+        calculateVelocities_(problem, element, elemVolVars);
+        calculateporousDiffCoeff_(problem, element, elemVolVars);
+    };
+
+protected:
+    void calculateGradients_(const Problem &problem,
+                             const Element &element,
+                             const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate gradients
+        DimVector tmp(0.0);
+        for (int idx = 0;
+             idx < this->fvGeometry_.numScv;
+             idx++) // loop over adjacent vertices
+        {
+            // FE gradient at vertex idx
+            const DimVector &feGrad = face().grad[idx];
+
+            // compute sum of pressure gradients for each phase
+            for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+            {
+                // the pressure gradient
+                tmp = feGrad;
+                tmp *= elemVolVars[idx].pressure(phaseIdx); //FE grad times phase pressure
+                potentialGrad_[phaseIdx] += tmp;
+            }
+
+            // the concentration gradient of the non-wetting
+            // component in the wetting phase
+
+            for(int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            {
+                for(int compIdx = 0; compIdx < numComponents; ++compIdx)
+                {
+                    if(compIdx != phaseIdx) //No grad is needed for this case
+                    {
+                        tmp = feGrad;
+                        tmp *= elemVolVars[idx].fluidState().massFraction(phaseIdx, compIdx);
+                        massFractionGrad_[phaseIdx][compIdx] += tmp;
+
+                        tmp = feGrad;
+                        tmp *= elemVolVars[idx].fluidState().moleFraction(phaseIdx, compIdx);
+                        moleFractionGrad_[phaseIdx][compIdx] += tmp;
+                    }
+                }
+            }
+        }
+
+        // correct the pressure gradients by the hydrostatic
+        // pressure due to gravity
+        for (int phaseIdx=0; phaseIdx < numPhases; phaseIdx++)
+        {
+            int i = face().i;
+            int j = face().j;
+            Scalar fI = rhoFactor_(phaseIdx, i, elemVolVars);
+            Scalar fJ = rhoFactor_(phaseIdx, j, elemVolVars);
+            if (fI + fJ <= 0)
+                fI = fJ = 0.5; // doesn't matter because no phase is
+                               // present in both cells!
+            density_[phaseIdx] =
+                (fI*elemVolVars[i].density(phaseIdx) +
+                 fJ*elemVolVars[j].density(phaseIdx))
+                /
+                (fI + fJ);
+            // phase density
+            molarDensity_[phaseIdx]
+                =
+                (fI*elemVolVars[i].molarDensity(phaseIdx) +
+                 fJ*elemVolVars[j].molarDensity(phaseIdx))
+                /
+                (fI + fJ); //arithmetic averaging
+
+            tmp = problem.gravity();
+            tmp *= density_[phaseIdx];
+
+            potentialGrad_[phaseIdx] -= tmp;
+        }
+    }
+
+    Scalar rhoFactor_(int phaseIdx, int scvIdx, const ElementVolumeVariables &vDat)
+    {
+
+        static const Scalar eps = 1e-2;
+        const Scalar sat = vDat[scvIdx].density(phaseIdx);
+        if (sat > eps)
+            return 0.5;
+        if (sat <= 0)
+            return 0;
+
+        static const Dumux::Spline<Scalar> sp(0, eps, // x0, x1
+                                              0, 0.5, // y0, y1
+                                              0, 0); // m0, m1
+        return sp.eval(sat);
+    }
+
+    void calculateVelocities_(const Problem &problem,
+                              const Element &element,
+                              const ElementVolumeVariables &elemVolVars)
+    {
+        const SpatialParams &spatialParams = problem.spatialParams();
+        // multiply the pressure potential with the intrinsic
+        // permeability
+        DimMatrix K(0.0);
+
+        for (int phaseIdx=0; phaseIdx < numPhases; phaseIdx++)
+        {
+            auto K_i = spatialParams.intrinsicPermeability(element,this->fvGeometry_,face().i);
+            //K_i *= volVarsI.permFactor();
+
+            auto K_j = spatialParams.intrinsicPermeability(element,this->fvGeometry_,face().j);
+            //K_j *= volVarsJ.permFactor();
+
+            spatialParams.meanK(K,K_i,K_j);
+
+            K.mv(potentialGrad_[phaseIdx], Kmvp_[phaseIdx]);
+            KmvpNormal_[phaseIdx] = - (Kmvp_[phaseIdx] * face().normal);
+        }
+
+        // set the upstream and downstream vertices
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            upstreamIdx_[phaseIdx] = face().i;
+            downstreamIdx_[phaseIdx] = face().j;
+
+            if (KmvpNormal_[phaseIdx] < 0) {
+                std::swap(upstreamIdx_[phaseIdx],
+                          downstreamIdx_[phaseIdx]);
+            }
+        }
+    }
+
+    void calculateporousDiffCoeff_(const Problem &problem,
+                                   const Element &element,
+                                   const ElementVolumeVariables &elemVolVars)
+    {
+        const VolumeVariables &volVarsI = elemVolVars[face().i];
+        const VolumeVariables &volVarsJ = elemVolVars[face().j];
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            /* If there is no phase saturation on either side of the face
+                * no diffusion takes place */
+
+            if (volVarsI.saturation(phaseIdx) <= 0 ||
+                volVarsJ.saturation(phaseIdx) <= 0)
+                {
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                    {
+                        porousDiffCoeff_[phaseIdx][compIdx] = 0.0;
+                    }
+                }
+
+            else
+            {
+            // calculate tortuosity at the nodes i and j needed
+            // for porous media diffusion coefficient
+            Scalar tauI =  1.0/(volVarsI.porosity() * volVarsI.porosity()) *
+                            pow(volVarsI.porosity() * volVarsI.saturation(phaseIdx), 7.0/3);
+
+            Scalar tauJ =	1.0/(volVarsJ.porosity() * volVarsJ.porosity()) *
+                            pow(volVarsJ.porosity() * volVarsJ.saturation(phaseIdx), 7.0/3);
+            // Diffusion coefficient in the porous medium
+
+            // -> harmonic mean
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                {
+                    if(phaseIdx==compIdx)
+                        porousDiffCoeff_[phaseIdx][compIdx] = 0.0;
+                    else
+                    {
+                        porousDiffCoeff_[phaseIdx][compIdx] = harmonicMean(volVarsI.porosity() * volVarsI.saturation(phaseIdx) * tauI * volVarsI.diffCoeff(phaseIdx, compIdx),
+                                                                            volVarsJ.porosity() * volVarsJ.saturation(phaseIdx) * tauJ * volVarsJ.diffCoeff(phaseIdx, compIdx));
+                    }
+                }
+            }
+        }
+    }
+
+public:
+    /*!
+     * \brief Return the pressure potential multiplied with the
+     *        intrinsic permeability which goes from vertex i to
+     *        vertex j.
+     *
+     * Note that the length of the face's normal is the area of the
+     * face, so this is not the actual velocity by the integral of
+     * the velocity over the face's area. Also note that the phase
+     * mobility is not yet included here since this would require a
+     * decision on the upwinding approach (which is done in the
+     * model and/or local residual file).
+     * 
+     *   \param phaseIdx The phase index
+     */
+    Scalar KmvpNormal(int phaseIdx) const
+    { return KmvpNormal_[phaseIdx]; }
+
+    /*!
+     * \brief Return the pressure potential multiplied with the
+     *        intrinsic permeability as vector (for velocity output)
+     * 
+     *   \param phaseIdx The phase index
+     */
+    DimVector Kmvp(int phaseIdx) const
+    { return Kmvp_[phaseIdx]; }
+
+    /*!
+     * \brief Return the local index of the upstream control volume
+     *        for a given phase.
+     * 
+     *   \param phaseIdx The phase index
+     */
+    int upstreamIdx(int phaseIdx) const
+    { return upstreamIdx_[phaseIdx]; }
+
+    /*!
+     * \brief Return the local index of the downstream control volume
+     *        for a given phase.
+     * 
+     *   \param phaseIdx The phase index
+     */
+    int downstreamIdx(int phaseIdx) const
+    { return downstreamIdx_[phaseIdx]; }
+
+    /*!
+     * \brief The binary diffusion coefficient for each fluid phase.
+     * 
+     *   \param phaseIdx The phase index
+     *   \param compIdx The component index
+     */
+    Scalar porousDiffCoeff(int phaseIdx, int compIdx) const
+    { return porousDiffCoeff_[phaseIdx][compIdx];}
+
+    /*!
+     * \brief Return density \f$\mathrm{[kg/m^3]}\f$ of a phase at the integration
+     *        point.
+     * 
+     * \param phaseIdx The phase index
+     */
+    Scalar density(int phaseIdx) const
+    { return density_[phaseIdx]; }
+
+    /*!
+     * \brief Return molar density \f$\mathrm{[mol/m^3]}\f$ of a phase at the integration
+     *        point.
+     * 
+     * \param phaseIdx The phase index
+     */
+    Scalar molarDensity(int phaseIdx) const
+    { return molarDensity_[phaseIdx]; }
+
+    /*!
+     * \brief The concentration gradient of a component in a phase.
+     * 
+     * \param phaseIdx The phase index
+     * \param compIdx The component index
+     */
+    const DimVector &massFractionGrad(int phaseIdx, int compIdx) const
+    { return massFractionGrad_[phaseIdx][compIdx]; }
+
+    /*!
+     * \brief The molar concentration gradient of a component in a phase.
+     * 
+     * \param phaseIdx The phase index
+     * \param compIdx The component index
+     */
+    const DimVector &moleFractionGrad(int phaseIdx, int compIdx) const
+    { return moleFractionGrad_[phaseIdx][compIdx]; }
+
+    const SCVFace &face() const
+    {
+    if (this->onBoundary_)
+        return this->fvGeometry_.boundaryFace[this->faceIdx_];
+    else
+        return this->fvGeometry_.subContVolFace[this->faceIdx_];
+    }
+
+protected:
+
+    // gradients
+    DimVector potentialGrad_[numPhases];
+    DimVector massFractionGrad_[numPhases][numComponents];
+    DimVector moleFractionGrad_[numPhases][numComponents];
+
+    // density of each face at the integration point
+    Scalar density_[numPhases], molarDensity_[numPhases];
+
+    // intrinsic permeability times pressure potential gradient
+    DimVector Kmvp_[numPhases];
+    // projected on the face normal
+    Scalar KmvpNormal_[numPhases];
+
+    // local index of the upwind vertex for each phase
+    int upstreamIdx_[numPhases];
+    // local index of the downwind vertex for each phase
+    int downstreamIdx_[numPhases];
+
+    // the diffusion coefficient for the porous medium
+    Dune::FieldMatrix<Scalar, numPhases, numComponents> porousDiffCoeff_;
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/2pnc/2pncindices.hh b/dumux/implicit/2pnc/2pncindices.hh
new file mode 100644
index 0000000000000000000000000000000000000000..671917a14488bd82a5f8d39c79cdd28ba09a5364
--- /dev/null
+++ b/dumux/implicit/2pnc/2pncindices.hh
@@ -0,0 +1,80 @@
+// -*- 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 Defines the indices required for the two-phase n-component
+ *        fully implicit model.
+ */
+#ifndef DUMUX_2PNC_INDICES_HH
+#define DUMUX_2PNC_INDICES_HH
+#include "2pncproperties.hh"
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPNCModel
+ * \ingroup ImplicitIndices
+ * \brief Enumerates the formulations which the two-phase n-component model accepts.
+ *
+ */
+struct TwoPNCFormulation//TODO: This might need to be change similar to 2p2c indices
+{
+    enum {
+            plSg,
+            pgSl,
+            pnSw = pgSl,
+            pwSn = plSg
+          };
+};
+
+/*!
+ * \ingroup TwoPNCModel
+ * \ingroup ImplicitIndices
+ * \brief The indices for the isothermal two-phase n-component model.
+ *
+ * \tparam PVOffset The first index in a primary variable vector.
+ */
+template <class TypeTag, int PVOffset = 0>
+class TwoPNCIndices
+{
+	typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+public:
+	// Phase indices
+    static const int wPhaseIdx = FluidSystem::wPhaseIdx; //!< Index of the wetting phase
+    static const int nPhaseIdx = FluidSystem::nPhaseIdx; //!< Index of the non-wetting phase
+    // present phases (-> 'pseudo' primary variable)
+    static const int wPhaseOnly = 1; //!< Only the non-wetting phase is present
+    static const int nPhaseOnly = 2; //!< Only the wetting phase is present
+    static const int bothPhases = 3; //!< Both phases are present
+
+    // Primary variable indices
+    static const int pressureIdx = PVOffset + 0; //!< Index for wetting/non-wetting phase pressure (depending on formulation) in a solution vector
+    static const int switchIdx = PVOffset + 1; //!< Index of the either the saturation or the mass fraction of the non-wetting/wetting phase
+    // equation indices
+    static const int conti0EqIdx = PVOffset + 0; //!< Reference index for mass conservation equations.
+    static const int contiWEqIdx = conti0EqIdx + FluidSystem::wCompIdx; //!< Index of the mass conservation equation for the wetting phase major component
+    static const int contiNEqIdx = conti0EqIdx + FluidSystem::nCompIdx; //!< Index of the mass conservation equation for the non-wetting phase major component
+};
+
+// \}
+
+}
+
+#endif
diff --git a/dumux/implicit/2pnc/2pnclocalresidual.hh b/dumux/implicit/2pnc/2pnclocalresidual.hh
new file mode 100644
index 0000000000000000000000000000000000000000..43755d5731123449c1672ac274b78bff4002a172
--- /dev/null
+++ b/dumux/implicit/2pnc/2pnclocalresidual.hh
@@ -0,0 +1,370 @@
+// -*- 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 n-component mineralisation box model.
+ */
+
+#ifndef DUMUX_2PNC_LOCAL_RESIDUAL_BASE_HH
+#define DUMUX_2PNC_LOCAL_RESIDUAL_BASE_HH
+
+#include "2pncproperties.hh"
+#include "2pncvolumevariables.hh"
+#include <dumux/nonlinear/newtoncontroller.hh>
+
+#include <iostream>
+#include <vector>
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPNCModel
+ * \ingroup ImplicitLocalResidual
+ * \brief Element-wise calculation of the Jacobian matrix for problems
+ *        using the two-phase n-component fully implicit box model.
+ *
+ * This class is used to fill the gaps in ImplicitLocalResidual for the two-phase n-component flow.
+ */
+template<class TypeTag>
+class TwoPNCLocalResidual: public GET_PROP_TYPE(TypeTag, BaseLocalResidual)
+{
+protected:
+    typedef TwoPNCLocalResidual<TypeTag> ThisType;
+    typedef typename GET_PROP_TYPE(TypeTag, LocalResidual) Implementation;
+    typedef BoxLocalResidual<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementSolutionVector) ElementSolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+
+    typedef CompositionalFluidState<Scalar, FluidSystem> FluidState;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    enum
+    {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld,
+
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+        numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
+
+        replaceCompEqIdx = GET_PROP_VALUE(TypeTag, ReplaceCompEqIdx),
+
+        pressureIdx = Indices::pressureIdx,
+        switchIdx = Indices::switchIdx,
+
+        wPhaseIdx = FluidSystem::wPhaseIdx,
+        nPhaseIdx = FluidSystem::nPhaseIdx,
+
+        wCompIdx = FluidSystem::wCompIdx,
+        nCompIdx = FluidSystem::nCompIdx,
+
+        conti0EqIdx = Indices::conti0EqIdx,
+
+        wPhaseOnly = Indices::wPhaseOnly,
+        nPhaseOnly = Indices::nPhaseOnly,
+        bothPhases = Indices::bothPhases,
+
+        plSg = TwoPNCFormulation::plSg,
+        pgSl = TwoPNCFormulation::pgSl,
+        formulation = GET_PROP_VALUE(TypeTag, Formulation)
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, VolumeVariables) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::ctype CoordScalar;
+
+
+public:
+    /*!
+     * \brief Constructor. Sets the upwind weight.
+     */
+    TwoPNCLocalResidual()
+    {
+        // retrieve the upwind weight for the mass conservation equations. Use the value
+        // specified via the property system as default, and overwrite
+        // it by the run-time parameter from the Dune::ParameterTree
+        massUpwindWeight_ = GET_PARAM_FROM_GROUP(TypeTag, Scalar, Implicit, MassUpwindWeight);
+    };
+
+    /*!
+     * \brief Evaluate the storage term of the current solution in a
+     *        single phase.
+     *
+     * \param element The element
+     * \param phaseIdx The index of the fluid phase
+     */
+    void evalPhaseStorage(const Element &element, int phaseIdx)
+    {
+        FVElementGeometry fvGeometry;
+        fvGeometry.update(this->gridView_(), element);
+        ElementBoundaryTypes bcTypes;
+        bcTypes.update(this->problem_(), element, fvGeometry);
+        ElementVolumeVariables volVars;
+        volVars.update(this->problem_(), element, fvGeometry, false);
+
+        this->residual_.resize(fvGeometry.numScv);
+        this->residual_ = 0;
+
+        this->elemPtr_ = &element;
+        this->fvElemGeomPtr_ = &fvGeometry;
+        this->bcTypesPtr_ = &bcTypes;
+        this->prevVolVarsPtr_ = 0;
+        this->curVolVarsPtr_ = &volVars;
+        evalPhaseStorage_(phaseIdx);
+    }
+
+    /*!
+     * \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, 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 fluid components in the fluid phases
+        storage = 0;
+        for (unsigned int phaseIdx = 0; phaseIdx < numPhases /*+ numSPhases*/; ++phaseIdx)
+        {
+            //if(phaseIdx< numPhases)
+            //{
+                for (unsigned int compIdx = 0; compIdx < numComponents; ++compIdx) //H2O, Air, Salt
+                {
+                    int eqIdx = conti0EqIdx + compIdx;
+                    if (replaceCompEqIdx != eqIdx)
+                    {
+                        storage[eqIdx] += volVars.molarDensity(phaseIdx)
+                                        * volVars.saturation(phaseIdx)
+                                        * volVars.fluidState().moleFraction(phaseIdx, compIdx)
+                                        * volVars.porosity();
+                    }
+                    else
+                    {
+                        storage[replaceCompEqIdx] += volVars.molarDensity(phaseIdx)
+                                                * volVars.saturation(phaseIdx)
+                                                * volVars.porosity();
+                    }
+                }
+        }
+         Valgrind::CheckDefined(storage);
+    }
+    /*!
+     * \brief Evaluates the total flux of all conservation quantities
+     *        over a face of a sub-control volume.
+     *
+     * \param flux The flux over the sub-control-volume face for each component
+     * \param fIdx The index of the sub-control-volume face
+     * \param onBoundary Evaluate flux at inner sub-control-volume face or on a boundary face
+     */
+    void computeFlux(PrimaryVariables &flux, const int fIdx, bool onBoundary = false) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                      this->element_(),
+                      this->fvGeometry_(),
+                      fIdx,
+                      this->curVolVars_(),
+                      onBoundary);
+
+        flux = 0;
+        asImp_()->computeAdvectiveFlux(flux, fluxVars);
+        asImp_()->computeDiffusiveFlux(flux, fluxVars);
+        Valgrind::CheckDefined(flux);
+    }
+    /*!
+     * \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
+    {
+        ////////
+        // advective fluxes of all components in all phases
+        ////////
+        for (unsigned 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));
+
+         for (unsigned int compIdx = 0; compIdx < numComponents; ++compIdx)
+         {
+         // add advective flux of current component in current
+         // phase
+            unsigned int eqIdx = conti0EqIdx + compIdx;
+            
+         if (eqIdx != replaceCompEqIdx)
+         {
+            // upstream vertex
+            flux[eqIdx] += fluxVars.KmvpNormal(phaseIdx)
+                        * (massUpwindWeight_
+                            * up.mobility(phaseIdx)
+                            * up.molarDensity(phaseIdx)
+                            * up.fluidState().moleFraction(phaseIdx, compIdx)
+                        +
+                            (1.0 - massUpwindWeight_)
+                            * dn.mobility(phaseIdx)
+                            * dn.molarDensity(phaseIdx)
+                            * dn.fluidState().moleFraction(phaseIdx, compIdx));
+
+            Valgrind::CheckDefined(fluxVars.KmvpNormal(phaseIdx));
+            Valgrind::CheckDefined(up.molarDensity(phaseIdx));
+            Valgrind::CheckDefined(dn.molarDensity(phaseIdx));
+         }
+         else
+         {
+         flux[replaceCompEqIdx] += fluxVars.KmvpNormal(phaseIdx)
+                                * (massUpwindWeight_
+                                    * up.molarDensity(phaseIdx)
+                                    * up.mobility(phaseIdx)
+                                    +
+                                    (1.0 - massUpwindWeight_)
+                                    * dn.molarDensity(phaseIdx)
+                                    * dn.mobility(phaseIdx));
+
+
+         Valgrind::CheckDefined(fluxVars.KmvpNormal(phaseIdx));
+         Valgrind::CheckDefined(up.molarDensity(phaseIdx));
+         Valgrind::CheckDefined(dn.molarDensity(phaseIdx));
+         }
+         }
+       }
+     }
+
+    /*!
+     * \brief Evaluates the diffusive mass flux of all components over
+     *        a face of a sub-control volume.
+     *
+     * \param flux The flux over the sub-control-volume face for each component
+     * \param fluxVars The flux variables at the current sub-control-volume face
+     */
+    void computeDiffusiveFlux(PrimaryVariables &flux, const FluxVariables &fluxVars) const
+    {
+        //Loop calculates the diffusive flux for every component in a phase. The amount of moles of a component
+        //(eg Air in liquid) in a phase
+        //which is not the main component (eg. H2O in the liquid phase) moved from i to j equals the amount of moles moved
+        //from the main component in a phase (eg. H2O in the liquid phase) from j to i. So two fluxes in each component loop
+        // are calculated in the same phase.
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            {
+                //add diffusive fluxes only to the component balances
+                if (replaceCompEqIdx != (conti0EqIdx + compIdx))
+                {
+                    Scalar diffCont = - fluxVars.porousDiffCoeff(phaseIdx ,compIdx)
+                                        * fluxVars.molarDensity(phaseIdx)
+                                        * (fluxVars.moleFractionGrad(phaseIdx, compIdx)
+                                            * fluxVars.face().normal);
+                    flux[conti0EqIdx + compIdx] += diffCont;
+                    flux[conti0EqIdx + phaseIdx] -= diffCont;
+                }
+            }
+    }
+
+    /*!
+     * \brief Evaluates the source term
+     *
+     * \param source The source/sink in the sub-control volume
+     * \param scvIdx The index of the sub-control volume
+     *
+     * Be careful what you use, mole or mass fraction! Think of the units!
+     * If a total mass balance is used, the sum of both components has to be specified as source.
+     */
+    void computeSource(PrimaryVariables &source, int scvIdx)
+    {
+        this->problem_().solDependentSource(source,
+                                        this->element_(),
+                                        this->fvGeometry_(),
+                                        scvIdx,
+                                            this->curVolVars_());
+        
+        Valgrind::CheckDefined(source);
+    }
+
+
+protected:
+
+    void evalPhaseStorage_(int phaseIdx)
+    {
+        // evaluate the storage terms of a single phase
+        for (int i=0; i < this->fvGeometry_().numScv; i++) 
+        {
+            PrimaryVariables &result = this->residual_[i];
+            const ElementVolumeVariables &elemVolVars = this->curVolVars_();
+            const VolumeVariables &volVars = elemVolVars[i];
+
+            // compute storage term of all fluid components within all phases
+            result = 0;
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            {
+                result[conti0EqIdx + compIdx] += volVars.density(phaseIdx)
+                                * volVars.saturation(phaseIdx)
+                                * volVars.fluidState().massFraction(phaseIdx, compIdx)
+                                * volVars.porosity();
+            }
+            result *= this->fvGeometry_().subContVol[i].volume;
+        }
+    }
+
+    Implementation *asImp_()
+    { return static_cast<Implementation *> (this); }
+    const Implementation *asImp_() const
+    { return static_cast<const Implementation *> (this); }
+
+public:
+   Scalar massUpwindWeight_;
+};
+
+} // end namespace
+
+#endif
diff --git a/dumux/implicit/2pnc/2pncmodel.hh b/dumux/implicit/2pnc/2pncmodel.hh
new file mode 100644
index 0000000000000000000000000000000000000000..4d6e779d08aad9dd4af9cd7e5ecebc819daa3b8a
--- /dev/null
+++ b/dumux/implicit/2pnc/2pncmodel.hh
@@ -0,0 +1,819 @@
+// -*- 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 Adaption of the fully implicit box scheme to the two-phase n-component flow model.
+*/
+
+#ifndef DUMUX_2PNC_MODEL_HH
+#define DUMUX_2PNC_MODEL_HH
+
+#include <dune/common/version.hh>
+// #include <dumux/material/constants.hh>
+
+#include "2pncproperties.hh"
+#include "2pncindices.hh"
+#include "2pnclocalresidual.hh"
+#include <dumux/implicit/common/implicitvelocityoutput.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup TwoPNCModel
+ * \brief Adaption of the fully implicit scheme to the
+ *        two-phase n-component fully implicit model.
+ *
+ * This model implements two-phase n-component flow of two compressible and
+ * partially miscible fluids \f$\alpha \in \{ w, n \}\f$ composed of the n components
+ * \f$\kappa \in \{ w, a,\cdots \}\f$. The standard multiphase Darcy
+ * approach is used as the equation for the conservation of momentum:
+ * \f[
+ v_\alpha = - \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K}
+ \left(\text{grad}\, p_\alpha - \varrho_{\alpha} \mbox{\bf g} \right)
+ * \f]
+ *
+ * By inserting this into the equations for the conservation of the
+ * components, one gets one transport equation for each component
+ * \f{eqnarray}
+ && \phi \frac{\partial (\sum_\alpha \varrho_\alpha X_\alpha^\kappa S_\alpha )}
+ {\partial t}
+ - \sum_\alpha  \text{div} \left\{ \varrho_\alpha X_\alpha^\kappa
+ \frac{k_{r\alpha}}{\mu_\alpha} \mbox{\bf K}
+ (\text{grad}\, p_\alpha - \varrho_{\alpha}  \mbox{\bf g}) \right\}
+ \nonumber \\ \nonumber \\
+    &-& \sum_\alpha \text{div} \left\{{\bf D_{\alpha, pm}^\kappa} \varrho_{\alpha} \text{grad}\, X^\kappa_{\alpha} \right\}
+ - \sum_\alpha q_\alpha^\kappa = 0 \qquad \kappa \in \{w, a,\cdots \} \, ,
+ \alpha \in \{w, g\}
+ \f}
+ *
+ * All equations are discretized using a vertex-centered finite volume (box)
+ * or cell-centered finite volume scheme (this is not done for 2pnc approach yet, however possible) as  
+ * spatial and the implicit Euler method as time discretization.
+ *
+ * By using constitutive relations for the capillary pressure \f$p_c =
+ * p_n - p_w\f$ and relative permeability \f$k_{r\alpha}\f$ and taking
+ * advantage of the fact that \f$S_w + S_n = 1\f$ and \f$X^\kappa_w + X^\kappa_n = 1\f$, the number of
+ * unknowns can be reduced to number of components.
+ *
+ * The used primary variables are, like in the two-phase model, either \f$p_w\f$ and \f$S_n\f$
+ * or \f$p_n\f$ and \f$S_w\f$. The formulation which ought to be used can be
+ * specified by setting the <tt>Formulation</tt> property to either
+ * TwoPTwoCIndices::pWsN or TwoPTwoCIndices::pNsW. By
+ * default, the model uses \f$p_w\f$ and \f$S_n\f$.
+ *
+ * Moreover, the second primary variable depends on the phase state, since a
+ * primary variable switch is included. The phase state is stored for all nodes
+ * of the system. The model is uses mole fractions.
+ *Following cases can be distinguished:
+ * <ul>
+ *  <li> Both phases are present: The saturation is used (either \f$S_n\f$ or \f$S_w\f$, dependent on the chosen <tt>Formulation</tt>),
+ *      as long as \f$ 0 < S_\alpha < 1\f$</li>.
+ *  <li> Only wetting phase is present: The mass fraction of, e.g., air in the wetting phase \f$X^a_w\f$ is used,
+ *      as long as the maximum mass fraction is not exceeded (\f$X^a_w<X^a_{w,max}\f$)</li>
+ *  <li> Only non-wetting phase is present: The mass fraction of, e.g., water in the non-wetting phase, \f$X^w_n\f$, is used,
+ *      as long as the maximum mass fraction is not exceeded (\f$X^w_n<X^w_{n,max}\f$)</li>
+ * </ul>
+ */
+
+template<class TypeTag>
+class TwoPNCModel: public GET_PROP_TYPE(TypeTag, BaseModel)
+{
+    typedef TwoPNCModel<TypeTag> ThisType;
+    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, ElementBoundaryTypes) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, VertexMapper) VertexMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementMapper) ElementMapper;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    typedef Dumux::Constants<Scalar> Constant;
+
+    enum {
+            dim = GridView::dimension,
+            dimWorld = GridView::dimensionworld,
+
+            numEq = GET_PROP_VALUE(TypeTag, NumEq),
+            numPhases = GET_PROP_VALUE(TypeTag, NumPhases),
+            numComponents = GET_PROP_VALUE(TypeTag, NumComponents),
+            numMajorComponents = GET_PROP_VALUE(TypeTag, NumMajorComponents),
+
+            pressureIdx = Indices::pressureIdx,
+            switchIdx = Indices::switchIdx,
+
+            wPhaseIdx = Indices::wPhaseIdx,
+            nPhaseIdx = Indices::nPhaseIdx,
+
+            wCompIdx = FluidSystem::wCompIdx,
+            nCompIdx = FluidSystem::nCompIdx,
+
+            wPhaseOnly = Indices::wPhaseOnly,
+            nPhaseOnly = Indices::nPhaseOnly,
+            bothPhases = Indices::bothPhases,
+
+            plSg = TwoPNCFormulation::plSg,
+            pgSl = TwoPNCFormulation::pgSl,
+            formulation = GET_PROP_VALUE(TypeTag, Formulation),
+            useElectrochem = GET_PROP_VALUE(TypeTag, useElectrochem)
+          };
+
+    typedef CompositionalFluidState<Scalar, FluidSystem> FluidState;
+
+    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::FieldVector<Scalar, dimWorld> GlobalPosition;
+    typedef typename GridView::ctype CoordScalar;
+    typedef Dune::FieldMatrix<CoordScalar, dimWorld, dimWorld> Tensor;
+    typedef Dune::FieldVector<Scalar, numPhases> PhasesVector;
+
+    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);
+
+        unsigned numDofs = this->numDofs();
+
+        staticDat_.resize(numDofs);
+
+        setSwitched_(false);
+
+        ElementIterator eIt = this->gridView_().template begin<0>();
+        ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; eIt != elemEndIt; ++eIt)
+        {
+            if (!isBox) // i.e. cell-centered discretization
+            {
+#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 4)
+                int eIdxGlobal = this->dofMapper().index(*eIt);
+#else
+                int eIdxGlobal = this->dofMapper().map(*eIt);
+#endif
+                const GlobalPosition &globalPos = eIt->geometry().center();
+
+                // initialize phase presence
+                staticDat_[eIdxGlobal].phasePresence
+                    = this->problem_().initialPhasePresence(*(this->gridView_().template begin<dim>()),
+                                                            eIdxGlobal, globalPos);
+                staticDat_[eIdxGlobal].wasSwitched = false;
+
+                staticDat_[eIdxGlobal].oldPhasePresence
+                    = staticDat_[eIdxGlobal].phasePresence;
+            }
+        }
+
+        if (isBox) // i.e. vertex-centered discretization
+        {
+            VertexIterator vIt = this->gridView_().template begin<dim> ();
+            const VertexIterator &vEndIt = this->gridView_().template end<dim> ();
+            for (; vIt != vEndIt; ++vIt)
+            {
+#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 4)
+                int vIdxGlobal = this->dofMapper().index(*vIt);
+#else
+                int vIdxGlobal = this->dofMapper().map(*vIt);
+#endif
+                const GlobalPosition &globalPos = vIt->geometry().corner(0);
+
+                // initialize phase presence
+                staticDat_[vIdxGlobal].phasePresence
+                    = this->problem_().initialPhasePresence(*vIt, vIdxGlobal,
+                                                            globalPos);
+                staticDat_[vIdxGlobal].wasSwitched = false;
+
+                staticDat_[vIdxGlobal].oldPhasePresence
+                    = staticDat_[vIdxGlobal].phasePresence;
+            }
+        }
+    }
+
+    /*!
+     * \brief Compute the total storage of all conservation quantities in one phase
+     *
+     * \param storage Contains the storage of each component in one phase
+     * \param phaseIdx The phase index
+     */
+    void globalPhaseStorage(PrimaryVariables &storage, int phaseIdx)
+    {
+        storage = 0;
+
+        ElementIterator eIt = this->gridView_().template begin<0>();
+        const ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; eIt != elemEndIt; ++eIt)
+        {
+            if(eIt->partitionType() == Dune::InteriorEntity)
+            {
+              this->localResidual().evalPhaseStorage(*eIt, phaseIdx); 
+              
+              for (unsigned int i = 0; i < this->localResidual().storageTerm().size(); ++i)
+                    storage += this->localResidual().storageTerm()[i];
+            }
+        }
+
+        this->gridView_().comm().sum(storage);
+    }
+
+    /*!
+     * \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 vertex.
+     *
+     * \param globalVertexIdx The global vertex index
+     * \param oldSol Evaluate function with solution of current or previous time step
+     */
+    int phasePresence(int globalVertexIdx, bool oldSol) const
+    {
+        return oldSol ? staticDat_[globalVertexIdx].oldPhasePresence
+                : staticDat_[globalVertexIdx].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<Scalar, 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 *currentDensity = writer.allocateManagedBuffer (numDofs);
+        ScalarField *reactionSourceH2O = writer.allocateManagedBuffer (numDofs);
+        ScalarField *reactionSourceO2 = writer.allocateManagedBuffer (numDofs);
+
+        ScalarField *Sg            = writer.allocateManagedBuffer (numDofs);
+        ScalarField *Sl            = writer.allocateManagedBuffer (numDofs);
+        ScalarField *pg            = writer.allocateManagedBuffer (numDofs);
+        ScalarField *pl            = writer.allocateManagedBuffer (numDofs);
+        ScalarField *pc            = writer.allocateManagedBuffer (numDofs);
+        ScalarField *rhoL          = writer.allocateManagedBuffer (numDofs);
+        ScalarField *rhoG          = writer.allocateManagedBuffer (numDofs);
+        ScalarField *mobL          = writer.allocateManagedBuffer (numDofs);
+        ScalarField *mobG          = writer.allocateManagedBuffer (numDofs);
+        ScalarField *temperature   = writer.allocateManagedBuffer (numDofs);
+        ScalarField *poro          = writer.allocateManagedBuffer (numDofs);
+        ScalarField *boxVolume     = writer.allocateManagedBuffer (numDofs);
+        VectorField *velocityN = writer.template allocateManagedBuffer<double, dim>(numDofs);
+        VectorField *velocityW = 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)
+            {
+                (*velocityN)[i] = Scalar(0);
+                (*velocityW)[i] = Scalar(0);
+            }
+        }
+
+        ScalarField *moleFraction[numPhases][numComponents];
+        for (int i = 0; i < numPhases; ++i)
+            for (int j = 0; j < numComponents; ++j)
+                moleFraction[i][j] = writer.allocateManagedBuffer(numDofs);
+
+        ScalarField *molarity[numComponents];
+        for (int j = 0; j < numComponents ; ++j)
+            molarity[j] = writer.allocateManagedBuffer(numDofs);
+
+        ScalarField *Perm[dim];
+        for (int j = 0; j < dim; ++j) //Permeability only in main directions xx and yy
+            Perm[j] = writer.allocateManagedBuffer(numDofs);
+
+        *boxVolume = 0;
+
+        unsigned numElements = this->gridView_().size(0);
+        ScalarField *rank =
+                writer.allocateManagedBuffer (numElements);
+
+        FVElementGeometry fvGeometry;
+        VolumeVariables volVars;
+        ElementVolumeVariables elemVolVars;
+
+        ElementIterator eIt = this->gridView_().template begin<0>();
+        ElementIterator eEndIt = this->gridView_().template end<0>();
+        for (; eIt != eEndIt; ++eIt)
+        {
+            int idx = this->problem_().elementMapper().map(*eIt);
+            (*rank)[idx] = this->gridView_().comm().rank();
+            fvGeometry.update(this->gridView_(), *eIt);
+
+            elemVolVars.update(this->problem_(),
+                               *eIt,
+                               fvGeometry,
+                               false /* oldSol? */);
+
+#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 4)
+            int numVerts = eIt->subEntities(dim);
+#else
+            int numVerts = eIt->template count<dim> ();
+#endif
+            for (int i = 0; i < numVerts; ++i)
+            {
+                int globalIdx = this->vertexMapper().map(*eIt, i, dim);
+                volVars.update(sol[globalIdx],
+                               this->problem_(),
+                               *eIt,
+                               fvGeometry,
+                               i,
+                               false);
+
+                GlobalPosition globalPos = fvGeometry.subContVol[i].global;
+                //Scalar zmax = this->problem_().bBoxMax()[dim-1];
+                (*Sg)[globalIdx]             = volVars.saturation(nPhaseIdx);
+                (*Sl)[globalIdx]             = volVars.saturation(wPhaseIdx);
+                (*pg)[globalIdx]             = volVars.pressure(nPhaseIdx);
+                (*pl)[globalIdx]             = volVars.pressure(wPhaseIdx);
+                (*pc)[globalIdx]             = volVars.capillaryPressure();
+                (*rhoL)[globalIdx]           = volVars.fluidState().density(wPhaseIdx);
+                (*rhoG)[globalIdx]           = volVars.fluidState().density(nPhaseIdx);
+                (*mobL)[globalIdx]           = volVars.mobility(wPhaseIdx);
+                (*mobG)[globalIdx]           = volVars.mobility(nPhaseIdx);
+                (*boxVolume)[globalIdx]     += fvGeometry.subContVol[i].volume;
+                (*poro)[globalIdx]           = volVars.porosity();
+
+                if(useElectrochem){
+
+                    //for electrochemistry output we need elemVolVars
+                    elemVolVars.update(this->problem_(), *eIt, fvGeometry,/*oldSol=*/false);
+
+                    //reactionSource Output
+                    PrimaryVariables source;
+                    this->problem_().solDependentSource(source, *eIt, fvGeometry, i, elemVolVars);
+
+                    (*reactionSourceH2O)[globalIdx] = source[wPhaseIdx];
+                    (*reactionSourceO2)[globalIdx] = source[numComponents-1];
+
+                    //Current Output
+                    (*currentDensity)[globalIdx] = -1.0*source[numComponents-1]*4*Constant::F;
+                    //recorrection of the area for output
+                    Scalar gridYMin = GET_RUNTIME_PARAM(TypeTag, Scalar, Grid.yMin);
+                    Scalar gridYMax = GET_RUNTIME_PARAM(TypeTag, Scalar, Grid.yMax);
+                    Scalar nCellsY  = GET_RUNTIME_PARAM(TypeTag, Scalar, Grid.CellsY);
+
+                    Scalar lengthBox= (gridYMax - gridYMin)/nCellsY;
+
+                    (*currentDensity)[globalIdx] = (*currentDensity)[globalIdx]/2*lengthBox/10000; //i in [A/cm^2], cf. paper Oliver
+                }
+
+                (*temperature)[globalIdx]    = volVars.temperature();
+                
+                for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+                    for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                    {
+                        (*moleFraction[phaseIdx][compIdx])[globalIdx]= volVars.fluidState().moleFraction(phaseIdx,compIdx);
+
+                        Valgrind::CheckDefined((*moleFraction[phaseIdx][compIdx])[globalIdx]);
+
+                    }
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                    (*molarity[compIdx])[globalIdx] = (volVars.fluidState().molarity(wPhaseIdx, compIdx));
+
+                Tensor K = perm_(this->problem_().spatialParams().intrinsicPermeability(*eIt, fvGeometry, i));
+
+                for (int j = 0; j<dim; ++j)
+                    (*Perm[j])[globalIdx] = K[j][j] /* volVars.permFactor()*/;
+            };
+
+            // velocity output
+            if(velocityOutput.enableOutput()){
+                velocityOutput.calculateVelocity(*velocityW, elemVolVars, fvGeometry, *eIt, wPhaseIdx);
+                velocityOutput.calculateVelocity(*velocityN, elemVolVars, fvGeometry, *eIt, nPhaseIdx);
+            }
+
+        } // loop over element
+
+        writer.attachVertexData(*Sg, "Sg");
+        writer.attachVertexData(*Sl, "Sl");
+        writer.attachVertexData(*pg, "pg");
+        writer.attachVertexData(*pl, "pl");
+        writer.attachVertexData(*pc, "pc");
+        writer.attachVertexData(*rhoL, "rhoL");
+        writer.attachVertexData(*rhoG, "rhoG");
+        writer.attachVertexData(*mobL, "mobL");
+        writer.attachVertexData(*mobG, "mobG");
+        writer.attachVertexData(*poro, "porosity");
+        writer.attachVertexData(*temperature, "temperature");
+        writer.attachVertexData(*boxVolume, "boxVolume");
+
+        if(useElectrochem){
+            writer.attachVertexData(*reactionSourceH2O, "reactionSourceH2O [mol/(sm^2)]");
+            writer.attachVertexData(*reactionSourceO2, "reactionSourceO2 [mol/(sm^2)]");
+            writer.attachVertexData(*currentDensity, "currentDensity [A/cm^2]");
+        }
+
+        writer.attachVertexData(*Perm[0], "Kxx");
+        if (dim >= 2)
+            writer.attachVertexData(*Perm[1], "Kyy");
+        if (dim == 3)
+            writer.attachVertexData(*Perm[2], "Kzz");
+
+        for (int i = 0; i < numPhases; ++i)
+        {
+            for (int j = 0; j < numComponents; ++j)
+            {
+                std::ostringstream oss;
+                oss << "x"
+                    << FluidSystem::componentName(j)
+                    << FluidSystem::phaseName(i);
+                writer.attachVertexData(*moleFraction[i][j], oss.str().c_str());
+            }
+        }
+
+        for (int j = 0; j < numComponents; ++j)
+        {
+            std::ostringstream oss;
+            oss << "m^w_"
+                << FluidSystem::componentName(j);
+            writer.attachVertexData(*molarity[j], oss.str().c_str());
+        }
+
+        if (velocityOutput.enableOutput()) // check if velocity output is demanded
+        {
+            writer.attachDofData(*velocityW,  "velocityW", isBox, dim);
+            writer.attachDofData(*velocityN,  "velocityN", 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
+     */
+    template<class Entity>
+    void serializeEntity(std::ostream &outStream, const Entity &entity)
+    {
+        // write primary variables
+        ParentType::serializeEntity(outStream, entity);
+
+        int vertIdx = this->dofMapper().map(entity);
+        if (!outStream.good())
+            DUNE_THROW(Dune::IOError, "Could not serialize vertex " << vertIdx);
+
+        outStream << staticDat_[vertIdx].phasePresence << " ";
+    }
+
+    /*!
+     * \brief Reads the current solution for a vertex from a restart
+     *        file.
+     *
+     * \param inStream The input stream of one vertex from the restart file
+     * \param entity The Entity
+     */
+    template<class Entity>
+    void deserializeEntity(std::istream &inStream, const Entity &entity)
+    {
+        // read primary variables
+        ParentType::deserializeEntity(inStream, entity);
+
+        // read phase presence
+        int vertIdx = this->dofMapper().map(entity);
+        if (!inStream.good())
+            DUNE_THROW(Dune::IOError,
+                       "Could not deserialize vertex " << vertIdx);
+
+        inStream >> staticDat_[vertIdx].phasePresence;
+        staticDat_[vertIdx].oldPhasePresence
+                = staticDat_[vertIdx].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;
+
+        for (unsigned i = 0; i < staticDat_.size(); ++i)
+            staticDat_[i].visited = false;
+
+        FVElementGeometry fvGeometry;
+        static VolumeVariables volVars;
+        ElementIterator it = this->gridView_().template begin<0> ();
+        const ElementIterator &endit = this->gridView_().template end<0> ();
+        for (; it != endit; ++it)
+        {
+            fvGeometry.update(this->gridView_(), *it);
+            for (int i = 0; i < fvGeometry.numScv; ++i)
+            {
+                int globalIdx = this->vertexMapper().map(*it, i, dim);
+
+                if (staticDat_[globalIdx].visited)
+                    continue;
+
+                staticDat_[globalIdx].visited = true;
+                volVars.update(curGlobalSol[globalIdx],
+                               this->problem_(),
+                               *it,
+                               fvGeometry,
+                               i,
+                               false);
+                const GlobalPosition &global = it->geometry().corner(i);
+                if (primaryVarSwitch_(curGlobalSol,
+                                      volVars,
+                                      globalIdx,
+                                      global))
+                { wasSwitched = true;
+//                std::cout<<"Switch works :) "<<std::endl;
+                }
+            }
+        }
+
+        // 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;
+    };
+
+    Tensor perm_(Scalar perm)
+    {
+        Tensor K(0.0);
+
+        for(int i=0; i<dim; i++)
+            K[i][i] = perm;
+
+       return K;
+    }
+
+    Tensor perm_(Tensor perm)
+    {
+       return perm;
+    }
+
+    /*!
+     * \brief Reset the current phase presence of all vertices to the old one.
+     *
+     * This is done after an update failed.
+     */
+    void resetPhasePresence_()
+    {
+        int numDofs = this->gridView_().size(dim);
+        for (int i = 0; i < 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_()
+    {
+        int numDofs = this->gridView_().size(dim);
+        for (int i = 0; i < 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;
+
+            //check if a primary variable switch is necessary
+            if (phasePresence == bothPhases)
+            {
+                Scalar Smin = 0; //saturation threshold
+                if (staticDat_[globalIdx].wasSwitched)
+                    Smin = -0.01;
+
+                //if saturation of liquid phase is smaller 0 switch
+                if (volVars.saturation(wPhaseIdx) <= Smin)
+                {
+                    wouldSwitch = true;
+                    //liquid phase has to disappear
+                    std::cout << "Liquid Phase disappears at vertex " << globalIdx
+                                << ", coordinated: " << globalPos << ", Sl: "
+                                << volVars.saturation(wPhaseIdx) << std::endl;
+                    newPhasePresence = nPhaseOnly;
+
+                    //switch not depending on formulation
+                    //switch "Sl" to "xgH20"
+                    globalSol[globalIdx][switchIdx]
+                            = volVars.fluidState().moleFraction(nPhaseIdx, wCompIdx /*H2O*/);
+
+                    //switch all secondary components to mole fraction in gas phase
+                    for (int compIdx=numMajorComponents; compIdx<numComponents; ++compIdx)
+                        globalSol[globalIdx][compIdx] = volVars.fluidState().moleFraction(nPhaseIdx,compIdx);
+                }
+                //if saturation of gas phase is smaller than 0 switch
+                else if (volVars.saturation(nPhaseIdx) <= Smin)
+                {
+                    wouldSwitch = true;
+                    //gas phase has to disappear
+                    std::cout << "Gas Phase disappears at vertex " << globalIdx
+                                << ", coordinated: " << globalPos << ", Sg: "
+                                << volVars.saturation(nPhaseIdx) << std::endl;
+                    newPhasePresence = wPhaseOnly;
+
+                    //switch "Sl" to "xlN2"
+                    globalSol[globalIdx][switchIdx]
+                            = volVars.fluidState().moleFraction(wPhaseIdx, nCompIdx /*N2*/);
+                }
+            }
+            else if (phasePresence == nPhaseOnly)
+            {
+                Scalar xlmax = 1;
+                Scalar sumxl = 0;
+                //Calculate sum of mole fractions in the hypothetical liquid phase
+                for (int compIdx = 0; compIdx < numComponents; compIdx++)
+                {
+                    sumxl += volVars.fluidState().moleFraction(wPhaseIdx, compIdx);
+                }
+                if (sumxl > xlmax)
+                    wouldSwitch = true;
+                if (staticDat_[globalIdx].wasSwitched)
+                    xlmax *=1.02;
+                //liquid phase appears if sum is larger than one
+                if (sumxl/*sum of mole fractions*/ > xlmax/*1*/)
+                {
+                    std::cout << "Liquid Phase appears at vertex " << globalIdx
+                            << ", coordinated: " << globalPos << ", sumxl: "
+                            << sumxl << std::endl;
+                    newPhasePresence = bothPhases;
+
+                    //saturation of the liquid phase set to 0.0001 (if formulation pgSl and vice versa)
+                    if (formulation == pgSl)
+                        globalSol[globalIdx][switchIdx] = 0.0001;
+                    else if (formulation == plSg)
+                        globalSol[globalIdx][switchIdx] = 0.9999;
+
+                    //switch all secondary components back to liquid mole fraction
+                    for (int compIdx=numMajorComponents; compIdx<numComponents; ++compIdx)
+                        globalSol[globalIdx][compIdx] = volVars.fluidState().moleFraction(wPhaseIdx,compIdx);
+                }
+            }
+            else if (phasePresence == wPhaseOnly)
+            {
+                Scalar xgmax = 1;
+                Scalar sumxg = 0;
+                //Calculate sum of mole fractions in the hypothetical liquid phase
+                for (int compIdx = 0; compIdx < numComponents; compIdx++)
+                {
+                    sumxg += volVars.fluidState().moleFraction(nPhaseIdx, compIdx);
+                }
+                if (sumxg > xgmax)
+                    wouldSwitch = true;
+                if (staticDat_[globalIdx].wasSwitched)
+                    xgmax *=1.02;
+                //liquid phase appears if sum is larger than one
+                if (sumxg > xgmax)
+                {
+                    std::cout << "Gas Phase appears at vertex " << globalIdx
+                            << ", coordinated: " << globalPos << ", sumxg: "
+                            << sumxg << std::endl;
+                    newPhasePresence = bothPhases;
+                    //saturation of the liquid phase set to 0.9999 (if formulation pgSl and vice versa)
+                    if (formulation == pgSl)
+                        globalSol[globalIdx][switchIdx] = 0.9999;
+                    else if (formulation == plSg)
+                        globalSol[globalIdx][switchIdx] = 0.0001;
+
+                }
+            }
+
+
+            staticDat_[globalIdx].phasePresence = newPhasePresence;
+            staticDat_[globalIdx].wasSwitched = wouldSwitch;
+            return phasePresence != newPhasePresence;
+        }
+
+    // parameters given in constructor
+    std::vector<StaticVars> staticDat_;
+    bool switchFlag_;
+};
+
+}
+
+#include "2pncpropertydefaults.hh"
+
+#endif
diff --git a/dumux/implicit/2pnc/2pncnewtoncontroller.hh b/dumux/implicit/2pnc/2pncnewtoncontroller.hh
new file mode 100644
index 0000000000000000000000000000000000000000..2f970c83b100a4a0c9589bb22b0e7d695183f3e5
--- /dev/null
+++ b/dumux/implicit/2pnc/2pncnewtoncontroller.hh
@@ -0,0 +1,105 @@
+// -*- 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 two-phase n-component specific controller for the newton solver.
+ */
+#ifndef DUMUX_2PNC_NEWTON_CONTROLLER_HH
+#define DUMUX_2PNC_NEWTON_CONTROLLER_HH
+
+#include "2pncproperties.hh"
+
+#include <dumux/nonlinear/newtoncontroller.hh>
+
+namespace Dumux {
+/*!
+ * \ingroup Newton
+ * \ingroup TwoPNCModel
+ * \brief A two-phase n-component 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 TwoPNCNewtonController : public NewtonController<TypeTag>
+{
+    typedef NewtonController<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SolutionVector)) SolutionVector;
+
+public:
+  TwoPNCNewtonController(Problem &problem)
+      : ParentType(problem)
+    {};
+
+
+    /*!
+     * \brief
+     * Suggest a new time step size based either on the number of newton
+     * iterations required or on the variable switch
+     *
+     * \param uCurrentIter The current global solution vector
+     * \param uLastIter The previous global solution vector
+     *
+     */
+    void newtonEndStep(SolutionVector &uCurrentIter,
+                       const SolutionVector &uLastIter)
+    {
+        int succeeded;
+        try {
+            // call the method of the base class
+            this->method().model().updateStaticData(uCurrentIter, uLastIter);
+            ParentType::newtonEndStep(uCurrentIter, uLastIter);
+
+            succeeded = 1;
+            if (this->gridView_().comm().size() > 1)
+                succeeded = this->gridView_().comm().min(succeeded);
+        }
+        catch (Dumux::NumericalProblem &e)
+        {
+            std::cout << "rank " << this->problem_().gridView().comm().rank()
+                      << " caught an exception while updating:" << e.what()
+                      << "\n";
+            succeeded = 0;
+            if (this->gridView_().comm().size() > 1)
+                succeeded = this->gridView_().comm().min(succeeded);
+        }
+
+        if (!succeeded) {
+            DUNE_THROW(NumericalProblem,
+                       "A process did not succeed in linearizing the system");
+        }
+    }
+
+    /*!
+     * \brief Returns true if the current solution can be considered to
+     *        be accurate enough
+     */
+    bool newtonConverged()
+    {
+        if (this->method().model().switched())
+            return false;
+
+        return ParentType::newtonConverged();
+    }
+};
+}
+
+#endif
diff --git a/dumux/implicit/2pnc/2pncproperties.hh b/dumux/implicit/2pnc/2pncproperties.hh
new file mode 100644
index 0000000000000000000000000000000000000000..42c3ed31b5d5b1e2bb3125223eaec9a271f69837
--- /dev/null
+++ b/dumux/implicit/2pnc/2pncproperties.hh
@@ -0,0 +1,73 @@
+// -*- 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 Properties
+ * \ingroup ImplicitProperties
+ * \ingroup TwoPNCModel
+ *
+ * \file
+ *
+ * \brief Defines the properties required for the two-phase n-component
+ *        fully implicit model.
+ */
+#ifndef DUMUX_2PNC_PROPERTIES_HH
+#define DUMUX_2PNC_PROPERTIES_HH
+
+#include <dumux/implicit/box/boxproperties.hh>
+
+namespace Dumux
+{
+
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for the isothermal two phase n component mineralisation problems
+NEW_TYPE_TAG(BoxTwoPNC, INHERITS_FROM(BoxModel));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+NEW_PROP_TAG(NumPhases);   //!< Number of fluid phases in the system
+NEW_PROP_TAG(NumComponents); //!< Number of fluid components in the system
+NEW_PROP_TAG(NumMajorComponents); //!< Number of major fluid components which are considered in the calculation of the phase density
+NEW_PROP_TAG(TwoPNCIndices); //!< Enumerations for the 2pncMin models
+NEW_PROP_TAG(Formulation);   //!< The formulation of the model
+NEW_PROP_TAG(SpatialParams); //!< The type of the spatial parameters
+NEW_PROP_TAG(FluidSystem); //!< Type of the multi-component relations
+NEW_PROP_TAG(Indices); //!< Enumerations for the model
+NEW_PROP_TAG(Chemistry); //!< The chemistry class with which solves equlibrium reactions
+NEW_PROP_TAG(useElectrochem); //!< Determines if Output for Electrochemistry is needed
+
+NEW_PROP_TAG(MaterialLaw);   //!< The material law which ought to be used (extracted from the spatial parameters)
+NEW_PROP_TAG(MaterialLawParams); //!< The parameters of the material law (extracted from the spatial parameters)
+
+NEW_PROP_TAG(ReplaceCompEqIdx); //!< The index of the total mass balance equation, if one component balance is replaced (ReplaceCompEqIdx < NumComponents)
+NEW_PROP_TAG(VtkAddVelocity); //!< Returns whether velocity vectors are written into the vtk output
+NEW_PROP_TAG(ProblemEnableGravity); //!< Returns whether gravity is considered in the problem
+NEW_PROP_TAG(ImplicitMassUpwindWeight); //!< The value of the upwind weight for the mass conservation equations
+NEW_PROP_TAG(ImplicitMobilityUpwindWeight); //!< The value of the upwind parameter for the mobility
+NEW_PROP_TAG(BaseFluxVariables); //! The base flux variables
+}
+}
+
+#endif
diff --git a/dumux/implicit/2pnc/2pncpropertydefaults.hh b/dumux/implicit/2pnc/2pncpropertydefaults.hh
new file mode 100644
index 0000000000000000000000000000000000000000..c5620b4d4217b455cfaa3084b728689d2cd7d4a8
--- /dev/null
+++ b/dumux/implicit/2pnc/2pncpropertydefaults.hh
@@ -0,0 +1,173 @@
+// -*- 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 Properties
+ * \ingroup ImplicitProperties
+ * \ingroup TwoPNCModel
+ * \file
+ *
+ * \brief Defines default values for most properties required by the
+ *        two-phase n-component fully implicit model.
+ */
+#ifndef DUMUX_2PNC_PROPERTY_DEFAULTS_HH
+#define DUMUX_2PNC_PROPERTY_DEFAULTS_HH
+
+#include "2pncindices.hh"
+#include "2pncmodel.hh"
+#include "2pncindices.hh"
+#include "2pncfluxvariables.hh"
+#include "2pncvolumevariables.hh"
+#include "2pncproperties.hh"
+#include "2pncnewtoncontroller.hh"
+
+
+#include <dumux/implicit/common/implicitdarcyfluxvariables.hh>
+#include <dumux/material/spatialparams/implicitspatialparams.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
+ *
+ */
+SET_PROP(BoxTwoPNC, NumComponents)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+public:
+    static const int value = FluidSystem::numComponents;
+
+};
+//! Set as default that no component mass balance is replaced by the total mass balance
+SET_PROP(BoxTwoPNC, ReplaceCompEqIdx)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+public:
+    static const int value = FluidSystem::numComponents;
+};
+//! The major components belonging to the existing phases are mentioned here e.g., 2 for water and air being the major component in the liquid and gas phases in a 2 phase system 
+SET_PROP(BoxTwoPNC, NumMajorComponents)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+public:
+    static const int value = FluidSystem::numPhases;
+    static_assert(value == 2,
+                  "The model is restricted to two-phases, thus number of major components must also be two.");
+};
+
+/*!
+ * \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(BoxTwoPNC, NumPhases)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+public:
+    static const int value = FluidSystem::numPhases;
+    static_assert(value == 2,
+                  "Only fluid systems with 2 fluid phases are supported by the 2p-nc model!");
+};
+/*!
+ * \brief Set the property for the number of equations: For each existing component one equation has to be solved.
+ */
+SET_PROP(BoxTwoPNC, NumEq)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+public:
+    static const int value = FluidSystem::numComponents;
+};
+
+//! Set the default formulation to pl-Sg: This can be over written in the problem.
+SET_INT_PROP(BoxTwoPNC, Formulation, TwoPNCFormulation::plSg);
+
+//! Set the property for the material parameters by extracting it from the material law.
+SET_PROP(BoxTwoPNC, MaterialLawParams)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MaterialLaw)) MaterialLaw;
+
+public:
+    typedef typename MaterialLaw::Params type;
+};
+
+//! Use the 2pnc local residual operator
+SET_TYPE_PROP(BoxTwoPNC,
+              LocalResidual,
+              TwoPNCLocalResidual<TypeTag>);
+
+//! Use the 2pnc newton controller
+SET_TYPE_PROP(BoxTwoPNC, NewtonController, TwoPNCNewtonController<TypeTag>);
+
+//! the Model property
+SET_TYPE_PROP(BoxTwoPNC, Model, TwoPNCModel<TypeTag>);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxTwoPNC, VolumeVariables, TwoPNCVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxTwoPNC, FluxVariables, TwoPNCFluxVariables<TypeTag>);
+
+//! define the base flux variables to realize Darcy flow
+SET_TYPE_PROP(BoxTwoPNC, BaseFluxVariables, ImplicitDarcyFluxVariables<TypeTag>);
+
+//! the upwind weight for the mass conservation equations.
+SET_SCALAR_PROP(BoxTwoPNC, ImplicitMassUpwindWeight, 1.0);
+
+//! Set default mobility upwind weight to 1.0, i.e. fully upwind
+SET_SCALAR_PROP(BoxTwoPNC, ImplicitMobilityUpwindWeight, 1.0);
+
+//! The indices required by the isothermal 2pnc model
+SET_TYPE_PROP(BoxTwoPNC, Indices, TwoPNCIndices <TypeTag, /*PVOffset=*/0>);
+
+//! Use the ImplicitSpatialParams by default
+SET_TYPE_PROP(BoxTwoPNC, SpatialParams, ImplicitSpatialParams<TypeTag>);
+
+//! Enable gravity by default
+SET_BOOL_PROP(BoxTwoPNC, ProblemEnableGravity, true);
+
+//! Disable velocity output by default
+SET_BOOL_PROP(BoxTwoPNC, VtkAddVelocity, false);
+
+//! disable electro-chemistry by default
+SET_BOOL_PROP(BoxTwoPNC, useElectrochem, false);
+
+}
+
+}
+
+#endif
diff --git a/dumux/implicit/2pnc/2pncvolumevariables.hh b/dumux/implicit/2pnc/2pncvolumevariables.hh
new file mode 100644
index 0000000000000000000000000000000000000000..9e70e3915dd0781b8d2a56ebf53e4bfdafc9cc33
--- /dev/null
+++ b/dumux/implicit/2pnc/2pncvolumevariables.hh
@@ -0,0 +1,501 @@
+// -*- 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 Contains the quantities which are constant within a
+ *        finite volume in the two-phase, n-component model.
+ */
+#ifndef DUMUX_2PNC_VOLUME_VARIABLES_HH
+#define DUMUX_2PNC_VOLUME_VARIABLES_HH
+
+#include <iostream>
+#include <vector>
+#include <dune/common/parallel/collectivecommunication.hh>
+
+#include <dumux/implicit/common/implicitmodel.hh>
+#include <dumux/material/fluidstates/compositionalfluidstate.hh>
+#include <dumux/common/math.hh>
+
+#include "2pncproperties.hh"
+#include "2pncindices.hh"
+#include <dumux/material/constraintsolvers/computefromreferencephase2pnc.hh>
+#include <dumux/material/constraintsolvers/miscible2pnccomposition.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup TwoPNCModel
+ * \ingroup ImplicitVolumeVariables
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the two-phase, n-component model.
+ */
+template <class TypeTag>
+class TwoPNCVolumeVariables : 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, Grid) Grid;
+    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, MaterialLawParams) MaterialLawParams;
+    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),
+        numMajorComponents = GET_PROP_VALUE(TypeTag, NumMajorComponents),
+
+        // formulations
+        formulation = GET_PROP_VALUE(TypeTag, Formulation),
+        plSg = TwoPNCFormulation::plSg,
+        pgSl = TwoPNCFormulation::pgSl,
+
+        // phase indices
+        wPhaseIdx = FluidSystem::wPhaseIdx,
+        nPhaseIdx = FluidSystem::nPhaseIdx,
+
+        // component indices
+        wCompIdx = FluidSystem::wCompIdx,
+        nCompIdx = FluidSystem::nCompIdx,
+
+        // phase presence enums
+        nPhaseOnly = Indices::nPhaseOnly,
+        wPhaseOnly = Indices::wPhaseOnly,
+        bothPhases = Indices::bothPhases,
+
+        // primary variable indices
+        pressureIdx = Indices::pressureIdx,
+        switchIdx = Indices::switchIdx,
+
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename Grid::ctype CoordScalar;
+    typedef Dumux::Miscible2pNcComposition<Scalar, FluidSystem> Miscible2pNcComposition;
+    typedef Dumux::ComputeFromReferencePhase2pNc<Scalar, FluidSystem> ComputeFromReferencePhase2pNc;
+
+    enum { isBox = GET_PROP_VALUE(TypeTag, ImplicitIsBox) };
+    enum { dofCodim = isBox ? dim : 0 };
+public:
+  
+      //! The type of the object returned by the fluidState() method
+      typedef CompositionalFluidState<Scalar, FluidSystem> FluidState;
+    /*!
+     * \copydoc ImplicitVolumeVariables::update
+     */
+    void update(const PrimaryVariables &primaryVariables,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                int scvIdx,
+                bool isOldSol)
+    {
+        ParentType::update(primaryVariables,
+                           problem,
+                           element,
+                           fvGeometry,
+                           scvIdx,
+                           isOldSol);
+        
+        completeFluidState(primaryVariables, problem, element, fvGeometry, scvIdx, fluidState_, isOldSol);
+            
+        /////////////
+        // calculate the remaining quantities
+        /////////////
+        const MaterialLawParams &materialParams = problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+        
+    // 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 liquid saturation
+                        // as parameter!
+                        kr = MaterialLaw::krn(materialParams, saturation(wPhaseIdx));
+                        mobility_[phaseIdx] = kr / fluidState_.viscosity(phaseIdx);
+                        Valgrind::CheckDefined(mobility_[phaseIdx]);
+                    int compIIdx = phaseIdx;
+                    for(int compIdx = 0; compIdx < numComponents; ++compIdx)
+                    {
+                    int compJIdx = compIdx;
+                    // binary diffusion coefficents
+                    diffCoeff_[phaseIdx][compIdx] = 0.0;
+                    if(compIIdx!= compJIdx)
+                    diffCoeff_[phaseIdx][compIdx] = FluidSystem::binaryDiffusionCoefficient(fluidState_,
+                                                                                    paramCache,
+                                                                                    phaseIdx,
+                                                                                    compIIdx,
+                                                                                    compJIdx);
+                    Valgrind::CheckDefined(diffCoeff_[phaseIdx][compIdx]);
+                }
+            }
+
+    // porosity 
+    porosity_ = problem.spatialParams().porosity(element,
+                                                        fvGeometry,
+                                                        scvIdx);
+    Valgrind::CheckDefined(porosity_);
+    // energy related quantities not contained in the fluid state
+            
+    asImp_().updateEnergy_(primaryVariables, problem,element, fvGeometry, scvIdx, isOldSol);
+    }
+
+   /*!
+    * \copydoc ImplicitModel::completeFluidState
+    * \param isOldSol Specifies whether this is the previous solution or the current one
+    */
+    static void completeFluidState(const PrimaryVariables& primaryVariables,
+                    const Problem& problem,
+                    const Element& element,
+                    const FVElementGeometry& fvGeometry,
+                    int scvIdx,
+                    FluidState& fluidState,
+                    bool isOldSol = false)
+
+    {
+        Scalar t = Implementation::temperature_(primaryVariables, problem, element,
+                                                fvGeometry, scvIdx);
+        fluidState.setTemperature(t);
+        
+#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 4)
+        int dofIdxGlobal = problem.model().dofMapper().subIndex(element, scvIdx, dofCodim);
+#else
+        int dofIdxGlobal = problem.model().dofMapper().map(element, scvIdx, dofCodim);
+#endif        
+        int phasePresence = problem.model().phasePresence(dofIdxGlobal, isOldSol);
+
+    /////////////
+        // set the saturations
+        /////////////
+
+    Scalar Sg;
+        if (phasePresence == nPhaseOnly)
+            Sg = 1.0;
+        else if (phasePresence == wPhaseOnly) {
+            Sg = 0.0;
+        }
+        else if (phasePresence == bothPhases) {
+            if (formulation == plSg)
+                Sg = primaryVariables[switchIdx];
+            else if (formulation == pgSl)
+                Sg = 1.0 - primaryVariables[switchIdx];
+            else DUNE_THROW(Dune::InvalidStateException, "Formulation: " << formulation << " is invalid.");
+        }   
+    else DUNE_THROW(Dune::InvalidStateException, "phasePresence: " << phasePresence << " is invalid.");
+        fluidState.setSaturation(nPhaseIdx, Sg);
+        fluidState.setSaturation(wPhaseIdx, 1.0 - Sg);
+
+            /////////////
+        // set the pressures of the fluid phases
+        /////////////
+
+        // calculate capillary pressure
+        const MaterialLawParams &materialParams
+        = problem.spatialParams().materialLawParams(element, fvGeometry, scvIdx);
+        Scalar pc = MaterialLaw::pc(materialParams, 1 - Sg);
+
+        // extract the pressures
+        if (formulation == plSg) {
+            fluidState.setPressure(wPhaseIdx, primaryVariables[pressureIdx]);
+            if (primaryVariables[pressureIdx] + pc < 0.0)
+                 DUNE_THROW(Dumux::NumericalProblem,"Capillary pressure is too low");
+            fluidState.setPressure(nPhaseIdx, primaryVariables[pressureIdx] + pc);
+        }
+        else if (formulation == pgSl) {
+            fluidState.setPressure(nPhaseIdx, primaryVariables[pressureIdx]);
+    // Here we check for (p_g - pc) in order to ensure that (p_l > 0)
+            if (primaryVariables[pressureIdx] - pc < 0.0)
+            {
+                std::cout<< "p_g: "<< primaryVariables[pressureIdx]<<" Cap_press: "<< pc << std::endl;
+                DUNE_THROW(Dumux::NumericalProblem,"Capillary pressure is too high");
+            }
+            fluidState.setPressure(wPhaseIdx, primaryVariables[pressureIdx] - pc);
+        }
+        else DUNE_THROW(Dune::InvalidStateException, "Formulation: " << formulation << " is invalid.");
+
+        /////////////
+        // calculate the phase compositions
+        /////////////
+
+    typename FluidSystem::ParameterCache paramCache;
+
+        // now comes the tricky part: calculate phase composition
+        if (phasePresence == bothPhases) {
+            // both phases are present, phase composition results from
+            // the gas <-> liquid equilibrium. This is
+            // the job of the "MiscibleMultiPhaseComposition"
+            // constraint solver
+
+            // set the known mole fractions in the fluidState so that they
+            // can be used by the Miscible2pNcComposition constraint solver
+            for (int compIdx=numMajorComponents; compIdx<numComponents; ++compIdx)
+            {
+                fluidState.setMoleFraction(wPhaseIdx, compIdx, primaryVariables[compIdx]);
+            }
+
+            Miscible2pNcComposition::solve(fluidState,
+                        paramCache,
+                        wPhaseIdx,	//known phaseIdx
+                        /*setViscosity=*/true,
+                        /*setInternalEnergy=*/false);
+        }
+        else if (phasePresence == nPhaseOnly){
+
+            Dune::FieldVector<Scalar, numComponents> moleFrac;
+
+
+            moleFrac[wCompIdx] =  primaryVariables[switchIdx];
+
+            for (int compIdx=numMajorComponents; compIdx<numComponents; ++compIdx)
+                    moleFrac[compIdx] = primaryVariables[compIdx];
+
+
+            Scalar sumMoleFracNotGas = 0;
+            for (int compIdx=numMajorComponents; compIdx<numComponents; ++compIdx)
+                    sumMoleFracNotGas+=moleFrac[compIdx];
+
+            sumMoleFracNotGas += moleFrac[wCompIdx];
+            moleFrac[nCompIdx] = 1 - sumMoleFracNotGas;
+
+
+            // Set fluid state mole fractions
+            for (int compIdx=0; compIdx<numComponents; ++compIdx)
+                    fluidState.setMoleFraction(nPhaseIdx, compIdx, moleFrac[compIdx]);
+
+
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase2pNc" constraint solver
+                ComputeFromReferencePhase2pNc::solve(fluidState,
+                                                paramCache,
+                                                nPhaseIdx,
+                                                /*setViscosity=*/true,
+                                                /*setInternalEnergy=*/false);
+
+            }
+        else if (phasePresence == wPhaseOnly){
+        // only the liquid phase is present, i.e. liquid phase
+        // composition is stored explicitly.
+        // extract _mass_ fractions in the gas phase
+            Dune::FieldVector<Scalar, numComponents> moleFrac;
+            
+            for (int compIdx=numMajorComponents; compIdx<numComponents; ++compIdx)
+            {
+                moleFrac[compIdx] = primaryVariables[compIdx];
+            }
+            moleFrac[nCompIdx] = primaryVariables[switchIdx];
+            Scalar sumMoleFracNotWater = 0;
+            for (int compIdx=numMajorComponents; compIdx<numComponents; ++compIdx)
+            {
+                    sumMoleFracNotWater+=moleFrac[compIdx];
+            }
+            sumMoleFracNotWater += moleFrac[nCompIdx];
+            moleFrac[wCompIdx] = 1 -sumMoleFracNotWater;
+
+
+            // convert mass to mole fractions and set the fluid state
+            for (int compIdx=0; compIdx<numComponents; ++compIdx)
+            {
+                fluidState.setMoleFraction(wPhaseIdx, compIdx, moleFrac[compIdx]);
+            }
+            
+            // calculate the composition of the remaining phases (as
+            // well as the densities of all phases). this is the job
+            // of the "ComputeFromReferencePhase2pNc" constraint solver
+            ComputeFromReferencePhase2pNc::solve(fluidState,
+                                                paramCache,
+                                                wPhaseIdx,
+                                                /*setViscosity=*/true,
+                                                /*setInternalEnergy=*/false);
+        }
+        paramCache.updateAll(fluidState);
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            Scalar rho = FluidSystem::density(fluidState, paramCache, phaseIdx);
+            Scalar mu = FluidSystem::viscosity(fluidState, paramCache, phaseIdx);
+
+            fluidState.setDensity(phaseIdx, rho);
+            fluidState.setViscosity(phaseIdx, mu);
+        }
+    }
+    
+    /*!
+     * \brief Returns the phase state for the control-volume.
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+    /*!
+     * \brief Returns the saturation of a given phase within
+     *        the control volume in \f$[-]\f$.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar saturation(int phaseIdx) const
+    { return fluidState_.saturation(phaseIdx); }
+
+    /*!
+     * \brief Returns the mass density of a given phase within the
+     *        control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar density(int phaseIdx) const
+    {
+        if (phaseIdx < numPhases)
+            return fluidState_.density(phaseIdx);
+        
+        else
+            DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx);
+    }
+
+    /*!
+     * \brief Returns the mass density of a given phase within the
+     *        control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar molarDensity(int phaseIdx) const
+    {
+        if (phaseIdx < numPhases)
+            return fluidState_.molarDensity(phaseIdx);
+
+        else
+            DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx);
+    }
+
+    /*!
+     * \brief Returns the effective pressure of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar pressure(int phaseIdx) const
+    { 
+        return fluidState_.pressure(phaseIdx); 
+    }
+
+    /*!
+     * \brief Returns temperature inside the sub-control volume.
+     *
+     * Note that we assume thermodynamic equilibrium, i.e. the
+     * temperature of the rock matrix and of all fluid phases are
+     * identical.
+     */
+    Scalar temperature() const
+    { return fluidState_.temperature(/*phaseIdx=*/0); }
+
+    /*!
+     * \brief Returns the effective mobility of a given phase within
+     *        the control volume.
+     *
+     * \param phaseIdx The phase index
+     */
+    Scalar mobility(int phaseIdx) const
+    {
+        return mobility_[phaseIdx];
+    }
+
+    /*!
+     * \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_.pressure(FluidSystem::nPhaseIdx) - fluidState_.pressure(FluidSystem::wPhaseIdx); }
+
+    /*!
+     * \brief Returns the average porosity within the control volume.
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+
+    /*!
+     * \brief Returns the binary diffusion coefficients for a phase in \f$[m^2/s]\f$.
+     */
+    Scalar diffCoeff(int phaseIdx, int compIdx) const
+    { return diffCoeff_[phaseIdx][compIdx]; }
+
+protected:
+  
+    static Scalar temperature_(const PrimaryVariables &priVars,
+                               const Problem& problem,
+                               const Element &element,
+                               const FVElementGeometry &fvGeometry,
+                               int scvIdx)
+    {
+        return problem.temperatureAtPos(fvGeometry.subContVol[scvIdx].global);
+    }
+    
+    template<class ParameterCache>
+    static Scalar enthalpy_(const FluidState& fluidState,
+                            const ParameterCache& paramCache,
+                            int phaseIdx)
+    {
+        return 0;
+    }
+
+    /*!
+        * \brief Called by update() to compute the energy related quantities
+        */
+    void updateEnergy_(const PrimaryVariables &priVars,
+                        const Problem &problem,
+                        const Element &element,
+                        const FVElementGeometry &fvGeometry,
+                        const int scvIdx,
+                        bool isOldSol)
+    { };
+
+    Scalar porosity_;        //!< Effective porosity within the control volume
+    Scalar mobility_[numPhases];  //!< Effective mobility within the control volume
+    Scalar density_;
+    FluidState fluidState_;
+    Scalar theta_;
+    Scalar InitialPorosity_;
+    Scalar molWtPhase_[numPhases];
+    Dune::FieldMatrix<Scalar, numPhases, numComponents> diffCoeff_;
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }  
+    
+};
+
+} // end namespace
+
+#endif