diff --git a/configure.ac b/configure.ac
index 702ef8b0ac89bbb28ab187a5a19df64a26e19656..4a22e14aefb9d920a7c7af7b25a8552da1b3ba02 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,6 +29,7 @@ AC_CONFIG_FILES([dumux.pc
     dumux/boxmodels/2p2cni/Makefile 
     dumux/boxmodels/2pni/Makefile 
     dumux/boxmodels/common/Makefile 
+    dumux/boxmodels/MpNc/Makefile 
     dumux/boxmodels/richards/Makefile 
     dumux/common/Makefile 
     dumux/decoupled/Makefile
@@ -50,9 +51,14 @@ AC_CONFIG_FILES([dumux.pc
     dumux/material/binarycoefficients/Makefile 
     dumux/material/components/Makefile 
     dumux/material/components/iapws/Makefile 
+    dumux/material/constraintsolvers/Makefile 
+    dumux/material/eos/Makefile 
     dumux/material/fluidmatrixinteractions/Makefile 
     dumux/material/fluidmatrixinteractions/2p/Makefile 
+    dumux/material/fluidmatrixinteractions/Mp/Makefile 
+    dumux/material/fluidstates/Makefile 
     dumux/material/fluidsystems/Makefile 
+    dumux/material/new_fluidsystems/Makefile 
     dumux/material/spatialparameters/Makefile 
     dumux/nonlinear/Makefile 
     m4/Makefile
@@ -64,6 +70,7 @@ AC_CONFIG_FILES([dumux.pc
     test/boxmodels/1p2c/Makefile 
     test/boxmodels/2p2c/Makefile
     test/boxmodels/2p2cni/Makefile
+    test/boxmodels/MpNc/Makefile
     test/boxmodels/richards/Makefile  
     test/common/Makefile
     test/common/generalproblem/Makefile
diff --git a/dumux/boxmodels/Makefile.am b/dumux/boxmodels/Makefile.am
index 0fd56c7e682abe8584cb21eab317367bf6cd563e..5f795772a5c222ffceeef8e8af13849a0e8a712c 100644
--- a/dumux/boxmodels/Makefile.am
+++ b/dumux/boxmodels/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = common 1p 1p2c 2p 2p2c 2p2cni 2pni richards
+SUBDIRS = common 1p 1p2c 2p 2p2c 2p2cni 2pni MpNc richards
 
 boxmodelsdir = $(includedir)/dumux/boxmodels
 
diff --git a/dumux/boxmodels/MpNc/Makefile.am b/dumux/boxmodels/MpNc/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..0df2b8036be53697cb070f10d551abc9c0e6399f
--- /dev/null
+++ b/dumux/boxmodels/MpNc/Makefile.am
@@ -0,0 +1,4 @@
+MpNcdir = $(includedir)/dumux/boxmodels/MpNc
+MpNc_HEADERS = *.hh
+
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/boxmodels/MpNc/MpNcfluxvariables.hh b/dumux/boxmodels/MpNc/MpNcfluxvariables.hh
new file mode 100644
index 0000000000000000000000000000000000000000..88201aba269a208fbb3102f6ed2161b8c330a20e
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcfluxvariables.hh
@@ -0,0 +1,322 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Copyright (C) 2008-2009 by Klaus Mosthaf                                *
+ *   Copyright (C) 2008 by Bernd Flemisch                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 This file contains the data which is required to calculate
+ *        all fluxes of components over a face of a finite volume.
+ *
+ * This means pressure, concentration and temperature gradients, phase
+ * densities at the integration point, etc.
+ */
+#ifndef DUMUX_MPNC_FLUX_VARIABLES_HH
+#define DUMUX_MPNC_FLUX_VARIABLES_HH
+
+#include <dumux/common/spline.hh>
+
+#include "diffusion/fluxvariables.hh"
+#include "energy/MpNcfluxvariablesenergy.hh"
+
+namespace Dumux
+{
+
+/*!
+ * \brief This template class contains the data which is required to
+ *        calculate all fluxes of components over a face of a finite
+ *        volume for the two-phase, three-component model.
+ *
+ * This means pressure and concentration gradients, phase densities at
+ * the intergration point, etc.
+ */
+template <class TypeTag>
+class MPNCFluxVariables
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) SpatialParameters;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+
+    enum {
+        dimWorld = GridView::dimensionworld,
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+        numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)),
+
+        enableDiffusion = GET_PROP_VALUE(TypeTag, PTAG(EnableDiffusion)),
+        enableEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)),
+        enableKinetic = GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)),
+        enableKineticEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy)),
+        enableGravity = GET_PROP_VALUE(TypeTag, PTAG(EnableGravity)),
+    };
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> Vector;
+    typedef Dune::FieldMatrix<CoordScalar, dimWorld, dimWorld> Tensor;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolume SCV;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+    typedef Dune::FieldVector<Scalar, numPhases> PhasesVector;
+
+    typedef MPNCFluxVariablesDiffusion<TypeTag, enableDiffusion>                  FluxVariablesDiffusion;
+    typedef MPNCFluxVariablesEnergy<TypeTag, enableEnergy, enableKineticEnergy>    FluxVariablesEnergy;
+
+public:
+    MPNCFluxVariables(const Problem &problem,
+                   const Element &element,
+                   const FVElementGeometry &elemGeom,
+                   int scvfIdx,
+                   const ElementVolumeVariables &elemVolVars)
+        : fvElemGeom_(elemGeom), volVars_(elemVolVars)
+    {
+        scvfIdx_ = scvfIdx;
+
+        // update the base module (i.e. advection)
+        calculateGradients_(problem, element, elemVolVars);
+        calculateVelocities_(problem, element, elemVolVars);
+
+        // update the flux data of the energy module (i.e. isothermal
+        // or non-isothermal)
+        energyDat_.update(problem, element, elemGeom, scvfIdx, *this, elemVolVars);
+
+        // update the flux data of the diffusion module (i.e. with or
+        // without diffusion)
+        diffusionDat_.update(problem, element, elemGeom, scvfIdx, elemVolVars);
+
+        extrusionFactor_ =
+            (elemVolVars[face().i].extrusionFactor() 
+             + elemVolVars[face().j].extrusionFactor()) / 2;
+    }
+
+
+    /*!
+     * \brief Calculate a phase's darcy velocity [m/s] at a
+     *        sub-control volume face.
+     *
+     * So far, this method only exists in the Mp-Nc model!
+     *
+     *  Of course, in the setting of a finite volume scheme, the velocities are
+     *  on the faces rather than in the volume. Therefore, the velocity
+     *
+     * \param problem The problem object
+     * \param element The current element
+     * \param elemGeom The finite-volume geometry in the box scheme
+     * \param scvIdx The local index of the SCV (sub-control volume)
+     * \param isOldSol Evaluate function with solution of current or previous time step
+     */
+    void computeDarcy(Vector & vDarcy,
+                      const ElementVolumeVariables &elemVolVars,
+                      int phaseIdx) const
+    {
+        intrinsicPermeability().mv(potentialGrad(phaseIdx),
+                                            vDarcy);
+        // darcy velocity is along *negative* potential gradient
+        // (i.e. from high to low pressures), this means that we need
+        // to negate the product of the intrinsic permeability and the
+        // potential gradient!
+        vDarcy *= -1;
+
+        // JUST for upstream decision
+        Scalar normalFlux = vDarcy * face().normal;
+        // data attached to upstream and the downstream vertices
+        // of the current phase
+        int upIdx = face().i;
+        int dnIdx = face().j;
+
+        if (!std::isfinite(normalFlux))
+            DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux");
+
+        if (normalFlux < 0)
+            std::swap(upIdx, dnIdx);
+
+        const VolumeVariables &up = elemVolVars[upIdx];
+
+        ////////
+        // Jipie this is a velocity now, finally deserves the name
+        ////////
+        vDarcy *= up.mobility(phaseIdx);
+    }
+
+    const SCVFace &face() const
+    { return fvElemGeom_.subContVolFace[scvfIdx_]; }
+
+    const VolumeVariables &volVars(int idx) const
+    { return volVars_[idx]; }
+
+    /*!
+     * \brief Returns th extrusion factor for the sub-control volume face
+     */
+    Scalar extrusionFactor() const
+    { return extrusionFactor_; }
+
+    /*!
+     * \brief Return the intrinsic permeability.
+     */
+    const Tensor &intrinsicPermeability() const
+    { return K_; }
+
+    /*!
+     * \brief Return the pressure potential gradient.
+     */
+    const Vector &potentialGrad(int phaseIdx) const
+    { return potentialGrad_[phaseIdx]; }
+
+    ////////////////////////////////////////////////
+    // forward calls to the diffusion module
+    Scalar porousDiffCoeffL(int compIdx) const
+    { return diffusionDat_.porousDiffCoeffL(compIdx); };
+
+    Scalar porousDiffCoeffG(int compIIdx, int compJIdx) const
+    { return diffusionDat_.porousDiffCoeffG(compIIdx, compJIdx); };
+
+    const Scalar moleFrac(int phaseIdx, int compIdx) const
+    { return diffusionDat_.moleFrac(phaseIdx, compIdx); };
+
+    const Vector &moleFracGrad(int phaseIdx,
+                               int compIdx) const
+    { return diffusionDat_.moleFracGrad(phaseIdx, compIdx); };
+    // end of forward calls to the diffusion module
+    ////////////////////////////////////////////////
+
+    ////////////////////////////////////////////////
+    // forward calls to the temperature module
+    const Vector &temperatureGrad() const
+    { return energyDat_.temperatureGrad(); };
+
+    const FluxVariablesEnergy &energyData() const
+    { return energyDat_; }
+    // end of forward calls to the temperature module
+    ////////////////////////////////////////////////
+
+private:
+    void calculateGradients_(const Problem &problem,
+                             const Element &element,
+                             const ElementVolumeVariables &elemVolVars)
+    {
+        for (int phaseIdx=0; phaseIdx < numPhases; phaseIdx++) {
+            potentialGrad_[phaseIdx] = Scalar(0);
+        }
+
+        // calculate pressure gradients using finite element gradients
+        Vector tmp(0.0);
+        for (int idx = 0;
+             idx < fvElemGeom_.numVertices;
+             idx++) // loop over adjacent vertices
+        {
+            // FE gradient at vertex idx
+            const Vector &feGrad = face().grad[idx];
+
+            // TODO: only calculate the gradients for the present
+            // phases.
+            //
+            // compute sum of pressure gradients for each phase
+            for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+            {
+                // the pressure gradient
+                tmp = feGrad;
+                tmp *= elemVolVars[idx].fluidState().pressure(phaseIdx);
+                potentialGrad_[phaseIdx] += tmp;
+            }
+        }
+
+        ///////////////
+        // correct the pressure gradients by the gravitational acceleration
+        ///////////////
+        if (enableGravity) {
+            // estimate the gravitational acceleration at a given SCV face
+            // using the arithmetic mean
+            Vector g(problem.boxGravity(element, fvElemGeom_, face().i));
+            g += problem.boxGravity(element, fvElemGeom_, face().j);
+            g /= 2;
+
+            for (int phaseIdx=0; phaseIdx < numPhases; phaseIdx++)
+            {
+                // calculate the phase density at the integration point. we
+                // only do this if the wetting phase is present in both cells
+                Scalar SI = elemVolVars[face().i].fluidState().saturation(phaseIdx);
+                Scalar SJ = elemVolVars[face().j].fluidState().saturation(phaseIdx);
+                Scalar rhoI = elemVolVars[face().i].fluidState().density(phaseIdx);
+                Scalar rhoJ = elemVolVars[face().j].fluidState().density(phaseIdx);
+                Scalar fI = std::max(0.0, std::min(SI/1e-5, 0.5));
+                Scalar fJ = std::max(0.0, std::min(SJ/1e-5, 0.5));
+                if (fI + fJ == 0)
+                    // doesn't matter because no wetting phase is present in
+                    // both cells!
+                    fI = fJ = 0.5;
+                Scalar density = (fI*rhoI + fJ*rhoJ)/(fI + fJ);
+                
+                // make gravity acceleration a force
+                Vector f(g);
+                f *= density;
+        
+                // calculate the final potential gradient
+                potentialGrad_[phaseIdx] -= f;
+            }
+        }
+    }
+
+    void calculateVelocities_(const Problem &problem,
+                              const Element &element,
+                              const ElementVolumeVariables &elemVolVars)
+    {
+        // multiply the pressure potential with the intrinsic
+        // permeability
+        const SpatialParameters &sp = problem.spatialParameters();
+        for (int phaseIdx=0; phaseIdx < numPhases; phaseIdx++)
+        {
+            sp.meanK(K_,
+                     sp.intrinsicPermeability(element,
+                                              fvElemGeom_,
+                                              face().i),
+                     sp.intrinsicPermeability(element,
+                                              fvElemGeom_,
+                                              face().j));
+        }
+    }
+
+
+
+
+    const FVElementGeometry &fvElemGeom_;
+    int scvfIdx_;
+
+    const ElementVolumeVariables &volVars_;
+
+    // The extrusion factor for the sub-control volume face
+    Scalar extrusionFactor_;
+
+    // pressure potential gradients
+    Vector potentialGrad_[numPhases];
+
+    // intrinsic permeability
+    Tensor K_;
+
+    FluxVariablesDiffusion     diffusionDat_;
+    FluxVariablesEnergy     energyDat_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcindices.hh b/dumux/boxmodels/MpNc/MpNcindices.hh
new file mode 100644
index 0000000000000000000000000000000000000000..799761d10331882fa1495a13bb541c8c54767801
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcindices.hh
@@ -0,0 +1,105 @@
+/*****************************************************************************
+ *   Copyright (C) 2008-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_INDICES_HH
+#define DUMUX_MPNC_INDICES_HH
+
+#include "MpNcproperties.hh"
+
+#include "mass/MpNcindicesmass.hh"
+#include "energy/MpNcindicesenergy.hh"
+
+namespace Dumux
+{
+/*!
+ * \brief The primary variable and equation indices for the MpNc
+ *        model.
+ */
+template <class TypeTag, int BasePVOffset = 0>
+struct MPNCIndices :
+        public MPNCMassIndices<BasePVOffset,
+                               TypeTag,
+                               GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)) >,
+        public MPNCEnergyIndices<BasePVOffset +
+                                 MPNCMassIndices<0, TypeTag, GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)) >::NumPrimaryVars,
+                                 GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)),
+                                 GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy))>
+{
+private:
+    enum { enableEnergy         = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)) };
+    enum { enableDiffusion      = GET_PROP_VALUE(TypeTag, PTAG(EnableDiffusion)) };
+    enum { enableKinetic        = GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)) }; //mass transfer
+    enum { enableKineticEnergy  = GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy)) }; // energy transfer
+
+    typedef MPNCMassIndices<BasePVOffset, TypeTag, enableKinetic> MassIndices;
+    typedef MPNCEnergyIndices<BasePVOffset + MassIndices::NumPrimaryVars, enableEnergy, enableKineticEnergy> EnergyIndices;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    enum { numComponents = FluidSystem::numComponents };
+    enum { numPhases = FluidSystem::numPhases };
+
+public:
+    /*!
+     * \brief The number of primary variables / equations.
+     */
+    // temperature + Mass Balance  + constraints for switch stuff
+    static const int NumPrimaryVars =
+        MassIndices::NumPrimaryVars +
+        EnergyIndices::NumPrimaryVars +
+        numPhases;
+
+    /*!
+     * \brief The number of primary variables / equations of the erngy module.
+     */
+    static const int NumPrimaryEnergyVars =
+        EnergyIndices::NumPrimaryVars ;
+
+    /*!
+     * \brief Index of the saturation of the first phase in a vector
+     *        of primary variables.
+     *
+     * The following (numPhases - 1) primary variables represent the
+     * saturations for the phases [1, ..., numPhases - 1]
+     */
+    static const int S0Idx =
+        MassIndices::NumPrimaryVars +
+        EnergyIndices::NumPrimaryVars;
+
+    /*!
+     * \brief Index of the first phase' pressure in a vector of
+     *        primary variables.
+     */
+    static const int p0Idx =
+        MassIndices::NumPrimaryVars +
+        EnergyIndices::NumPrimaryVars +
+        numPhases - 1;
+
+    /*!
+     * \brief Index of the first phase NCP equation.
+     *
+     * The index for the remaining phases are consecutive.
+     */
+    static const int phase0NcpIdx =
+        MassIndices::NumPrimaryVars +
+        EnergyIndices::NumPrimaryVars;
+};
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNclocalresidual.hh b/dumux/boxmodels/MpNc/MpNclocalresidual.hh
new file mode 100644
index 0000000000000000000000000000000000000000..1c3152994de253b92a2180bc9a4113dbf2d554fe
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNclocalresidual.hh
@@ -0,0 +1,264 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_HH
+#define DUMUX_MPNC_LOCAL_RESIDUAL_HH
+
+#include "MpNcfluxvariables.hh"
+#include "diffusion/diffusion.hh"
+#include "energy/MpNclocalresidualenergy.hh"
+#include "mass/MpNclocalresidualmass.hh"
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+
+#include <dumux/common/math.hh>
+
+
+namespace Dumux
+{
+/*!
+ * \brief two-phase, N-component specific details needed to
+ *        approximately calculate the local defect in the BOX scheme.
+ *
+ * This class is used to fill the gaps in BoxLocalResidual for the
+ * two-phase, N-component twophase flow.
+ */
+template<class TypeTag>
+class MPNCLocalResidual : public BoxLocalResidual<TypeTag>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+
+protected:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(LocalResidual)) Implementation;
+    typedef MPNCLocalResidual<TypeTag> ThisType;
+    typedef BoxLocalResidual<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld,
+
+        numEq = GET_PROP_VALUE(TypeTag, PTAG(NumEq)),
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+        numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)),
+
+        enableEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)),
+        enableKineticEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy)),
+
+        enableDiffusion = GET_PROP_VALUE(TypeTag, PTAG(EnableDiffusion)),
+        enableKinetic = GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)),
+        enableSmoothUpwinding = GET_PROP_VALUE(TypeTag, PTAG(EnableSmoothUpwinding)),
+
+        phase0NcpIdx = Indices::phase0NcpIdx
+    };
+
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GridView::IntersectionIterator IntersectionIterator;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+
+    typedef typename GridView::CollectiveCommunication CollectiveCommunication;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementBoundaryTypes)) ElementBoundaryTypes;
+
+    typedef Dune::FieldVector<Scalar, numPhases> PhasesVector;
+    typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;
+
+    typedef Dune::FieldVector<Scalar, dim> LocalPosition;
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+    typedef Dune::FieldVector<Scalar, dimWorld> Vector;
+    typedef Dune::FieldMatrix<Scalar, dimWorld, dimWorld> Tensor;
+
+    typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, enableKineticEnergy> EnergyResid;
+    typedef MPNCLocalResidualMass<TypeTag, enableKinetic> MassResid;
+
+public:
+    /*!
+     * \brief Evaluate the amount all conservation quantites
+     *        (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)
+     */
+    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 mass and energy storage terms
+        MassResid::computeStorage(storage, volVars);
+        EnergyResid::computeStorage(storage, volVars);
+        Valgrind::CheckDefined(storage);
+    }
+
+    /*!
+     * \brief Evaluate the amount all conservation quantites
+     *        (e.g. phase mass) within all sub-control volumes of an
+     *        element.
+     */
+    void addPhaseStorage(PrimaryVariables &storage,
+                         const Element &element,
+                         int phaseIdx) const
+    {
+        // create a finite volume element geometry
+        FVElementGeometry fvElemGeom;
+        fvElemGeom.update(this->gridView_(), element);
+
+        // calculate volume variables
+        ElementVolumeVariables volVars;
+        this->model_().setHints(element, volVars);
+        volVars.update(this->problem_(),
+                       element,
+                       fvElemGeom,
+                       /*useOldSolution=*/false);
+
+        // calculate the phase storage for all sub-control volumes
+        for (int scvIdx=0;
+             scvIdx < fvElemGeom.numVertices;
+             scvIdx++)
+        {
+            PrimaryVariables tmp(0.0);
+
+            // compute mass and energy storage terms in terms of
+            // averaged quantities
+            MassResid::addPhaseStorage(tmp,
+                                       volVars[scvIdx],
+                                       phaseIdx);
+            EnergyResid::addPhaseStorage(tmp,
+                                         volVars[scvIdx],
+                                         phaseIdx);
+
+            // multiply with volume of sub-control volume
+            tmp *= fvElemGeom.subContVol[scvIdx].volume;
+
+            // Add the storage of the current SCV to the total storage
+            storage += tmp;
+        }
+    }
+
+    /*!
+     * \brief Calculate the source term of the equation
+     */
+    void computeSource(PrimaryVariables &source,
+                       int scvIdx)
+     {
+        Valgrind::SetUndefined(source);
+        this->problem_().boxSDSource(source,
+                                     this->elem_(),
+                                     this->fvElemGeom_(),
+                                     scvIdx,
+                                     this->curVolVars_() );
+        const VolumeVariables &volVars = this->curVolVars_(scvIdx);
+
+        PrimaryVariables tmp(0);
+        MassResid::computeSource(tmp, volVars);
+        source += tmp;
+
+        tmp = 0.;
+        EnergyResid::computeSource(tmp, volVars);
+        source += tmp;
+        Valgrind::CheckDefined(source);
+     };
+
+
+    /*!
+     * \brief Evaluates the total flux of all conservation quantities
+     *        over a face of a subcontrol volume.
+     */
+    void computeFlux(PrimaryVariables &flux, int faceIdx) const
+    {
+        FluxVariables fluxVars(this->problem_(),
+                               this->elem_(),
+                               this->fvElemGeom_(),
+                               faceIdx,
+                               this->curVolVars_());
+
+        flux = 0.0;
+        MassResid::computeFlux(flux, fluxVars, this->curVolVars_() );
+        Valgrind::CheckDefined(flux);
+/*
+ *      EnergyResid also called in the MassResid
+ *      1) Makes some sense because energy is also carried by mass
+ *      2) The component-wise mass flux in each phase is needed.
+ */
+    }
+
+    /*!
+     * \brief Compute the local residual, i.e. the deviation of the
+     *        equations from zero.
+     */
+    void eval(const Element &element)
+    { ParentType::eval(element); }
+
+    /*!
+     * \brief Evaluate the local residual.
+     */
+    void eval(const Element &element,
+              const FVElementGeometry &fvGeom,
+              const ElementVolumeVariables &prevVolVars,
+              const ElementVolumeVariables &curVolVars,
+              const ElementBoundaryTypes &bcType)
+    {
+        ParentType::eval(element,
+                         fvGeom,
+                         prevVolVars,
+                         curVolVars,
+                         bcType);
+
+        for (int i = 0; i < this->fvElemGeom_().numVertices; ++i) {
+            // add the two auxiliary equations, make sure that the
+            // dirichlet boundary condition is conserved
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            {
+                if (!bcType[i].isDirichlet(phase0NcpIdx + phaseIdx))
+                {
+                    this->residual_[i][phase0NcpIdx + phaseIdx] =
+                        this->curVolVars_(i).phaseNcp(phaseIdx);
+                }
+            }
+        }
+    }
+
+protected:
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcmodel.hh b/dumux/boxmodels/MpNc/MpNcmodel.hh
new file mode 100644
index 0000000000000000000000000000000000000000..0d50817d39d9b310ad3ac04deb561c639f1727ef
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcmodel.hh
@@ -0,0 +1,201 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_MODEL_HH
+#define DUMUX_MPNC_MODEL_HH
+
+#include "MpNcproperties.hh"
+#include "MpNcvtkwriter.hh"
+
+#include <dumux/boxmodels/common/boxmodel.hh>
+#include <array>
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxProblems
+ * \defgroup MPNCProblems Two-phase three-component box problems
+ */
+
+/*!
+ * \ingroup BoxModels
+ * \defgroup MPNCModel Two-phase three-component box model
+ */
+
+/*!
+ * \ingroup MPNCModel
+ * \brief Adaption of the box scheme to compositional twophase flows.
+ *
+ * This model implements a two-phase flow of a fluid mixture composed
+ * of \f$N\f$ chemical species. The phases are denoted by \f$\alpha
+ * \in \{ l, g \}\f$ for liquid and gas. The liquid and the gas phase
+ * both are a mixture of of \f$N \geq 2\f$ species. The model assumes,
+ * a fluid configuration of a solvent species and \f$N-1\f$ solute
+ * species with very low solubility.
+ *
+ * The standard multiphase Darcy approach is used as the equation for
+ * the conservation of momentum:
+ * \f[
+     v_\alpha = - \frac{k_{r\alpha}}{\mu_\alpha} \boldsymbol{K}
+     \left(\text{grad} p_\alpha - \varrho_{\alpha} \boldsymbol{g} \right)
+ * \f]
+ *
+ * By inserting this into the equations for the conservation of the
+ * components, one gets one transport equation for each component \f$\kappa\f$
+ * \f{eqnarray*}
+    && \sum_{\kappa \in \alpha} \left(
+    %
+    \phi \frac{\partial \varrho_\alpha x_{\alpha\kappa} S_\alpha}{\partial t}
+    -
+    \nabla \cdot
+    \left\{
+       \frac{\varrho_\alpha}{\overline M_\alpha} x_{\alpha\kappa}
+       \frac{k_{r\alpha}}{\mu_\alpha} \boldsymbol{K}
+       (\nabla p_\alpha - \varrho_{\alpha} \boldsymbol{g})
+    \right\}
+    \left)
+    \nonumber \\
+    \nonumber \
+    &-& \sum_{\kappa \in \ \nabla \cdot \left\{{\bf D_{pm}^\kappa} \frac{\varrho_{\alpha}}{\overline M_\alpha} {\bf \nabla} x^\kappa_{\alpha} \right\}
+    - \sum_{\kappa \in \alpha} q_\alpha^\kappa = \quad 0 \qquad \kappa \in \{1, \dots, N\} \, ,
+    \alpha \in \{l, g\}
+    \f}
+ * with \f$\overline M_\alpha\f$ being the average molar mass of the phase \f$\alpha\f$:
+ * \f[ \overline M_\alpha = \sum_{\kappa = 1}^N M_\kappa \; x_{\alpha\kappa} \f]
+ *
+ * This is discretized in the model using the fully-coupled vertex
+ * centered finite volume (box) scheme as spatial and
+ * the implicit Euler method as temporal discretization.
+ *
+ * The model uses \f$x_{l1}, \dots, x_{lN}, S_g, p_g \f$ as primary
+ * variables. \f$x_{g\kappa}\f$ is calculated using Henry's law (if
+ * the componentis a solute), or the vapor pressure (if \f$\kappa\f$
+ * is the solvent) as \f$\beta_\kappa\f$, the constant of
+ * proportionality between the liquid mole fraction and the partial
+ * pressure of a component:
+ * \f[ x_{g\kappa} = \frac{\beta_kappa x_{l\kappa}}{\sum_{i=1}^N x_{l\kappa} \beta_kappa} \f]
+ *
+ * Additionally two auxiliary conditions are used to keep the solution physical.
+ * \TODO: describe NCP approach
+ */
+template<class TypeTag>
+class MPNCModel : public BoxModel<TypeTag>
+{
+    typedef MPNCModel<TypeTag> ThisType;
+    typedef BoxModel<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementBoundaryTypes)) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SolutionVector)) SolutionVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+    typedef Dune::BlockVector<Dune::FieldVector<Scalar, 1> > ScalarField;
+
+    typedef Dumux::MPNCVtkWriter<TypeTag> MPNCVtkWriter;
+
+
+    enum {
+        enableEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)),
+        enableDiffusion = GET_PROP_VALUE(TypeTag, PTAG(EnableDiffusion)),
+        enableKinetic = GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)),
+        enableKineticEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy)),
+        enableSmoothUpwinding = GET_PROP_VALUE(TypeTag, PTAG(EnableSmoothUpwinding)),
+        enablePartialReassemble = GET_PROP_VALUE(TypeTag, PTAG(EnablePartialReassemble)),
+        enableJacobianRecycling = GET_PROP_VALUE(TypeTag, PTAG(EnableJacobianRecycling)),
+        numDiffMethod = GET_PROP_VALUE(TypeTag, PTAG(NumericDifferenceMethod)),
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+        numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)),
+        numEq = GET_PROP_VALUE(TypeTag, PTAG(NumEq)),
+        dimWorld = GridView::dimensionworld,
+        dim = GridView::dimension
+    };
+
+public:
+    ~MPNCModel()
+    { delete vtkWriter_; };
+
+    void init(Problem &problem)
+    {
+        ParentType::init(problem);
+        vtkWriter_ = new MPNCVtkWriter(problem);
+
+        if (this->gridView_().comm().rank() == 0)
+            std::cout
+                << "Initializing M-phase N-component model: \n"
+                << "    phases: " << numPhases << "\n"
+                << "    components: " << numComponents << "\n"
+                << "    equations: " << numEq << "\n"
+                << "    kinetic mass transfer: " << enableKinetic<< "\n"
+                << "    kinetic energy transfer: " << enableKineticEnergy<< "\n"
+                << "    diffusion: " << enableDiffusion << "\n"
+                << "    energy equation: " << enableEnergy << "\n"
+                << "    smooth upwinding: " << enableSmoothUpwinding << "\n"
+                << "    partial jacobian reassembly: " << enablePartialReassemble << "\n"
+                << "    numeric differentiation method: " << numDiffMethod << " (-1: backward, 0: central, +1 forward)\n"
+                << "    jacobian recycling: " << enableJacobianRecycling << "\n";
+    }
+
+    /*!
+     * \brief Compute the total storage inside one phase of all
+     *        conservation quantities.
+     */
+    void globalPhaseStorage(PrimaryVariables &dest, int phaseIdx)
+    {
+        dest = 0;
+
+        ElementIterator elemIt = this->gridView_().template begin<0>();
+        const ElementIterator elemEndIt = this->gridView_().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt) {
+            this->localResidual().addPhaseStorage(dest, *elemIt, phaseIdx);
+        };
+
+        this->gridView_().comm().sum(dest);
+    }
+
+    /*!
+     * \brief Add the result of the current timestep to the VTK output.
+     */
+    template <class MultiWriter>
+    void addOutputVtkFields(const SolutionVector &sol,
+                            MultiWriter &writer)
+    {
+        vtkWriter_->addCurrentSolution(writer);
+    }
+
+    MPNCVtkWriter *vtkWriter_;
+};
+
+}
+
+#include "MpNcpropertydefaults.hh"
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcnewtoncontroller.hh b/dumux/boxmodels/MpNc/MpNcnewtoncontroller.hh
new file mode 100644
index 0000000000000000000000000000000000000000..2977cd89d18cc9053cdbd64494ea04313b38c38e
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcnewtoncontroller.hh
@@ -0,0 +1,273 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Copyright (C) 2008 by Bernd Flemisch                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 MpNc specific controller for the newton solver.
+ *
+ * This controller 'knows' what a 'physically meaningful' solution is
+ * which allows the newton method to abort quicker if the solution is
+ * way out of bounds.
+ */
+#ifndef DUMUX_MPNC_NEWTON_CONTROLLER_HH
+#define DUMUX_MPNC_NEWTON_CONTROLLER_HH
+
+#include "MpNcproperties.hh"
+
+#include <dumux/nonlinear/newtoncontroller.hh>
+#include <algorithm>
+
+namespace Dumux {
+
+template <class TypeTag, bool enableKinetic /* = false */>
+class MpNcNewtonChop
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SolutionVector)) SolutionVector;
+
+    enum { numPhases =  GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents =  GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { fug0Idx = Indices::fug0Idx };
+    enum { S0Idx = Indices::S0Idx };
+    enum { p0Idx = Indices::p0Idx };
+
+public:
+    static void chop(SolutionVector &uCurrentIter,
+                     const SolutionVector &uLastIter)
+    {
+        for (int i = 0; i < uLastIter.size(); ++i) {
+            for (int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx)
+                saturationChop_(uCurrentIter[i][S0Idx + phaseIdx],
+                                uLastIter[i][S0Idx + phaseIdx]);
+            pressureChop_(uCurrentIter[i][p0Idx], uLastIter[i][p0Idx]);
+            for (int comp = 0; comp < numComponents; ++comp) {
+                pressureChop_(uCurrentIter[i][fug0Idx + comp], uLastIter[i][fug0Idx + comp]);
+            }
+
+        }
+    };
+
+private:
+    static void clampValue_(Scalar &val, Scalar minVal, Scalar maxVal)
+    {
+        val = std::max(minVal, std::min(val, maxVal));
+    };
+
+    static void pressureChop_(Scalar &val, Scalar oldVal)
+    {
+        const Scalar maxDelta = std::max(oldVal/4.0, 10e3);
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        val = std::max(0.0, val); // don't allow negative pressures
+    }
+
+    static void saturationChop_(Scalar &val, Scalar oldVal)
+    {
+        const Scalar maxDelta = 0.25;
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        clampValue_(val, -0.001, 1.001);
+    }
+
+};
+
+template <class TypeTag>
+class MpNcNewtonChop<TypeTag, /*enableKinetic=*/true>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SolutionVector)) SolutionVector;
+
+    enum { numPhases =  GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents =  GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { moleFrac00Idx = Indices::moleFrac00Idx };
+    enum { S0Idx = Indices::S0Idx };
+    enum { p0Idx = Indices::p0Idx };
+
+public:
+    static void chop(SolutionVector &uCurrentIter,
+                     const SolutionVector &uLastIter)
+    {
+        for (int i = 0; i < uLastIter.size(); ++i) {
+            for (int phaseIdx = 0; phaseIdx < numPhases - 1; ++phaseIdx)
+                saturationChop_(uCurrentIter[i][S0Idx + phaseIdx],
+                                uLastIter[i][S0Idx + phaseIdx]);
+            pressureChop_(uCurrentIter[i][p0Idx], uLastIter[i][p0Idx]);
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                    moleFracChop_(uCurrentIter[i][moleFrac00Idx + phaseIdx*numComponents + compIdx],
+                                  uLastIter[i][moleFrac00Idx + phaseIdx*numComponents + compIdx]);
+                }
+            };
+
+        }
+    };
+
+private:
+    static void clampValue_(Scalar &val, Scalar minVal, Scalar maxVal)
+    {
+        val = std::max(minVal, std::min(val, maxVal));
+    };
+
+    static void pressureChop_(Scalar &val, Scalar oldVal)
+    {
+        const Scalar maxDelta = std::max(oldVal/4.0, 10e3);
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        val = std::max(0.0, val); // don't allow negative pressures
+    }
+
+    static void saturationChop_(Scalar &val, Scalar oldVal)
+    {
+        const Scalar maxDelta = 0.25;
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        clampValue_(val, -0.001, 1.001);
+    }
+
+    static void moleFracChop_(Scalar &val, Scalar oldVal)
+    {
+        // no component mole fraction can change by more than 20% per iteration
+        const Scalar maxDelta = 0.20;
+        clampValue_(val, oldVal - maxDelta, oldVal + maxDelta);
+        clampValue_(val, -0.001, 1.001);
+    }
+
+};
+
+/*!
+ * \brief A MpNc 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 MPNCNewtonController : public NewtonController<TypeTag>
+{
+    typedef MPNCNewtonController<TypeTag> ThisType;
+    typedef NewtonController<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SolutionVector)) SolutionVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(NewtonMethod)) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(JacobianAssembler)) JacobianAssembler;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+
+    enum {
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+        numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)),
+        enableEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)),
+        enableKinetic = GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)),
+        numEq = GET_PROP_VALUE(TypeTag, PTAG(NumEq)),
+
+        enablePartialReassemble = GET_PROP_VALUE(TypeTag, PTAG(EnablePartialReassemble)),
+
+        p0Idx = Indices::p0Idx,
+        S0Idx = Indices::S0Idx,
+
+        Red = JacobianAssembler::Red
+    };
+
+    typedef MpNcNewtonChop<TypeTag, enableKinetic> NewtonChop;
+
+public:
+    MPNCNewtonController(const Problem &problem)
+        : ParentType(problem)
+    { 
+        enableChop_ = GET_PARAM(TypeTag, bool, Newton, EnableChop);
+        Dune::FMatrixPrecision<>::set_singular_limit(1e-35);
+    };
+
+    void newtonUpdate(SolutionVector &uCurrentIter,
+                      const SolutionVector &uLastIter,
+                      const SolutionVector &deltaU)
+    {
+        this->writeConvergence_(uLastIter, deltaU);
+        this->newtonUpdateRelError(uLastIter, deltaU);
+
+        // compute the vertex and element colors for partial
+        // reassembly
+        if (enablePartialReassemble) {
+            Scalar minReasmTol = 0.5*this->tolerance_;
+            Scalar reassembleTol = Dumux::geometricMean(this->error_, minReasmTol);
+            reassembleTol = std::max(reassembleTol, minReasmTol);
+
+            this->model_().jacobianAssembler().updateDiscrepancy(uLastIter, deltaU);
+            this->model_().jacobianAssembler().computeColors(reassembleTol);
+        }
+
+        if (GET_PROP_VALUE(TypeTag, PTAG(NewtonUseLineSearch))) {
+            lineSearchUpdate_(uCurrentIter, uLastIter, deltaU);
+        }
+        else {
+            Scalar lambda = 1.0;
+            /*
+            if (this->error_ > 10) {
+                // Do a "poor man's line search"
+                lambda /= std::sqrt((this->numSteps_ + 1)*this->error_/10);
+                lambda = std::max(0.2, lambda);
+            }
+            */
+
+            uCurrentIter = deltaU;
+            uCurrentIter *= - lambda;
+            uCurrentIter += uLastIter;
+
+            if (this->numSteps_ < 4 && enableChop_) {
+                // put crash barriers along the update path at the
+                // beginning...
+                NewtonChop::chop(uCurrentIter, uLastIter);
+            }
+        }
+    }
+
+private:
+    void lineSearchUpdate_(SolutionVector &uCurrentIter,
+                           const SolutionVector &uLastIter,
+                           const SolutionVector &deltaU)
+    {
+       Scalar lambda = 1.0;
+       Scalar globDef;
+
+       SolutionVector tmp(uLastIter);
+       Scalar oldGlobDef = this->model_().globalResidual(tmp, uLastIter);
+       while (true) {
+           uCurrentIter  = deltaU;
+           uCurrentIter *= -lambda;
+           uCurrentIter += uLastIter;
+
+           globDef = this->model_().globalResidual(tmp, uCurrentIter);
+           if (globDef < oldGlobDef || lambda <= 1.0/64) {
+               this->endIterMsg() << ", defect " << oldGlobDef << "->"  << globDef << "@lambda=1/" << 1/lambda;
+               return;
+           }
+
+           // try with a smaller update
+           lambda /= 2;
+       }
+    };
+
+    bool enableChop_;
+};
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcproblem.hh b/dumux/boxmodels/MpNc/MpNcproblem.hh
new file mode 100644
index 0000000000000000000000000000000000000000..11b8a458ecf6416fae64e9543ec99e5077503e9a
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcproblem.hh
@@ -0,0 +1,179 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Base class for all problems which use the two-phase,
+ *        three-component box model
+ */
+#ifndef DUMUX_MPNC_BOX_PROBLEM_HH
+#define DUMUX_MPNC_BOX_PROBLEM_HH
+
+#include "dumux/boxmodels/MpNc/MpNcnewtoncontroller.hh"
+
+#include <dumux/boxmodels/common/boxproblem.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCProblems
+ * \brief  Base class for all problems which use the two-phase, three-component box model
+ *
+ * \todo Please doc me more!
+ */
+template<class TypeTag>
+class MPNCProblem : public BoxProblem<TypeTag>
+{
+    typedef BoxProblem<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::Grid Grid;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(TimeManager)) TimeManager;
+
+    // material properties
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) SpatialParameters;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+
+    enum {
+        dim = Grid::dimension,
+        dimWorld = Grid::dimensionworld
+    };
+
+    typedef Dune::FieldVector<typename GridView::Grid::ctype, dimWorld>      GlobalPosition;
+
+public:
+    MPNCProblem(TimeManager &timeManager, const GridView &gridView)
+        : ParentType(timeManager, gridView),
+          gravity_(0),
+          spatialParameters_(gridView)
+    {
+        if (GET_PROP_VALUE(TypeTag, PTAG(EnableGravity)))
+            gravity_[dim-1]  = -9.81;
+    }
+
+    /*!
+     * \name Problem parameters
+     */
+    // \{
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ within a control volume.
+     *
+     * This is the discretization specific interface for the box
+     * method. By default it just calls temperature(pos).
+     *
+     * \param element The DUNE Codim<0> enitiy which intersects with
+     *                the finite volume.
+     * \param fvGeom The finite volume geometry of the element.
+     * \param scvIdx The local index of the sub control volume inside the element
+     */
+    Scalar boxTemperature(const Element &element,
+                          const FVElementGeometry fvGeom,
+                          int scvIdx) const
+    { return asImp_().temperatureAtPos(fvGeom.subContVol[scvIdx].global); }
+    
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ at a given global position.
+     *
+     * This is not specific to the discretization. By default it just
+     * calls temperature().
+     *
+     * \param pos The position in global coordinates where the temperature should be specified.
+     */
+    Scalar temperatureAtPos(const GlobalPosition &pos) const
+    { return asImp_().temperature(); }
+
+    /*!
+     * \brief Returns the temperature \f$\mathrm{[K]}\f$ for an isothermal problem.
+     *
+     * This is not specific to the discretization. By default it just
+     * throws an exception so it must be overloaded by the problem if
+     * no energy equation is used.
+     */
+    Scalar temperature() const
+    { DUNE_THROW(Dune::NotImplemented, "temperature() method not implemented by the actual problem"); };
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This is the box discretization specific interface. By default
+     * it just calls gravityAtPos().
+     */
+    const GlobalPosition &boxGravity(const Element &element,
+                                     const FVElementGeometry &fvGeom,
+                                     int scvIdx) const
+    { return asImp_().gravityAtPos(fvGeom.subContVol[scvIdx].global); }
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This is discretization independent interface. By default it
+     * just calls gravity().
+     */
+    const GlobalPosition &gravityAtPos(const GlobalPosition &pos) const
+    { return asImp_().gravity(); }
+
+    /*!
+     * \brief Returns the acceleration due to gravity \f$\mathrm{[m/s^2]}\f$.
+     *
+     * This method is used for problems where the gravitational
+     * acceleration does not depend on the spatial position. The
+     * default behaviour is that if the <tt>EnableGravity</tt>
+     * property is true, \f$\boldsymbol{g} = ( 0,\dots,\ -9.81)^T \f$ holds,
+     * else \f$\boldsymbol{g} = ( 0,\dots, 0)^T \f$.
+     */
+    const GlobalPosition &gravity() const
+    { return gravity_; }
+
+    /*!
+     * \brief Returns the spatial parameters object.
+     */
+    SpatialParameters &spatialParameters()
+    { return spatialParameters_; }
+
+    /*!
+     * \copydoc spatialParameters()
+     */
+    const SpatialParameters &spatialParameters() const
+    { return spatialParameters_; }
+
+    // \}
+
+protected:
+    //! Returns the implementation of the problem (i.e. static polymorphism)
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+
+    //! \copydoc asImp_()
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+
+    GlobalPosition gravity_;
+
+    // fluids and material properties
+    SpatialParameters spatialParameters_;
+};
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcproperties.hh b/dumux/boxmodels/MpNc/MpNcproperties.hh
new file mode 100644
index 0000000000000000000000000000000000000000..40edab43e95b44eb195e8f2fd6dfc4b3b7534b84
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcproperties.hh
@@ -0,0 +1,113 @@
+/*****************************************************************************
+ *   Copyright (C) 2008-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_PROPERTIES_HH
+#define DUMUX_MPNC_PROPERTIES_HH
+
+#include <dumux/boxmodels/common/boxproperties.hh>
+
+namespace Dumux
+{
+namespace Properties
+{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+/*!
+ * \brief Define the type tag for the compositional twophase box model.
+ */
+NEW_TYPE_TAG(BoxMPNC, 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(MPNCIndices); //!< Enumerations for the 2pNc model
+NEW_PROP_TAG(MPNCEnergyIndices); //!< Enumerations for the 2pNc model
+
+NEW_PROP_TAG(MPNCVtkCommonModule); //!< Vtk writer module for writing the common quantities into the VTK output file
+NEW_PROP_TAG(MPNCVtkMassModule); //!< Vtk writer module for writing the mass related quantities into the VTK output file
+NEW_PROP_TAG(MPNCVtkEnergyModule); //!< Vtk writer module for writing the energy related quantities into the VTK output file
+NEW_PROP_TAG(MPNCVtkCustomModule); //!< Vtk writer module for writing the user-specified quantities into the VTK output file
+
+NEW_PROP_TAG(VelocityAveragingInProblem);//!< Should the averaging of velocities be done in the problem?
+
+//! specify which quantities are written to the vtk output files
+NEW_PROP_TAG(MPNCVtkAddPorosity);
+NEW_PROP_TAG(MPNCVtkAddBoundaryTypes);
+NEW_PROP_TAG(MPNCVtkAddSaturations);
+NEW_PROP_TAG(MPNCVtkAddPressures);
+NEW_PROP_TAG(MPNCVtkAddVarPressures);
+NEW_PROP_TAG(MPNCVtkAddVelocities);
+NEW_PROP_TAG(MPNCVtkAddDensities);
+NEW_PROP_TAG(MPNCVtkAddMobilities);
+NEW_PROP_TAG(MPNCVtkAddMeanMolarMass);
+NEW_PROP_TAG(MPNCVtkAddMassFractions);
+NEW_PROP_TAG(MPNCVtkAddMoleFractions);
+NEW_PROP_TAG(MPNCVtkAddMolarities);
+NEW_PROP_TAG(MPNCVtkAddFugacities);
+NEW_PROP_TAG(MPNCVtkAddFugacityCoefficients);
+NEW_PROP_TAG(MPNCVtkAddTemperatures);
+NEW_PROP_TAG(MPNCVtkAddEnthalpies);
+NEW_PROP_TAG(MPNCVtkAddInternalEnergies);
+
+NEW_PROP_TAG(MPNCVtkAddReynolds);
+NEW_PROP_TAG(MPNCVtkAddPrandtl);
+NEW_PROP_TAG(MPNCVtkAddNusselt);
+NEW_PROP_TAG(MPNCVtkAddInterfacialArea);
+
+NEW_PROP_TAG(SpatialParameters); //!< The type of the soil properties object
+
+NEW_PROP_TAG(MaterialLaw);   //!< The material law which ought to be used (extracted from the soil)
+NEW_PROP_TAG(MaterialLawParams); //!< The context material law (extracted from the soil)
+
+//! The compositional twophase system of fluids which is considered
+NEW_PROP_TAG(FluidSystem);
+
+//! The themodynamic constraint solver which calculates the
+//! composition of any phase given all component fugacities.
+NEW_PROP_TAG(CompositionFromFugacitiesSolver);
+
+//! Enable the energy equation?
+NEW_PROP_TAG(EnableEnergy);
+
+//! Enable diffusive fluxes?
+NEW_PROP_TAG(EnableDiffusion);
+
+//! Enable kinetic resolution of mass transfer processes?
+NEW_PROP_TAG(EnableKinetic);
+
+//! Enable kinetic resolution of energy transfer processes?
+NEW_PROP_TAG(EnableKineticEnergy);
+
+//! Enable gravity?
+NEW_PROP_TAG(EnableGravity);
+
+//! Use the smooth upwinding method?
+NEW_PROP_TAG(EnableSmoothUpwinding);
+
+//! Chop the Newton update at the beginning of the non-linear solver?
+NEW_PROP_TAG(NewtonEnableChop);
+}
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcpropertydefaults.hh b/dumux/boxmodels/MpNc/MpNcpropertydefaults.hh
new file mode 100644
index 0000000000000000000000000000000000000000..f3e912a486f87eeba6f68ea8e9e164ebe9d50ad2
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcpropertydefaults.hh
@@ -0,0 +1,226 @@
+/*****************************************************************************
+ *   Copyright (C) 2008-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_PROPERTY_DEFAULTS_HH
+#define DUMUX_MPNC_PROPERTY_DEFAULTS_HH
+
+#include "MpNcindices.hh"
+
+#include "MpNcmodel.hh"
+
+#include "MpNcproblem.hh"
+#include "MpNcindices.hh"
+#include "MpNclocalresidual.hh"
+#include "MpNcfluxvariables.hh"
+#include "MpNcvolumevariables.hh"
+#include "MpNcproperties.hh"
+#include "MpNcnewtoncontroller.hh"
+
+#include "MpNcvtkwritermodule.hh"
+#include "MpNcvtkwritercommon.hh"
+#include "mass/MpNcvtkwritermass.hh"
+#include "energy/MpNcvtkwriterenergy.hh"
+
+#include <dumux/material/constraintsolvers/compositionfromfugacities.hh>
+
+namespace Dumux
+{
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// default property values
+//////////////////////////////////////////////////////////////////
+
+/*!
+ * \brief Set the property for the number of components.
+ *
+ * We just forward the number from the fluid system.
+ */
+SET_PROP(BoxMPNC, NumComponents)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+public:
+    static const int value = FluidSystem::numComponents;
+};
+
+/*!
+ * \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(BoxMPNC, NumPhases)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+public:
+    static const int value = FluidSystem::numPhases;
+};
+
+/*!
+ * \brief Set the property for the number of equations and primary variables.
+ */
+SET_PROP(BoxMPNC, NumEq)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+
+public:
+    static const int value = Indices::NumPrimaryVars;
+};
+
+/*!
+ * \brief Set the property for the material parameters by extracting
+ *        it from the material law.
+ */
+SET_PROP(BoxMPNC, MaterialLawParams)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MaterialLaw)) MaterialLaw;
+
+public:
+    typedef typename MaterialLaw::Params type;
+};
+
+/*!
+ * \brief Set the themodynamic constraint solver which calculates the
+ *        composition of any phase given all component fugacities.
+ */
+SET_PROP(BoxMPNC, CompositionFromFugacitiesSolver)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+public:
+    typedef Dumux::CompositionFromFugacities<Scalar, FluidSystem> type;
+};
+
+//! Use the MpNc local jacobian operator for the MpNc model
+SET_TYPE_PROP(BoxMPNC,
+              LocalResidual,
+              MPNCLocalResidual<TypeTag>);
+
+//! Use the MpNc specific newton controller for the MpNc model
+SET_PROP(BoxMPNC, NewtonController)
+{public:
+    typedef MPNCNewtonController<TypeTag> type;
+};
+
+//! the Model property
+SET_TYPE_PROP(BoxMPNC, Model, MPNCModel<TypeTag>);
+
+//! use an isothermal model by default
+SET_BOOL_PROP(BoxMPNC, EnableEnergy, false);
+
+//! disable diffusion by default
+SET_BOOL_PROP(BoxMPNC, EnableDiffusion, false);
+
+//! disable kinetic mass transfer by default
+SET_BOOL_PROP(BoxMPNC, EnableKinetic, false);
+
+//! disable kinetic energy transfer by default
+SET_BOOL_PROP(BoxMPNC, EnableKineticEnergy, false);
+
+//! enable smooth upwinding by default
+SET_BOOL_PROP(BoxMPNC, EnableSmoothUpwinding, true);
+
+//! the VolumeVariables property
+SET_TYPE_PROP(BoxMPNC, VolumeVariables, MPNCVolumeVariables<TypeTag>);
+
+//! the FluxVariables property
+SET_TYPE_PROP(BoxMPNC, FluxVariables, MPNCFluxVariables<TypeTag>);
+
+// enable jacobian matrix recycling by default
+SET_BOOL_PROP(BoxMPNC, EnableJacobianRecycling, false);
+// enable partial reassembling by default
+SET_BOOL_PROP(BoxMPNC, EnablePartialReassemble, true);
+// truncate the newton update in the beginning
+SET_BOOL_PROP(BoxMPNC, NewtonEnableChop, true);
+
+
+//! The indices required by the compositional twophase model
+SET_PROP(BoxMPNC, MPNCIndices)
+{
+    typedef MPNCIndices<TypeTag, 0> type;
+};
+
+//! The VTK writer module for common quantities
+SET_PROP(BoxMPNC, MPNCVtkCommonModule)
+{
+    typedef MPNCVtkWriterCommon<TypeTag> type;
+};
+
+//! The VTK writer module for quantities which are specific for each
+//! mass module
+SET_PROP(BoxMPNC, MPNCVtkMassModule)
+{
+private: enum { enableKinetic = GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)) };
+public: typedef MPNCVtkWriterMass<TypeTag, enableKinetic> type;
+};
+
+//! The VTK writer module for quantities which are specific for each
+//! energy module
+SET_PROP(BoxMPNC, MPNCVtkEnergyModule)
+{
+private:
+    enum { enableEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)) };
+    enum { enableKineticEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy)) };
+public:
+    typedef MPNCVtkWriterEnergy<TypeTag, enableEnergy, enableKineticEnergy> type;
+};
+
+//! The VTK writer for user specified data (does nothing by default)
+SET_PROP(BoxMPNC, MPNCVtkCustomModule)
+{ typedef MPNCVtkWriterModule<TypeTag> type; };
+
+
+//!< Should the averaging of velocities be done in the problem? (By default in the output)
+SET_BOOL_PROP(BoxMPNC, VelocityAveragingInProblem, false);
+
+//! Specify what to add to the VTK output by default
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddPorosity, true);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddBoundaryTypes, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddSaturations, true);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddPressures, true);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddVarPressures, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddVelocities, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddDensities, true);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddMobilities, true);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddMeanMolarMass, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddMassFractions, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddMoleFractions, true);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddMolarities, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddFugacities, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddFugacityCoefficients, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddTemperatures, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddEnthalpies, true);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddInternalEnergies, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddReynolds, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddPrandtl, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddNusselt, false);
+SET_BOOL_PROP(BoxMPNC, MPNCVtkAddInterfacialArea, false);
+}
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcvolumevariables.hh b/dumux/boxmodels/MpNc/MpNcvolumevariables.hh
new file mode 100644
index 0000000000000000000000000000000000000000..9df8e9f3d2740d59783f0a79baa8b4d66292717a
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcvolumevariables.hh
@@ -0,0 +1,359 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2011 by Andreas Lauser                               *
+ *   Copyright (C) 2008-2009 by Klaus Mosthaf,                               *
+ *   Copyright (C) 2008-2009 by Bernd Flemisch                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 secondary variables (Quantities which are
+ *        constant within a finite volume) of the M-phase, N-component
+ *        model.
+ */
+#ifndef DUMUX_MPNC_VOLUME_VARIABLES_HH
+#define DUMUX_MPNC_VOLUME_VARIABLES_HH
+
+#include "diffusion/volumevariables.hh"
+#include "energy/MpNcvolumevariablesenergy.hh"
+#include "mass/MpNcvolumevariablesmass.hh"
+#include "MpNcvolumevariablesia.hh"
+
+#include <dumux/boxmodels/common/boxvolumevariables.hh>
+
+namespace Dumux
+{
+/*!
+ * \brief Contains the quantities which are are constant within a
+ *        finite volume in the M-phase, N-component model.
+ */
+template <class TypeTag>
+class MPNCVolumeVariables
+    : public BoxVolumeVariables<TypeTag>
+    , public MPNCVolumeVariablesIA<TypeTag, GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)), GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy))>
+    , public MPNCVolumeVariablesMass<TypeTag, GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic))>
+    , public MPNCVolumeVariablesDiffusion<TypeTag, GET_PROP_VALUE(TypeTag, PTAG(EnableDiffusion)) || GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic))>
+    , public MPNCVolumeVariablesEnergy<TypeTag, GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)), GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy))>
+{
+    typedef BoxVolumeVariables<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MaterialLaw)) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MaterialLawParams)) MaterialLawParams;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SpatialParameters)) SpatialParameters;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+    enum {
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+        numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)),
+        dimWorld = GridView::dimensionworld,
+
+        enableEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)),
+        enableKinetic = GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic)),
+        enableKineticEnergy = GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy)),
+        enableDiffusion = GET_PROP_VALUE(TypeTag, PTAG(EnableDiffusion)) || enableKinetic,
+
+        numEnergyEqs     = Indices::NumPrimaryEnergyVars,
+
+        S0Idx = Indices::S0Idx,
+        p0Idx = Indices::p0Idx,
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    typedef MPNCVolumeVariablesMass<TypeTag, enableKinetic> MassVolumeVariables;
+    typedef MPNCVolumeVariablesEnergy<TypeTag, enableEnergy, enableKineticEnergy> EnergyVolumeVariables;
+    typedef MPNCVolumeVariablesIA<TypeTag, enableKinetic, enableKineticEnergy> IAVolumeVariables;
+    typedef MPNCVolumeVariablesDiffusion<TypeTag, enableDiffusion> DiffusionVolumeVariables;
+
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+
+public:
+    //! The return type of the fluidState() method
+    typedef typename MassVolumeVariables::FluidState FluidState;
+
+    MPNCVolumeVariables()
+    { hint_ = NULL; };
+
+    /*!
+     * \brief Set the volume variables which should be used as initial
+     *        conditions for complex calculations.
+     */
+    void setHint(const Implementation *hint)
+    {
+        hint_ = hint;
+    }
+
+    /*!
+     * \brief Update all quantities for a given control volume.
+     */
+    void update(const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &elemGeom,
+                int scvIdx,
+                bool isOldSol)
+    {
+        Valgrind::CheckDefined(priVars);
+        ParentType::update(priVars,
+                           problem,
+                           element,
+                           elemGeom,
+                           scvIdx,
+                           isOldSol);
+
+        typename FluidSystem::MutableParameters mutParams;
+
+        /////////////
+        // set the phase saturations
+        /////////////
+        Scalar sumSat = 0;
+        for (int i = 0; i < numPhases - 1; ++i) {
+            sumSat += priVars[S0Idx + i];
+            mutParams.setSaturation(i, priVars[S0Idx + i]);
+        }
+        Valgrind::CheckDefined(sumSat);
+        mutParams.setSaturation(numPhases - 1, 1.0 - sumSat);
+
+        /////////////
+        // set the fluid phase temperatures
+        /////////////
+        // update the temperature part of the energy module
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx){
+            Scalar T = EnergyVolumeVariables::getTemperature(priVars,
+                                                             element,
+                                                             elemGeom,
+                                                             scvIdx,
+                                                             problem,
+                                                             phaseIdx);
+            mutParams.setTemperature(phaseIdx, T);
+        }
+
+        /////////////
+        // set the phase pressures
+        /////////////
+
+        // capillary pressure parameters
+        const MaterialLawParams &materialParams =
+            problem.spatialParameters().materialLawParams(element, elemGeom, scvIdx);
+        // capillary pressures
+        Scalar capPress[numPhases];
+        MaterialLaw::capillaryPressures(capPress, materialParams, mutParams);
+        // add to the pressure of the first fluid phase
+        Scalar p0 = priVars[p0Idx];
+        for (int i = 0; i < numPhases; ++ i)
+            mutParams.setPressure(i, p0 - capPress[0] + capPress[i]);
+
+        /////////////
+        // set the fluid compositions
+        /////////////
+        MassVolumeVariables::update(mutParams,
+                                    priVars,
+                                    hint_,
+                                    problem,
+                                    element,
+                                    elemGeom,
+                                    scvIdx);
+        MassVolumeVariables::checkDefined();
+        ParentType::checkDefined();
+
+        /////////////
+        // Porosity
+        /////////////
+
+        // porosity
+        porosity_ = problem.spatialParameters().porosity(element,
+                                                         elemGeom,
+                                                         scvIdx);
+        Valgrind::CheckDefined(porosity_);
+        ParentType::checkDefined();
+
+        /////////////
+        // Phase mobilities
+        /////////////
+
+        // relative permeabilities
+        MaterialLaw::relativePermeabilities(relativePermeability_,
+                                            materialParams, 
+                                            mutParams);
+
+        // dynamic viscosities
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // viscosities
+            Scalar mu = FluidSystem::computeViscosity(mutParams, phaseIdx);
+            mutParams.setViscosity(phaseIdx, mu);
+        }
+        ParentType::checkDefined();
+
+        /////////////
+        // diffusion
+        /////////////
+
+        // update the diffusion part of the volume data
+        DiffusionVolumeVariables::update(mutParams, *this, problem);
+        DiffusionVolumeVariables::checkDefined();
+        ParentType::checkDefined();
+
+        /////////////
+        // energy
+        /////////////
+
+        // update the remaining parts of the energy module
+        EnergyVolumeVariables::update(mutParams,
+                                      priVars,
+                                      element,
+                                      elemGeom,
+                                      scvIdx,
+                                      problem);
+
+        EnergyVolumeVariables::checkDefined();
+        ParentType::checkDefined();
+
+        // specific interfacial area, well also all the dimensionless numbers :-)
+        IAVolumeVariables::update(mutParams,
+                                  priVars,
+                                  problem,
+                                  element,
+                                  elemGeom,
+                                  scvIdx);
+        IAVolumeVariables::checkDefined();
+
+        // assign the fluid state to be stored
+        fluidState_.assign(mutParams);
+        fluidState_.checkDefined();
+        ParentType::checkDefined();
+
+        checkDefined();
+
+        ParentType::checkDefined();
+    }
+
+    /*!
+     * \brief Return the fluid configuration at the given primary
+     *        variables
+     */
+    const FluidState &fluidState() const
+    { return fluidState_; }
+
+    /*!
+     * \brief Returns the effective mobility of a given phase within
+     *        the control volume.
+     */
+    Scalar mobility(int phaseIdx) const
+    { return relativePermability(phaseIdx)/fluidState_.viscosity(phaseIdx); }
+
+    /*!
+     * \brief Returns the viscosity of a given phase within
+     *        the control volume.
+     */
+    Scalar viscosity(int phaseIdx) const
+    { return fluidState_.viscosity(phaseIdx); }
+
+    /*!
+     * \brief Returns the relative permeability of a given phase within
+     *        the control volume.
+     */
+    Scalar relativePermability(int phaseIdx) const
+    { return relativePermeability_[phaseIdx]; }
+
+    /*!
+     * \brief Returns the average porosity within the control volume.
+     */
+    Scalar porosity() const
+    { return porosity_; }
+
+    /*!
+     * \brief Returns true iff the fluid state is in the active set
+     *        for a phase,
+     */
+    bool isPhaseActive(int phaseIdx) const
+    {
+        return
+            phasePresentIneq(fluidState(), phaseIdx) -
+            phaseNotPresentIneq(fluidState(), phaseIdx)
+            >= 0;
+    }
+
+    /*!
+     * \brief Returns the value of the NCP-function for a phase.
+     */
+    Scalar phaseNcp(int phaseIdx) const
+    {
+        Scalar aEval = phaseNotPresentIneq(this->evalPoint().fluidState(), phaseIdx);
+        Scalar bEval = phasePresentIneq(this->evalPoint().fluidState(), phaseIdx);
+        if (aEval > bEval)
+            return phasePresentIneq(fluidState(), phaseIdx);
+        return phaseNotPresentIneq(fluidState(), phaseIdx);
+    };
+
+    /*!
+     * \brief Returns the value of the inequality where a phase is
+     *        present.
+     */
+    Scalar phasePresentIneq(const FluidState &fluidState, int phaseIdx) const
+    { return fluidState.saturation(phaseIdx); }
+
+    /*!
+     * \brief Returns the value of the inequality where a phase is not
+     *        present.
+     */
+    Scalar phaseNotPresentIneq(const FluidState &fluidState, int phaseIdx) const
+    {
+        // difference of sum of mole fractions in the phase from 100%
+        Scalar a = 1;
+        for (int i = 0; i < numComponents; ++i)
+            a -= fluidState.moleFrac(phaseIdx, i);
+        return a;
+    }
+
+    /*!
+     * \brief If running in valgrind this makes sure that all
+     *        quantities in the volume variables are defined.
+     */
+    void checkDefined() const
+    {
+#if !defined NDEBUG && HAVE_VALGRIND
+        ParentType::checkDefined();
+
+        Valgrind::CheckDefined(porosity_);
+        Valgrind::CheckDefined(hint_);
+        Valgrind::CheckDefined(relativePermeability_);
+
+        fluidState_.checkDefined();
+#endif
+    }
+
+protected:
+    Scalar porosity_; //!< Effective porosity within the control volume
+    Scalar relativePermeability_[numPhases]; //!< Effective mobility within the control volume
+
+    const Implementation *hint_;
+
+    //! Mass fractions of each component within each phase
+    FluidState fluidState_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcvolumevariablesia.hh b/dumux/boxmodels/MpNc/MpNcvolumevariablesia.hh
new file mode 100644
index 0000000000000000000000000000000000000000..05bb5dfdaba02ef3f7ebee7ba73d6faeea658ea1
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcvolumevariablesia.hh
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ *   Copyright (C) 2010-2011 by Philipp Nuske                                *
+ *   Copyright (C) 2011 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 This class contains the volume variables required for the
+ *        modules which require the specific interfacial area between
+ *        fluid phases.
+ */
+#ifndef DUMUX_MPNC_VOLUME_VARIABLES_IA_HH
+#define DUMUX_MPNC_VOLUME_VARIABLES_IA_HH
+
+namespace Dumux
+{
+
+/*!
+ * \brief This class contains the volume variables required for the
+ *        modules which require the specific interfacial area between
+ *        fluid phases.
+ *
+ * This is the specialization for the cases which do _not_ require
+ * specific interfacial area.
+ */
+template <class TypeTag, bool enableKinetic /* = false */, bool enableKineticEnergy /* = false */>
+class MPNCVolumeVariablesIA
+{
+    static_assert(!enableKinetic && !enableKineticEnergy,
+                  "The kinetic energy modules need specific interfacial area "
+                  "but no suitable specialization of the IA volume variables module "
+                  "has been included.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+public:
+    /*!
+     * \brief Updates the volume specific interfacial area [m^2 / m^3] between the phases.
+     */
+    template <class MutableParams>
+    void update(const MutableParams & mutParams,
+                const PrimaryVariables &priVars,
+                const Problem &problem,
+                const Element & element,
+                const FVElementGeometry & elemGeom,
+                const int scvIdx)
+    {
+    }
+
+    /*!
+     * \brief If running in valgrind this makes sure that all
+     *        quantities in the volume variables are defined.
+     */
+    void checkDefined() const
+    { }
+};
+
+} // namespace Dumux
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcvtkwriter.hh b/dumux/boxmodels/MpNc/MpNcvtkwriter.hh
new file mode 100644
index 0000000000000000000000000000000000000000..088d57198e715de7f95e5e0ca97c55b29613e62e
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcvtkwriter.hh
@@ -0,0 +1,140 @@
+/*****************************************************************************
+ *   Copyright (C) 2011 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_VTK_WRITER_HH
+#define DUMUX_MPNC_VTK_WRITER_HH
+
+#include "MpNcproperties.hh"
+
+#include <dumux/io/vtkmultiwriter.hh>
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxProblems
+ * \defgroup MPNCProblems Two-phase three-component box problems
+ */
+
+/*!
+ * \ingroup BoxModels
+ * \defgroup MPNCModel Two-phase three-component box model
+ */
+
+/*!
+ * \ingroup MPNCModel
+ * \brief Writes the VTK output files for a
+ * solution of the Mp-Nc model.
+ */
+template<class TypeTag>
+class MPNCVtkWriter
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCVtkCommonModule)) MPNCVtkCommonModule;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCVtkMassModule)) MPNCVtkMassModule;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCVtkEnergyModule)) MPNCVtkEnergyModule;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCVtkCustomModule)) MPNCVtkCustomModule;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementBoundaryTypes)) ElementBoundaryTypes;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    enum { dim = GridView::dimension };
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+
+public:
+    MPNCVtkWriter(const Problem &problem)
+        : problem_(problem)
+        , commonWriter_(problem)
+        , massWriter_(problem)
+        , energyWriter_(problem)
+        , customWriter_(problem)
+    {
+    }
+
+    /*!
+     * \brief Add  the current solution to the VtkMultiWriter.
+     */
+    template <class MultiWriter>
+    void addCurrentSolution(MultiWriter &writer)
+    {
+        // tell sub-writers to allocate their buffers
+        commonWriter_.allocBuffers(writer);
+        massWriter_.allocBuffers(writer);
+        energyWriter_.allocBuffers(writer);
+        customWriter_.allocBuffers(writer);
+
+        // iterate over grid
+        FVElementGeometry fvElemGeom;
+        ElementVolumeVariables elemVolVars;
+        ElementBoundaryTypes elemBcTypes;
+
+        ElementIterator elemIt = problem_.gridView().template begin<0>();
+        ElementIterator elemEndIt = problem_.gridView().template end<0>();
+        for (; elemIt != elemEndIt; ++elemIt)
+        {
+            fvElemGeom.update(problem_.gridView(), *elemIt);
+            elemBcTypes.update(problem_, *elemIt, fvElemGeom);
+            this->problem_.model().setHints(*elemIt, elemVolVars);
+            elemVolVars.update(problem_,
+                               *elemIt,
+                               fvElemGeom,
+                               false);
+            this->problem_.model().updateCurHints(*elemIt, elemVolVars);
+
+            // tell the sub-writers to do what ever they need to with
+            // their internal buffers when a given element is seen.
+            commonWriter_.processElement(*elemIt,
+                                         fvElemGeom,
+                                         elemVolVars,
+                                         elemBcTypes);
+            massWriter_.processElement(*elemIt,
+                                       fvElemGeom,
+                                       elemVolVars,
+                                       elemBcTypes);
+            energyWriter_.processElement(*elemIt,
+                                         fvElemGeom,
+                                         elemVolVars,
+                                         elemBcTypes);
+            customWriter_.processElement(*elemIt,
+                                         fvElemGeom,
+                                         elemVolVars,
+                                         elemBcTypes);
+        }
+
+        // write everything to the output file
+        commonWriter_.commitBuffers(writer);
+        massWriter_.commitBuffers(writer);
+        energyWriter_.commitBuffers(writer);
+        customWriter_.commitBuffers(writer);
+    }
+
+private:
+    const Problem &problem_;
+
+    MPNCVtkCommonModule commonWriter_;
+    MPNCVtkMassModule massWriter_;
+    MPNCVtkEnergyModule energyWriter_;
+    MPNCVtkCustomModule customWriter_;
+};
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcvtkwritercommon.hh b/dumux/boxmodels/MpNc/MpNcvtkwritercommon.hh
new file mode 100644
index 0000000000000000000000000000000000000000..63f91de4470f61a2b8a8a3a78b6d71560cbf5166
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcvtkwritercommon.hh
@@ -0,0 +1,290 @@
+/*****************************************************************************
+ *   Copyright (C) 2011 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 VTK writer module for the common quantities of the MpNc
+ *        model.
+ */
+#ifndef DUMUX_MPNC_VTK_WRITER_COMMON_HH
+#define DUMUX_MPNC_VTK_WRITER_COMMON_HH
+
+#include "MpNcvtkwritermodule.hh"
+
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief VTK writer module for the common quantities of the MpNc
+ *        model.
+ */
+template<class TypeTag>
+class MPNCVtkWriterCommon : public MPNCVtkWriterModule<TypeTag>
+{
+    typedef MPNCVtkWriterModule<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementBoundaryTypes)) ElementBoundaryTypes;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(LocalResidual)) LocalResidual;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+
+    typedef typename ParentType::ScalarBuffer ScalarBuffer;
+    typedef typename ParentType::PhaseBuffer PhaseBuffer;
+    typedef typename ParentType::ComponentBuffer ComponentBuffer;
+    typedef typename ParentType::PhaseComponentBuffer PhaseComponentBuffer;
+
+    enum { numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { numEq = GET_PROP_VALUE(TypeTag, PTAG(NumEq)) };
+
+    enum { velocityAveragingInProblem = GET_PROP_VALUE(TypeTag, PTAG(VelocityAveragingInProblem)) };
+
+    typedef Dune::FieldVector<Scalar, dim> VelocityVector;
+    typedef Dune::BlockVector<VelocityVector> VelocityField;
+    typedef VelocityField VectorField;
+    typedef std::array<VelocityField, numPhases> PhaseVelocityField;
+
+public:
+    MPNCVtkWriterCommon(const Problem &problem)
+        : ParentType(problem)
+    {
+        porosityOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddPorosity);
+        boundaryTypesOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddBoundaryTypes);
+        saturationOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddSaturations);
+        pressureOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddPressures);
+        velocityOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddVelocities);
+        densityOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddDensities);
+        mobilityOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddMobilities);
+        meanMolarMassOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddMeanMolarMass);
+        massFracOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddMassFractions);
+        moleFracOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddMoleFractions);
+        molarityOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddMolarities);
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+        if (porosityOutput_)
+            this->resizeScalarBuffer_(porosity_);
+        if (boundaryTypesOutput_)
+            this->resizeScalarBuffer_(boundaryTypes_);
+
+        if (velocityOutput_) {
+            Scalar nVerts = this->problem_.gridView().size(dim);
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
+                velocity_[phaseIdx].resize(nVerts);
+                velocity_[phaseIdx] = 0;
+            }
+            this->resizeScalarBuffer_(boxSurface_);
+        }
+
+        if (saturationOutput_) this->resizePhaseBuffer_(saturation_);
+        if (pressureOutput_) this->resizePhaseBuffer_(pressure_);
+        if (densityOutput_) this->resizePhaseBuffer_(density_);
+        if (mobilityOutput_) this->resizePhaseBuffer_(mobility_);
+        if (meanMolarMassOutput_) this->resizePhaseBuffer_(meanMolarMass_);
+
+        if (moleFracOutput_) this->resizePhaseComponentBuffer_(moleFrac_);
+        if (massFracOutput_) this->resizePhaseComponentBuffer_(massFrac_);
+        if (molarityOutput_) this->resizePhaseComponentBuffer_(molarity_);
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvElemGeom,
+                        const ElementVolumeVariables &elemVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+        int n = elem.template count<dim>();
+        for (int i = 0; i < n; ++i) {
+            int I = this->problem_.vertexMapper().map(elem, i, dim);
+            const VolumeVariables &volVars = elemVolVars[i];
+
+            if (porosityOutput_) porosity_[I] = volVars.porosity();
+
+            // calculate a single value for the boundary type: use one
+            // bit for each equation and set it to 1 if the equation
+            // is used for a dirichlet condition
+            int tmp = 0;
+            for (int j = 0; j < numEq; ++j) {
+                if (elemBcTypes[i].isDirichlet(j))
+                    tmp += (1 << j);
+            }
+            if (boundaryTypesOutput_) boundaryTypes_[I] = tmp;
+
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                if (saturationOutput_) saturation_[phaseIdx][I] = volVars.fluidState().saturation(phaseIdx);
+                if (pressureOutput_) pressure_[phaseIdx][I] = volVars.fluidState().pressure(phaseIdx);
+                if (densityOutput_) density_[phaseIdx][I] = volVars.fluidState().density(phaseIdx);
+                if (mobilityOutput_) mobility_[phaseIdx][I] = volVars.mobility(phaseIdx);
+                if (meanMolarMassOutput_) meanMolarMass_[phaseIdx][I] = volVars.fluidState().meanMolarMass(phaseIdx);
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                    if (moleFracOutput_) moleFrac_[phaseIdx][compIdx][I] = volVars.fluidState().moleFrac(phaseIdx, compIdx);
+                    if (massFracOutput_) massFrac_[phaseIdx][compIdx][I] = volVars.fluidState().massFrac(phaseIdx, compIdx);
+                    if (molarityOutput_) molarity_[phaseIdx][compIdx][I] = volVars.fluidState().molarity(phaseIdx, compIdx);
+                }
+            }
+        }
+
+        // calculate velocities if requested by the problem
+        if (velocityOutput_) {
+            for (int faceIdx = 0; faceIdx < fvElemGeom.numEdges; ++ faceIdx) {
+                int i = fvElemGeom.subContVolFace[faceIdx].i;
+                int I = this->problem_.vertexMapper().map(elem, i, dim);
+
+                int j = fvElemGeom.subContVolFace[faceIdx].j;
+                int J = this->problem_.vertexMapper().map(elem, j, dim);
+
+                FluxVariables fluxVars(this->problem_,
+                                       elem,
+                                       fvElemGeom,
+                                       faceIdx,
+                                       elemVolVars);
+
+                Scalar scvfArea = fvElemGeom.subContVolFace[faceIdx].normal.two_norm();
+                scvfArea *= fluxVars.extrusionFactor();
+
+                boxSurface_[I] += scvfArea;
+                boxSurface_[J] += scvfArea;
+
+                for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                    Dune::FieldVector<Scalar, dim> darcyVelocity;
+                    fluxVars.computeDarcy(darcyVelocity,
+                                          elemVolVars,
+                                          phaseIdx);
+                    darcyVelocity *= scvfArea;
+                    velocity_[phaseIdx][I] += darcyVelocity;
+                    velocity_[phaseIdx][J] += darcyVelocity;
+
+                } // end for all phases
+            } // end for all faces
+        } // end if velocityOutput_
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+        if (saturationOutput_)
+            this->commitPhaseBuffer_(writer, "S_%s", saturation_);
+
+        if (pressureOutput_)
+            this->commitPhaseBuffer_(writer, "p_%s", pressure_);
+
+        if (densityOutput_)
+            this->commitPhaseBuffer_(writer, "rho_%s", density_);
+
+        if (meanMolarMassOutput_)
+            this->commitPhaseBuffer_(writer, "M_%s", meanMolarMass_);
+
+        if (mobilityOutput_)
+            this->commitPhaseBuffer_(writer, "lambda_%s", mobility_);
+
+        if (porosityOutput_)
+            this->commitScalarBuffer_(writer, "porosity", porosity_);
+
+        if (boundaryTypesOutput_)
+            this->commitScalarBuffer_(writer, "boundary types", boundaryTypes_);
+
+        if (moleFracOutput_)
+            this->commitPhaseComponentBuffer_(writer, "x_%s^%s", moleFrac_);
+
+        if (massFracOutput_)
+            this->commitPhaseComponentBuffer_(writer, "X_%s^%s", massFrac_);
+
+        if(molarityOutput_)
+            this->commitPhaseComponentBuffer_(writer, "c_%s^%s", molarity_);
+
+        if (velocityOutput_) {
+            int nVerts = this->problem_.gridView().size(dim);
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+                // first, divide the velocity field by the
+                // respective finite volume's surface area
+                for (int i = 0; i < nVerts; ++i)
+                    velocity_[phaseIdx][i] /= boxSurface_[i];
+                // commit the phase velocity
+                std::string name;
+                const char *phaseName = FluidSystem::phaseName(phaseIdx);
+                name = (boost::format("velocity_%s")%phaseName).str();
+                writer.attachVertexData(velocity_[phaseIdx],
+                                        name.c_str(),
+                                        dim);
+            }
+        }
+    }
+
+private:
+    bool porosityOutput_;
+    bool boundaryTypesOutput_;
+    bool saturationOutput_;
+    bool pressureOutput_;
+    bool velocityOutput_;
+    bool densityOutput_;
+    bool mobilityOutput_;
+    bool massFracOutput_;
+    bool moleFracOutput_;
+    bool molarityOutput_;
+    bool meanMolarMassOutput_;
+
+    PhaseBuffer saturation_;
+    PhaseBuffer pressure_;
+    PhaseBuffer density_;
+    PhaseBuffer mobility_;
+    PhaseBuffer meanMolarMass_;
+
+    PhaseVelocityField velocity_;
+    ScalarBuffer boxSurface_;
+
+    ScalarBuffer porosity_;
+    ScalarBuffer temperature_;
+    ScalarBuffer boundaryTypes_;
+
+    PhaseComponentBuffer moleFrac_;
+    PhaseComponentBuffer massFrac_;
+    PhaseComponentBuffer molarity_;
+
+    ComponentBuffer fugacity_;
+};
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/MpNcvtkwritermodule.hh b/dumux/boxmodels/MpNc/MpNcvtkwritermodule.hh
new file mode 100644
index 0000000000000000000000000000000000000000..4aed0cfcf329e58487014d991961e1be2cf7a1d9
--- /dev/null
+++ b/dumux/boxmodels/MpNc/MpNcvtkwritermodule.hh
@@ -0,0 +1,276 @@
+/*****************************************************************************
+ *   Copyright (C) 2011 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_VTK_BASE_WRITER_HH
+#define DUMUX_MPNC_VTK_BASE_WRITER_HH
+
+#include "MpNcproperties.hh"
+
+#include <dumux/io/vtkmultiwriter.hh>
+#include <dune/istl/bvector.hh>
+
+#include <array>
+
+namespace Dumux
+{
+/*!
+ * \ingroup BoxProblems
+ * \defgroup MPNCProblems Two-phase three-component box problems
+ */
+
+/*!
+ * \ingroup BoxModels
+ * \defgroup MPNCModel Two-phase three-component box model
+ */
+
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief A VTK writer module which adheres to the required API but
+ *        does nothing.
+ *
+ * This class also provides some convenience methods for buffer
+ * management.
+ */
+template<class TypeTag>
+class MPNCVtkWriterModule
+{
+    enum { numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementBoundaryTypes)) ElementBoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim             = GridView::dimension };
+
+public:
+    typedef std::vector<Dune::FieldVector<Scalar, 1> > ScalarBuffer;
+    typedef std::array<ScalarBuffer, numPhases> PhaseBuffer;
+    typedef std::array<ScalarBuffer, numComponents> ComponentBuffer;
+    typedef std::array<ComponentBuffer,  numPhases> PhaseComponentBuffer;
+
+//    typedef Dune::FieldVector<Scalar, dim> VelocityVector;
+//    typedef Dune::BlockVector<VelocityVector> VelocityField;
+//    typedef std::array<VelocityField, numPhases> PhaseVelocityField;
+
+    MPNCVtkWriterModule(const Problem &problem)
+        : problem_(problem)
+    {
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvElemGeom,
+                        const ElementVolumeVariables &elemCurVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+    }
+
+protected:
+    /*!
+     * \brief Allocate the space for a buffer storing a scalar quantity
+     */
+    void resizeScalarBuffer_(ScalarBuffer &buffer,
+                             bool vertexCentered = true)
+    {
+        Scalar n;
+        if (vertexCentered)
+            n = problem_.gridView().size(dim);
+        else
+            n = problem_.gridView().size(0);
+
+        buffer.resize(n);
+        std::fill(buffer.begin(), buffer.end(), 0.0);
+    }
+
+    /*!
+     * \brief Allocate the space for a buffer storing a phase-specific
+     *        quantity
+     */
+    void resizePhaseBuffer_(PhaseBuffer &buffer,
+                            bool vertexCentered = true)
+    {
+        Scalar n;
+        if (vertexCentered)
+            n = problem_.gridView().size(dim);
+        else
+            n = problem_.gridView().size(0);
+
+        for (int i = 0; i < numPhases; ++i) {
+            buffer[i].resize(n);
+            std::fill(buffer[i].begin(), buffer[i].end(), 0.0);
+        }
+    }
+
+    /*!
+     * \brief Allocate the space for a buffer storing a component
+     *        specific quantity
+     */
+    void resizeComponentBuffer_(ComponentBuffer &buffer,
+                                bool vertexCentered = true)
+    {
+        Scalar n;
+        if (vertexCentered)
+            n = problem_.gridView().size(dim);
+        else
+            n = problem_.gridView().size(0);
+
+        for (int i = 0; i < numComponents; ++i) {
+            buffer[i].resize(n);
+            std::fill(buffer[i].begin(), buffer[i].end(), 0.0);
+        }
+    }
+
+    /*!
+     * \brief Allocate the space for a buffer storing a phase and
+     *        component specific buffer
+     */
+    void resizePhaseComponentBuffer_(PhaseComponentBuffer &buffer,
+                                     bool vertexCentered = true)
+    {
+        Scalar n;
+        if (vertexCentered)
+            n = problem_.gridView().size(dim);
+        else
+            n = problem_.gridView().size(0);
+
+        for (int i = 0; i < numPhases; ++i) {
+            for (int j = 0; j < numComponents; ++j) {
+                buffer[i][j].resize(n);
+                std::fill(buffer[i][j].begin(), buffer[i][j].end(), 0.0);
+            }
+        }
+    }
+
+    /*!
+     * \brief Add a phase-specific buffer to the VTK result file.
+     */
+    template <class MultiWriter>
+    void commitScalarBuffer_(MultiWriter &writer,
+                             const char *name,
+                             ScalarBuffer &buffer,
+                             bool vertexCentered = true)
+    {
+        if (vertexCentered)
+            writer.attachVertexData(buffer, name, 1);
+        else
+            writer.attachCellData(buffer, name, 1);
+    }
+
+    /*!
+     * \brief Add a phase-specific buffer to the VTK result file.
+     */
+    template <class MultiWriter>
+    void commitPhaseBuffer_(MultiWriter &writer,
+                            const char *pattern,
+                            PhaseBuffer &buffer,
+                            bool vertexCentered = true)
+    {
+        for (int i = 0; i < numPhases; ++i) {
+            std::string phaseName = FluidSystem::phaseName(i);
+            std::string name;
+            name = (boost::format(pattern)%phaseName).str();
+
+            if (vertexCentered)
+                writer.attachVertexData(buffer[i], name.c_str(), 1);
+            else
+                writer.attachCellData(buffer[i], name.c_str(), 1);
+        }
+    }
+
+    /*!
+     * \brief Add a component-specific buffer to the VTK result file.
+     */
+    template <class MultiWriter>
+    void commitComponentBuffer_(MultiWriter &writer,
+                                const char *pattern,
+                                ComponentBuffer &buffer,
+                                bool vertexCentered = true)
+    {
+        for (int i = 0; i < numComponents; ++i) {
+            std::string compName = FluidSystem::componentName(i);
+            std::string name;
+            name = (boost::format(pattern)%compName).str();
+
+            if (vertexCentered)
+                writer.attachVertexData(buffer[i], name.c_str(), 1);
+            else
+                writer.attachCellData(buffer[i], name.c_str(), 1);
+        }
+    }
+
+    /*!
+     * \brief Add a phase and component specific quantities to the output.
+     */
+    template <class MultiWriter>
+    void commitPhaseComponentBuffer_(MultiWriter &writer,
+                                     const char *pattern,
+                                     PhaseComponentBuffer &buffer,
+                                     bool vertexCentered = true)
+    {
+        for (int i= 0; i < numPhases; ++i) {
+            std::string phaseName = FluidSystem::phaseName(i);
+            for (int j = 0; j < numComponents; ++j) {
+                std::string compName = FluidSystem::componentName(j);
+                std::string name;
+                name = (boost::format(pattern)%phaseName%compName).str();
+
+                if (vertexCentered)
+                    writer.attachVertexData(buffer[i][j], name.c_str(), 1);
+                else
+                    writer.attachCellData(buffer[i][j], name.c_str(), 1);
+            }
+        }
+    }
+
+    const Problem &problem_;
+};
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/diffusion/diffusion.hh b/dumux/boxmodels/MpNc/diffusion/diffusion.hh
new file mode 100644
index 0000000000000000000000000000000000000000..34eb2618715230db4dcb67339efcf2b2988ee88b
--- /dev/null
+++ b/dumux/boxmodels/MpNc/diffusion/diffusion.hh
@@ -0,0 +1,152 @@
+/*****************************************************************************
+ *   Copyright (C) 2009 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 This file contains parts to calculate the diffusive flux in
+ *        the fully coupled two-phase N-component model
+ */
+#ifndef DUMUX_MPNC_DIFFUSION_HH
+#define DUMUX_MPNC_DIFFUSION_HH
+
+namespace Dumux {
+
+template <class TypeTag, bool enableDiffusion>
+class MPNCDiffusion
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+
+    enum { numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents))};
+    enum { enableKinetic= GET_PROP_VALUE(TypeTag, PTAG(EnableKinetic))};
+    enum { gPhaseIdx = FluidSystem::gPhaseIdx };
+    enum { lPhaseIdx = FluidSystem::lPhaseIdx };
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+
+    typedef Dune::FieldMatrix<Scalar, numComponents, numComponents> DiffMatrix;
+    typedef Dune::FieldVector<Scalar, numComponents> DiffVector;
+    typedef Dune::FieldVector<Scalar, numComponents> CompVector;
+
+public:
+    static void flux(CompVector &fluxes,
+                     int phaseIdx,
+                     const FluxVariables &fluxDat,
+                     Scalar molarDensity)
+    {
+        if (phaseIdx == gPhaseIdx)
+            gasFlux_(fluxes, fluxDat, molarDensity);
+        else if (phaseIdx == lPhaseIdx){
+            #if MACROSCALE_DIFFUSION_ONLY_GAS
+                    return ; // in the case that only the diffusion in the gas phase is considered, the liquidFlux should not be called
+            #endif
+            liquidFlux_(fluxes, fluxDat, molarDensity);
+        }
+        else
+            DUNE_THROW(Dune::InvalidStateException,
+                       "Invalid phase index: " << phaseIdx);
+    }
+
+protected:
+    static void liquidFlux_(CompVector &fluxes,
+                            const FluxVariables &fluxDat,
+                            Scalar molarDensity)
+    {
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+            // TODO: tensorial diffusion coefficients
+            Scalar xGrad = fluxDat.moleFracGrad(lPhaseIdx, compIdx)*fluxDat.face().normal;
+            fluxes[compIdx] =
+                - xGrad *
+                molarDensity *
+                fluxDat.face().normal.two_norm() * // because we want a mole flux and not an area specific flux
+                fluxDat.porousDiffCoeffL(compIdx) ;
+        }
+    }
+
+    static void gasFlux_(CompVector &fluxes,
+                         const FluxVariables &fluxDat,
+                         Scalar molarDensity)
+    {
+        // Stefan-Maxwell equation
+        //
+        // See: R. Reid, et al.: "The Properties of Liquids and
+        // Gases", 4th edition, 1987, McGraw-Hill, p 596
+
+        // TODO: tensorial diffusion coefficients
+        DiffMatrix M(0);
+
+        for (int i = 0; i < numComponents - 1; ++i) {
+            for (int j = 0; j < numComponents; ++j) {
+                Scalar Dij = fluxDat.porousDiffCoeffG(i, j);
+                if (Dij) {
+                    M[i][j] += fluxDat.moleFrac(gPhaseIdx, i) / Dij;
+                    M[i][i] -= fluxDat.moleFrac(gPhaseIdx, j) / Dij;
+                }
+            }
+        };
+
+        for (int i = 0; i < numComponents; ++i) {
+            M[numComponents - 1][i] = 1.0;
+        }
+
+        DiffVector rightHandSide ; // see source cited above
+        for (int i = 0; i < numComponents - 1; ++i) {
+            rightHandSide[i] = molarDensity*(fluxDat.moleFracGrad(gPhaseIdx, i)*fluxDat.face().normal);
+        }
+        rightHandSide[numComponents - 1] = 0.0;
+
+        M.solve(fluxes, rightHandSide);
+    }
+
+    // return whether a concentration can be assumed to be a trace
+    // component in the context of diffusion
+    static Scalar isTraceComp_(Scalar x)
+    { return x < 0.5/numComponents; }
+};
+
+/*!
+ * \brief Specialization of the diffusion module for the case where
+ *        diffusion is disabled.
+ *
+ * This class just does nothing.
+ */
+template <class TypeTag>
+class MPNCDiffusion<TypeTag, false>
+{
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef Dune::FieldVector<Scalar, numComponents>        CompVector;
+
+public:
+    static void flux(CompVector &fluxes,
+                     int phaseIdx,
+                     const FluxVariables &fluxVars,
+                     Scalar totalConcentration)
+    { fluxes = 0;  }
+};
+
+}
+
+#endif // DUMUX_MPNC_DIFFUSION_HH
diff --git a/dumux/boxmodels/MpNc/diffusion/fluxvariables.hh b/dumux/boxmodels/MpNc/diffusion/fluxvariables.hh
new file mode 100644
index 0000000000000000000000000000000000000000..acb0d48bc1df183a5fcca58434f50a65eb6c791e
--- /dev/null
+++ b/dumux/boxmodels/MpNc/diffusion/fluxvariables.hh
@@ -0,0 +1,237 @@
+/*****************************************************************************
+ *   Copyright (C) 2009 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 This file contains the diffusion module for the flux data of
+ *        the fully coupled two-phase N-component model
+ */
+#ifndef DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH
+#define DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH
+
+#include <dune/common/fvector.hh>
+
+#include "../MpNcproperties.hh"
+
+namespace Dumux {
+
+template<class TypeTag, bool enableDiffusion>
+class MPNCFluxVariablesDiffusion
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld,
+
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+        numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)),
+
+        lPhaseIdx = FluidSystem::lPhaseIdx,
+        gPhaseIdx = FluidSystem::gPhaseIdx,
+    };
+
+    typedef Dune::FieldVector<Scalar, dimWorld>  GlobalPosition;
+    typedef Dune::FieldVector<Scalar, dimWorld>  Vector;
+    typedef Dune::FieldVector<Scalar, dim>       LocalPosition;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolume SCV;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+    typedef Dune::FieldVector<Scalar, numPhases>      PhasesVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+
+public:
+    MPNCFluxVariablesDiffusion()
+    {}
+
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &elemGeom,
+                int scvfIdx,
+                const ElementVolumeVariables &vDat)
+    {
+        int i = elemGeom.subContVolFace[scvfIdx].i;
+        int j = elemGeom.subContVolFace[scvfIdx].j;
+
+        for (int phase = 0; phase < numPhases; ++phase) {
+            for (int comp = 0; comp < numComponents; ++comp) {
+                moleFrac_[phase][comp]  = vDat[i].fluidState().moleFrac(phase, comp);
+                moleFrac_[phase][comp] += vDat[j].fluidState().moleFrac(phase, comp);
+                moleFrac_[phase][comp] /= 2;
+            }
+        }
+
+        // update the concentration gradients using two-point
+        // gradients
+        const GlobalPosition &normal = elemGeom.subContVolFace[scvfIdx].normal;
+
+        GlobalPosition tmp = element.geometry().corner(j);
+        tmp -= element.geometry().corner(i);
+        Scalar dist = tmp.two_norm()*normal.two_norm();
+        for (int phaseIdx = 0; phaseIdx < numPhases; phaseIdx++)
+        {
+            // concentration gradients
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                moleFracGrad_[phaseIdx][compIdx] = normal;
+                moleFracGrad_[phaseIdx][compIdx]
+                    *=
+                    (vDat[j].fluidState().moleFrac(phaseIdx, compIdx) -
+                     vDat[i].fluidState().moleFrac(phaseIdx, compIdx))
+                    / dist;
+            }
+        }
+
+        // initialize the diffusion coefficients to zero
+        for (int i = 0; i < numComponents; ++i) {
+            porousDiffCoeffL_[i] = 0.0;
+            for (int j = 0; j < numComponents; ++j)
+                porousDiffCoeffG_[i][j] = 0.0;
+        }
+
+        // calculate the diffusion coefficients at the integration
+        // point in the porous medium
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+        {
+            // make sure to only calculate diffusion coefficents
+            // for phases which exist in both finite volumes
+            if (vDat[i].fluidState().saturation(phaseIdx) <= 1e-4 ||
+                vDat[j].fluidState().saturation(phaseIdx) <= 1e-4)
+            {
+                continue;
+            }
+
+            // reduction factor for the diffusion coefficients in the
+            // porous medium in nodes i and j. this is the tortuosity
+            // times porosity times phase saturation at the nodes i
+            // and j
+            //
+            // TODO (?): move this calculation to the soil (possibly
+            // that's a bad idea, though)
+            Scalar red_i =
+                vDat[i].fluidState().saturation(phaseIdx)/vDat[i].porosity() *
+                pow(vDat[i].porosity() * vDat[i].fluidState().saturation(phaseIdx), 7.0/3);
+            Scalar red_j =
+                vDat[j].fluidState().saturation(phaseIdx)/vDat[j].porosity() *
+                pow(vDat[j].porosity() * vDat[j].fluidState().saturation(phaseIdx), 7.0/3);
+
+            if (phaseIdx == FluidSystem::lPhaseIdx) {
+                // Liquid phase diffusion coefficients in the porous medium
+                for (int i = 0; i < numComponents; ++i) {
+                    // -> arithmetic mean
+                    porousDiffCoeffL_[i]
+                        = 1./2*(red_i * vDat[i].diffCoeff(lPhaseIdx, 0, i) +
+                                red_j * vDat[j].diffCoeff(lPhaseIdx, 0, i));
+                }
+            }
+            else {
+                // Gas phase diffusion coefficients in the porous medium
+                for (int i = 0; i < numComponents; ++i) {
+                    for (int j = 0; j < numComponents; ++j) {
+                        // -> arithmetic mean
+                        porousDiffCoeffG_[i][j]
+                            = 1./2*(red_i * vDat[i].diffCoeff(gPhaseIdx, i, j) +
+                                    red_j * vDat[j].diffCoeff(gPhaseIdx, i, j));
+                    }
+                }
+            }
+        }
+    };
+
+    Scalar porousDiffCoeffL(int compIdx) const
+    {
+        // TODO: tensorial diffusion coefficients
+        return porousDiffCoeffL_[compIdx];
+    };
+
+    Scalar porousDiffCoeffG(int compIIdx, int compJIdx) const
+    {
+        // TODO: tensorial diffusion coefficients
+        return porousDiffCoeffG_[compIIdx][compJIdx];
+    };
+
+    Scalar moleFrac(int phaseIdx,
+                    int compIdx) const
+    {
+        return moleFrac_[phaseIdx][compIdx];
+    };
+
+    const GlobalPosition &moleFracGrad(int phaseIdx,
+                                            int compIdx) const
+    {
+        return moleFracGrad_[phaseIdx][compIdx];
+    };
+
+protected:
+    // the diffusion coefficients for the porous medium for the
+    // liquid phase
+    Scalar porousDiffCoeffL_[numComponents];
+
+    // the diffusion coefficients for the porous medium for the
+    // gas phase
+    Scalar porousDiffCoeffG_[numComponents][numComponents];
+
+    // the concentration gradients of all components in all phases
+    GlobalPosition moleFracGrad_[numPhases][numComponents];
+
+    // the mole fractions of each component at the integration point
+    Scalar moleFrac_[numPhases][numComponents];
+};
+
+
+template<class TypeTag>
+class MPNCFluxVariablesDiffusion<TypeTag, false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+
+public:
+    MPNCFluxVariablesDiffusion()
+    {}
+
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &elemGeom,
+                int scvfIdx,
+                const ElementVolumeVariables &vDat)
+    {
+    };
+};
+
+};
+
+#endif // DUMUX_MPNC_DIFFUSION_FLUX_VARIABLES_HH
diff --git a/dumux/boxmodels/MpNc/diffusion/volumevariables.hh b/dumux/boxmodels/MpNc/diffusion/volumevariables.hh
new file mode 100644
index 0000000000000000000000000000000000000000..2056a66a345c93f8c50019380cf1132581628a9e
--- /dev/null
+++ b/dumux/boxmodels/MpNc/diffusion/volumevariables.hh
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ *   Copyright (C) 2009 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 This file contains the diffusion module for the vertex data
+ *        of the fully coupled two-phase N-component model
+ */
+#ifndef DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH
+#define DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH
+
+namespace Dumux {
+
+template<class TypeTag, bool enableDiffusion>
+class MPNCVolumeVariablesDiffusion
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+
+    typedef typename FluidSystem::MutableParameters MutableParameters;
+
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { lPhaseIdx = FluidSystem::lPhaseIdx };
+    enum { gPhaseIdx = FluidSystem::gPhaseIdx };
+
+public:
+    MPNCVolumeVariablesDiffusion()
+    {}
+
+    void update(MutableParameters &mutParams,
+                const VolumeVariables &volVars,
+                const Problem &problem)
+    {
+        Valgrind::SetUndefined(*this);
+
+        // diffusion coefficents in liquid
+        diffCoeffL_[0] = 0.0;
+        for (int compIdx = 1; compIdx < numComponents; ++compIdx) {
+            diffCoeffL_[compIdx] =
+                FluidSystem::binaryDiffCoeff(mutParams,
+                                             lPhaseIdx,
+                                             0,
+                                             compIdx);
+        }
+        Valgrind::CheckDefined(diffCoeffL_);
+
+        // diffusion coefficents in gas
+        for (int compIIdx = 0; compIIdx < numComponents; ++compIIdx) {
+            diffCoeffG_[compIIdx][compIIdx] = 0;
+            for (int compJIdx = compIIdx + 1; compJIdx < numComponents; ++compJIdx) {
+                diffCoeffG_[compIIdx][compJIdx] =
+                    FluidSystem::binaryDiffCoeff(mutParams,
+                                                 gPhaseIdx,
+                                                 compIIdx,
+                                                 compJIdx);
+
+                // fill the symmetric part of the diffusion coefficent
+                // matrix
+                diffCoeffG_[compJIdx][compIIdx] = diffCoeffG_[compIIdx][compJIdx];
+            }
+        }
+        Valgrind::CheckDefined(diffCoeffG_);
+    };
+
+
+    Scalar diffCoeff(int phaseIdx, int compIIdx, int compJIdx) const
+    {
+        if (phaseIdx == gPhaseIdx)
+            // TODO: tensorial diffusion coefficients
+            return diffCoeffG_[compIIdx][compJIdx];
+
+        int i = std::min(compIIdx, compJIdx);
+        int j = std::max(compIIdx, compJIdx);
+        if (i != 0)
+            return 0;
+        return diffCoeffL_[j];
+    };
+
+    /*!
+     * \brief If running under valgrind this produces an error message
+     *        if some of the object's attributes is undefined.
+     */
+    void checkDefined() const
+    {
+        Valgrind::CheckDefined(diffCoeffL_);
+        Valgrind::CheckDefined(diffCoeffG_);
+    }
+
+
+protected:
+    // the diffusion coefficients for the porous medium for the
+    // liquid phase
+    Scalar diffCoeffL_[numComponents];
+
+    // the diffusion coefficients for the porous medium for the
+    // gas phase
+    Scalar diffCoeffG_[numComponents][numComponents];
+};
+
+// dummy class for the case where diffusion is disabled
+template<class TypeTag>
+class MPNCVolumeVariablesDiffusion<TypeTag, false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename FluidSystem::MutableParameters MutableParameters;
+
+public:
+    MPNCVolumeVariablesDiffusion()
+    {}
+
+    void update(MutableParameters &mutParams,
+        const VolumeVariables &volVars,
+                const Problem &problem)
+    {
+    };
+
+    Scalar diffCoeffL(int compIdx) const
+    { return 0; };
+
+    Scalar diffCoeffG(int compIIdx, int compJIdx) const
+    { return 0; };
+
+    /*!
+     * \brief If running under valgrind this produces an error message
+     *        if some of the object's attributes is undefined.
+     */
+    void checkDefined() const
+    { }
+};
+
+};
+
+#endif // DUMUX_MPNC_DIFFUSION_VOLUME_VARIABLES_HH
diff --git a/dumux/boxmodels/MpNc/energy/MpNcfluxvariablesenergy.hh b/dumux/boxmodels/MpNc/energy/MpNcfluxvariablesenergy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..d4589e3b4c0899605f3717ccb5a793948a9befa0
--- /dev/null
+++ b/dumux/boxmodels/MpNc/energy/MpNcfluxvariablesenergy.hh
@@ -0,0 +1,194 @@
+/*****************************************************************************
+ *   Copyright (C) 2008,2009 by Andreas Lauser                               *
+ *   Copyright (C) 2008,2009 by Melanie Darcis                               *
+ *                                                                           *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 to calculate the energy flux in the
+ *        MpNc box model.
+ */
+#ifndef DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH
+#define DUMUX_MPNC_ENERGY_FLUX_VARIABLES_HH
+
+namespace Dumux
+{
+
+template <class TypeTag, bool enableEnergy/*=false*/, bool kineticEnergyTransfer/*=false*/>
+class MPNCFluxVariablesEnergy
+{
+    static_assert(!(kineticEnergyTransfer && !enableEnergy),
+                  "No kinetic energy transfer may only be enabled "
+                  "if energy is enabled in general.");
+    static_assert(!kineticEnergyTransfer,
+                  "No kinetic energy transfer module included, "
+                  "but kinetic energy transfer enabled.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+
+public:
+    MPNCFluxVariablesEnergy()
+    {
+    }
+
+    void update(const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &fvElemGeom,
+                int scvfIdx,
+                const FluxVariables &fluxDat,
+                const ElementVolumeVariables &elemVolVars)
+    {};
+};
+
+template <class TypeTag>
+class MPNCFluxVariablesEnergy<TypeTag, /*enableEnergy=*/true,  /*kineticEnergyTransfer=*/false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum {
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld,
+        gPhaseIdx = FluidSystem::gPhaseIdx,
+        lPhaseIdx = FluidSystem::lPhaseIdx,
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+    };
+
+    typedef Dune::FieldVector<CoordScalar, dimWorld>  Vector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename FVElementGeometry::SubControlVolume SCV;
+    typedef typename FVElementGeometry::SubControlVolumeFace SCVFace;
+
+public:
+    MPNCFluxVariablesEnergy()
+    {}
+
+    void update(const  Problem & problem,
+                const Element &element,
+                const FVElementGeometry &fvElemGeom,
+                int scvfIdx,
+                const FluxVariables &fluxDat,
+                const ElementVolumeVariables &elemVolVars)
+    {
+        // calculate temperature gradient using finite element
+        // gradients
+        Vector tmp(0.0);
+        Vector temperatureGradient(0.);
+        for (int scvIdx = 0; scvIdx < fvElemGeom.numVertices; scvIdx++)
+        {
+            tmp = fvElemGeom.subContVolFace[scvfIdx].grad[scvIdx];
+            tmp *= elemVolVars[scvIdx].temperature();
+            temperatureGradient += tmp;
+        }
+
+        // project the heat flux vector on the face's normal vector
+        temperatureGradientNormal_ = temperatureGradient * fvElemGeom.subContVolFace[scvfIdx].normal;
+
+
+        lambdaPm_ = lumpedLambdaPm(problem,
+                                    fvElemGeom,
+                                    scvfIdx,
+                                    elemVolVars) ;
+
+    }
+
+     Scalar lumpedLambdaPm(const Problem & problem,
+                              const FVElementGeometry & fvElemGeom,
+                           int faceIdx,
+                           const ElementVolumeVariables & elemVolVars)
+    {
+         // arithmetic mean of the liquid saturation and the porosity
+         const int i = fvElemGeom.subContVolFace[faceIdx].i;
+         const int j = fvElemGeom.subContVolFace[faceIdx].j;
+
+         const Scalar Sli = elemVolVars[i].fluidState().saturation(lPhaseIdx);
+         const Scalar Slj = elemVolVars[j].fluidState().saturation(lPhaseIdx);
+
+         const Scalar Sl = std::max<Scalar>(0.0, 0.5*(Sli + Slj));
+
+        //        const Scalar lambdaDry = 0.583; // W / (K m) // works, orig
+        //        const Scalar lambdaWet = 1.13; // W / (K m) // works, orig
+
+        const typename FluidSystem::MutableParameters mutParams; //dummy
+        const Scalar lambdaDry = 0.5 * (problem.spatialParameters().soilThermalConductivity() + FluidSystem::thermalConductivity(mutParams, gPhaseIdx) ); // W / (K m)
+        const Scalar lambdaWet = 0.5 * (problem.spatialParameters().soilThermalConductivity() + FluidSystem::thermalConductivity(mutParams, lPhaseIdx)) ; // W / (K m)
+
+        // the heat conductivity of the matrix. in general this is a
+        // tensorial value, but we assume isotropic heat conductivity.
+        // This is the Sommerton approach with lambdaDry =
+        // lambdaSn100%.  Taken from: H. Class: "Theorie und
+        // numerische Modellierung nichtisothermer Mehrphasenprozesse
+        // in NAPL-kontaminierten poroesen Medien", PhD Thesis, University of
+        // Stuttgart, Institute of Hydraulic Engineering, p. 57
+
+        Scalar result;
+        if (Sl < 0.1) {
+            // regularization
+            Dumux::Spline<Scalar> sp(0, 0.1, // x1, x2
+                                    0, sqrt(0.1), // y1, y2
+                                    5*0.5/sqrt(0.1), 0.5/sqrt(0.1)); // m1, m2
+            result = lambdaDry + sp.eval(Sl)*(lambdaWet - lambdaDry);
+        }
+        else
+            result = lambdaDry + std::sqrt(Sl)*(lambdaWet - lambdaDry);
+
+        return result;
+    }
+
+    /*!
+     * \brief The lumped / average conductivity of solid plus phases \f$[W/mK]\f$.
+     */
+    Scalar lambdaPm() const
+    { return lambdaPm_; }
+
+    /*!
+     * \brief The normal of the gradient of temperature .
+     */
+    Scalar temperatureGradientNormal() const
+    {
+        return temperatureGradientNormal_;
+    }
+
+private:
+    Scalar lambdaPm_;
+    Scalar temperatureGradientNormal_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/boxmodels/MpNc/energy/MpNcindicesenergy.hh b/dumux/boxmodels/MpNc/energy/MpNcindicesenergy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..b9b8f9c46e54d6f7a65ad561dda4a6b6a149fe23
--- /dev/null
+++ b/dumux/boxmodels/MpNc/energy/MpNcindicesenergy.hh
@@ -0,0 +1,76 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2011 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+/*!
+ * \brief The indices for the non-isothermal part of the compositional
+ *        multi-phase model.
+ */
+#ifndef DUMUX_MPNC_INDICES_ENERGY_HH
+#define DUMUX_MPNC_INDICES_ENERGY_HH
+
+namespace Dumux
+{
+/*!
+ * \brief The indices for the energy equation.
+ *
+ * This is a dummy class for the isothermal case.
+ */
+template <int PVOffset, bool enableEnergy/*=false*/, bool kineticEnergyTransfer/*=false*/>
+struct MPNCEnergyIndices
+{
+    static_assert(!(kineticEnergyTransfer && !enableEnergy),
+                  "No kinetic energy transfer may only be enabled "
+                  "if energy is enabled in general.");
+    static_assert(!kineticEnergyTransfer,
+                  "No kinetic energy transfer module included, "
+                  "but kinetic energy transfer enabled.");
+public:
+    /*!
+     * \brief This module does not define any primary variables in the
+     *        isothermal case.
+     */
+    static const int NumPrimaryVars = 0;
+};
+
+/*!
+ * \brief The indices required for the energy equation.
+ */
+template <int PVOffset>
+struct MPNCEnergyIndices<PVOffset, /*isNonIsothermal=*/true, /*kineticEnergyTransfer*/false>
+{
+public:
+    /*!
+     * \brief This module defines one new primary variable.
+     */
+    static const int NumPrimaryVars = 1;
+
+    /*!
+     * \brief Index for the temperature in a vector of primary
+     *        variables.
+     */
+    static const int temperatureIdx = PVOffset + 0;
+    /*!
+     * \brief Equation index of the energy equation.
+     */
+    static const int energyEqIdx = PVOffset + 0;
+};
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/energy/MpNclocalresidualenergy.hh b/dumux/boxmodels/MpNc/energy/MpNclocalresidualenergy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..d5cbc78bfa5addcf5f637b19d48f81fe5e6a6674
--- /dev/null
+++ b/dumux/boxmodels/MpNc/energy/MpNclocalresidualenergy.hh
@@ -0,0 +1,233 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2011 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 This file contains the parts of the local residual to
+ *        calculate the heat flux in the fully coupled two-phase
+ *        N-component model
+ */
+#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH
+#define DUMUX_MPNC_LOCAL_RESIDUAL_ENERGY_HH
+
+namespace Dumux {
+
+/*!
+ * \brief Specialization of the energy module for the isothermal case.
+ *
+ * This class just does nothing.
+ */
+template <class TypeTag, bool enableEnergy/*=false*/, bool kineticEnergyTransfer /*=false*/>
+class MPNCLocalResidualEnergy
+{
+    static_assert(!(kineticEnergyTransfer && !enableEnergy),
+                  "No kinetic energy transfer may only be enabled "
+                  "if energy is enabled in general.");
+    static_assert(!kineticEnergyTransfer,
+                  "No kinetic energy transfer module included, "
+                  "but kinetic energy transfer enabled.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+
+    enum { numPhases        = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents    = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    typedef typename Dune::FieldVector<Scalar, numComponents>  ComponentVector;
+
+public:
+    static void computeStorage(PrimaryVariables &result,
+                               const VolumeVariables &volVars)
+    {
+        // do nothing, we're isothermal!
+    };
+
+
+    static void addPhaseStorage(PrimaryVariables &storage,
+                                const VolumeVariables &volVars,
+                                int phaseIdx)
+    {
+        // do nothing, we're isothermal!
+    };
+
+    static void phaseEnthalpyFlux(PrimaryVariables &result,
+                                  int phaseIdx,
+                                  const PrimaryVariables &compMolFlux,
+                                  const ElementVolumeVariables &volVars,
+                                  const FluxVariables &fluxVars)
+    {
+        // do nothing, we're isothermal!
+    };
+
+    static void heatConduction(PrimaryVariables &result,
+                               const ElementVolumeVariables &volVars,
+                               const FluxVariables &fluxVars)
+    {
+        // do nothing, we're isothermal!
+    };
+
+
+    static void computeFlux(PrimaryVariables & flux,
+                                const FluxVariables & fluxVars,
+                                const ElementVolumeVariables & volVars,
+                                const ComponentVector molarPhaseComponentValuesMassTransport[numPhases])
+    {
+        // do nothing, we're isothermal!
+    }
+
+    static void computeSource(PrimaryVariables &result,
+                              const VolumeVariables &volVars)
+    {
+        // do nothing, we're isothermal!
+    }
+};
+
+template <class TypeTag>
+class MPNCLocalResidualEnergy<TypeTag, /*enableEnergy=*/true, /*kineticenergyTransfer=*/false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+
+    enum { dim = GridView::dimension };
+    enum { numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { conti0EqIdx = Indices::conti0EqIdx };
+    enum { energyEqIdx = Indices::energyEqIdx };
+
+    typedef Dune::FieldVector<Scalar, dim> Vector;
+    typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector;
+    typedef typename Dune::FieldMatrix<Scalar, numPhases, numComponents>    PhaseComponentMatrix;
+
+
+
+public:
+    static void computeStorage(PrimaryVariables &result,
+                               const VolumeVariables &volVars)
+    {
+        result[energyEqIdx] = 0;
+
+        // energy of the fluids
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            addPhaseStorage(result, volVars, phaseIdx);
+        }
+
+        // heat stored in the rock matrix
+        result[energyEqIdx] +=
+            volVars.temperature()
+            * volVars.soilDensity()
+            * (1.0 - volVars.porosity())
+            * volVars.heatCapacity();
+    }
+
+    static void addPhaseStorage(PrimaryVariables &storage,
+                                const VolumeVariables &volVars,
+                                int phaseIdx)
+    {
+        const typename VolumeVariables::FluidState &fs =
+            volVars.fluidState();
+
+        // energy of the fluid
+        storage[energyEqIdx] +=
+            fs.density(phaseIdx)
+            * fs.internalEnergy(phaseIdx)
+            * fs.saturation(phaseIdx)
+            * volVars.porosity();
+    }
+
+    static void computeFlux(PrimaryVariables & flux,
+                            const FluxVariables & fluxVars,
+                            const ElementVolumeVariables & volVars,
+                            const ComponentVector molarPhaseComponentValuesMassTransport[numPhases])
+    {
+        flux[energyEqIdx] = 0.0;
+
+        // fluid phases transport enthalpy individually
+        for(int phaseIdx=0; phaseIdx<numPhases; ++phaseIdx)
+            computePhaseEnthalpyFlux(flux,
+                                fluxVars,
+                                volVars,
+                                phaseIdx,
+                                molarPhaseComponentValuesMassTransport[phaseIdx]);
+
+        //conduction is treated lumped in this model
+        computeHeatConduction(flux,
+                             fluxVars,
+                             volVars);
+    }
+
+    static void computePhaseEnthalpyFlux(PrimaryVariables & result,
+                                         const FluxVariables & fluxVars,
+                                         const ElementVolumeVariables & volVars,
+                                         const int phaseIdx,
+                                         const ComponentVector & molarComponentValuesMassTransport)
+    {
+        Scalar massFlux = 0;
+
+        // calculate the mass flux in the phase i.e. make mass flux out of mole flux and add up the fluxes of a phase
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            massFlux += molarComponentValuesMassTransport[compIdx]
+                                    * FluidSystem::molarMass(compIdx);
+
+        int upIdx = fluxVars.face().i;
+        if (massFlux < 0) upIdx = fluxVars.face().j;
+
+        // use the phase enthalpy of the upstream vertex to calculate
+        // the enthalpy transport
+        const VolumeVariables &up = volVars[upIdx];
+        result[energyEqIdx] += up.fluidState().enthalpy(phaseIdx) * massFlux;
+    }
+
+    static void computeHeatConduction(PrimaryVariables & result,
+                                    const FluxVariables & fluxVars,
+                                    const ElementVolumeVariables & volVars)
+    {
+        //lumped heat conduction of the rock matrix and the fluid phases
+        Scalar lumpedConductivity   = fluxVars.energyData().lambdaPm() ;
+        Scalar temperatureGradientNormal  = fluxVars.energyData().temperatureGradientNormal() ;
+        Scalar lumpedHeatConduction = - lumpedConductivity * temperatureGradientNormal ;
+        result[energyEqIdx] += lumpedHeatConduction ;
+    }
+
+
+
+    static void computeSource(PrimaryVariables &result,
+                              const VolumeVariables &volVars)
+    {
+        result[energyEqIdx] = 0.0;
+    }
+};
+
+
+
+
+
+};
+
+#endif // DUMUX_MPNC_ENERGY_HH
diff --git a/dumux/boxmodels/MpNc/energy/MpNcvolumevariablesenergy.hh b/dumux/boxmodels/MpNc/energy/MpNcvolumevariablesenergy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..8d0bba1ecf544607e5f4a92a826761a8c8038614
--- /dev/null
+++ b/dumux/boxmodels/MpNc/energy/MpNcvolumevariablesenergy.hh
@@ -0,0 +1,232 @@
+/*****************************************************************************
+ *   Copyright (C) 2008-2011 by Andreas Lauser                               *
+ *   Copyright (C) 2008-2009 by Melanie Darcis                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 energy part of volume variables of the M-phase,
+ *        N-component model.
+ */
+#ifndef DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH
+#define DUMUX_MPNC_ENERGY_VOLUME_VARIABLES_HH
+
+namespace Dumux
+{
+/*!
+ * \brief Contains the energy related quantities which are constant within a
+ *        finite volume in the two-phase, N-component model.
+ *
+ * This is the dummy class for the isothermal case. Note that we're
+ * only isothermal in the sense that the temperature at a location and
+ * a time is specified outside of the model!
+ */
+template <class TypeTag, bool enableEnergy/*=false*/, bool kineticEnergyTransfer /*=don't care*/>
+class MPNCVolumeVariablesEnergy
+{
+    static_assert(!(kineticEnergyTransfer && !enableEnergy),
+                  "No kinetic energy transfer may only be enabled "
+                  "if energy is enabled in general.");
+    static_assert(!kineticEnergyTransfer,
+                  "No kinetic energy transfer module included, "
+                  "but kinetic energy transfer enabled.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    enum { numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    //typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCEnergyIndices)) EnergyIndices;
+
+
+public:
+    /*!
+     * \brief Update the temperature of the sub-control volume.
+     */
+    Scalar getTemperature(const PrimaryVariables &sol,
+                          const Element &element,
+                          const FVElementGeometry &elemGeom,
+                          int scvIdx,
+                          const Problem &problem,
+                          const int temperatureIdx) const
+    {
+        return problem.boxTemperature(element, elemGeom, scvIdx);
+    }
+
+
+    /*!
+     * \brief Update the enthalpy and the internal energy for a given
+     *        control volume.
+     *
+     * Since we are isothermal, we don't need to do anything!
+     */
+    template <class MutableParams>
+    void update(MutableParams &mutParams,
+                const PrimaryVariables &sol,
+                const Element &element,
+                const FVElementGeometry &elemGeom,
+                int scvIdx,
+                const Problem &problem)
+    {
+        temperature_ = problem.boxTemperature(element, elemGeom, scvIdx);
+
+        // set the fluid temperatures
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            mutParams.setTemperature(phaseIdx, temperature_);
+    }
+
+    /*!
+     * \brief Return the temperature of any given phase [K]
+     */
+    Scalar temperature(int phaseIdx = 0) const
+    { return temperature_; }
+
+    /*!
+     * \brief If running under valgrind this produces an error message
+     *        if some of the object's attributes is undefined.
+     */
+    void checkDefined() const
+    {
+        Valgrind::CheckDefined(temperature_);
+    }
+
+protected:
+    Scalar temperature_;
+
+};
+
+/*!
+ * \brief Contains the energy related quantities which are constant within a
+ *        finite volume in the two-phase, N-component model.
+ */
+template <class TypeTag>
+class MPNCVolumeVariablesEnergy<TypeTag, /*enableEnergy=*/true, /*kineticEnergyTransfer=*/false>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+
+    enum { numPhases        = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents    = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { temperatureIdx   = Indices::temperatureIdx };
+    enum { numEnergyEqs     = Indices::NumPrimaryEnergyVars};
+    enum { temperature0Idx = Indices::temperatureIdx };
+
+public:
+    /*!
+     * \brief Update the temperature of the sub-control volume.
+     */
+    Scalar getTemperature(const PrimaryVariables &sol,
+                          const Element &element,
+                          const FVElementGeometry &elemGeom,
+                          int scvIdx,
+                          const Problem &problem,
+                          const int dummy) const
+    {
+        // retrieve temperature from solution vector
+        return sol[temperatureIdx];
+    }
+
+    /*!
+     * \brief Update the enthalpy and the internal energy for a given
+     *        control volume.
+     */
+    template <class MutableParams>
+    void update(MutableParams &mutParams,
+                const PrimaryVariables &sol,
+                const Element &element,
+                const FVElementGeometry &elemGeom,
+                int scvIdx,
+                const Problem &problem)
+    {
+        Valgrind::SetUndefined(*this);
+
+        // set the fluid temperatures
+        temperature_ = sol[temperature0Idx];
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            mutParams.setTemperature(phaseIdx, temperature_);
+
+        heatCapacity_ =
+            problem.spatialParameters().heatCapacity(element, elemGeom, scvIdx);
+        Valgrind::CheckDefined(heatCapacity_);
+
+        soilDensity_ =
+                problem.spatialParameters().soilDensity(element, elemGeom, scvIdx);
+        Valgrind::CheckDefined(soilDensity_);
+
+        // set the enthalpies
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            Scalar h =
+                FluidSystem::computeEnthalpy(mutParams, phaseIdx);
+            mutParams.setEnthalpy(phaseIdx, h);
+        }
+    }
+
+    /*!
+     * \brief Returns the total heat capacity [J/(K m^3)] of the rock matrix in
+     *        the sub-control volume.
+     */
+    Scalar heatCapacity() const
+    { return heatCapacity_; };
+
+    /*!
+     * \brief Returns the temperature in fluid / solid phase(s)
+     *        the sub-control volume.
+     */
+    Scalar temperature(int phaseIdx = 0) const
+    { return temperature_; }
+
+    /*!
+     * \brief Returns the total density of the given soil [kg / m^3] in
+     *        the sub-control volume.
+     */
+    Scalar soilDensity() const
+    { return soilDensity_; };
+
+    /*!
+     * \brief If running under valgrind this produces an error message
+     *        if some of the object's attributes is undefined.
+     */
+    void checkDefined() const
+    {
+        Valgrind::CheckDefined(heatCapacity_);
+        Valgrind::CheckDefined(soilDensity_);
+        Valgrind::CheckDefined(temperature_);
+    };
+
+protected:
+    Scalar heatCapacity_;
+    Scalar soilDensity_;
+    Scalar temperature_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/boxmodels/MpNc/energy/MpNcvtkwriterenergy.hh b/dumux/boxmodels/MpNc/energy/MpNcvtkwriterenergy.hh
new file mode 100644
index 0000000000000000000000000000000000000000..c09ba8b3800cb0dc036b3b1afe23e605b68d3017
--- /dev/null
+++ b/dumux/boxmodels/MpNc/energy/MpNcvtkwriterenergy.hh
@@ -0,0 +1,232 @@
+/*****************************************************************************
+ *   Copyright (C) 2011 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 VTK writer module for the energy related quantities of the
+ *        MpNc model.
+ */
+#ifndef DUMUX_MPNC_VTK_WRITER_ENERGY_HH
+#define DUMUX_MPNC_VTK_WRITER_ENERGY_HH
+
+#include "../MpNcvtkwritermodule.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief VTK writer module for the energy related quantities of the
+ *        MpNc model.
+ *
+ * This is the specialization for the case without energy.
+ */
+template<class TypeTag,
+         bool enableEnergy /* = false */,
+         bool enableKineticEnergy /* = false */>
+class MPNCVtkWriterEnergy : public MPNCVtkWriterModule<TypeTag>
+{
+    static_assert(enableKineticEnergy == false,
+                  "If you enable kinetic energy transfer between fluids, you"
+                  "also have to enable the energy in general!");
+
+    typedef MPNCVtkWriterModule<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementBoundaryTypes)) ElementBoundaryTypes;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+
+    typedef typename ParentType::ScalarBuffer ScalarBuffer;
+    typedef typename ParentType::PhaseBuffer PhaseBuffer;
+    typedef typename ParentType::ComponentBuffer ComponentBuffer;
+    typedef typename ParentType::PhaseComponentBuffer PhaseComponentBuffer;
+
+public:
+    MPNCVtkWriterEnergy(const Problem &problem)
+        : ParentType(problem)
+    {
+        temperatureOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddTemperatures);
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+        if (temperatureOutput_) this->resizeScalarBuffer_(temperature_);
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvElemGeom,
+                        const ElementVolumeVariables &elemVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+        int n = elem.template count<dim>();
+        for (int i = 0; i < n; ++i) {
+            int I = this->problem_.vertexMapper().map(elem, i, dim);
+            const VolumeVariables &volVars = elemVolVars[i];
+
+            if (temperatureOutput_) 
+                temperature_[I] = volVars.fluidState().temperature(0);
+        }
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+        if (temperatureOutput_)
+            this->commitScalarBuffer_(writer, "T", temperature_);
+    }
+
+private:
+    bool temperatureOutput_;
+
+    ScalarBuffer temperature_;
+};
+
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief VTK writer module for the energy related quantities of the
+ *        MpNc model.
+ *
+ * This is the specialization for the case with an energy equation but
+ * local thermal equilibrium. (i.e. no kinetic energy transfer)
+ */
+template<class TypeTag>
+class MPNCVtkWriterEnergy<TypeTag, /* enableEnergy = */ true, /* enableKineticEnergy = */ false >
+    : public MPNCVtkWriterModule<TypeTag>
+{
+    typedef MPNCVtkWriterModule<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementBoundaryTypes)) ElementBoundaryTypes;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+    enum { numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+
+    typedef typename ParentType::ScalarBuffer ScalarBuffer;
+    typedef typename ParentType::PhaseBuffer PhaseBuffer;
+    typedef typename ParentType::ComponentBuffer ComponentBuffer;
+    typedef typename ParentType::PhaseComponentBuffer PhaseComponentBuffer;
+
+
+public:
+    MPNCVtkWriterEnergy(const Problem &problem)
+        : ParentType(problem)
+    {
+        temperatureOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddTemperatures);
+        enthalpyOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddEnthalpies);
+        internalEnergyOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddInternalEnergies);       
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+        if (temperatureOutput_) this->resizeScalarBuffer_(temperature_);
+        if (enthalpyOutput_) this->resizePhaseBuffer_(enthalpy_);
+        if (internalEnergyOutput_) this->resizePhaseBuffer_(internalEnergy_);
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvElemGeom,
+                        const ElementVolumeVariables &elemVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+        int n = elem.template count<dim>();
+        for (int i = 0; i < n; ++i) {
+            int I = this->problem_.vertexMapper().map(elem, i, dim);
+            const VolumeVariables &volVars = elemVolVars[i];
+
+            if (temperatureOutput_) temperature_[I] = volVars.fluidState().temperature(0);
+            for (int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
+                if (enthalpyOutput_) 
+                    enthalpy_[phaseIdx][I] = volVars.fluidState().temperature(phaseIdx);
+                if (internalEnergyOutput_) 
+                    internalEnergy_[phaseIdx][I] = volVars.fluidState().internalEnergy(phaseIdx);
+            }
+        }
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+        if (temperatureOutput_)
+            this->commitScalarBuffer_(writer, "T", temperature_);
+        if (enthalpyOutput_)
+            this->commitPhaseBuffer_(writer, "h_%s", enthalpy_);
+        if (internalEnergyOutput_)
+            this->commitPhaseBuffer_(writer, "u_%s", internalEnergy_);
+    }
+
+private:
+    bool temperatureOutput_;
+    bool enthalpyOutput_;
+    bool internalEnergyOutput_;
+
+    ScalarBuffer temperature_;
+    PhaseBuffer enthalpy_;
+    PhaseBuffer internalEnergy_;
+};
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/mass/MpNcindicesmass.hh b/dumux/boxmodels/MpNc/mass/MpNcindicesmass.hh
new file mode 100644
index 0000000000000000000000000000000000000000..175c9dd68dbf9763b00a8e2127fe6acdadb99db3
--- /dev/null
+++ b/dumux/boxmodels/MpNc/mass/MpNcindicesmass.hh
@@ -0,0 +1,85 @@
+/*****************************************************************************
+ *   Copyright (C) 2010-2011 by Philipp Nuske                                *
+ *   Copyright (C) 2011 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+/*!
+ * \brief The indices for the mass flow part of the compositional
+ *        multi-phase model.
+ */
+#ifndef DUMUX_MPNC_MASS_INDICES_HH
+#define DUMUX_MPNC_MASS_INDICES_HH
+
+namespace Dumux
+{
+/*!
+ * \brief The indices required for conservation of mass.
+ *
+ * This is the specialization for the case without kinetic mass
+ * transfer (i.e. assuming chemical equilibrium)
+ */
+template <int PVOffset,
+          class TypeTag,
+          bool enableKinetic /*=false*/>
+class MPNCMassIndices
+{
+    static_assert(!enableKinetic,
+                  "No kinetic mass transfer module included, "
+                  "but kinetic mass transfer enabled.");
+
+    enum { numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+
+public:
+    /*!
+     * \brief This module defines one new primary variable.
+     */
+    static const int NumPrimaryVars = numComponents;
+
+    /*!
+     * \brief Index for the fugacity of the first component in the
+     *        first phase in a vector of primary variables.
+     *
+     * The next numComponents indices represent the remaining
+     * fugacities:
+     *
+     *  fug0Idx + 0 = fugacity of component 0
+     *  fug0Idx + 1 = fugacity of component 1
+     *  ...
+     *  fug0Idx + N - 1 = fugacity of component N
+     */
+    static const int fug0Idx = PVOffset + 0;
+
+    /*!
+     * \brief Equation index of the mass conservation equation for the
+     *        first component.
+     *
+     * The next numComponents indices represent the equations of all
+     * components in all phases:
+     *
+     *  conti00EqIdx + 0 = continuity of component 0
+     *  conti00EqIdx + 1 = continuity of component 1
+     *  ...
+     *  conti00EqIdx + N - 1 = continuity of component N
+     */
+    static const int conti0EqIdx = PVOffset + 0;
+};
+
+}
+
+#endif
diff --git a/dumux/boxmodels/MpNc/mass/MpNclocalresidualmass.hh b/dumux/boxmodels/MpNc/mass/MpNclocalresidualmass.hh
new file mode 100644
index 0000000000000000000000000000000000000000..80047434e854a3345743e26ddc1d43c3ecb2ec4b
--- /dev/null
+++ b/dumux/boxmodels/MpNc/mass/MpNclocalresidualmass.hh
@@ -0,0 +1,346 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2011 by Andreas Lauser                               *
+ *   Copyright (C) 2011 by Philipp Nuske                                     *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH
+#define DUMUX_MPNC_LOCAL_RESIDUAL_MASS_HH
+
+#include <dune/common/fvector.hh>
+#include <dumux/material/constraintsolvers/compositionfromfugacities.hh>
+
+#include "../diffusion/diffusion.hh"
+
+namespace Dumux
+{
+/*!
+ * \brief The mass conservation part of the Mp-Nc model.
+ *
+ * This is the class represents methods which are shared amongst all
+ * mass conservation modules.
+ */
+template<class TypeTag>
+class MPNCLocalResidualMassCommon
+{
+protected:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+
+    enum { dim = GridView::dimension };
+    enum { numPhases        = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents    = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { enableDiffusion  = GET_PROP_VALUE(TypeTag, PTAG(EnableDiffusion)) };
+    enum { enableEnergy     = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)) };
+    enum { enableKineticEnergy     = GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy)) };
+
+    typedef typename Dune::FieldVector<Scalar, dim> Vector;
+    typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector;
+    typedef MPNCDiffusion<TypeTag, enableDiffusion> Diffusion;
+
+    typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, enableKineticEnergy> EnergyResid;
+
+public:
+    /*!
+     * \brief Evaluate the amount moles within a sub-control volume in
+     *        a phase.
+     *
+     * The result should be averaged over the volume.
+     */
+    static void computePhaseStorage(ComponentVector &result,
+                                    const VolumeVariables &volVars,
+                                    int phaseIdx)
+    {
+        // compute storage term of all components within all phases
+        result = 0;
+        for (int compIdx = 0; compIdx < numComponents; ++ compIdx) {
+            result[compIdx] +=
+                volVars.fluidState().saturation(phaseIdx)*
+                volVars.fluidState().molarity(phaseIdx, compIdx);
+        }
+
+        result *= volVars.porosity();
+    }
+
+    /*!
+     * \brief Evaluates the advective flux of all conservation
+     *        quantities over a face of a subcontrol volume via a
+     *        fluid phase.
+     */
+    static void computeAdvectivePhaseFlux(ComponentVector &phaseComponentValues,
+                                          const FluxVariables &fluxVars,
+                                          const int phaseIdx)
+    {
+        static bool enableSmoothUpwinding_ = GET_PARAM(TypeTag, bool, EnableSmoothUpwinding);
+
+        Vector tmpVec;
+        fluxVars.intrinsicPermeability().mv(fluxVars.potentialGrad(phaseIdx),
+                                            tmpVec);
+
+        // advective part is flux over face, therefore needs to be multiplied by normal vector
+        // (length: area of face)
+        Scalar normalFlux = - (tmpVec*fluxVars.face().normal);
+
+        // data attached to upstream and the downstream vertices
+        // of the current phase
+        int upIdx = fluxVars.face().i;
+        int dnIdx = fluxVars.face().j;
+#ifndef NDEBUG
+        if (!std::isfinite(normalFlux))
+            DUNE_THROW(NumericalProblem, "Calculated non-finite normal flux");
+#endif
+
+        if (normalFlux < 0) std::swap(upIdx, dnIdx);
+        const VolumeVariables &up = fluxVars.volVars(upIdx);
+        const VolumeVariables &dn = fluxVars.volVars(dnIdx);
+
+        ////////
+        // advective fluxes of all components in the phase
+        ////////
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+            // add advective flux of current component in current
+            // phase. we use full upwinding.
+
+            if (enableSmoothUpwinding_) {
+                Scalar mobUp = up.mobility(phaseIdx);
+                Scalar cUp = up.fluidState().molarity(phaseIdx, compIdx);
+
+                Scalar mobDn = dn.mobility(phaseIdx);
+                Scalar cDn = dn.fluidState().molarity(phaseIdx, compIdx);
+
+                Scalar mUp = mobUp*cUp;
+                Scalar mDn = mobDn*cDn;
+                Scalar m0 = Dumux::harmonicMean(mUp, mDn);
+
+                Scalar x = std::abs(normalFlux);
+                Scalar sign = (normalFlux < 0)?-1:1;
+
+                // the direction from upstream to downstream
+                //GlobalPosition delta = this->curElement_().geometry().corner(upIdx);
+                //delta -= this->curElement_().geometry().corner(dnIdx);
+
+                // approximate the mean viscosity at the face
+                Scalar meanVisc = (up.fluidState().viscosity(phaseIdx) +
+                                   dn.fluidState().viscosity(phaseIdx))/2;
+
+                // put the mean viscosity and permeanbility in
+                // relation to the viscosity of water at
+                // approximatly 20 degrees Celsius.
+                const Scalar pGradRef = 10; // [Pa/m]
+                const Scalar muRef = 1e-3; // [Ns/m^2]
+                const Scalar Kref = 1e-12; // [m^2] = approx 1 Darcy
+
+                Scalar faceArea = fluxVars.face().normal.two_norm();
+                Scalar eps = pGradRef * Kref * faceArea * meanVisc/muRef; // * (1e3/18e-3)/meanC;
+
+                Scalar compFlux;
+                if (x >= eps) {
+                    // we only do tricks if x is below the epsilon
+                    // value
+                    compFlux = x*mUp;
+                }
+                else {
+                    Scalar xPos[] = { 0, eps };
+                    Scalar yPos[] = { 0, eps*mUp };
+                    Spline<Scalar> sp2(xPos, yPos, m0, mUp);
+                    compFlux = sp2.eval(x);
+                }
+
+                phaseComponentValues[compIdx] = sign*compFlux;
+            }
+            else {// !use smooth upwinding
+                phaseComponentValues[compIdx] =
+                    up.mobility(phaseIdx) *
+                    up.fluidState().molarity(phaseIdx, compIdx) *
+                    normalFlux;
+            }
+        }
+    }
+
+
+    /*!
+     * \brief Evaluates the advective flux of all conservation
+     *        quantities over a face of a subcontrol volume via a
+     *        fluid phase.
+     */
+    static void computeDiffusivePhaseFlux(ComponentVector &flux,
+                                          const FluxVariables &fluxVars,
+                                          int phaseIdx)
+    {
+        if (!enableDiffusion) {
+            flux = 0.0;
+            return;
+        }
+
+
+        const VolumeVariables &volVarsI = fluxVars.volVars(fluxVars.face().i);
+        const VolumeVariables &volVarsJ = fluxVars.volVars(fluxVars.face().j);
+        if (volVarsI.fluidState().saturation(phaseIdx) < 1e-4 ||
+            volVarsJ.fluidState().saturation(phaseIdx) < 1e-4)
+        {
+            return; // phase is not present in one of the finite volumes
+        }
+
+        // approximate the total concentration of the phase at the
+        // integration point by the arithmetic mean of the
+        // concentration of the sub-control volumes
+        Scalar molarDensityAtIP;
+        molarDensityAtIP = volVarsI.fluidState().molarDensity(phaseIdx);
+        molarDensityAtIP += volVarsJ.fluidState().molarDensity(phaseIdx);
+        molarDensityAtIP /= 2;
+
+        Diffusion::flux(flux, phaseIdx, fluxVars, molarDensityAtIP);
+    }
+};
+
+/*!
+ * \brief The mass conservation part of the Mp-Nc model.
+ *
+ * This is the specialization for the case where kinetic mass transfer
+ * is _not_ considered.
+ */
+template<class TypeTag, bool enableKinetic /*=false*/>
+class MPNCLocalResidualMass
+{
+    static_assert(!enableKinetic,
+                  "No kinetic mass transfer module included, "
+                  "but kinetic mass transfer enabled.");
+
+    typedef MPNCLocalResidualMassCommon<TypeTag> MassCommon;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+    enum { numPhases        = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents    = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { conti0EqIdx      = Indices::conti0EqIdx };
+    enum { numEnergyEqs     = Indices::NumPrimaryEnergyVars};
+
+    typedef typename Dune::FieldVector<Scalar, numComponents> ComponentVector;
+
+    enum { enableEnergy     = GET_PROP_VALUE(TypeTag, PTAG(EnableEnergy)) };
+    enum { enableKineticEnergy     = GET_PROP_VALUE(TypeTag, PTAG(EnableKineticEnergy)) };
+    typedef MPNCLocalResidualEnergy<TypeTag, enableEnergy, enableKineticEnergy> EnergyResid;
+
+public:
+    /*!
+     * \brief Calculate the storage for all mass balance equations
+     */
+    static void computeStorage(PrimaryVariables &storage,
+                               const VolumeVariables &volVars)
+    {
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            storage[conti0EqIdx + compIdx] = 0.0;
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            addPhaseStorage(storage, volVars, phaseIdx);
+        }
+    };
+
+    /*!
+     * \brief Calculate the storage for all mass balance equations
+     *        within a single fluid phase
+     */
+    static void addPhaseStorage(PrimaryVariables &storage,
+                                const VolumeVariables &volVars,
+                                int phaseIdx)
+    {
+        // calculate the component-wise mass storage
+        ComponentVector phaseComponentValues;
+        MassCommon::computePhaseStorage(phaseComponentValues,
+                                        volVars,
+                                        phaseIdx);
+
+        // copy to the primary variables
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            storage[conti0EqIdx + compIdx] += phaseComponentValues[compIdx];
+    };
+
+    /*!
+     * \brief Calculate the storage for all mass balance equations
+     */
+    static void computeFlux(PrimaryVariables &flux,
+                            const FluxVariables &fluxVars,
+                            const ElementVolumeVariables & elemVolVars)
+    {
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            flux[conti0EqIdx + compIdx] = 0.0;
+
+        ComponentVector phaseComponentValuesAdvection(0.);
+        ComponentVector phaseComponentValuesDiffusion(0.);
+        ComponentVector phaseComponentValuesMassTransport[numPhases]; // what goes into the energy module
+
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            MassCommon::computeAdvectivePhaseFlux(phaseComponentValuesAdvection, fluxVars, phaseIdx);
+            Valgrind::CheckDefined(phaseComponentValuesAdvection);
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                flux[conti0EqIdx + compIdx] +=
+                        phaseComponentValuesAdvection[compIdx];
+
+            MassCommon::computeDiffusivePhaseFlux(phaseComponentValuesDiffusion, fluxVars, phaseIdx);
+            Valgrind::CheckDefined(phaseComponentValuesDiffusion);
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+                flux[conti0EqIdx + compIdx] +=
+                        phaseComponentValuesDiffusion[compIdx];
+
+            // Right now I think that adding the two contributions individually into the flux is best for debugging and understanding.
+            // The Energy module needs both contributions.
+            phaseComponentValuesMassTransport[phaseIdx] = phaseComponentValuesDiffusion + phaseComponentValuesAdvection ;
+            Valgrind::CheckDefined(flux);
+        }
+
+        // \todo
+        //
+        // The computeflux() of the Energy module needs a
+        // component-wise flux (for the diffusive enthalpy transport)
+        // It makes some sense calling energy from here, because energy
+        // is carried by mass However, it is not really a clean
+        // solution.
+
+        // energy transport in fluid phases
+        EnergyResid::computeFlux(flux,
+                                 fluxVars,
+                                 elemVolVars,
+                                 phaseComponentValuesMassTransport);
+        Valgrind::CheckDefined(flux);
+    }
+
+
+
+    /*!
+     * \brief Calculate the source terms for all mass balance
+     *        equations
+     */
+    static void computeSource(PrimaryVariables &source,
+                              const VolumeVariables &volVars)
+    {
+        // mass transfer is not considered in this mass module
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            source[conti0EqIdx + compIdx] = 0.0;
+    };
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/boxmodels/MpNc/mass/MpNcvolumevariablesmass.hh b/dumux/boxmodels/MpNc/mass/MpNcvolumevariablesmass.hh
new file mode 100644
index 0000000000000000000000000000000000000000..e1775f476ff1f079a7d47a25bee40da5eac7b668
--- /dev/null
+++ b/dumux/boxmodels/MpNc/mass/MpNcvolumevariablesmass.hh
@@ -0,0 +1,142 @@
+/*****************************************************************************
+ *   Copyright (C) 2010-2011 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 mass conservation part of the volume variables
+ */
+#ifndef DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH
+#define DUMUX_MPNC_VOLUME_VARIABLES_MASS_HH
+
+#include <dumux/material/fluidstates/genericfluidstate.hh>
+#include <dumux/material/fluidstates/equilibriumfluidstate.hh>
+
+namespace Dumux
+{
+/*!
+ * \brief The compositional part of the volume variables if chemical
+ *        equilibrium _is_ assumed
+ */
+template <class TypeTag, bool enableKinetic /* = false */>
+class MPNCVolumeVariablesMass
+{
+    static_assert(!enableKinetic,
+                  "No kinetic mass transfer module included, "
+                  "but kinetic mass transfer enabled.");
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(CompositionFromFugacitiesSolver)) CompositionFromFugacitiesSolver;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+
+    enum { numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    enum { fug0Idx = Indices::fug0Idx };
+
+    typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;
+
+public:
+    /*!
+     * \brief The fluid state which is used by the volume variables to
+     *        store the thermodynamic state.
+     *
+     * If chemical equilibrium is assumed, we use the fluid state
+     * which saves some memory.
+     */
+    typedef EquilibriumFluidState<Scalar, FluidSystem> FluidState;
+
+    /*!
+     * \brief Update composition of all phases in the mutable
+     *        parameters from the primary variables.
+     */
+    template <class MutableParams>
+    void update(MutableParams &mutParams,
+                const PrimaryVariables &priVars,
+                const VolumeVariables *hint,
+
+                const Problem &problem,
+                const Element &element,
+                const FVElementGeometry &elemGeom,
+                int scvIdx)
+    {
+        ComponentVector fug;
+        // retrieve component fugacities
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx)
+            fug[compIdx] = priVars[fug0Idx + compIdx];
+
+        // calculate phase compositions
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            // initial guess
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                Scalar x_ij = 1.0/numComponents;
+                if (hint)
+                    // use the hint for the initial mole fraction!
+                    x_ij = hint->fluidState().moleFrac(phaseIdx, compIdx);
+
+                // set initial guess of the component's mole fraction
+                mutParams.setMoleFrac(phaseIdx,
+                                      compIdx,
+                                      x_ij);
+
+            }
+
+            // calculate the phase composition from the component
+            // fugacities
+            if (!hint)
+                // if no hint was given, we ask the constraint solver
+                // to make an initial guess
+                CompositionFromFugacitiesSolver::guessInitial(mutParams, phaseIdx, fug);
+            CompositionFromFugacitiesSolver::solve(mutParams, phaseIdx, fug);
+
+            /*
+              std::cout << "final composition: " << FluidSystem::phaseName(phaseIdx) << "="
+              << mutParams.moleFrac(phaseIdx, 0) << " "
+              << mutParams.moleFrac(phaseIdx, 1) << " "
+              << mutParams.moleFrac(phaseIdx, 2) << " "
+              << mutParams.moleFrac(phaseIdx, 3) << " "
+              << mutParams.moleFrac(phaseIdx, 4) << " "
+              << mutParams.moleFrac(phaseIdx, 5) << " "
+              << mutParams.moleFrac(phaseIdx, 6) << "\n";
+            */
+
+        }
+    }
+
+    /*!
+     * \brief If running in valgrind this makes sure that all
+     *        quantities in the volume variables are defined.
+     */
+    void checkDefined() const
+    {
+    }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/boxmodels/MpNc/mass/MpNcvtkwritermass.hh b/dumux/boxmodels/MpNc/mass/MpNcvtkwritermass.hh
new file mode 100644
index 0000000000000000000000000000000000000000..ebc9fcc611a50440066c595c3b3a698818d90c3d
--- /dev/null
+++ b/dumux/boxmodels/MpNc/mass/MpNcvtkwritermass.hh
@@ -0,0 +1,128 @@
+/*****************************************************************************
+ *   Copyright (C) 2011 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 VTK writer module for the mass related quantities of the
+ *        MpNc model.
+ */
+#ifndef DUMUX_MPNC_VTK_WRITER_MASS_HH
+#define DUMUX_MPNC_VTK_WRITER_MASS_HH
+
+#include "../MpNcvtkwritermodule.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MPNCModel
+ *
+ * \brief VTK writer module for the mass related quantities of the
+ *        MpNc model.
+ *
+ * This is the specialization for the case _without_ kinetic mass
+ * transfer between phases.
+ */
+template<class TypeTag, bool enableKinetic /* = false */>
+class MPNCVtkWriterMass : public MPNCVtkWriterModule<TypeTag>
+{
+    static_assert(!enableKinetic,
+                  "No kinetic mass transfer module included, "
+                  "but kinetic mass transfer enabled.");
+
+    typedef MPNCVtkWriterModule<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Problem)) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementBoundaryTypes)) ElementBoundaryTypes;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(VolumeVariables)) VolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    enum { dim = GridView::dimension };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)) };
+    bool fugacityOutput_;
+
+    typedef typename ParentType::ScalarBuffer ScalarBuffer;
+    typedef typename ParentType::PhaseBuffer PhaseBuffer;
+    typedef typename ParentType::ComponentBuffer ComponentBuffer;
+    typedef typename ParentType::PhaseComponentBuffer PhaseComponentBuffer;
+
+
+public:
+    MPNCVtkWriterMass(const Problem &problem)
+        : ParentType(problem)
+    {
+        fugacityOutput_ = GET_PARAM(TypeTag, bool, MPNC, VtkAddFugacities);
+    }
+
+    /*!
+     * \brief Allocate memory for the scalar fields we would like to
+     *        write to the VTK file.
+     */
+    template <class MultiWriter>
+    void allocBuffers(MultiWriter &writer)
+    {
+        if (fugacityOutput_) this->resizeComponentBuffer_(fugacity_);
+    }
+
+    /*!
+     * \brief Modify the internal buffers according to the volume
+     *        variables seen on an element
+     */
+    void processElement(const Element &elem,
+                        const FVElementGeometry &fvElemGeom,
+                        const ElementVolumeVariables &elemVolVars,
+                        const ElementBoundaryTypes &elemBcTypes)
+    {
+        int n = elem.template count<dim>();
+        for (int i = 0; i < n; ++i) {
+            int I = this->problem_.vertexMapper().map(elem, i, dim);
+            const VolumeVariables &volVars = elemVolVars[i];
+
+            if (fugacityOutput_) {
+                for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                    fugacity_[compIdx][I] = volVars.fluidState().fugacity(compIdx);
+                }
+            }
+        }
+    }
+
+    /*!
+     * \brief Add all buffers to the VTK output writer.
+     */
+    template <class MultiWriter>
+    void commitBuffers(MultiWriter &writer)
+    {
+        if (fugacityOutput_)
+            this->commitComponentBuffer_(writer, "f_%s", fugacity_);
+    }
+
+private:
+    ComponentBuffer fugacity_;
+};
+
+}
+
+#endif
diff --git a/dumux/material/constraintsolvers/Makefile.am b/dumux/material/constraintsolvers/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..70f8f174617e3dd8488fc44a23ad1680eef4c247
--- /dev/null
+++ b/dumux/material/constraintsolvers/Makefile.am
@@ -0,0 +1 @@
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/material/constraintsolvers/compositionfromfugacities.hh b/dumux/material/constraintsolvers/compositionfromfugacities.hh
new file mode 100644
index 0000000000000000000000000000000000000000..65716f9a6d2c12d27335a240804c591897c8e76d
--- /dev/null
+++ b/dumux/material/constraintsolvers/compositionfromfugacities.hh
@@ -0,0 +1,356 @@
+/*****************************************************************************
+ *   Copyright (C) 2010-2011 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Determines the fluid composition given the component
+ *        fugacities and an arbitary equation of state.
+ */
+#ifndef DUMUX_COMPOSITION_FROM_FUGACITIES_HH
+#define DUMUX_COMPOSITION_FROM_FUGACITIES_HH
+
+#include "../fluidstates/genericfluidstate.hh"
+
+namespace Dumux {
+
+/*!
+ * \brief Calculates the chemical equilibrium from the component
+ *        fugacities in a phase.
+ */
+template <class Scalar, class FluidSystem>
+class CompositionFromFugacities
+{
+    typedef typename FluidSystem::MutableParameters MutableParameters;
+
+    enum { numPhases = FluidSystem::numPhases };
+    enum { numComponents = FluidSystem::numComponents };
+    
+public:
+    typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;
+
+    /*!
+     * \brief Guess an initial value for the composition of the phase.
+     */
+    static void guessInitial(MutableParameters &mutParams, int phaseIdx, const ComponentVector &fugVec)
+    {
+        if (FluidSystem::isIdealMixture(phaseIdx)) 
+            return;
+        
+        // Pure component fugacities
+        for (int i = 0; i < numComponents; ++ i) {
+            //std::cout << f << " -> " << mutParams.fugacity(phaseIdx, i)/f << "\n";
+            mutParams.setMoleFrac(phaseIdx,
+                                  i, 
+                                  1.0/numComponents);
+        }
+    };
+
+    /*!
+     * \brief Calculates the chemical equilibrium from the component
+     *        fugacities in a phase.
+     *
+     * The phase's fugacities must already be set.
+     */
+    static void solve(MutableParameters &mutParams, 
+                      int phaseIdx, 
+                      const ComponentVector &targetFug)
+    {
+        // use a much more efficient method in case the phase is an
+        // ideal mixture
+        if (FluidSystem::isIdealMixture(phaseIdx)) {
+            solveIdealMix_(mutParams, phaseIdx, targetFug);
+            return;
+        }
+
+        Dune::FMatrixPrecision<Scalar>::set_singular_limit(1e-25);
+
+        // save initial composition in case something goes wrong
+        Dune::FieldVector<Scalar, numComponents> xInit;
+        for (int i = 0; i < numComponents; ++i) {
+            xInit[i] = mutParams.moleFrac(phaseIdx, i);
+        };
+        
+        /////////////////////////
+        // Newton method
+        /////////////////////////
+
+        // Jacobian matrix
+        Dune::FieldMatrix<Scalar, numComponents, numComponents> J;
+        // solution, i.e. phase composition
+        Dune::FieldVector<Scalar, numComponents> x;
+        // right hand side
+        Dune::FieldVector<Scalar, numComponents> b;
+        
+        // maximum number of iterations
+        const int nMax = 25;
+        for (int nIdx = 0; nIdx < nMax; ++nIdx) {
+            // calculate Jacobian matrix and right hand side
+            linearize_(J, b, mutParams, phaseIdx, targetFug); 
+            Valgrind::CheckDefined(J);
+            Valgrind::CheckDefined(b);
+
+            /*
+            std::cout << FluidSystem::phaseName(phaseIdx) << "Phase composition: ";
+            for (int i = 0; i < FluidSystem::numComponents; ++i)
+                std::cout << mutParams.moleFrac(phaseIdx, i) << " ";
+            std::cout << "\n";
+            std::cout << FluidSystem::phaseName(phaseIdx) << "Phase phi: ";
+            for (int i = 0; i < FluidSystem::numComponents; ++i)
+                std::cout << mutParams.fugacityCoeff(phaseIdx, i) << " ";
+            std::cout << "\n";
+            */
+
+            // Solve J*x = b
+            x = 0;
+            try { J.solve(x, b); }
+            catch (Dune::FMatrixError e) 
+            { throw Dumux::NumericalProblem(e.what()); }
+
+            //std::cout << "original delta: " << x << "\n";
+
+            Valgrind::CheckDefined(x);
+            
+            /*
+            std::cout << FluidSystem::phaseName(phaseIdx) << "Phase composition: ";
+            for (int i = 0; i < FluidSystem::numComponents; ++i)
+                std::cout << mutParams.moleFrac(phaseIdx, i) << " ";
+            std::cout << "\n";
+            std::cout << "J: " << J << "\n";
+            std::cout << "rho: " << mutParams.density(phaseIdx) << "\n";
+            std::cout << "delta: " << x << "\n";
+            std::cout << "defect: " << b << "\n";
+
+            std::cout << "J: " << J << "\n";
+
+            std::cout << "---------------------------\n";
+            */
+
+            // update the fluid composition. b is also used to store
+            // the defect for the next iteration.
+            Scalar relError = update_(mutParams, x, b, phaseIdx, targetFug);
+            //std::cout << "relError: " << relError << "\n";
+            
+            if (relError < 1e-9) {
+                mutParams.updateMeanMolarMass(phaseIdx);
+                
+                Scalar Vm = FluidSystem::computeMolarVolume(mutParams, phaseIdx);
+                mutParams.setMolarVolume(phaseIdx, Vm);
+
+                //std::cout << "num iterations: " << nIdx << "\n";
+                return;
+            }
+        }
+        
+        DUNE_THROW(NumericalProblem, 
+                   "Calculating the " << FluidSystem::phaseName(phaseIdx)
+                   << "Phase composition failed. Initial {x} = {"
+                   << xInit 
+                   << "}, {fug_t} = {" << targetFug << "}, p = " << mutParams.pressure(phaseIdx)
+                   << ", T = " << mutParams.temperature(phaseIdx));
+    };
+
+
+protected:
+    // update the phase composition in case the phase is an ideal
+    // mixture, i.e. the component's fugacity coefficients are
+    // independent of the phase's composition.
+    static void solveIdealMix_(MutableParameters &mutParams, 
+                               int phaseIdx,
+                               const ComponentVector &fugacities)
+    {        
+        for (int i = 0; i < numComponents; ++ i) {
+            Scalar phi = FluidSystem::computeFugacityCoeff(mutParams, phaseIdx, i);
+            Scalar gamma = phi * mutParams.pressure(phaseIdx);
+            mutParams.setFugacityCoeff(phaseIdx, i, phi);
+            mutParams.setMoleFrac(phaseIdx, i, fugacities[i]/gamma);
+        };
+        mutParams.updateMeanMolarMass(phaseIdx);
+        
+        Scalar Vm = FluidSystem::computeMolarVolume(mutParams, phaseIdx);
+        mutParams.setMolarVolume(phaseIdx, Vm);
+        return;
+    };
+
+    static void linearize_(Dune::FieldMatrix<Scalar, numComponents, numComponents> &J,
+                           Dune::FieldVector<Scalar, numComponents> &defect,
+                           MutableParameters &mutParams, 
+                           int phaseIdx,
+                           const ComponentVector &targetFug)
+    {       
+        // reset jacobian
+        J = 0;
+        
+        // calculate the defect (deviation of the current fugacities
+        // from the target fugacities)
+        for (int i = 0; i < numComponents; ++ i) {
+            Scalar phi = FluidSystem::computeFugacityCoeff(mutParams,
+                                                           phaseIdx,
+                                                           i);
+            Scalar f = phi*mutParams.pressure(phaseIdx)*mutParams.moleFrac(phaseIdx, i);
+            mutParams.setFugacityCoeff(phaseIdx, i, phi);
+                
+            defect[i] = targetFug[i] - f;
+        }
+        
+        // assemble jacobian matrix of the constraints for the composition
+        for (int i = 0; i < numComponents; ++ i) {            
+            const Scalar eps = 1e-11; //std::max(1e-16, std::abs(x_i)*1e-9);
+
+            ////////
+            // approximately calculate partial derivatives of the
+            // fugacity defect of all components in regard to the mole
+            // fraction of the i-th component. This is done via
+            // forward differences
+
+            // deviate the mole fraction of the i-th component
+            Scalar x_i = mutParams.moleFrac(phaseIdx, i);
+            mutParams.setMoleFrac(phaseIdx, i, x_i + eps);
+
+            // compute new defect and derivative for all component
+            // fugacities
+            for (int j = 0; j < numComponents; ++j) {
+                // compute the j-th component's fugacity coefficient ...
+                Scalar phi = FluidSystem::computeFugacityCoeff(mutParams,
+                                                               phaseIdx,
+                                                               j);
+                // ... and its fugacity ...
+                Scalar f = 
+                    phi *
+                    mutParams.pressure(phaseIdx) *
+                    mutParams.moleFrac(phaseIdx, j);
+                // as well as the defect for this fugacity
+                Scalar defJPlusEps = targetFug[j] - f;
+
+                // use forward differences to calculate the defect's
+                // derivative
+                J[j][i] = (defJPlusEps - defect[j])/eps;
+            }
+            
+            // reset composition to original value
+            mutParams.setMoleFrac(phaseIdx, i, x_i);
+            
+            // end forward differences
+            ////////
+        }
+    }
+
+    static Scalar update_(MutableParameters &mutParams,
+                          Dune::FieldVector<Scalar, numComponents> &x,
+                          Dune::FieldVector<Scalar, numComponents> &b,
+                          int phaseIdx,
+                          const Dune::FieldVector<Scalar, numComponents> &targetFug)
+    {
+        // store original composition and calculate relative error
+        Dune::FieldVector<Scalar, numComponents> origComp;
+        Scalar relError = 0;
+        Scalar sumDelta = 0;
+        Scalar sumx = 0;
+        for (int i = 0; i < numComponents; ++i) {
+            origComp[i] = mutParams.moleFrac(phaseIdx, i);
+            relError = std::max(relError, std::abs(x[i]));
+            
+            sumx += std::abs(mutParams.moleFrac(phaseIdx, i));
+            sumDelta += std::abs(x[i]);
+        };
+
+#if 1
+        // chop update to at most 20% change in composition
+        const Scalar maxDelta = 0.2;
+        if (sumDelta > maxDelta)
+            x /= (sumDelta/maxDelta);
+#endif
+
+        //Scalar curDefect = calculateDefect_(mutParams, phaseIdx, targetFug);
+        //Scalar nextDefect;
+        //Scalar sumMoleFrac = 0.0;
+        //ComponentVector newB(1e100);
+        //for (int numTries = 0; numTries < 1; ++numTries) {
+            // change composition
+            for (int i = 0; i < numComponents; ++i) {
+                Scalar newx = origComp[i] - x[i];
+#if 1
+                // only allow negative mole fractions if the target fugacity is negative
+                if (targetFug[i] > 0)
+                    newx = std::max(0.0, newx);
+                // only allow positive mole fractions if the target fugacity is positive
+                else if (targetFug[i] < 0)
+                    newx = std::min(0.0, newx);
+                // if the target fugacity is zero, the mole fraction must also be zero
+                else
+                    newx = 0;
+#endif
+                mutParams.setMoleFrac(phaseIdx, i, newx);
+                //sumMoleFrac += std::abs(newx);
+            }
+
+            /*
+            // if the sum of the mole fractions gets 0, we take the
+            // original composition divided by 100
+            if (sumMoleFrac < 1e-10) {
+                for (int i = 0; i < numComponents; ++i) {
+                    mutParams.setMoleFrac(phaseIdx, i, origComp[i]/100);
+                }
+                return relError;
+            }
+            */
+
+            /*
+            // calculate new residual
+            for (int i = 0; i < numComponents; ++i) {
+                Scalar phi = FluidSystem::computeFugacityCoeff(mutParams,
+                                                               phaseIdx,
+                                                               i);
+                mutParams.setFugacityCoeff(phaseIdx, i, phi);
+            }
+
+            nextDefect = calculateDefect_(mutParams, phaseIdx, targetFug);
+            //std::cout << "try delta: " << x << "\n";
+            //std::cout << "defect: old=" << curDefect << " new=" << nextDefect << "\n"; 
+            if (nextDefect <= curDefect)
+                break;
+
+             // divide delta vector
+             x /= 2;
+        }
+            */
+
+        return relError;
+    }
+
+    static Scalar calculateDefect_(const MutableParameters &params, 
+                                   int phaseIdx, 
+                                   const ComponentVector &targetFug)
+    {
+        Scalar result = 0.0;
+        for (int i = 0; i < numComponents; ++i) {
+            // sum of the fugacity defect weighted by the inverse
+            // fugacity coefficient
+            result += std::abs( 
+                (targetFug[i] - params.fugacity(phaseIdx, i))
+                /
+                params.fugacityCoeff(phaseIdx, i) );
+        };
+        return result;
+    }
+};
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/material/eos/Makefile.am b/dumux/material/eos/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..70f8f174617e3dd8488fc44a23ad1680eef4c247
--- /dev/null
+++ b/dumux/material/eos/Makefile.am
@@ -0,0 +1 @@
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/material/eos/pengrobinson.hh b/dumux/material/eos/pengrobinson.hh
new file mode 100644
index 0000000000000000000000000000000000000000..793ff06d7566331b194c9e85f07f2d86c826659c
--- /dev/null
+++ b/dumux/material/eos/pengrobinson.hh
@@ -0,0 +1,483 @@
+/*****************************************************************************
+ *   Copyright (C) 2010-2011 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Implements the Peng-Robinson equation of state for liquids
+ *        and gases.
+ *
+ * See:
+ *
+ * D.-Y. Peng, D.B. Robinson: A new two-constant equation of state,
+ * Industrial & Engineering Chemistry Fundamentals, 1976, 15 (1),
+ * pp. 59–64
+ *
+ * R. Reid, et al.: The Properties of Gases and Liquids,
+ * 4th edition, McGraw-Hill, 1987, pp. 42-44, 82
+ */
+#ifndef DUMUX_PENG_ROBINSON_HH
+#define DUMUX_PENG_ROBINSON_HH
+
+#include <dumux/material/idealgas.hh>
+#include <dumux/common/math.hh>
+
+#include <iostream>
+
+namespace Dumux
+{
+
+/*!
+ *
+ * \brief Implements the Peng-Robinson equation of state for liquids
+ *        and gases.
+ *
+ * See:
+ *
+ * D.-Y. Peng, D.B. Robinson: A new two-constant equation of state,
+ * Industrial & Engineering Chemistry Fundamentals, 1976, 15 (1),
+ * pp. 59–64
+ *
+ * R. Reid, et al.: The Properties of Gases and Liquids,
+ * 4th edition, McGraw-Hill, 1987, pp. 42-44, 82
+ */
+template <class Scalar>
+class PengRobinson
+{
+    //! The ideal gas constant [Pa * m^3/mol/K]
+    static constexpr Scalar R = Dumux::Constants<Scalar>::R;
+
+    PengRobinson()
+    { }
+
+public:
+    /*!
+     * \brief Predicts the vapor pressure for the temperature given in
+     *        setTP().
+     *
+     * Initially, the vapor pressure is roughly estimated by using the
+     * Ambrose-Walton method, then the Newton method is used to make
+     * difference between the gas and liquid phase fugacity zero.
+     */
+    template <class Params>
+    static Scalar computeVaporPressure(const Params &params, Scalar T) 
+    {
+        typedef typename Params::Component Component;
+        if (T >= Component::criticalTemperature())
+            return Component::criticalPressure();
+
+        // initial guess of the vapor pressure
+        Scalar Vm[3];
+        const Scalar eps = Component::criticalPressure()*1e-10;
+        
+        // use the Ambrose-Walton method to get an initial guess of
+        // the vapor pressure
+        Scalar pVap = ambroseWalton_(params, T);
+
+        // Newton-Raphson method
+        for (int i = 0; i < 5; ++i) {
+            // calculate the molar densities
+            int numSol = molarVolumes(Vm, params, T, pVap);
+            assert(numSol == 3);
+
+            Scalar f = fugacityDifference_(params, T, pVap, Vm[0], Vm[2]);
+            Scalar df_dp = 
+                fugacityDifference_(params, T, pVap  + eps, Vm[0], Vm[2])
+                -
+                fugacityDifference_(params, T, pVap - eps, Vm[0], Vm[2]);
+            df_dp /= 2*eps;
+                        
+            Scalar delta = f/df_dp;
+            pVap = pVap - delta;
+
+            if (std::abs(delta/pVap) < 1e-10)
+                break;
+        }
+        
+        return pVap;
+    }
+
+    /*!
+     * \brief Computes molar volumes where the Peng-Robinson EOS is
+     *        true.
+     */
+    template <class Params>
+    static Scalar computeMolarVolume(const Params &params,
+                                     int phaseIdx,
+                                     bool gasPhase)
+    {
+        Valgrind::CheckDefined(params.temperature(phaseIdx));
+        Valgrind::CheckDefined(params.pressure(phaseIdx));
+
+        Scalar Vm;
+        Valgrind::SetUndefined(Vm);
+
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+
+        Scalar RT= R*T;
+        Scalar Astar = params.a(phaseIdx)*p/(RT*RT);
+        Scalar Bstar = params.b(phaseIdx)*p/RT;
+
+        Scalar a1 = 1.0;
+        Scalar a2 = - (1 - Bstar);
+        Scalar a3 = Astar - Bstar*(3*Bstar + 2);
+        Scalar a4 = Bstar*(- Astar + Bstar*(1 + Bstar));
+        
+        // ignore the first two results if the smallest
+        // compressibility factor is <= 0.0. (this means that if we
+        // would get negative molar volumes for the liquid phase, we
+        // consider the liquid phase non-existant.)
+        Scalar Z[3] = {0.0,0.0,0.0};
+        int numSol = invertCubicPolynomial(Z, a1, a2, a3, a4);
+        if (numSol == 3) {
+            // the EOS has three intersections with the pressure,
+            // i.e. the molar volume of gas is the largest one and the
+            // molar volume of liquid is the smallest one
+            if (gasPhase)
+                Vm = Z[2]*RT/p;
+            else
+                Vm = Z[0]*RT/p;
+        }
+        else if (numSol == 1) {
+            // the EOS only has one intersection with the pressure,
+            // for the other phase, we take the extremum of the EOS
+            // with the largest distance from the intersection.
+            Scalar VmCubic = Z[0]*RT/p;
+
+            // find the extrema (if they are present)
+            Scalar Vmin, Vmax;
+            bool hasExtrema;
+            hasExtrema = findExtrema_(Vmin, Vmax, params, phaseIdx);
+            
+            if (!hasExtrema) {
+                // if the EOS does not exhibit any extrema, the fluid
+                // is critical...
+                Vm = VmCubic;
+                handleCriticalFluid_(Vm, params, phaseIdx, gasPhase);
+            }
+            else {
+                if (gasPhase)
+                    Vm = std::max(Vmax, VmCubic);
+                else
+                    Vm = std::min(Vmin, VmCubic);
+            }
+        }
+
+        Valgrind::CheckDefined(Vm);
+        return Vm;
+    }
+
+    /*!
+     * \brief Returns the fugacity coefficient for a given pressure
+     *        and molar volume.
+     *
+     * This is the same value as computeFugacity() because the mole
+     * fraction of a component in a pure fluid is obviously always
+     * 100%.
+     *
+     * \param T pressure [K]
+     * \param p pressure [Pa]
+     * \param Vm Molar volume [m^3/mol]
+     */
+    template <class Params>
+    static Scalar computeFugacityCoeff(const Params &params)
+    {
+        Scalar T = params.temperature();
+        Scalar p = params.pressure();
+        Scalar Vm = params.molarVolume();
+
+        Scalar RT = R*T;
+        Scalar Z = p*Vm/RT;
+        Scalar Bstar = p*params.b() / RT;
+
+        Scalar tmp = 
+            (Vm + params.b()*(1 + std::sqrt(2))) / 
+            (Vm + params.b()*(1 - std::sqrt(2)));
+        Scalar expo = - params.a()/(RT * 2 * params.b() * std::sqrt(2));
+        Scalar fugCoeff =
+            std::exp(Z - 1) / (Z - Bstar) *
+            std::pow(tmp, expo);
+
+        return fugCoeff;
+    };
+
+    /*!
+     * \brief Returns the fugacity coefficient for a given pressure
+     *        and molar volume.
+     *
+     * This is the fugacity coefficient times the pressure. The mole
+     * fraction of a component in a pure fluid is obviously always
+     * 100%, so it is not required.
+     *
+     * \param T pressure [K]
+     * \param p pressure [Pa]
+     * \param Vm Molar volume [m^3/mol]
+     */
+    template <class Params>
+    static Scalar computeFugacity(const Params &params)
+    { return params.pressure()*computeFugacityCoeff(params); }
+
+protected:
+    template <class Params>
+    static void handleCriticalFluid_(Scalar &Vm,
+                                     const Params &params,
+                                     int phaseIdx,
+                                     bool gasPhase)
+    {
+        Scalar Vcrit;
+        findCriticalMolarVolume_(Vcrit,
+                                 params, 
+                                 phaseIdx, 
+                                 Vm,
+                                 gasPhase);
+        if (gasPhase)
+            Vm = std::max(Vm, Vcrit);
+        else
+            Vm = std::min(Vm, Vcrit);
+    }
+
+    template <class Params>
+    static void findCriticalMolarVolume_(Scalar &Vcrit, 
+                                         const Params &params,
+                                         int phaseIdx,
+                                         Scalar Vcubic,
+                                         bool gasPhase)
+    {
+        Params tmpParams(params);
+
+        // use an isotherm where the EOS should exhibit two maxima
+        Scalar Tmin = 150; // [K]
+
+        Scalar minVm;
+        Scalar maxVm;
+        Scalar T = Tmin;
+        for (int i = 0; ; ++i) {
+            tmpParams.setTemperature(phaseIdx, T);
+            tmpParams.updateEosParams(phaseIdx);
+            
+            if (findExtrema_(minVm, maxVm, tmpParams, phaseIdx, /*hintSet=*/false))
+                break;
+            
+            T = (T + params.temperature(phaseIdx)) / 2;
+            if (i >= 3) {
+                DUNE_THROW(NumericalProblem,
+                           "TODO: better way to identify a non-critical temperature");
+            };
+        }
+
+        // Newton's method: Start at minimum temperature and minimize
+        // the "gap" between the extrema of the EOS
+        for (int i = 0; i < 25; ++i) {
+            // calculate function we would like to minimize
+            Scalar f = maxVm - minVm;
+
+            // check if we're converged
+            if (f < 1e-8 ||
+                (gasPhase && maxVm < Vcubic) ||
+                (!gasPhase && minVm > Vcubic))
+            {
+                Vcrit = (maxVm + minVm)/2;
+                return;
+            }
+
+            // backward differences. Forward differences are not
+            // robust, since the isotherm could be critical if an
+            // epsilon was added to the temperature. (this is case
+            // rarely happens, though)
+            const Scalar eps = - 1e-8;
+            T = T + eps;
+            tmpParams.updateEosParams(phaseIdx);
+            tmpParams.setTemperature(phaseIdx, T);
+            if (!findExtrema_(minVm, maxVm, tmpParams, phaseIdx, /*hintSet=*/true))
+                DUNE_THROW(NumericalProblem,
+                           "Error when calculating derivative of extrema "
+                           "to calculate the critical point of phase "
+                           << phaseIdx);
+            T = T - eps;
+            Scalar fStar = maxVm - minVm;
+
+            // derivative of the difference between the maximum's
+            // molar volume and the minimum's molar volume regarding
+            // temperature
+            Scalar fPrime = (fStar - f)/eps;
+                            
+            // update value for the current iteration
+            Scalar delta = f/fPrime;
+            if (delta > 0)
+                delta = -10;
+
+            // line search (we have to make sure that both extrema
+            // still exist after the update)
+            Scalar Tstar = T - delta;
+            for (int j = 0; ; ++j) {
+                if (j >= 10) {
+                    DUNE_THROW(NumericalProblem,
+                               "Could not determine the critical point of phase "
+                               << phaseIdx);
+                }
+                
+                tmpParams.setTemperature(phaseIdx, Tstar);
+                tmpParams.updateEosParams(phaseIdx);
+                if (findExtrema_(minVm, maxVm, tmpParams, phaseIdx, /*hintSet=*/(j==0))) {
+                    // if the isotherm at Tstar exhibits two extrema
+                    // the update is finished
+                    T = Tstar;
+                    break;
+                }
+                else {
+                    delta /= 2;
+                    Tstar = T - delta;
+                }
+            };
+        }
+    };
+
+    // find the two molar volumes where the EOS exhibits extrema and
+    // which are larger than the covolume of the phase
+    template <class Params>
+    static bool findExtrema_(Scalar &Vmin, 
+                             Scalar &Vmax,
+                             const Params &params,
+                             int phaseIdx, 
+                             bool hintSet = false)
+    {
+        Scalar a = params.a(phaseIdx);
+        Scalar b = params.b(phaseIdx);
+        Scalar u = 2;
+        Scalar w = -1;
+
+        Scalar RT = R*params.temperature(phaseIdx);
+        
+        // calculate coefficients of the 4th order polynominal in
+        // monomial basis
+        Scalar a1 = RT;
+        Scalar a2 = 2*RT*u*b - 2*a;
+        Scalar a3 = 2*RT*w*b*b + RT*u*u*b*b  + 4*a*b - u*a*b;
+        Scalar a4 = 2*RT*u*w*b*b*b + 2*u*a*b*b - 2*a*b*b;
+        Scalar a5 = RT*w*w*b*b*b*b - u*a*b*b*b;
+            
+        // Newton method to find first root
+
+        // if the values which we got on Vmin and Vmax are usefull, we
+        // will reuse them as initial value, else we will start 10%
+        // above the covolume
+        Scalar V = hintSet?Vmin:b*1.1;
+        Scalar delta = 1.0;
+        for (int i = 0; std::abs(delta) > 1e-9; ++i) {
+            Scalar f = a5 + V*(a4 + V*(a3 + V*(a2 + V*a1)));
+            Scalar fPrime = a4 + V*(2*a3 + V*(3*a2 + V*4*a1));
+            
+            if (std::abs(fPrime) < 1e-20) {
+                // give up if the derivative is zero
+                Vmin = 0;
+                Vmax = 0;
+                return false;
+            }
+                
+
+            delta = f/fPrime;
+            V -= delta;
+
+            if (i > 20) {
+                // give up after 20 iterations...
+                Vmin = 0;
+                Vmax = 0;
+                return false;
+            }
+        }
+        
+        // polynomial division
+        Scalar b1 = a1;
+        Scalar b2 = a2 + V*b1;
+        Scalar b3 = a3 + V*b2;
+        Scalar b4 = a4 + V*b3;
+        
+        // invert resulting cubic polynomial analytically 
+        Scalar allV[4];
+        allV[0] = V;
+        int numSol = 1 + Dumux::invertCubicPolynomial(&allV[1], b1, b2, b3, b4);
+
+        // sort all roots of the derivative
+        std::sort(allV + 0, allV + numSol);
+
+        // check whether the result is physical
+        if (allV[numSol - 2] < b) {
+            // the second largest extremum is smaller than the phase's
+            // covolume which is physically impossible
+            Vmin = Vmax = 0;
+            return false;
+        }
+
+        // it seems that everything is okay...
+        Vmin = allV[numSol - 2];
+        Vmax = allV[numSol - 1];
+        return true;
+    }
+
+    /*!
+     * \brief The Ambrose-Walton method to estimate the vapor
+     *        pressure.
+     *
+     * \return Vapor pressure estimate in bar
+     *
+     * See:
+     * 
+     * D. Ambrose, J. Walton: "Vapor Pressures up to Their Critical
+     * Temperatures of Normal Alkanes and 1-Alkanols", Pure
+     * Appl. Chem., 61, 1395-1403, 1989
+     */
+    template <class Params>
+    static Scalar ambroseWalton_(const Params &params, Scalar T)
+    {
+        typedef typename Params::Component Component;
+        
+        Scalar Tr = T / Component::criticalTemperature();
+        Scalar tau = 1 - Tr;
+        Scalar omega = Component::acentricFactor();
+        
+        Scalar f0 = (tau*(-5.97616 + std::sqrt(tau)*(1.29874 - tau*0.60394)) - 1.06841*std::pow(tau, 5))/Tr;
+        Scalar f1 = (tau*(-5.03365 + std::sqrt(tau)*(1.11505 - tau*5.41217)) - 7.46628*std::pow(tau, 5))/Tr;
+        Scalar f2 = (tau*(-0.64771 + std::sqrt(tau)*(2.41539 - tau*4.26979)) + 3.25259*std::pow(tau, 5))/Tr;
+
+        return Component::criticalPressure()*std::exp(f0 + omega * (f1 + omega*f2));
+    };
+
+    /*!
+     * \brief Returns the difference between the liquid and the gas phase
+     *        fugacities in [bar]
+     *
+     * \param p Pressure [bar]
+     *
+     * \param VmLiquid Molar volume of the liquid phase [cm^3/mol]
+     *
+     * \param VmGas Molar volume of the gas phase [cm^3/mol]
+     */
+    template <class Params>
+    static Scalar fugacityDifference_(const Params &params,
+                                      Scalar T,
+                                      Scalar p,
+                                      Scalar VmLiquid,
+                                      Scalar VmGas)
+    { return fugacity(params, T, p, VmLiquid) - fugacity(params, T, p, VmGas); };
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/material/eos/pengrobinsonmixture.hh b/dumux/material/eos/pengrobinsonmixture.hh
new file mode 100644
index 0000000000000000000000000000000000000000..06e994c84c1b9e2423a8316eabac7575d9fb0ad2
--- /dev/null
+++ b/dumux/material/eos/pengrobinsonmixture.hh
@@ -0,0 +1,157 @@
+/*****************************************************************************
+ *   Copyright (C) 2010 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Implements the Peng-Robinson equation of state for a
+ *        mixture.
+ */
+#ifndef DUMUX_PENG_ROBINSON_MIXTURE_HH
+#define DUMUX_PENG_ROBINSON_MIXTURE_HH
+
+#include <stdlib.h>
+#include "pengrobinson.hh"
+
+#include <dumux/material/constants.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \brief Implements the Peng-Robinson equation of state for a
+ *        mixture.
+ */
+template <class Scalar, class StaticParameters>
+class PengRobinsonMixture
+{
+    enum { numComponents = StaticParameters::numComponents };
+    typedef Dumux::PengRobinson<Scalar> PengRobinson;
+
+    // this class cannot be instantiated!
+    PengRobinsonMixture() {};
+
+    // the ideal gas constant
+    static constexpr Scalar R = Dumux::Constants<Scalar>::R;
+
+    // the u and w parameters as given by the Peng-Robinson EOS
+    static constexpr Scalar u = 2.0;
+    static constexpr Scalar w = -1.0;
+
+public:
+    /*!
+     * \brief Computes molar volumes where the Peng-Robinson EOS is
+     *        true.
+     *
+     * \return Number of solutions.
+     */
+    template <class MutableParams, class FluidState>
+    static int computeMolarVolumes(Scalar *Vm,
+                                   const MutableParams &params,
+                                   int phaseIdx,
+                                   const FluidState &fs)
+    {
+        return PengRobinson::computeMolarVolumes(Vm, params, phaseIdx, fs);
+    }
+
+    /*!
+     * \brief Returns the fugacity coefficient of an individual
+     *        component in the phase.
+     *
+     * The fugacity coefficient \f$\phi_i\f$ of a component $i$ is
+     * defined as
+     * \f[
+     f_i = \phi_i x_i \;,
+     \f]
+     * where \f$f_i\f$ is the component's fugacity and \f$x_i\f$ is 
+     * the component's mole fraction.
+     *
+     * See:
+     *
+      * R. Reid, et al.: The Properties of Gases and Liquids,
+      * 4th edition, McGraw-Hill, 1987, pp. 42-44, 143-145
+      */
+    template <class Params>
+    static Scalar computeFugacityCoeff(const Params &params,
+                                       int phaseIdx,
+                                       int compIdx)
+    {
+        // note that we normalize the component mole fractions, so
+        // that their sum is 100%. This increases numerical stability
+        // considerably if the fluid state is not physical.
+
+        Scalar Vm = params.molarVolume(phaseIdx);
+
+        // Calculate b_i / b
+        Scalar bi_b = params.bPure(phaseIdx, compIdx) / params.b(phaseIdx);
+
+        // Calculate the compressibility factor
+        Scalar RT = R*params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx); // molar volume in [bar]
+        Scalar Z = p*Vm/RT; // compressibility factor
+
+        // Calculate A^* and B^* (see: Reid, p. 42)
+        Scalar Astar = params.a(phaseIdx)*p/(RT*RT);
+        Scalar Bstar = params.b(phaseIdx)*p/(RT);
+
+        
+        // calculate delta_i (see: Reid, p. 145)
+        Scalar deltai = 2*std::sqrt(params.aPure(phaseIdx, compIdx))/params.a(phaseIdx);
+        Scalar tmp = 0;
+        for (int j = 0; j < numComponents; ++j) {
+            tmp +=
+                params.moleFrac(phaseIdx, j) / params.sumMoleFrac(phaseIdx) *
+                std::sqrt(params.aPure(phaseIdx, j))
+                *(1.0 - StaticParameters::interactionCoefficient(compIdx, j));
+        };
+        deltai *= tmp;
+
+        Scalar base = 
+            (2*Z + Bstar*(u + std::sqrt(u*u - 4*w))) /
+            (2*Z + Bstar*(u - std::sqrt(u*u - 4*w)));
+        Scalar expo =  Astar/(Bstar*std::sqrt(u*u - 4*w))*(bi_b - deltai);
+
+        Scalar fugCoeff =
+            std::exp(bi_b*(Z - 1))/std::max(1e-9, Z - Bstar) *
+            std::pow(base, expo);
+
+        ////////
+        // limit the fugacity coefficient to a reasonable range:
+        //
+        // on one side, we want the mole fraction to be at
+        // least 10^-3 if the fugacity is at the current pressure
+        //
+        fugCoeff = std::min(1e10, fugCoeff);
+        //
+        // on the other hand, if the mole fraction of the component is 100%, we want the
+        // fugacity to be at least 10^-3 Pa
+        //
+        fugCoeff = std::max(1e-10, fugCoeff);
+        ///////////
+        if (!std::isfinite(fugCoeff)) {
+            std::cout << "Non finite phi: " << fugCoeff << "\n";
+        }
+
+        return fugCoeff;
+    };
+
+};
+} // end namepace Dumux
+
+#endif
diff --git a/dumux/material/eos/pengrobinsonparams.hh b/dumux/material/eos/pengrobinsonparams.hh
new file mode 100644
index 0000000000000000000000000000000000000000..19d20cfb54508b912eabc3c20eb112f6c4d4bc48
--- /dev/null
+++ b/dumux/material/eos/pengrobinsonparams.hh
@@ -0,0 +1,95 @@
+/*****************************************************************************
+ *   Copyright (C) 2010 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Base class for Peng-Robinson parameters of a
+ *        single-component fluid or a mixture
+ *
+ * See:
+ * 
+ * R. Reid, et al.: The Properties of Gases and Liquids, 4th edition,
+ * McGraw-Hill, 1987, pp. 43-44
+ */
+#ifndef DUMUX_PENG_ROBINSON_PARAMS_HH
+#define DUMUX_PENG_ROBINSON_PARAMS_HH
+
+namespace Dumux
+{
+/*!
+ * \brief Stores and provides access to the Peng-Robinson parameters
+ *
+ * See:
+ * 
+ * R. Reid, et al.: The Properties of Gases and Liquids, 4th edition,
+ * McGraw-Hill, 1987, pp. 43-44
+ */
+template <class Scalar>
+class PengRobinsonParams
+{
+public:
+    /*!
+     * \brief Returns the attractive parameter 'a' of the
+     *        Peng-Robinson fluid.
+     */
+    Scalar a() const
+    { return a_; }
+
+    /*!
+     * \brief Returns the repulsive parameter 'b' of the Peng-Robinson
+     *        fluid.
+     */
+    Scalar b() const
+    { return b_; }
+
+    /*!
+     * \brief If run under valgrind, this method produces an warning
+     *        if the parameters where not determined correctly.
+     */
+    void checkDefined() const
+    {
+#ifndef NDEBUG
+        Valgrind::CheckDefined(a_);
+        Valgrind::CheckDefined(b_);
+#endif
+    };
+
+    /*!
+     * \brief Set the attractive parameter 'a' of the Peng-Robinson
+     *        fluid.
+     */
+    void setA(Scalar value)
+    { a_ = value; }
+
+    /*!
+     * \brief Set the repulsive parameter 'b' of the Peng-Robinson
+     *        fluid.
+     */
+    void setB(Scalar value)
+    { b_ = value; }
+
+protected:
+    Scalar a_;
+    Scalar b_;
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/material/eos/pengrobinsonparamsmixture.hh b/dumux/material/eos/pengrobinsonparamsmixture.hh
new file mode 100644
index 0000000000000000000000000000000000000000..4828ae8f2e7d99d978cd3a179463ac831bd5ea38
--- /dev/null
+++ b/dumux/material/eos/pengrobinsonparamsmixture.hh
@@ -0,0 +1,177 @@
+/*****************************************************************************
+ *   Copyright (C) 2010 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief The Peng-Robinson parameters for a mixture
+ *
+ * See:
+ * 
+ * R. Reid, et al.: The Properties of Gases and Liquids, 4th edition,
+ * McGraw-Hill, 1987, pp. 43-44
+ */
+#ifndef DUMUX_PENG_ROBINSON_PARAMS_MIXTURE_HH
+#define DUMUX_PENG_ROBINSON_PARAMS_MIXTURE_HH
+
+#include "pengrobinsonparams.hh"
+#include "pengrobinson.hh"
+
+#include <dumux/material/constants.hh>
+
+namespace Dumux
+{
+/*!
+ * \brief The mixing rule for the Peng-Robinson equation of state as given in Reid, p. 82
+ *
+ * See:
+ * 
+ * R. Reid, et al.: The Properties of Gases and Liquids, 4th edition,
+ * McGraw-Hill, 1987, p. 82
+ */
+template <class Scalar, class StaticParams, int phaseIdx>
+class PengRobinsonParamsMixture : public PengRobinsonParams<Scalar>
+{
+    typedef Dumux::PengRobinsonParams<Scalar> ParentType;
+    
+    // Peng-Robinson parameters for pure substances
+    typedef Dumux::PengRobinsonParams<Scalar> PureParams;
+    
+    // The Peng-Robinson EOS for this mixture
+    typedef Dumux::PengRobinson<Scalar> PengRobinson;
+
+    // number of components of which the fluid is composed
+    enum { numComponents = StaticParams::numComponents };
+    
+    // ideal gas constant
+    static constexpr Scalar R = Dumux::Constants<Scalar>::R;
+
+public:
+    typedef StaticParams StaticParameters;
+
+    /*!
+     * \brief Update Peng-Robinson parameters for the pure components.
+     */
+    template <class FluidState>
+    void updatePure(const FluidState &fluidState)
+    {
+        updatePure(fluidState.temperature(phaseIdx), 
+                   fluidState.pressure(phaseIdx));
+    }
+
+    /*!
+     * \brief Update Peng-Robinson parameters for the pure components.
+     *
+     * This method is given by the SPE5 paper.
+     */
+    void updatePure(Scalar temperature, Scalar pressure)
+    {
+        // Calculate the Peng-Robinson parameters of the pure
+        // components
+        //
+        // See: R. Reid, et al.: The Properties of Gases and Liquids,
+        // 4th edition, McGraw-Hill, 1987, p. 43
+        for (int i = 0; i < numComponents; ++i) {
+            Scalar pc = StaticParams::criticalPressure(i);
+            Scalar omega = StaticParams::acentricFactor(i);
+            Scalar Tr = temperature/StaticParams::criticalTemperature(i);
+            Scalar RTc = R*StaticParams::criticalTemperature(i);
+            Scalar f_omega = 0.37464 + omega*(1.54226 - omega*0.26992);
+
+            Scalar tmp = 1 + f_omega*(1 - std::sqrt(Tr));
+            this->pureParams_[i].setA(0.4572355*RTc*RTc/pc
+                                      *
+                                      tmp*tmp);
+            this->pureParams_[i].setB(0.0777961 * RTc / pc);
+        }
+    }
+
+    /*!
+     * \brief Calculates the "a" and "b" Peng-Robinson parameters for
+     *        the mixture.
+     *
+     * The updatePure() method needs to be called _before_ calling
+     * this method!
+     */
+    template <class FluidState>
+    void updateMix(const FluidState &fluidState)
+    {
+        // Calculate the Peng-Robinson parameters of the mixture
+        //
+        // See: R. Reid, et al.: The Properties of Gases and Liquids,
+        // 4th edition, McGraw-Hill, 1987, p. 82
+        Scalar a = 0;
+        Scalar b = 0;
+        for (int i = 0; i < numComponents; ++i) {
+            Scalar xi = fluidState.moleFrac(phaseIdx, i);
+            for (int j = i; j < numComponents; ++j) {
+                Scalar xj = fluidState.moleFrac(phaseIdx, j);
+
+                // interaction coefficient as given in SPE5
+                Scalar Psi = StaticParams::interactionCoefficient(i, j);
+                
+                // mixing rule from Reid, page 82
+                a += xi*xj*std::sqrt(pureParams_[i].a()*pureParams_[j].a())*(1 - Psi); 
+            }
+
+            // mixing rule from Reid, page 82
+            b += xi * pureParams_[i].b();
+        }
+        
+        this->setA(a);
+        this->setB(b);
+    }
+
+    /*!
+     * \brief Returns the Peng-Robinson parameters for a pure component.
+     */
+    const PureParams &operator[](int compIdx) const
+    {
+        assert(0 <= compIdx && compIdx < numComponents);
+        return pureParams_[compIdx];
+    }
+
+    /*!
+     * \brief If run under valgrind, this method produces an warning
+     *        if the parameters where not determined correctly.
+     */
+    void checkDefined() const
+    {
+#ifndef NDEBUG
+        ParentType::checkDefined();
+        for (int i = 0; i < numComponents; ++i)
+            pureParams_[i].checkDefined();
+#endif
+    };
+
+    /*!
+     * \brief Return the Peng-Robinson parameters of a pure substance,
+     */
+    const PureParams &pureParams(int compIdx) const
+    { return pureParams_[compIdx]; }
+      
+        
+protected:
+    PureParams pureParams_[numComponents];
+};
+
+
+} // end namepace
+
+#endif
diff --git a/dumux/material/eos/pengrobinsonparamspure.hh b/dumux/material/eos/pengrobinsonparamspure.hh
new file mode 100644
index 0000000000000000000000000000000000000000..eebad5abb637c0475a13d85db0d60ef5f5f84550
--- /dev/null
+++ b/dumux/material/eos/pengrobinsonparamspure.hh
@@ -0,0 +1,156 @@
+/*****************************************************************************
+ *   Copyright (C) 2010 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief The Peng-Robinson parameters for a pure component
+ *
+ * See:
+ * 
+ * R. Reid, et al.: The Properties of Gases and Liquids, 4th edition,
+ * McGraw-Hill, 1987, pp. 43-44
+ */
+#ifndef DUMUX_PENG_ROBINSON_PARAMS_PURE_HH
+#define DUMUX_PENG_ROBINSON_PARAMS_PURE_HH
+
+#include "pengrobinsonparams.hh"
+
+#include <dumux/material/constants.hh>
+
+namespace Dumux
+{
+/*!
+ * \brief Stores, provides access to and calculates the Peng-Robinson
+ *        parameters of a pure component.
+ *
+ * See:
+ * 
+ * R. Reid, et al.: The Properties of Gases and Liquids, 4th edition,
+ * McGraw-Hill, 1987, pp. 43-44
+ */
+template <class Scalar, class ComponentT>
+class PengRobinsonParamsPure : public PengRobinsonParams<Scalar>
+{
+    typedef PengRobinsonParams<Scalar> ParentType;
+    
+    // the ideal gas constant
+    static const Scalar R = Dumux::Constants<Scalar>::R;
+
+public:
+    typedef ComponentT Component;
+
+    /*!
+     * \brief Calculates the "a" and "b" Peng-Robinson parameters for
+     *        the component.
+     *
+     * See:
+     * 
+     * R. Reid, et al.: The Properties of Gases and Liquids, 4th edition,
+     * McGraw-Hill, 1987, pp. 43-44
+     */
+    void update(Scalar T, Scalar p)
+    {
+        temperature_ = T;
+        pressure_ = p;
+
+        Scalar pc = Component::criticalPressure();
+        Scalar omega = Component::acentricFactor();
+        Scalar Tr = T/Component::criticalTemperature();
+        Scalar RTc = R*Component::criticalTemperature();
+        Scalar f_omega = 0.37464 + omega*(1.54226 - omega*0.26992);
+        Scalar tmp = 1.0 + f_omega*(1.0 - std::sqrt(Tr));
+        tmp = tmp*tmp;
+
+        Scalar a = 0.4572355 * RTc*RTc/pc * tmp;
+        Scalar b =  0.0777961 * RTc/pc;
+
+        this->setA(a);
+        this->setB(b);
+    }
+
+    /*!
+     * \brief Sets the molar volume [m^3/mol] of the substance.
+     *
+     * The phaseIdx parameter is there to adhere to the common
+     * interface with the multi-phase stuff and is just ignored.
+     */
+    void setMolarVolume(int phaseIdx, Scalar Vm)
+    { setMolarVolume(Vm); }
+
+    /*!
+     * \brief Sets the molar volume [m^3/mol] of the substance.
+     */
+    void setMolarVolume(Scalar Vm)
+    { molarVolume_ = Vm; }
+
+    /*!
+     * \brief Returns the temperature [K] of the system.
+     *
+     * The phaseIdx parameter is there to adhere to the common
+     * interface with the multi-phase stuff and is just ignored.
+     */
+    Scalar temperature(int phaseIdx = 0) const
+    { return temperature_; }
+
+    /*!
+     * \brief Returns the pressure [Pa] of the system.
+     *
+     * The phaseIdx parameter is there to adhere to the common
+     * interface with the multi-phase stuff and is just ignored.
+     */
+    Scalar pressure(int phaseIdx = 0) const
+    { return pressure_; }
+
+    /*!
+     * \brief Returns the molar volume [m^3/mol] of the substance.
+     *
+     * The phaseIdx parameter is there to adhere to the common
+     * interface with the multi-phase stuff and is just ignored.
+     */
+    Scalar molarVolume(int phaseIdx = 0) const
+    { return molarVolume_; }
+
+    /*!
+     * \brief Returns the attractive parameter "a" [Pa (m^3/mol)^2] for the cubic EOS.
+     *
+     * The phaseIdx parameter is there to adhere to the common
+     * interface with the multi-phase stuff and is just ignored.
+     */
+    Scalar a(int phaseIdx = 0) const
+    { return ParentType::a(); }
+
+    /*!
+     * \brief Returns the covolume of the substance [m^3/mol]
+     *
+     * The phaseIdx parameter is there to adhere to the common
+     * interface with the multi-phase stuff and is just ignored.
+     */
+    Scalar b(int phaseIdx = 0) const
+    { return ParentType::b(); }
+
+
+private:
+    Scalar temperature_;
+    Scalar pressure_;
+    Scalar molarVolume_;
+};
+} // end namepace
+
+#endif
diff --git a/dumux/material/fluidmatrixinteractions/Makefile.am b/dumux/material/fluidmatrixinteractions/Makefile.am
index 631c0d226d1333fc9ac4eef24e2a1d4b8b7d6c94..1e1fef223fd8ee5915237290d11ba55b31b6615d 100644
--- a/dumux/material/fluidmatrixinteractions/Makefile.am
+++ b/dumux/material/fluidmatrixinteractions/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = 2p
+SUBDIRS = 2p Mp
 
 fluidmatrixinteractionsdir = $(includedir)/dumux/material/fluidmatrixinteractions
 
diff --git a/dumux/material/fluidmatrixinteractions/Mp/2padapter.hh b/dumux/material/fluidmatrixinteractions/Mp/2padapter.hh
new file mode 100644
index 0000000000000000000000000000000000000000..e0c2c67b0e86eb84ed91680d4a5d845f108c7e2f
--- /dev/null
+++ b/dumux/material/fluidmatrixinteractions/Mp/2padapter.hh
@@ -0,0 +1,82 @@
+/*****************************************************************************
+ *   Copyright (C) 2010 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 2padapter.hh
+ *
+ * Makes the twophase capillary pressure-saturation relations
+ * available under the M-phase API for material laws
+ */
+#ifndef DUMUX_MP_2P_ADAPTER_HH
+#define DUMUX_MP_2P_ADAPTER_HH
+
+#include <algorithm>
+
+namespace Dumux
+{
+/*!
+ * \ingroup material
+ *
+ * \brief Implements a brookscorey saturation-capillary pressure relation
+ *
+ * Implements a brookscorey saturation-capillary pressure relation for
+ * M-phase fluid systems.
+ *
+ * \sa MpBrookscoreyMaterialParams
+ */
+template <int wPhaseIdx, class TwoPLaw >
+class TwoPAdapter
+{
+    enum { nPhaseIdx = (wPhaseIdx == 0)?1:0 };
+
+public:
+    typedef typename TwoPLaw::Params Params;
+    typedef typename Params::Scalar Scalar;
+    enum { numPhases = 2 };
+
+    /*!
+     * \brief The capillary pressure-saturation curve.
+     */
+    template <class ContainerT, class FluidState>
+    static void capillaryPressures(ContainerT &values,
+                                   const Params &params, 
+                                   const FluidState &state)
+    {
+        // non-wetting phase gets the capillary pressure added
+        values[nPhaseIdx] = 0;
+
+        // wetting phase does not get anything added
+        values[wPhaseIdx] = - TwoPLaw::pC(params, state.saturation(wPhaseIdx)); 
+    }
+
+    /*!
+     * \brief The relative permeability of all phases.
+     */
+    template <class ContainerT, class FluidState>
+    static void relativePermeabilities(ContainerT &values,
+                                       const Params &params, 
+                                       const FluidState &state)
+    {
+        values[wPhaseIdx] = TwoPLaw::krw(params, state.saturation(wPhaseIdx));
+        values[nPhaseIdx] = TwoPLaw::krn(params, state.saturation(wPhaseIdx));
+    };
+};
+}
+
+#endif
diff --git a/dumux/material/fluidmatrixinteractions/Mp/2poftadapter.hh b/dumux/material/fluidmatrixinteractions/Mp/2poftadapter.hh
new file mode 100644
index 0000000000000000000000000000000000000000..e13abdddaabee8dac199494d5b5e5271d5ad46f4
--- /dev/null
+++ b/dumux/material/fluidmatrixinteractions/Mp/2poftadapter.hh
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ *   Copyright (C) 2010 by Philipp Nuske                                     *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 2poftadapter.hh
+ *
+ * Makes the twophase capillary pressure-saturation relations
+ * available under the M-phase API for material laws.
+ *
+ * Also use the temperature dependent version of the material laws.
+ */
+#ifndef DUMUX_MP_2P_OFT_ADAPTER_HH
+#define DUMUX_MP_2P_OFT_ADAPTER_HH
+
+#include <algorithm>
+
+namespace Dumux
+{
+/*!
+ * \ingroup material
+ *
+ * \brief Adapts the interface of the MpNc material law to the standard-\Dumux material law.
+ *
+ *        Also use the temperature dependent version of the material laws.
+ */
+template <int wPhaseIdx, class TwoPLaw>
+class TwoPOfTAdapter
+{
+    enum { nPhaseIdx = (wPhaseIdx == 0)?1:0 };
+
+public:
+    typedef typename TwoPLaw::Params Params;
+    typedef typename Params::Scalar Scalar;
+    enum { numPhases = 2 };
+
+    /*!
+     * \brief The capillary pressure-saturation curve.
+     */
+    template <class pcContainerT, class FluidState>
+    static void capillaryPressures(pcContainerT &pc,
+                   const Params &params, 
+                   const FluidState &fluidState)
+    {
+        // non-wetting phase gets the capillary pressure added
+        pc[nPhaseIdx] = 0;
+
+        // wetting phase does not get anything added
+        pc[wPhaseIdx] = - TwoPLaw::pC(params, fluidState.saturation(wPhaseIdx), fluidState.temperature(wPhaseIdx));
+    }
+
+
+
+    /*!
+     * \brief The relative permeability of all phases.
+     */
+    template <class krContainerT, class FluidState>
+    static void relativePermeabilities(krContainerT &kr,
+                   const Params &params, 
+                   const FluidState &fluidState)
+    {
+        kr[wPhaseIdx] = TwoPLaw::krw(params, fluidState.saturation(wPhaseIdx));
+        kr[nPhaseIdx] = TwoPLaw::krn(params, fluidState.saturation(wPhaseIdx));
+    };
+};
+}
+
+#endif
diff --git a/dumux/material/fluidmatrixinteractions/Mp/Mpbrookscorey.hh b/dumux/material/fluidmatrixinteractions/Mp/Mpbrookscorey.hh
new file mode 100644
index 0000000000000000000000000000000000000000..70058f0c5d3d233987423678a69a2acfa046e83b
--- /dev/null
+++ b/dumux/material/fluidmatrixinteractions/Mp/Mpbrookscorey.hh
@@ -0,0 +1,152 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Mpbrookscoreymaterial.hh
+ *
+ * Implements a Brooks-Corey saturation-capillary pressure relation
+ * for M-phase fluid systems.
+ */
+#ifndef DUMUX_MP_BROOKSCOREY_MATERIAL_HH
+#define DUMUX_MP_BROOKSCOREY_MATERIAL_HH
+
+#include "Mpbrookscoreymaterialparams.hh"
+
+#include <algorithm>
+
+namespace Dumux
+{
+/*!
+ * \ingroup material
+ *
+ * \brief Implements a brookscorey saturation-capillary pressure relation
+ *
+ * Implements a brookscorey saturation-capillary pressure relation for
+ * M-phase fluid systems.
+ *
+ * \sa MpBrookscoreyMaterialParams
+ */
+template <int numPhasesV, class ScalarT,
+          class ParamsT = MpBrookscoreyMaterialParams<numPhasesV, ScalarT> >
+class MpBrookscoreyMaterial
+{
+public:
+    typedef ParamsT Params;
+    typedef typename Params::Scalar Scalar;
+    enum { numPhases = numPhasesV };
+    
+    /*!
+     * \brief The Brooks-Corey capillary pressure-saturation curve.
+     *
+     * The Brooks-Corey material law is given by the relation:
+     * \f[
+     p_i - p_{i - 1} = p_{e,i}\overline{S}_{i}^{-1/\alpha}
+     \f]
+    */
+    template <class pcContainerT, class SatContainerT>
+    static void pC(pcContainerT &pc,
+                   const Params &params, 
+                   const SatContainerT &saturations,
+                   Scalar temperature)
+    {
+        for (int i = 0; i < numPhases; ++i) {
+            Scalar S = saturations[i];
+            assert(0 <= S && S <= 1);
+            pc[i] = 
+                params.entryPressure(i) *
+                std::pow(S, -1.0/params.alpha(i));
+        }
+    }
+
+    /*!
+     * \brief The saturation-capillary pressure curve.
+     *
+     * This is the inverse of the capillary pressure-saturation curve:
+     * \f[
+     S_w = 1 - \frac{p_C - p_{C,entry}}{p_{C,max} - p_{C,entry}}
+     \f]
+     *
+     * \param pC Capillary pressure \f$\p_C\f$
+     * \return The effective saturaion of the wetting phase \f$\overline{S}_w\f$
+     */
+    template <class SatContainerT, class pcContainerT>
+    static void S(SatContainerT &saturations,
+                  const Params &params, 
+                  const pcContainerT &pc,
+                  Scalar temperature)
+    {
+        int refPhaseIdx = -1;
+        for (int i = 0; i < numPhases; ++i) {
+            Scalar p_Ci = pc[i];
+            assert(0 =< p_Ci);
+            if (params.entryPressure(i) == 0) {
+                assert(refPhaseIdx == -1);
+                refPhaseIdx = i;
+                continue;
+            }
+
+            Scalar tmp = pow(p_Ci/params.entryPressure(i), -params.alpha(i));
+            saturations[i] = tmp;
+        }
+    }
+
+#warning TODO
+#if 0
+    /*!
+     * \brief Returns the partial derivative of the capillary
+     *        pressure to the effective saturation.
+     *
+     * This is equivalent to
+     * \f[
+     \frac{\partial p_C}{\partial \overline{S}_w} =
+     - (p_{C,max} - p_{C,min})
+     \f]
+    */
+    static Scalar dpC_dSw(const Params &params, Scalar Swe)
+    {
+        return - (params.maxPC() - params.entryPC());
+    }
+
+    /*!
+     * \brief Returns the partial derivative of the effective
+     *        saturation to the capillary pressure.
+     */
+    static Scalar dSw_dpC(const Params &params, Scalar pC)
+    {
+        return - 1/(params.maxPC() - params.entryPC());
+    }
+#endif
+
+    /*!
+     * \brief The relative permeability of all phases.
+     */
+    template <class krContainerT, class SatContainerT>
+    static void kr(krContainerT &kr,
+                   const Params &params, 
+                   const SatContainerT &saturations,
+                   Scalar temperature)
+    {
+        for (int i = 0; i < numPhases; ++i)
+            // TODO: probably incorrect!
+            kr[i] = pow(saturations[i], 2.0/params.alpha(i) + 3);
+    };
+};
+}
+
+#endif
diff --git a/dumux/material/fluidmatrixinteractions/Mp/Mpbrookscoreyparams.hh b/dumux/material/fluidmatrixinteractions/Mp/Mpbrookscoreyparams.hh
new file mode 100644
index 0000000000000000000000000000000000000000..bcc373110ebfdf782b0aefa36e5aa6fc6d75bc48
--- /dev/null
+++ b/dumux/material/fluidmatrixinteractions/Mp/Mpbrookscoreyparams.hh
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ *   Copyright (C) 2008-2010 by Andreas Lauser                               *
+ *   Copyright (C) 2008 by Bernd Flemisch                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Mpbrookscoreymaterialparams.hh 
+ *
+ * Reference implementation of parameters for the M-phase brookscorey
+ * material material.
+ */
+#ifndef DUMUX_MP_BROOKS_COREY_MATERIAL_PARAMS_HH
+#define DUMUX_MP_BROOKS_COREY_MATERIAL_PARAMS_HH
+
+namespace Dumux
+{
+/*!
+ * \brief Reference implementation of a parameter class for the
+ *        M-phase Brooks-Corey material law.
+ */
+template<int numPhasesV, class ScalarT>
+class MpBrooksCoreyMaterialParams
+{
+public:
+    typedef ScalarT Scalar;
+    enum { numPhases = numPhasesV };
+
+    MpBrooksCoreyMaterialParams()
+    {
+        for (int i = 0; i < numPhases; ++i) {
+            setEntryPressure(i, 0.0);
+            setLambda(i, 0.0);
+        }
+    }
+
+    /*!
+     * \brief Return the entry pressure for a phase.
+     */
+    Scalar entryPressure(int phaseIdx) const
+    { return entryPressure_[phaseIdx]; }
+
+    /*!
+     * \brief Set the entry pressure for a phase.
+     */
+    void setEntryPressure(int phaseIdx, Scalar val) const
+    { entryPressure_[phaseIdx] = val; }
+
+    /*!
+     * \brief Return the alpha shape parameter of the Brooks-Corey law
+     *        for a phase.
+     */
+    Scalar alpha(int phaseIdx) const
+    { return alpha_[phaseIdx]; }
+
+    /*!
+     * \brief Set the alpha shape parameter of the Brooks-Corey law
+     *        for a phase.
+     */
+    void setLambda(int phaseIdx, Scalar val) const
+    { alpha_[phaseIdx] = val; }
+
+private:
+    Scalar entryPressure_[numPhases];
+    Scalar alpha_[numPhases];
+};
+} // namespace Dumux
+
+#endif
diff --git a/dumux/material/fluidmatrixinteractions/Mp/Mplinearmaterial.hh b/dumux/material/fluidmatrixinteractions/Mp/Mplinearmaterial.hh
new file mode 100644
index 0000000000000000000000000000000000000000..15583d9a12857147320687bf609c85d3242fcf66
--- /dev/null
+++ b/dumux/material/fluidmatrixinteractions/Mp/Mplinearmaterial.hh
@@ -0,0 +1,118 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Mplinearmaterial.hh
+ *
+ * Implements a linear saturation-capillary pressure relation for
+ * M-phase fluid systems.
+ */
+#ifndef MP_LINEAR_MATERIAL_HH
+#define MP_LINEAR_MATERIAL_HH
+
+#include "Mplinearmaterialparams.hh"
+
+#include <algorithm>
+
+namespace Dumux
+{
+/*!
+ * \ingroup material
+ *
+ * \brief Implements a linear saturation-capillary pressure relation
+ *
+ * Implements a linear saturation-capillary pressure relation for
+ * M-phase fluid systems.
+ *
+ * \sa MpLinearMaterialParams
+ */
+template <int numPhasesV, class ScalarT, class ParamsT = MpLinearMaterialParams<numPhasesV, ScalarT> >
+class MpLinearMaterial
+{
+public:
+    typedef ParamsT Params;
+    typedef typename Params::Scalar Scalar;
+    enum { numPhases = numPhasesV };
+
+    /*!
+     * \brief The linear capillary pressure-saturation curve.
+     *
+     * This material law is linear:
+     * \f[
+     p_C = (1 - \overline{S}_w) (p_{C,max} - p_{C,entry}) + p_{C,entry}
+     \f]
+     *
+     * \param Swe Effective saturation of of the wetting phase \f$\overline{S}_w\f$
+     */
+    template <class ContainerT, class FluidState>
+    static void capillaryPressures(ContainerT &values,
+                                   const Params &params, 
+                                   const FluidState &state)
+    {
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            Scalar S = state.saturation(phaseIdx);
+            values[phaseIdx] = 
+                S*params.pcMaxSat(phaseIdx) + 
+                (1 - S)*params.pcMinSat(phaseIdx);
+        }
+    }
+
+#if 0
+#warning TODO
+    /*!
+     * \brief The saturation-capillary pressure curve.
+     *
+     * This is the inverse of the capillary pressure-saturation curve:
+     * \f[
+     S_w = 1 - \frac{p_C - p_{C,entry}}{p_{C,max} - p_{C,entry}}
+     \f]
+     *
+     * \param pC Capillary pressure \f$\p_C\f$
+     * \return The effective saturaion of the wetting phase \f$\overline{S}_w\f$
+     */
+    template <class SatContainerT, class FluidState>
+    static void saturations(SatContainerT &saturations,
+                            const Params &params, 
+                            const FluidState &state)
+    {
+        for (int i = 0; i < numPhases; ++i) {
+            saturations[i] = 
+                (pc[i] - params.pcMaxSat(i))
+                /
+                (params.pcMinSat(i) - params.pcMaxSat(i));
+        }
+    }
+
+#endif
+
+    /*!
+     * \brief The relative permeability of all phases.
+     */
+    template <class ContainerT, class FluidState>
+    static void relativePermeabilities(ContainerT &values,
+                                       const Params &params, 
+                                       const FluidState &state)
+    {
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
+            values[phaseIdx] = std::max(std::min(state.saturation(phaseIdx),1.0),0.0);
+    };
+};
+}
+
+#endif
diff --git a/dumux/material/fluidmatrixinteractions/Mp/Mplinearmaterialparams.hh b/dumux/material/fluidmatrixinteractions/Mp/Mplinearmaterialparams.hh
new file mode 100644
index 0000000000000000000000000000000000000000..57ac059d998624611975e971904d1282e9a983af
--- /dev/null
+++ b/dumux/material/fluidmatrixinteractions/Mp/Mplinearmaterialparams.hh
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ *   Copyright (C) 2008-2010 by Andreas Lauser                               *
+ *   Copyright (C) 2008 by Bernd Flemisch                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 linearmaterialparams.hh 
+ *
+ * Reference implementation of parameters for the M-phase linear
+ * material material.
+ */
+#ifndef MP_LINEAR_MATERIAL_PARAMS_HH
+#define MP_LINEAR_MATERIAL_PARAMS_HH
+
+namespace Dumux
+{
+/*!
+ * \brief Reference implementation of params for the linear M-phase
+ *        material material.
+ */
+template<int numPhasesV, class ScalarT>
+class MpLinearMaterialParams
+{
+public:
+    typedef ScalarT Scalar;
+    enum { numPhases = numPhasesV };
+
+    MpLinearMaterialParams()
+    {
+        for (int i = 0; i < numPhases; ++i) {
+            setPcMinSat(i, 0.0);
+            setPcMaxSat(i, 0.0);
+        }
+    }
+
+    /*!
+     * \brief Return the threshold saturation at which the relative
+     *        permeability starts to get regularized.
+     *
+     * This is simply 10%
+     */
+    Scalar Sreg(int phaseIdx) const
+    { return 0.10; }
+
+    /*!
+     * \brief Return the capillary pressure for a phase \alpha at S_\alpha=0.
+     */
+    Scalar pcMinSat(int phaseIdx) const
+    { return pcMinSat_[phaseIdx]; }
+
+    /*!
+     * \brief Set the capillary pressure for a phase \alpha at S_\alpha=0.
+     */
+    void setPcMinSat(int phaseIdx, Scalar val)
+    { pcMinSat_[phaseIdx] = val; }
+
+    /*!
+     * \brief Return the capillary pressure for a phase \alpha at S_\alpha=1.
+     */
+    Scalar pcMaxSat(int phaseIdx) const
+    { return pcMaxSat_[phaseIdx]; }
+
+    /*!
+     * \brief Set the capillary pressure for a phase \alpha at S_\alpha=1.
+     */
+    void setPcMaxSat(int phaseIdx, Scalar val)
+    { pcMaxSat_[phaseIdx] = val; }
+
+    /*!
+     * \brief Return the threshold saturation respective phase below
+     *        which the relative permeability gets regularized.
+     *
+     * This is just 5%. If you need a different value, write your own
+     * parameter class.
+     */
+    Scalar krLowS(int phaseIdx) const
+    { return 0.05; }
+
+    /*!
+     * \brief Return the threshold saturation of the respective phase
+     *        above which the relative permeability gets regularized.
+     *
+     * This is just 95%. If you need a different value, write your own
+     * parameter class.
+     */
+    Scalar krHighS(int phaseIdx) const
+    { return 0.95; }
+
+private:
+    Scalar pcMaxSat_[numPhases];
+    Scalar pcMinSat_[numPhases];
+};
+} // namespace Dumux
+
+#endif
diff --git a/dumux/material/fluidstates/Makefile.am b/dumux/material/fluidstates/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..70f8f174617e3dd8488fc44a23ad1680eef4c247
--- /dev/null
+++ b/dumux/material/fluidstates/Makefile.am
@@ -0,0 +1 @@
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/material/fluidstates/equilibriumfluidstate.hh b/dumux/material/fluidstates/equilibriumfluidstate.hh
new file mode 100644
index 0000000000000000000000000000000000000000..5f2e2d611c661cf89049dedfe524f225cfbd4ae2
--- /dev/null
+++ b/dumux/material/fluidstates/equilibriumfluidstate.hh
@@ -0,0 +1,349 @@
+/*****************************************************************************
+ *   Copyright (C) 2010-2011 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Represents all relevant thermodynamic quantities of a
+ *        multi-phase, multi-component fluid system assuming
+ *        thermodynamic equilibrium.
+ */
+#ifndef DUMUX_EQUILIBRIUM_FLUID_STATE_HH
+#define DUMUX_EQUILIBRIUM_FLUID_STATE_HH
+
+#include <dumux/common/valgrind.hh>
+
+namespace Dumux
+{
+/*!
+ * \brief Represents all relevant thermodynamic quantities of a
+ *        multi-phase, multi-component fluid system assuming
+ *        thermodynamic equilibrium.
+ */
+template <class Scalar, class StaticParameters>
+class EquilibriumFluidState
+{
+public:
+    enum { numComponents = StaticParameters::numComponents };
+    enum { numPhases = StaticParameters::numPhases };
+
+    EquilibriumFluidState()
+    { Valgrind::SetUndefined(*this); }
+
+    template <class FluidState>
+    EquilibriumFluidState(FluidState &fs)
+    { assign(fs); }
+
+    /*****************************************************
+     * Generic access to fluid properties (No assumptions 
+     * on thermodynamic equilibrium required)
+     *****************************************************/
+    /*!
+     * \brief Returns the saturation of a phase []
+     */
+    Scalar saturation(int phaseIdx) const
+    { return saturation_[phaseIdx]; }
+
+    /*!
+     * \brief The mole fraction of a component in a phase []
+     */
+    Scalar moleFrac(int phaseIdx, int compIdx) const
+    { return moleFrac_[phaseIdx][compIdx]; }
+
+    /*!
+     * \brief The mass fraction of a component in a phase []
+     */
+    Scalar massFrac(int phaseIdx, int compIdx) const
+    { 
+        return
+            sumMassFrac(phaseIdx)*
+            molarity(phaseIdx, compIdx)*
+            StaticParameters::molarMass(compIdx)
+            /
+            density(phaseIdx);
+    }
+
+    /*!
+     * \brief The sum of all component mole fractions in a phase []
+     *
+     * We define this to be the same as the sum of all mass fractions.
+     */
+    Scalar sumMoleFrac(int phaseIdx) const
+    { return sumMoleFrac_[phaseIdx]; }
+
+    /*!
+     * \brief The sum of all component mass fractions in a phase []
+     *
+     * We define this to be the same as the sum of all mole fractions.
+     */
+    Scalar sumMassFrac(int phaseIdx) const
+    { return sumMoleFrac_[phaseIdx]; }
+
+    /*!
+     * \brief The mean molar mass of a fluid phase [kg/mol]
+     */
+    Scalar meanMolarMass(int phaseIdx) const
+    { return meanMolarMass_[phaseIdx]; }
+
+    /*!
+     * \brief The concentration of a component in a phase [mol/m^3]
+     *
+     * This is usually just called "molar concentration" or just
+     * "concentration", but there are many other (though less common)
+     * measures for concentration.
+     *
+     * http://en.wikipedia.org/wiki/Concentration
+     */
+    Scalar molarity(int phaseIdx, int compIdx) const
+    { return molarDensity(phaseIdx)*moleFrac(phaseIdx, compIdx); }
+
+    /*!
+     * \brief The fugacity of a component in a phase [Pa]
+     */
+    Scalar fugacity(int phaseIdx, int compIdx) const
+    { return fugacityCoeff(phaseIdx, compIdx)*moleFrac(phaseIdx, compIdx)*pressure(phaseIdx); }
+
+    /*!
+     * \brief The fugacity coefficient of a component in a phase [Pa]
+     */
+    Scalar fugacityCoeff(int phaseIdx, int compIdx) const
+    { return fugacityCoeff_[phaseIdx][compIdx]; }
+
+    /*!
+     * \brief The molar volume of a fluid phase [m^3/mol]
+     */
+    Scalar molarVolume(int phaseIdx) const
+    { return molarVolume_[phaseIdx]; }
+
+    /*!
+     * \brief The mass density of a fluid phase [kg/m^3]
+     */
+    Scalar density(int phaseIdx) const
+    { return molarDensity(phaseIdx)*meanMolarMass(phaseIdx); }
+
+    /*!
+     * \brief The molar density of a fluid phase [mol/m^3]
+     */
+    Scalar molarDensity(int phaseIdx) const
+    { return 1/molarVolume(phaseIdx); }
+
+    /*!
+     * \brief The temperature of a fluid phase [K]
+     */
+    Scalar temperature(int phaseIdx) const
+    { return temperature_; }
+    
+    /*!
+     * \brief The pressure of a fluid phase [Pa]
+     */
+    Scalar pressure(int phaseIdx) const
+    { return pressure_[phaseIdx]; }
+
+    /*!
+     * \brief The specific enthalpy of a fluid phase [J/kg]
+     */
+    Scalar enthalpy(int phaseIdx) const
+    { return enthalpy_[phaseIdx]; }
+
+    /*!
+     * \brief The specific internal energy of a fluid phase [J/kg]
+     */
+    Scalar internalEnergy(int phaseIdx) const
+    { return enthalpy(phaseIdx) - pressure(phaseIdx)/(density(phaseIdx)); }
+
+    /*!
+     * \brief The dynamic viscosity of a fluid phase [Pa s]
+     */
+    Scalar viscosity(int phaseIdx) const
+    { return viscosity_[phaseIdx]; }
+
+
+    /*****************************************************
+     * Access to fluid properties which only make sense
+     * if assuming thermodynamic equilibrium
+     *****************************************************/
+
+    /*!
+     * \brief The temperature within the domain [K]
+     */
+    Scalar temperature() const
+    { return temperature_; }
+
+    /*!
+     * \brief The capillary pressure [Pa] between a phase and a
+     *        reference phase.
+     *
+     * In order to make the term "capillary pressure" meaningful in a
+     * physical sense, mechanic equilibrium needs to be assumed.
+     */
+    Scalar capillaryPressure(int refPhaseIdx, int phaseIdx) const
+    { return pressure_[phaseIdx] - pressure_[refPhaseIdx]; }
+
+    /*!
+     * \brief The fugacity of a component
+     *
+     * This assumes chemical equilibrium.
+     */
+    Scalar fugacity(int compIdx) const
+    { return fugacity(0, compIdx); }
+
+
+    /*****************************************************
+     * Setter methods. Note that these are not part of the 
+     * generic FluidState interface but specific for each
+     * implementation...
+     *****************************************************/
+    
+    /*!
+     * \brief Retrieve all parameters from an arbitrary fluid 
+     *        state.
+     *
+     * \note If the other fluid state object is inconsistent with the
+     *       thermodynamic equilibrium, the result of this method is
+     *       undefined.
+     */
+    template <class FluidState>
+    void assign(const FluidState &fs)
+    {
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                moleFrac_[phaseIdx][compIdx] = fs.moleFrac(phaseIdx, compIdx);
+                fugacityCoeff_[phaseIdx][compIdx] = fs.fugacityCoeff(phaseIdx, compIdx);
+            }
+            meanMolarMass_[phaseIdx] = fs.meanMolarMass(phaseIdx);
+            pressure_[phaseIdx] = fs.pressure(phaseIdx);
+            saturation_[phaseIdx] = fs.saturation(phaseIdx);
+            molarVolume_[phaseIdx] = fs.molarVolume(phaseIdx);
+            enthalpy_[phaseIdx] = fs.enthalpy(phaseIdx);
+            viscosity_[phaseIdx] = fs.viscosity(phaseIdx);
+        }
+        temperature_ = fs.temperature(0);
+    };
+
+    /*!
+     * \brief Set the temperature [K] of a fluid phase
+     */
+    void setTemperature(Scalar value)
+    { temperature_ = value; }   
+
+    /*!
+     * \brief Set the fluid pressure of a phase [Pa]
+     */
+    void setPressure(int phaseIdx, Scalar value)
+    { pressure_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Set the saturation of a phase []
+     */
+    void setSaturation(int phaseIdx, Scalar value)
+    { saturation_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Set the mole fraction of a component in a phase []
+     */
+    void setMoleFrac(int phaseIdx, int compIdx, Scalar value)
+    { moleFrac_[phaseIdx][compIdx] = value; }   
+
+    /*!
+     * \brief Set the fugacity of a component in a phase []
+     */
+    void setFugacityCoeff(int phaseIdx, int compIdx, Scalar value)
+    { fugacityCoeff_[phaseIdx][compIdx] = value; }   
+
+    /*!
+     * \brief Set the molar volume of a phase [m^3/mol]
+     */
+    void setMolarVolume(int phaseIdx, Scalar value)
+    { molarVolume_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Set the specific enthalpy of a phase [J/m^3]
+     */
+    void setEnthalpy(int phaseIdx, Scalar value)
+    { enthalpy_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Set the dynamic viscosity of a phase [Pa s]
+     */
+    void setViscosity(int phaseIdx, Scalar value)
+    { viscosity_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Calculatate the mean molar mass of a phase given that
+     *        all mole fractions have been set
+     */
+    void updateMeanMolarMass(int phaseIdx)
+    {
+        meanMolarMass_[phaseIdx] = 0;
+        sumMoleFrac_[phaseIdx] = 0;
+     
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+            sumMoleFrac_[phaseIdx] += moleFrac_[phaseIdx][compIdx];
+            meanMolarMass_[phaseIdx] += moleFrac_[phaseIdx][compIdx]*StaticParameters::molarMass(compIdx);
+        }
+        sumMoleFrac_[phaseIdx] = std::max(1e-15, sumMoleFrac_[phaseIdx]);
+        Valgrind::CheckDefined(meanMolarMass_[phaseIdx]);
+        Valgrind::CheckDefined(sumMoleFrac_[phaseIdx]);
+    }
+    
+    /*!
+     * \brief Make sure that all attributes are defined.
+     *
+     * This method does not do anything if the program is not run
+     * under valgrind. If it is, then valgrind will print an error
+     * message if some attributes of the object have not been properly
+     * defined.
+     */
+    void checkDefined() const
+    {
+#if HAVE_VALGRIND && ! defined NDEBUG
+        for (int i = 0; i < numPhases; ++i) {
+            for (int j = 0; j < numComponents; ++j) {
+                Valgrind::CheckDefined(moleFrac_[i][j]);
+                Valgrind::CheckDefined(fugacityCoeff_[i][j]);
+            }
+            Valgrind::CheckDefined(meanMolarMass_[i]);
+            Valgrind::CheckDefined(pressure_[i]);
+            Valgrind::CheckDefined(saturation_[i]);
+            Valgrind::CheckDefined(molarVolume_[i]);
+            //Valgrind::CheckDefined(enthalpy_[i]);
+            Valgrind::CheckDefined(viscosity_[i]);
+        }
+
+        Valgrind::CheckDefined(temperature_);
+#endif // HAVE_VALGRIND
+    }
+
+protected:
+    Scalar moleFrac_[numPhases][numComponents];
+    Scalar fugacityCoeff_[numPhases][numComponents];
+
+    Scalar meanMolarMass_[numPhases];
+    Scalar sumMoleFrac_[numPhases];
+    Scalar pressure_[numPhases];
+    Scalar saturation_[numPhases];
+    Scalar molarVolume_[numPhases];
+    Scalar enthalpy_[numPhases];
+    Scalar viscosity_[numPhases];
+    Scalar temperature_;
+};
+
+} // end namepace Dumux
+
+#endif
diff --git a/dumux/material/fluidstates/genericfluidstate.hh b/dumux/material/fluidstates/genericfluidstate.hh
new file mode 100644
index 0000000000000000000000000000000000000000..16a00e2038635ebc10d8d2033e465db78e0974e0
--- /dev/null
+++ b/dumux/material/fluidstates/genericfluidstate.hh
@@ -0,0 +1,316 @@
+/*****************************************************************************
+ *   Copyright (C) 2010-2011 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Represents all relevant thermodynamic quantities of a
+ *        multi-phase, multi-component fluid system without using
+ *        any assumptions.
+ */
+#ifndef DUMUX_GENERIC_FLUID_STATE_HH
+#define DUMUX_GENERIC_FLUID_STATE_HH
+
+#include <dumux/common/valgrind.hh>
+
+#include <cmath>
+#include <algorithm>
+
+namespace Dumux
+{
+/*!
+ * \brief Represents all relevant thermodynamic quantities of a
+ *        multi-phase, multi-component fluid system without using
+ *        any assumptions.
+ */
+template <class Scalar, class StaticParameters>
+class GenericFluidState
+{
+public:
+    enum { numComponents    = StaticParameters::numComponents };
+    enum { numPhases        = StaticParameters::numPhases };
+
+    GenericFluidState()
+    { Valgrind::SetUndefined(*this); }
+
+    /*****************************************************
+     * Generic access to fluid properties (No assumptions 
+     * on thermodynamic equilibrium required)
+     *****************************************************/
+    /*!
+     * \brief Returns the saturation of a phase []
+     */
+    Scalar saturation(int phaseIdx) const
+    { return saturation_[phaseIdx]; }
+
+    /*!
+     * \brief The mole fraction of a component in a phase []
+     */
+    Scalar moleFrac(int phaseIdx, int compIdx) const
+    { return moleFrac_[phaseIdx][compIdx]; }
+
+
+    /*!
+     * \brief The mass fraction of a component in a phase []
+     */
+    Scalar massFrac(int phaseIdx, int compIdx) const
+    { 
+        return
+            sumMassFrac(phaseIdx) *
+            moleFrac_[phaseIdx][compIdx] *
+            StaticParameters::molarMass(compIdx) /
+            meanMolarMass_[phaseIdx];
+    }
+
+    /*!
+     * \brief The sum of all component mole fractions in a phase []
+     *
+     * We define this to be the same as the sum of all mass fractions.
+     */
+    Scalar sumMoleFrac(int phaseIdx) const
+    { return sumMoleFrac_[phaseIdx]; }
+
+    /*!
+     * \brief The sum of all component mass fractions in a phase []
+     *
+     * We define this to be the same as the sum of all mole fractions.
+     */
+    Scalar sumMassFrac(int phaseIdx) const
+    { return sumMoleFrac_[phaseIdx]; }
+
+    /*!
+     * \brief The mean molar mass of a fluid phase [kg/mol]
+     */
+    Scalar meanMolarMass(int phaseIdx) const
+    { return meanMolarMass_[phaseIdx]; }
+
+    /*!
+     * \brief The molar concentration of a component in a phase [mol/m^3]
+     *
+     * This is often just called "concentration", but there are many
+     * other (though less common) measures for concentration.
+     *
+     * http://en.wikipedia.org/wiki/Concentration
+     */
+    Scalar molarity(int phaseIdx, int compIdx) const
+    { return molarDensity(phaseIdx)*moleFrac(phaseIdx, compIdx); }
+
+    /*!
+     * \brief The fugacity coefficient of a component in a phase []
+     */
+    Scalar fugacityCoeff(int phaseIdx, int compIdx) const
+    { return fugacityCoeff_[phaseIdx][compIdx]; }
+
+    /*!
+     * \brief The fugacity of a component in a phase [Pa]
+     */
+    Scalar fugacity(int phaseIdx, int compIdx) const
+    { return pressure_[phaseIdx]*fugacityCoeff_[phaseIdx][compIdx]*moleFrac_[phaseIdx][compIdx]; }
+
+    /*!
+     * \brief The molar volume of a fluid phase [m^3/mol]
+     */
+    Scalar molarVolume(int phaseIdx) const
+    { return molarVolume_[phaseIdx]; }
+
+    /*!
+     * \brief The mass density of a fluid phase [kg/m^3]
+     */
+    Scalar density(int phaseIdx) const
+    {
+        return 
+            meanMolarMass_[phaseIdx]/molarVolume_[phaseIdx];
+    }
+
+    /*!
+     * \brief The molar density of a fluid phase [mol/m^3]
+     */
+    Scalar molarDensity(int phaseIdx) const
+    { return 1/molarVolume(phaseIdx); }
+
+    /*!
+     * \brief The temperature of a fluid phase [K]
+     */
+    Scalar temperature(int phaseIdx) const
+    { return temperature_[phaseIdx]; }
+    
+    /*!
+     * \brief The pressure of a fluid phase [Pa]
+     */
+    Scalar pressure(int phaseIdx) const
+    { return pressure_[phaseIdx]; };
+
+    /*!
+     * \brief The specific enthalpy of a fluid phase [J/kg]
+     */
+    Scalar enthalpy(int phaseIdx) const
+    { return enthalpy_[phaseIdx]; };
+
+    /*!
+     * \brief The specific internal energy of a fluid phase [J/kg]
+     */
+    Scalar internalEnergy(int phaseIdx) const
+    { return enthalpy(phaseIdx) - pressure(phaseIdx)/(density(phaseIdx)); };
+
+    /*!
+     * \brief The dynamic viscosity of a fluid phase [Pa s]
+     */
+    Scalar viscosity(int phaseIdx) const
+    { return viscosity_[phaseIdx]; };
+
+    /*****************************************************
+     * Setter methods. Note that these are not part of the 
+     * generic FluidState interface but specific for each
+     * implementation...
+     *****************************************************/
+    /*!
+     * \brief Set the temperature [K] of a fluid phase
+     */
+    void setTemperature(int phaseIdx, Scalar value)
+    { temperature_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Set the fluid pressure of a phase [Pa]
+     */
+    void setPressure(int phaseIdx, Scalar value)
+    { pressure_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Set the saturation of a phase []
+     */
+    void setSaturation(int phaseIdx, Scalar value)
+    { saturation_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Set the mole fraction of a component in a phase []
+     */
+    void setMoleFrac(int phaseIdx, int compIdx, Scalar value)
+    { moleFrac_[phaseIdx][compIdx] = value; }   
+
+    /*!
+     * \brief Set the fugacity of a component in a phase []
+     */
+    void setFugacityCoeff(int phaseIdx, int compIdx, Scalar value)
+    { fugacityCoeff_[phaseIdx][compIdx] = value; }   
+
+    /*!
+     * \brief Set the molar volume of a phase [m^3/mol]
+     */
+    void setMolarVolume(int phaseIdx, Scalar value)
+    {
+        molarVolume_[phaseIdx] = value;
+    }
+
+    /*!
+     * \brief Set the specific enthalpy of a phase [J/m^3]
+     */
+    void setEnthalpy(int phaseIdx, Scalar value)
+    { enthalpy_[phaseIdx] = value; }
+
+    /*!
+     * \brief Set the dynamic viscosity of a phase [Pa s]
+     */
+    void setViscosity(int phaseIdx, Scalar value)
+    { viscosity_[phaseIdx] = value; }   
+
+    /*!
+     * \brief Calculatate the mean molar mass of a phase given that
+     *        all mole fractions have been set
+     */
+    void updateMeanMolarMass(int phaseIdx)
+    {
+        meanMolarMass_[phaseIdx] = 0;
+        sumMoleFrac_[phaseIdx] = 0;
+     
+        for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+            sumMoleFrac_[phaseIdx] += moleFrac_[phaseIdx][compIdx];
+            meanMolarMass_[phaseIdx] += moleFrac_[phaseIdx][compIdx]*StaticParameters::molarMass(compIdx);
+        }
+        sumMoleFrac_[phaseIdx] = std::max(1e-15, sumMoleFrac_[phaseIdx]);
+        Valgrind::CheckDefined(meanMolarMass_[phaseIdx]);
+        Valgrind::CheckDefined(sumMoleFrac_[phaseIdx]);
+    }
+    
+    /*!
+     * \brief Retrieve all parameters from an arbitrary fluid 
+     *        state.
+     */
+    template <class FluidState>
+    void assign(const FluidState& fs)
+    {
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            for (int compIdx = 0; compIdx < numComponents; ++compIdx) {
+                moleFrac_[phaseIdx][compIdx] = fs.moleFrac(phaseIdx, compIdx);
+                fugacityCoeff_[phaseIdx][compIdx] = fs.fugacityCoeff(phaseIdx, compIdx);
+            }
+            updateMeanMolarMass(phaseIdx);
+
+            pressure_[phaseIdx] = fs.pressure(phaseIdx);
+            saturation_[phaseIdx] = fs.saturation(phaseIdx);
+            molarVolume_[phaseIdx] = fs.molarVolume(phaseIdx);
+            enthalpy_[phaseIdx] = fs.enthalpy(phaseIdx);
+            viscosity_[phaseIdx] = fs.viscosity(phaseIdx);
+            temperature_[phaseIdx] = fs.temperature(phaseIdx);
+        }
+    };
+
+    /*!
+     * \brief Make sure that all attributes are defined.
+     *
+     * This method does not do anything if the program is not run
+     * under valgrind. If it is, then valgrind will print an error
+     * message if some attributes of the object have not been properly
+     * defined.
+     */
+    void checkDefined() const
+    {
+#if HAVE_VALGRIND && ! defined NDEBUG
+        for (int i = 0; i < numPhases; ++i) {
+            for (int j = 0; j < numComponents; ++j) {
+                Valgrind::CheckDefined(fugacityCoeff_[i][j]);
+                Valgrind::CheckDefined(moleFrac_[i][j]);
+            }
+            Valgrind::CheckDefined(meanMolarMass_[i]);
+            Valgrind::CheckDefined(pressure_[i]);
+            Valgrind::CheckDefined(saturation_[i]);
+            Valgrind::CheckDefined(molarVolume_[i]);
+            Valgrind::CheckDefined(temperature_[i]);
+            //Valgrind::CheckDefined(enthalpy_[i]);
+            Valgrind::CheckDefined(viscosity_[i]);
+        }
+#endif // HAVE_VALGRIND
+    }
+
+protected:
+    Scalar moleFrac_[numPhases][numComponents];
+    Scalar fugacityCoeff_[numPhases][numComponents];
+
+    Scalar meanMolarMass_[numPhases];
+    Scalar sumMoleFrac_[numPhases];
+    Scalar pressure_[numPhases];
+    Scalar saturation_[numPhases];
+    Scalar molarVolume_[numPhases];
+    Scalar enthalpy_[numPhases];
+    Scalar viscosity_[numPhases];
+    Scalar temperature_[numPhases];
+};
+
+} // end namepace Dumux
+
+#endif
diff --git a/dumux/material/fluidstates/trackinggenericfluidstate.hh b/dumux/material/fluidstates/trackinggenericfluidstate.hh
new file mode 100644
index 0000000000000000000000000000000000000000..8960a49dc4386f66d9159310c1101181c5dfac23
--- /dev/null
+++ b/dumux/material/fluidstates/trackinggenericfluidstate.hh
@@ -0,0 +1,398 @@
+/*****************************************************************************
+ *   Copyright (C) 2011 by Andreas Lauser                                    *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 GenericFluidState which keeps track on which variables changed.
+ */
+#ifndef DUMUX_TRACKING_GENERIC_FLUID_STATE_HH
+#define DUMUX_TRACKING_GENERIC_FLUID_STATE_HH
+
+#include "genericfluidstate.hh"
+
+#include <dumux/common/valgrind.hh>
+
+#include <cmath>
+#include <algorithm>
+
+namespace Dumux
+{
+/*!
+ * \brief A GenericFluidState which keeps track on which variables changed.
+ */
+template <class Scalar, class StaticParameters>
+class TrackingGenericFluidState
+{
+    typedef Dumux::GenericFluidState<Scalar, StaticParameters> GenericFluidState;
+public:
+    enum { numComponents = StaticParameters::numComponents };
+    enum { numPhases = StaticParameters::numPhases };
+
+    TrackingGenericFluidState()
+    {
+        for (int i = 0; i < numPhases; ++i)
+            changed_[i].raw = ~((unsigned) 0x00);
+    }
+
+    /*****************************************************
+     * Generic access to fluid properties (No assumptions 
+     * on thermodynamic equilibrium required)
+     *****************************************************/
+    /*!
+     * \brief Returns the saturation of a phase []
+     */
+    Scalar saturation(int phaseIdx) const
+    { return fs_.saturation(phaseIdx); }
+
+    /*!
+     * \brief The mole fraction of a component in a phase []
+     */
+    Scalar moleFrac(int phaseIdx, int compIdx) const
+    { return fs_.moleFrac(phaseIdx, compIdx); }
+
+    /*!
+     * \brief The mass fraction of a component in a phase []
+     */
+    Scalar massFrac(int phaseIdx, int compIdx) const
+    { return fs_.massFrac(phaseIdx, compIdx); }
+
+    /*!
+     * \brief The sum of all component mole fractions in a phase []
+     *
+     * We define this to be the same as the sum of all mass fractions.
+     */
+    Scalar sumMoleFrac(int phaseIdx) const
+    { return fs_.sumMoleFrac(phaseIdx); }
+
+    /*!
+     * \brief The sum of all component mass fractions in a phase []
+     *
+     * We define this to be the same as the sum of all mole fractions.
+     */
+    Scalar sumMassFrac(int phaseIdx) const
+    { return fs_.sumMassFrac(phaseIdx); }
+
+    /*!
+     * \brief The mean molar mass of a fluid phase [kg/mol]
+     */
+    Scalar meanMolarMass(int phaseIdx) const
+    { return fs_.meanMolarMass(phaseIdx); }
+
+    /*!
+     * \brief The molar concentration of a component in a phase [mol/m^3]
+     *
+     * This is often just called "concentration", but there are many
+     * other (though less common) measures for concentration.
+     *
+     * http://en.wikipedia.org/wiki/Concentration
+     */
+    Scalar molarity(int phaseIdx, int compIdx) const
+    { return fs_.molarity(phaseIdx, compIdx); }
+
+    /*!
+     * \brief The fugacity of a component in a phase [Pa]
+     */
+    Scalar fugacity(int phaseIdx, int compIdx) const
+    { return fs_.fugacity(phaseIdx, compIdx); }
+
+    /*!
+     * \brief The fugacity coefficient of a component in a phase []
+     */
+    Scalar fugacityCoeff(int phaseIdx, int compIdx) const
+    { return fs_.fugacityCoeff(phaseIdx, compIdx); }
+
+    /*!
+     * \brief The molar volume of a fluid phase [m^3/mol]
+     */
+    Scalar molarVolume(int phaseIdx) const
+    { return fs_.molarVolume(phaseIdx); }
+
+    /*!
+     * \brief The mass density of a fluid phase [kg/m^3]
+     */
+    Scalar density(int phaseIdx) const
+    { return fs_.density(phaseIdx); }
+
+    /*!
+     * \brief The molar density of a fluid phase [mol/m^3]
+     */
+    Scalar molarDensity(int phaseIdx) const
+    { return fs_.molarDensity(phaseIdx); }
+
+    /*!
+     * \brief The temperature of a fluid phase [K]
+     */
+    Scalar temperature(int phaseIdx) const
+    { return fs_.temperature(phaseIdx); }
+    
+    /*!
+     * \brief The pressure of a fluid phase [Pa]
+     */
+    Scalar pressure(int phaseIdx) const
+    { return fs_.pressure(phaseIdx); }
+
+    /*!
+     * \brief The specific enthalpy of a fluid phase [J/kg]
+     */
+    Scalar enthalpy(int phaseIdx) const
+    { return fs_.enthalpy(phaseIdx); }
+
+    /*!
+     * \brief The specific internal energy of a fluid phase [J/kg]
+     */
+    Scalar internalEnergy(int phaseIdx) const
+    { return fs_.internalEnergy(phaseIdx); }
+
+    /*!
+     * \brief The dynamic viscosity of a fluid phase [Pa s]
+     */
+    Scalar viscosity(int phaseIdx) const
+    { return fs_.viscosity(phaseIdx); };
+
+    /*****************************************************
+     * Setter methods. Note that these are not part of the 
+     * generic FluidState interface but specific for each
+     * implementation...
+     *****************************************************/
+    /*!
+     * \brief Set the temperature [K] of a fluid phase
+     */
+    void setTemperature(int phaseIdx, Scalar value)
+    { 
+        changed_[phaseIdx].fields.temperature = 1;
+        fs_.setTemperature(phaseIdx, value);
+    };
+
+    /*!
+     * \brief Set the fluid pressure of a phase [Pa]
+     */
+    void setPressure(int phaseIdx, Scalar value)
+    { 
+        changed_[phaseIdx].fields.pressure = 1;
+        fs_.setPressure(phaseIdx, value);
+    };
+
+    /*!
+     * \brief Set the saturation of a phase []
+     */
+    void setSaturation(int phaseIdx, Scalar value)
+    { 
+        changed_[phaseIdx].fields.saturation = 1;
+        fs_.setSaturation(phaseIdx, value);
+    };
+
+    /*!
+     * \brief Set the mole fraction of a component in a phase []
+     */
+    void setMoleFrac(int phaseIdx, int compIdx, Scalar value)
+    { 
+        changed_[phaseIdx].fields.moleFrac |= 1 << compIdx;
+        fs_.setMoleFrac(phaseIdx, compIdx, value);
+    };
+
+
+    /*!
+     * \brief Set the fugacity of a component in a phase []
+     */
+    void setFugacityCoeff(int phaseIdx, int compIdx, Scalar value)
+    { 
+        changed_[phaseIdx].fields.fugacityCoeff |= 1 << compIdx;
+        fs_.setFugacityCoeff(phaseIdx, compIdx, value);
+    }
+
+    /*!
+     * \brief Set the molar volume of a phase [m^3/mol]
+     */
+    void setMolarVolume(int phaseIdx, Scalar value)
+    { 
+        changed_[phaseIdx].fields.molarVolume = 1;
+        fs_.setMolarVolume(phaseIdx, value);
+    }
+
+    /*!
+     * \brief Set the specific enthalpy of a phase [J/m^3]
+     */
+    void setEnthalpy(int phaseIdx, Scalar value)
+    { 
+        changed_[phaseIdx].fields.enthalpy = 1;
+        fs_.setEnthalpy(phaseIdx, value);
+    }   
+
+    /*!
+     * \brief Set the dynamic viscosity of a phase [Pa s]
+     */
+    void setViscosity(int phaseIdx, Scalar value)
+    { 
+        changed_[phaseIdx].fields.viscosity = 1;
+        fs_.setViscosity(phaseIdx, value);
+    }   
+
+    /*!
+     * \brief Calculatate the mean molar mass of a phase given that
+     *        all mole fractions have been set
+     */
+    void updateMeanMolarMass(int phaseIdx)
+    { fs_.updateMeanMolarMass(phaseIdx); }
+    
+
+    /*!
+     * \brief Reset the dirty tracking for a phase.
+     */
+    void setPhaseClean(int phaseIdx)
+    {
+        // set all tracking bits for the phase to zero
+        changed_[phaseIdx].raw = 0;
+    }
+
+    /*!
+     * \brief Reset the dirty tracking of all phases.
+     */
+    void setClean()
+    {
+        for (int i = 0; i < numPhases; ++i)
+            changed_[i].raw = 0;
+    }
+
+    /*!
+     * \brief Return if all phases are clean.
+     */
+    bool isClean() const
+    { 
+        for (int i = 0; i < numPhases; ++i)
+            if (changed_[i].raw != 0)
+                return false;
+        return true;
+    };
+
+    /*!
+     * \brief Find out whether the values for a phase been since the
+     *        last call to cleanPhase().
+     */
+    bool phaseClean(int phaseIdx) const
+    { return changed_[phaseIdx].raw == 0; }
+
+
+    /*!
+     * \brief Find out whether a specific phase's temperature has been
+     *        changed.
+     */
+    bool temperatureClean(int phaseIdx) const
+    { return changed_[phaseIdx].fields.temperature == 0; }
+
+    /*!
+     * \brief Find out whether a specific phase's saturation has been
+     *        changed.
+     */
+    bool saturationClean(int phaseIdx) const
+    { return changed_[phaseIdx].fields.saturation == 0; }
+
+    /*!
+     * \brief Find out whether a specific phase's pressure has been
+     *        changed.
+     */
+    bool pressureClean(int phaseIdx) const
+    { return changed_[phaseIdx].fields.pressure == 0; }
+
+    /*!
+     * \brief Find out whether a specific phase's enthalpy has been
+     *        changed.
+     */
+    bool enthalpyClean(int phaseIdx) const
+    { return changed_[phaseIdx].enthalpy == 0; }
+
+    /*!
+     * \brief Find out whether a specific phase's temperature has been
+     *        changed.
+     */
+    bool molarVolumeClean(int phaseIdx) const
+    { return changed_[phaseIdx].fields.molarVolume == 0; }
+
+    /*!
+     * \brief Find out whether some of the mole fractions of a phase
+     *        have been changed since the last call to
+     *        setCleanPhase().
+     */
+    bool moleFracsClean(int phaseIdx) const
+    { return changed_[phaseIdx].fields.moleFrac == 0; }
+
+    /*!
+     * \brief Find out whether a specific mole fraction of a component
+     *        in a phase has been changed since the last call to
+     *        setCleanPhase().
+     */
+    bool moleFracsClean(int phaseIdx, int compIdx) const
+    { return (changed_[phaseIdx].fields.moleFrac  & (1 << compIdx)) == 0; }
+
+    /*!
+     * \brief Find out whether at least one fugacity of a component in
+     *        a phase has been changed since the last call to
+     *        setCleanPhase().
+     */
+    bool fugacityCoeffsClean(int phaseIdx) const
+    { return changed_[phaseIdx].fields.fugacitCoeffs == 0; }
+
+    /*!
+     * \brief Find out whether a specific fugacity of a component in a
+     *        phase has been changed since the last call to
+     *        setCleanPhase().
+     */
+    bool fugacityCoeffClean(int phaseIdx, int compIdx) const
+    { return (changed_[phaseIdx].fields.fugacityCoeffs  & (1 << compIdx)) == 0; }
+    
+
+    /*!
+     * \brief Make sure that all attributes are defined.
+     *
+     * This method does not do anything if the program is not run
+     * under valgrind. If it is, then valgrind will print an error
+     * message if some attributes of the object have not been properly
+     * defined.
+     */
+    void checkDefined() const
+    {
+#if HAVE_VALGRIND && ! defined NDEBUG
+        Valgrind::CheckDefined(changed_);
+        fs_.checkDefined();
+#endif // HAVE_VALGRIND
+    }
+
+protected:
+    static_assert(sizeof(unsigned)*8 >= 5 + 2*numComponents,
+                  "Too many components to use the bitfield trick");
+    union {
+        unsigned raw;
+        struct {
+            unsigned char moleFrac : numComponents;
+            unsigned char fugacityCoeff : numComponents;
+
+            unsigned char molarVolume : 1;
+            unsigned char temperature : 1;
+            unsigned char saturation : 1;
+            unsigned char pressure : 1;
+            unsigned char enthalpy : 1;
+            unsigned char viscosity : 1;
+        } __attribute__((__packed__)) fields;
+    } changed_[numPhases];
+    GenericFluidState fs_;
+};
+
+} // end namepace Dumux
+
+#endif
diff --git a/dumux/material/new_fluidsystems/Makefile.am b/dumux/material/new_fluidsystems/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..70f8f174617e3dd8488fc44a23ad1680eef4c247
--- /dev/null
+++ b/dumux/material/new_fluidsystems/Makefile.am
@@ -0,0 +1 @@
+include $(top_srcdir)/am/global-rules
diff --git a/dumux/material/new_fluidsystems/basicmutableparameters.hh b/dumux/material/new_fluidsystems/basicmutableparameters.hh
new file mode 100644
index 0000000000000000000000000000000000000000..d2a6adb203be3c6b37e60f52d12b0604ee195ba9
--- /dev/null
+++ b/dumux/material/new_fluidsystems/basicmutableparameters.hh
@@ -0,0 +1,97 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 Specifies the basic API for mutable parameter objects.
+ *
+ * Fluid systems which do not need any complicated mixture parameters
+ * just need this class to be happy.
+ */
+#ifndef BASIC_MUTABLE_PARAMETERS_HH
+#define BASIC_MUTABLE_PARAMETERS_HH
+
+#include <dumux/material/fluidstates/genericfluidstate.hh>
+#include <assert.h>
+
+namespace Dumux
+{
+/*!
+ * \brief Specifies the basic API for mutable parameter objects.
+ *
+ * Fluid systems which do not need any complicated mixture parameters
+ * just need this class to be happy.
+ */
+template <class Scalar,
+          class StaticParams,
+          class FluidStateT = GenericFluidState<Scalar, StaticParams> >
+class BasicMutableParameters
+{
+    enum { numPhases = StaticParams::numPhases };
+    enum { numComponents = StaticParams::numComponents };
+
+public:
+    /*!
+     * \brief The type of fluid state objects.
+     */
+    typedef FluidStateT FluidState;
+
+    /*!
+     * \brief Returns the fluid state for which the parameter object
+     *        is valid.
+     */
+    FluidState &fluidState() 
+    { return fluidState_; }
+
+    /*!
+     * \brief Returns the fluid state for which the parameter object
+     *        is valid.
+     */
+    const FluidState &fluidState()  const
+    { return fluidState_; }
+
+    /*!
+     * \brief Update all parameters of a phase which only depend on 
+     *        temperature and/or pressure.
+     *
+     * This usually means the parameters for the pure components.
+     */
+    void updatePure(int phaseIdx)
+    { }
+
+    /*!
+     * \brief Update all parameters of a phase which depend on the
+     *        fluid composition. It is assumed that updatePure() has
+     *        been called before this method.
+     *
+     * Here, the mixing rule kicks in.
+     */
+    void updateMix(int phaseIdx)
+    {
+        fluidState_.updateMeanMolarMass(phaseIdx);
+    };
+  
+private:
+    FluidState fluidState_;
+};
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/material/new_fluidsystems/h2oh2n2o2fluidsystem.hh b/dumux/material/new_fluidsystems/h2oh2n2o2fluidsystem.hh
new file mode 100644
index 0000000000000000000000000000000000000000..843951295243edba7e43c23854a17198887ec487
--- /dev/null
+++ b/dumux/material/new_fluidsystems/h2oh2n2o2fluidsystem.hh
@@ -0,0 +1,557 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 twophase fluid system with water and nitrogen as components.
+ */
+#ifndef DUMUX_H2O_H2_N2_O2_FLUID_SYSTEM_HH
+#define DUMUX_H2O_H2_N2_O2_FLUID_SYSTEM_HH
+
+#include <dumux/material/fluidstates/genericfluidstate.hh>
+
+#include <dumux/material/components/simpleh2o.hh>
+#include <dumux/material/components/h2o.hh>
+#include <dumux/material/components/h2.hh>
+#include <dumux/material/components/n2.hh>
+#include <dumux/material/components/o2.hh>
+#include <dumux/material/components/tabulatedcomponent.hh>
+#include <dumux/material/idealgas.hh>
+
+#include <dumux/material/binarycoefficients/h2o_h2.hh>
+#include <dumux/material/binarycoefficients/h2o_n2.hh>
+#include <dumux/material/binarycoefficients/h2o_o2.hh>
+#include <dumux/material/binarycoefficients/h2_n2.hh>
+#include <dumux/material/binarycoefficients/h2_o2.hh>
+#include <dumux/material/binarycoefficients/n2_o2.hh>
+
+#include <dumux/material/fluidstates/genericfluidstate.hh>
+
+#include <dumux/common/exceptions.hh>
+
+namespace Dumux
+{
+
+
+template <class Scalar>
+struct H2OH2N2O2StaticParameters {
+    /****************************************
+     * Fluid phase parameters
+     ****************************************/
+
+    //! Number of phases in the fluid system
+    static const int numPhases = 2;
+
+    //! Index of the liquid phase
+    static const int lPhaseIdx = 0;
+    //! Index of the gas phase
+    static const int gPhaseIdx = 1;
+    
+    //! The component for pure water 
+    typedef Dumux::SimpleH2O<Scalar> SimpleH2O;
+    typedef Dumux::H2O<Scalar> IapwsH2O;
+    typedef Dumux::TabulatedComponent<Scalar, IapwsH2O> TabulatedH2O;
+    
+    //! The component for pure water
+    //typedef IapwsH2O H2O;
+    //typedef TabulatedH2O H2O;
+    typedef SimpleH2O H2O;
+    
+    //! The component for pure hydrogen
+    typedef Dumux::H2<Scalar> H2;
+
+    //! The component for pure nitrogen
+    typedef Dumux::N2<Scalar> N2;
+
+    //! The component for pure oxygen
+    typedef Dumux::O2<Scalar> O2;
+
+    /*!
+     * \brief Initialize the static parameters.
+     */
+    static void init(Scalar tempMin, Scalar tempMax, unsigned nTemp,
+                     Scalar pressMin, Scalar pressMax, unsigned nPress)
+    {
+        if (H2O::isTabulated) {
+            std::cout << "Initializing tables for the H2O fluid properties ("
+                      << nTemp*nPress
+                      << " entries).\n";
+            
+            TabulatedH2O::init(tempMin, tempMax, nTemp,
+                               pressMin, pressMax, nPress);
+        }
+
+    }
+   
+    /*!
+     * \brief Return the human readable name of a fluid phase
+     */
+    static const char *phaseName(int phaseIdx)
+    {
+        static const char *name[] = {
+            "l",
+            "g"
+        };
+
+        assert(0 <= phaseIdx && phaseIdx < numPhases);
+        return name[phaseIdx];
+    }
+
+    /****************************************
+     * Component related parameters
+     ****************************************/
+
+    //! Number of components in the fluid system
+    static const int numComponents = 4;
+    
+    static const int H2OIdx = 0;
+    static const int H2Idx = 1;
+    static const int N2Idx = 2;
+    static const int O2Idx = 3;
+
+    /*!
+     * \brief Return the human readable name of a component
+     */
+    static const char *componentName(int compIdx)
+    {
+        static const char *name[] = {
+            H2O::name(),
+            H2::name(),
+            N2::name(),
+            O2::name(),
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return name[compIdx];
+    }
+    
+    /*!
+     * \brief Return the molar mass of a component in [kg/mol].
+     */
+    static Scalar molarMass(int compIdx)
+    {
+        static const Scalar M[] = {
+            H2O::molarMass(),
+            H2::molarMass(),
+            N2::molarMass(),
+            O2::molarMass(),
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return M[compIdx];
+    }
+
+    /*!
+     * \brief Critical temperature of a component [K].
+     */
+    static Scalar criticalTemperature(int compIdx)
+    {
+        static const Scalar Tcrit[] = {
+            H2O::criticalTemperature(), // H2O
+            H2::criticalTemperature(), // H2O
+            N2::criticalTemperature(), // H2O
+            O2::criticalTemperature(), // H2O
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return Tcrit[compIdx];
+    };
+
+    /*!
+     * \brief Critical pressure of a component [Pa].
+     */
+    static Scalar criticalPressure(int compIdx)
+    {
+        static const Scalar pcrit[] = {
+            H2O::criticalPressure(),
+            H2::criticalPressure(),
+            N2::criticalPressure(),
+            O2::criticalPressure(),
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return pcrit[compIdx];
+    };
+
+    /*!
+     * \brief Molar volume of a component at the critical point [m^3/mol].
+     */
+    static Scalar criticalMolarVolume(int compIdx)
+    {
+        DUNE_THROW(Dune::NotImplemented,
+                   "H2OH2N2O2StaticParams::criticalMolarVolume()");
+    };
+
+    /*!
+     * \brief The acentric factor of a component [].
+     */
+    static Scalar acentricFactor(int compIdx)
+    {
+        static const Scalar accFac[] = {
+            H2O::acentricFactor(), // H2O (from Reid, et al.)
+            H2::acentricFactor(),
+            N2::acentricFactor(),
+            O2::acentricFactor(),
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return accFac[compIdx];
+    };
+};
+
+/*!
+ * \brief A twophase fluid system with water, hydrogen, nitrogen and oxygen as components.
+ */
+template <class Scalar>
+class H2OH2N2O2FluidSystem : public H2OH2N2O2StaticParameters<Scalar>
+{
+public:
+    typedef Dumux::H2OH2N2O2StaticParameters<Scalar> StaticParameters;
+    typedef Dumux::GenericFluidState<Scalar, StaticParameters> MutableParameters;
+
+private:
+    // convenience typedefs
+    typedef StaticParameters SP;
+    typedef Dumux::IdealGas<Scalar> IdealGas;
+
+public:
+
+    /*!
+     * \brief Initialize the fluid system's static parameters
+     */
+    static void init(Scalar tempMin, Scalar tempMax, unsigned nTemp,
+                     Scalar pressMin, Scalar pressMax, unsigned nPress)
+    {
+        SP::init(tempMin, tempMax, nTemp,
+                 pressMin, pressMax, nPress);
+    }
+    /*!
+     * \brief Returns true if and only if a fluid phase is assumed to
+     *        be an ideal mixture.
+     *
+     * We define an ideal mixture as a fluid phase where the fugacity
+     * coefficients of all components times the pressure of the phase
+     * are indepent on the fluid composition. This assumtion is true
+     * if Henry's law and Rault's law apply. If you are unsure what
+     * this function should return, it is safe to return false. The
+     * only damage done will be (slightly) increased computation times
+     * in some cases.
+     */
+    static bool isIdealMixture(int phaseIdx)
+    {
+        // we assume Henry's and Rault's laws for the water phase and
+        // and no interaction between gas molecules of different
+        // components, so all phases are ideal mixtures!
+        return true;
+    }
+
+    /*!
+     * \brief Calculate the molar volume [m^3/mol] of a fluid phase
+     */
+    static Scalar computeMolarVolume(MutableParameters &params, 
+                                     int phaseIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= SP::numPhases);
+
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+
+        switch (phaseIdx) {
+        case SP::lPhaseIdx:
+            // assume pure water where one water molecule gets
+            // replaced by one nitrogen molecule
+            return SP::H2O::molarMass()/SP::H2O::liquidDensity(T, p);
+        case SP::gPhaseIdx:
+            // assume ideal gas
+            return 1.0 / IdealGas::concentration(T, p);
+        }
+        
+        DUNE_THROW(Dune::InvalidStateException, "Unhandled phase index " << phaseIdx);
+    };
+
+    /*!
+     * \brief Calculate the fugacity of a component in a fluid phase
+     *        [Pa]
+     *
+     * The components chemical \f$mu_\kappa\f$ potential is connected
+     * to the component's fugacity \f$f_\kappa\f$ by the relation
+     *
+     * \f[ \mu_\kappa = R T_\alpha \mathrm{ln} \frac{f_\kappa}{p_\alpha} \f]
+     *
+     * where \f$p_\alpha\f$ and \f$T_\alpha\f$ are the fluid phase'
+     * pressure and temperature.
+     */
+    static Scalar computeFugacity(MutableParameters &params,
+                                  int phaseIdx, 
+                                  int compIdx)
+    {
+        Scalar x = params.moleFrac(phaseIdx,compIdx);
+        Scalar p = params.pressure(phaseIdx);
+        return x*p*computeFugacityCoeff(params, phaseIdx, compIdx);
+    };
+
+    /*!
+     * \brief Calculate the fugacity coefficient [Pa] of an individual
+     *        component in a fluid phase
+     *
+     * The fugacity coefficient \f$\phi_\kappa\f$ is connected to the
+     * fugacity \f$f_\kappa\f$ and the component's molarity
+     * \f$x_\kappa\f$ by means of the relation
+     *
+     * \f[ f_\kappa = \phi_\kappa * x_{\kappa} \f]
+     */
+    static Scalar computeFugacityCoeff(MutableParameters &params,
+                                       int phaseIdx, 
+                                       int compIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= SP::numPhases);
+        assert(0 <= compIdx  && compIdx <= SP::numComponents);
+
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+        switch (phaseIdx) {
+        case SP::lPhaseIdx: 
+            switch (compIdx) {
+            case SP::H2OIdx: return SP::H2O::vaporPressure(T)/p;
+            case SP::H2Idx: return BinaryCoeff::H2O_H2::henry(T)/p;
+            case SP::N2Idx: return BinaryCoeff::H2O_N2::henry(T)/p;
+            case SP::O2Idx: return BinaryCoeff::H2O_O2::henry(T)/p;
+            };
+        case SP::gPhaseIdx:
+            return 1.0; // ideal gas
+        };
+
+        DUNE_THROW(Dune::InvalidStateException, "Unhandled phase or component index");
+    }
+    
+    /*!
+     * \brief Calculate the dynamic viscosity of a fluid phase [Pa*s]
+     */
+    static Scalar computeViscosity(MutableParameters &params,
+                                   int phaseIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= SP::numPhases);
+
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+        switch (phaseIdx) {
+        case SP::lPhaseIdx:
+            // assume pure water for the liquid phase
+            return SP::H2O::liquidViscosity(T, p);
+        case SP::gPhaseIdx:
+            // assume pure nitrogen for the gas phase
+            return SP::N2::gasViscosity(T, p);
+        }
+        
+        DUNE_THROW(Dune::InvalidStateException, "Unhandled phase index " << phaseIdx);
+    };
+
+    /*!
+     * \brief Calculate the binary molecular diffusion coefficient for
+     *        a component in a fluid phase [mol^2 * s / (kg*m^3)]
+     *
+     * Molecular diffusion of a compoent $\kappa$ is caused by a
+     * gradient of the chemical potential and follows the law
+     *
+     * \f[ J = - D \grad mu_\kappa \f] 
+     *
+     * where \f$\mu_\kappa\$ is the component's chemical potential,
+     * \f$D\f$ is the diffusion coefficient and \f$J\f$ is the
+     * diffusive flux. \f$mu_\kappa\f$ is connected to the component's
+     * fugacity \f$f_\kappa\f$ by the relation
+     *
+     * \f[ \mu_\kappa = R T_\alpha \mathrm{ln} \frac{f_\kappa}{p_\alpha} \f]
+     *
+     * where \f$p_\alpha\f$ and \f$T_\alpha\f$ are the fluid phase'
+     * pressure and temperature.
+     */
+    static Scalar computeDiffusionCoeff(MutableParameters &params, 
+                                        int phaseIdx,
+                                        int compIdx)
+    {
+        // TODO!
+        DUNE_THROW(Dune::NotImplemented, "Diffusion coefficients");
+    };
+
+    /*!
+     * \brief Given a phase's composition, temperature and pressure,
+     *        return the binary diffusion coefficient for components
+     *        \f$i\f$ and \f$j\f$ in this phase.
+     */
+    static Scalar binaryDiffCoeff(MutableParameters &params, 
+                                  int phaseIdx,
+                                  int compIIdx,
+                                  int compJIdx)
+                                  
+    {
+        params.updateMeanMolarMass(phaseIdx);
+        if (compIIdx > compJIdx)
+            std::swap(compIIdx, compJIdx);
+
+#ifndef NDEBUG
+        if (compIIdx == compJIdx ||
+            phaseIdx > SP::numPhases - 1 ||
+            compJIdx > SP::numComponents - 1)
+        {
+            DUNE_THROW(Dune::InvalidStateException,
+                       "Binary diffusion coefficient of components "
+                       << compIIdx << " and " << compJIdx
+                       << " in phase " << phaseIdx << " is undefined!\n");
+        }
+#endif
+
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);       
+
+        switch (phaseIdx) {
+        case SP::lPhaseIdx:
+            switch (compIIdx) {
+            case SP::H2OIdx:
+                switch (compJIdx) {
+                case SP::H2Idx: return BinaryCoeff::H2O_H2::liquidDiffCoeff(T, p);
+                case SP::N2Idx: return BinaryCoeff::H2O_N2::liquidDiffCoeff(T, p);
+                case SP::O2Idx: return BinaryCoeff::H2O_O2::liquidDiffCoeff(T, p);
+                }
+            default:
+                DUNE_THROW(Dune::InvalidStateException,
+                           "Binary diffusion coefficients of trace "
+                           "substances in liquid phase is undefined!\n");
+            }
+        case SP::gPhaseIdx:
+            switch (compIIdx) {
+            case SP::H2OIdx:
+                switch (compJIdx) {
+                case SP::H2Idx: return BinaryCoeff::H2O_H2::gasDiffCoeff(T, p);
+                case SP::N2Idx: return BinaryCoeff::H2O_N2::gasDiffCoeff(T, p);
+                case SP::O2Idx: return BinaryCoeff::H2O_O2::gasDiffCoeff(T, p);
+                }
+            
+            case SP::H2Idx:
+                switch (compJIdx) {
+                case SP::N2Idx: return BinaryCoeff::H2_N2::gasDiffCoeff(T, p);
+                case SP::O2Idx: return BinaryCoeff::H2_O2::gasDiffCoeff(T, p);
+                }
+                
+            case SP::N2Idx:
+                switch (compJIdx) {
+                case SP::O2Idx: return BinaryCoeff::N2_O2::gasDiffCoeff(T, p);
+                }
+            }
+        }
+    
+        DUNE_THROW(Dune::InvalidStateException,
+                   "Binary diffusion coefficient of components "
+                   << compIIdx << " and " << compJIdx
+                   << " in phase " << phaseIdx << " is undefined!\n");
+    };
+
+    /*!
+     * \brief Given a phase's composition, temperature, pressure and
+     *        density, calculate its specific enthalpy [J/kg].
+     */
+    static Scalar computeEnthalpy(MutableParameters &params, 
+                                  int phaseIdx)
+    {
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+        Valgrind::CheckDefined(T);
+        Valgrind::CheckDefined(p);
+        if (phaseIdx == SP::lPhaseIdx) {
+            Scalar cH2 = params.molarity(SP::lPhaseIdx, SP::H2Idx);
+            Scalar cN2 = params.molarity(SP::lPhaseIdx, SP::N2Idx);
+            Scalar cO2 = params.molarity(SP::lPhaseIdx, SP::O2Idx);
+            Scalar pH2 = SP::H2::gasPressure(T, cN2*SP::H2::molarMass());
+            Scalar pN2 = SP::N2::gasPressure(T, cN2*SP::N2::molarMass());
+            Scalar pO2 = SP::O2::gasPressure(T, cN2*SP::O2::molarMass());
+
+            Scalar XH2O = params.massFrac(SP::lPhaseIdx, SP::H2OIdx);
+            Scalar XH2 = params.massFrac(SP::lPhaseIdx, SP::H2Idx);
+            Scalar XN2 = params.massFrac(SP::lPhaseIdx, SP::N2Idx);
+            Scalar XO2 = params.massFrac(SP::lPhaseIdx, SP::O2Idx);
+            
+            // TODO: correct way to deal with the solutes???
+            return 
+                (XH2O*SP::H2O::liquidEnthalpy(T, p) +
+                 XH2*SP::N2::gasEnthalpy(T, pH2) + 
+                 XN2*SP::N2::gasEnthalpy(T, pN2) + 
+                 XO2*SP::N2::gasEnthalpy(T, pO2))
+                /
+                (XH2O + XN2);
+        }
+        else {
+            Scalar cH2O = params.molarity(SP::gPhaseIdx, SP::H2OIdx);
+            Scalar cH2 = params.molarity(SP::gPhaseIdx, SP::H2Idx);
+            Scalar cN2 = params.molarity(SP::gPhaseIdx, SP::N2Idx);
+            Scalar cO2 = params.molarity(SP::gPhaseIdx, SP::O2Idx);
+            
+            // assume ideal mixture for gas
+            Scalar pH2O = SP::H2O::gasPressure(T, cH2O*SP::H2O::molarMass());
+            Scalar pH2 = SP::H2::gasPressure(T, cH2*SP::H2::molarMass());
+            Scalar pN2 = SP::N2::gasPressure(T, cN2*SP::N2::molarMass());
+            Scalar pO2 = SP::O2::gasPressure(T, cO2*SP::O2::molarMass());
+
+            Scalar XH2O = params.massFrac(SP::gPhaseIdx, SP::H2OIdx);
+            Scalar XH2 = params.massFrac(SP::gPhaseIdx, SP::H2Idx);
+            Scalar XN2 = params.massFrac(SP::gPhaseIdx, SP::N2Idx);
+            Scalar XO2 = params.massFrac(SP::gPhaseIdx, SP::O2Idx);
+
+            // add up all the "partial enthalpies"
+            Scalar result = 0;
+            result += SP::H2O::gasEnthalpy(T, pH2O);
+            result += SP::H2::gasEnthalpy(T, pH2);
+            result += SP::N2::gasEnthalpy(T, pN2);
+            result += SP::O2::gasEnthalpy(T, pO2);
+
+            // normalize the result to 100%
+            result /= XH2O + XH2 + XN2 + XO2;
+
+            return result;
+        }
+    };
+
+    /*!
+     * \brief Thermal conductivity of phases [W m / (m^2 K)]
+     * 		Use the cunductivity of air and water as a first approximation.
+     * 		Source: http://en.wikipedia.org/wiki/List_of_thermal_conductivities
+     */
+    static Scalar thermalConductivity(const MutableParameters &params,
+    								  const int phaseIdx)
+    {
+//    	TODO thermal conductivity is a function of:
+//        Scalar p = params.pressure(phaseIdx);
+//        Scalar T = params.temperature(phaseIdx);
+//        Scalar x = params.moleFrac(phaseIdx,compIdx);
+        switch (phaseIdx) {
+        case SP::lPhaseIdx: // use conductivity of pure water
+            return  0.6;   // conductivity of water[W / (m K ) ]
+        case SP::gPhaseIdx:// use conductivity of pure air
+            return  0.025; // conductivity of air [W / (m K ) ]
+        }
+        DUNE_THROW(Dune::InvalidStateException, "Unhandled phase index " << phaseIdx);
+    }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/material/new_fluidsystems/h2on2fluidsystem.hh b/dumux/material/new_fluidsystems/h2on2fluidsystem.hh
new file mode 100644
index 0000000000000000000000000000000000000000..4d86c5ac5e04c016290394b5dffae05ea9509678
--- /dev/null
+++ b/dumux/material/new_fluidsystems/h2on2fluidsystem.hh
@@ -0,0 +1,512 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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 twophase fluid system with water and nitrogen as components.
+ */
+#ifndef DUMUX_H2O_N2_FLUID_SYSTEM_HH
+#define DUMUX_H2O_N2_FLUID_SYSTEM_HH
+
+#include <dumux/material/fluidstates/genericfluidstate.hh>
+
+#include <dumux/material/components/simpleh2o.hh>
+#include <dumux/material/components/h2o.hh>
+#include <dumux/material/components/n2.hh>
+#include <dumux/material/components/tabulatedcomponent.hh>
+#include <dumux/material/idealgas.hh>
+
+#include <dumux/material/binarycoefficients/h2o_n2.hh>
+#include <dumux/material/fluidstates/genericfluidstate.hh>
+
+#include <dumux/common/exceptions.hh>
+
+namespace Dumux
+{
+
+
+template <class Scalar>
+struct H2ON2StaticParameters {
+    /****************************************
+     * Fluid phase parameters
+     ****************************************/
+
+    //! Number of phases in the fluid system
+    static constexpr int numPhases = 2;
+
+    //! Index of the liquid phase
+    static constexpr int lPhaseIdx = 0;
+    //! Index of the gas phase
+    static constexpr int gPhaseIdx = 1;
+    //! Index of the solid phase
+    static constexpr int sPhaseIdx = 2;
+    
+    //! The component for pure water 
+    typedef Dumux::SimpleH2O<Scalar> SimpleH2O;
+    typedef Dumux::H2O<Scalar> IapwsH2O;
+    typedef Dumux::TabulatedComponent<Scalar, IapwsH2O> TabulatedH2O;
+
+//    typedef IapwsH2O H2O;
+    typedef TabulatedH2O H2O;
+//    typedef SimpleH2O H2O;
+    
+    //! The component for pure nitrogen
+    typedef Dumux::N2<Scalar> N2;
+
+    /*!
+     * \brief Initialize the static parameters.
+     */
+    static void init(Scalar tempMin, Scalar tempMax, unsigned nTemp,
+                     Scalar pressMin, Scalar pressMax, unsigned nPress)
+    {
+        if (H2O::isTabulated) {
+            std::cout << "Initializing tables for the H2O fluid properties ("
+                      << nTemp*nPress
+                      << " entries).\n";
+            
+            TabulatedH2O::init(tempMin, tempMax, nTemp,
+                               pressMin, pressMax, nPress);
+        }
+
+    }
+   
+    /*!
+     * \brief Return the human readable name of a fluid phase
+     */
+    static const char *phaseName(int phaseIdx)
+    {
+        static const char *name[] = {
+            "l",
+            "g",
+            "s"
+        };
+
+        assert(0 <= phaseIdx && phaseIdx < numPhases + 1);
+        return name[phaseIdx];
+    }
+
+    /*!
+     * \brief Return whether a phase is liquid
+     */
+    static bool phaseIsLiquid(int phaseIdx)
+    {
+        assert(0 <= phaseIdx && phaseIdx < numPhases);
+        return phaseIdx != gPhaseIdx;
+    }
+
+    /****************************************
+     * Component related parameters
+     ****************************************/
+
+    //! Number of components in the fluid system
+    static constexpr int numComponents = 2;
+    
+    static constexpr int H2OIdx = 0;
+    static constexpr int N2Idx = 1;
+
+    /*!
+     * \brief Return the human readable name of a component
+     */
+    static const char *componentName(int compIdx)
+    {
+        static const char *name[] = {
+            H2O::name(),
+            N2::name()
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return name[compIdx];
+    }
+    
+    /*!
+     * \brief Return the molar mass of a component in [kg/mol].
+     */
+    static Scalar molarMass(int compIdx)
+    {
+        static const Scalar M[] = {
+            H2O::molarMass(),
+            N2::molarMass(),
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return M[compIdx];
+    }
+
+    /*!
+     * \brief Critical temperature of a component [K].
+     */
+    static Scalar criticalTemperature(int compIdx)
+    {
+        static const Scalar Tcrit[] = {
+            H2O::criticalTemperature(), // H2O
+            N2::criticalTemperature(), // H2O
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return Tcrit[compIdx];
+    };
+
+    /*!
+     * \brief Critical pressure of a component [Pa].
+     */
+    static Scalar criticalPressure(int compIdx)
+    {
+        static const Scalar pcrit[] = {
+            H2O::criticalPressure(),
+            N2::criticalPressure()
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return pcrit[compIdx];
+    };
+
+    /*!
+     * \brief Molar volume of a component at the critical point [m^3/mol].
+     */
+    static Scalar criticalMolarVolume(int compIdx)
+    {
+        DUNE_THROW(Dune::NotImplemented,
+                   "H2ON2StaticParams::criticalMolarVolume()");
+    };
+
+    /*!
+     * \brief The acentric factor of a component [].
+     */
+    static Scalar acentricFactor(int compIdx)
+    {
+        static const Scalar accFac[] = {
+            H2O::acentricFactor(), // H2O (from Reid, et al.)
+            N2::acentricFactor()
+        };
+
+        assert(0 <= compIdx && compIdx < numComponents);
+        return accFac[compIdx];
+    };
+};
+
+/*!
+ * \brief A twophase fluid system with water and nitrogen as components.
+ */
+template <class Scalar>
+class H2ON2FluidSystem : public H2ON2StaticParameters<Scalar>
+{
+public:
+    typedef Dumux::H2ON2StaticParameters<Scalar> StaticParameters;
+    typedef Dumux::GenericFluidState<Scalar, StaticParameters> MutableParameters;
+
+private:
+    // convenience typedefs
+    typedef StaticParameters SP;
+    typedef Dumux::IdealGas<Scalar> IdealGas;
+
+public:
+
+    /*!
+     * \brief Initialize the fluid system's static parameters
+     */
+    static void init(Scalar tempMin, Scalar tempMax, unsigned nTemp,
+    				 Scalar pressMin, Scalar pressMax, unsigned nPress)
+    {
+        SP::init(tempMin, tempMax, nTemp,
+                 pressMin, pressMax, nPress);
+    }
+    /*!
+     * \brief Returns true if and only if a fluid phase is assumed to
+     *        be an ideal mixture.
+     *
+     * We define an ideal mixture as a fluid phase where the fugacity
+     * coefficients of all components times the pressure of the phase
+     * are indepent on the fluid composition. This assumtion is true
+     * if Henry's law and Rault's law apply. If you are unsure what
+     * this function should return, it is safe to return false. The
+     * only damage done will be (slightly) increased computation times
+     * in some cases.
+     */
+    static bool isIdealMixture(int phaseIdx)
+    {
+        // we assume Henry's and Rault's laws for the water phase and
+        // and no interaction between gas molecules of different
+        // components, so all phases are ideal mixtures!
+        return true;
+    }
+
+    /*!
+     * \brief Calculate the molar volume [m^3/mol] of a fluid phase
+     */
+    static Scalar computeMolarVolume(MutableParameters &params,
+                                     int phaseIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= SP::numPhases);
+
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+
+        switch (phaseIdx) {
+        case SP::lPhaseIdx:
+            // assume pure water where one water molecule gets
+            // replaced by one nitrogen molecule
+            return SP::H2O::molarMass()/SP::H2O::liquidDensity(T, p);
+        case SP::gPhaseIdx:
+            // assume ideal gas
+            return 1.0 / IdealGas::concentration(T, p);
+        }
+        
+        DUNE_THROW(Dune::InvalidStateException, "Unhandled phase index " << phaseIdx);
+    };
+
+    /*!
+     * \brief Calculate the fugacity of a component in a fluid phase
+     *        [Pa]
+     *
+     * The components chemical \f$mu_\kappa\f$ potential is connected
+     * to the component's fugacity \f$f_\kappa\f$ by the relation
+     *
+     * \f[ \mu_\kappa = R T_\alpha \mathrm{ln} \frac{f_\kappa}{p_\alpha} \f]
+     *
+     * where \f$p_\alpha\f$ and \f$T_\alpha\f$ are the fluid phase'
+     * pressure and temperature.
+     */
+    static Scalar computeFugacity(const MutableParameters &params,
+                                  int phaseIdx,
+                                  int compIdx)
+    {
+        Scalar x = params.moleFrac(phaseIdx,compIdx);
+        Scalar p = params.pressure(phaseIdx);
+        return x*p*computeFugacityCoeff(params, phaseIdx, compIdx);
+    };
+
+    /*!
+     * \brief Calculate the fugacity coefficient [Pa] of an individual
+     *        component in a fluid phase
+     *
+     * The fugacity coefficient \f$\phi_\kappa\f$ is connected to the
+     * fugacity \f$f_\kappa\f$ and the component's molarity
+     * \f$x_\kappa\f$ by means of the relation
+     *
+     * \f[ f_\kappa = \phi_\kappa * x_{\kappa} \f]
+     */
+    static Scalar computeFugacityCoeff(MutableParameters &params,
+                                       int phaseIdx,
+                                       int compIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= SP::numPhases);
+        assert(0 <= compIdx  && compIdx <= SP::numComponents);
+
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+        switch (phaseIdx) {
+        case SP::lPhaseIdx: 
+            switch (compIdx) {
+            case SP::H2OIdx: return SP::H2O::vaporPressure(T)/p;
+            case SP::N2Idx: return BinaryCoeff::H2O_N2::henry(T)/p;
+            };
+        case SP::gPhaseIdx:
+            return 1.0; // ideal gas
+        };
+
+        DUNE_THROW(Dune::InvalidStateException, "Unhandled phase or component index");
+    }
+    
+    /*!
+     * \brief Calculate the dynamic viscosity of a fluid phase [Pa*s]
+     */
+    static Scalar computeViscosity(MutableParameters &params,
+                                   int phaseIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= SP::numPhases);
+
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+        switch (phaseIdx) {
+        case SP::lPhaseIdx:
+            // assume pure water for the liquid phase
+            return SP::H2O::liquidViscosity(T, p);
+        case SP::gPhaseIdx:
+            // assume pure water for the gas phase
+            return SP::N2::gasViscosity(T, p);
+        }
+        
+        DUNE_THROW(Dune::InvalidStateException, "Unhandled phase index " << phaseIdx);
+    };
+
+    /*!
+     * \brief Calculate the binary molecular diffusion coefficient for
+     *        a component in a fluid phase [mol^2 * s / (kg*m^3)]
+     *
+     * Molecular diffusion of a compoent $\kappa$ is caused by a
+     * gradient of the chemical potential and follows the law
+     *
+     * \f[ J = - D \grad mu_\kappa \f] 
+     *
+     * where \f$\mu_\kappa\$ is the component's chemical potential,
+     * \f$D\f$ is the diffusion coefficient and \f$J\f$ is the
+     * diffusive flux. \f$mu_\kappa\f$ is connected to the component's
+     * fugacity \f$f_\kappa\f$ by the relation
+     *
+     * \f[ \mu_\kappa = R T_\alpha \mathrm{ln} \frac{f_\kappa}{p_\alpha} \f]
+     *
+     * where \f$p_\alpha\f$ and \f$T_\alpha\f$ are the fluid phase'
+     * pressure and temperature.
+     */
+    static Scalar computeDiffusionCoeff(const MutableParameters &params,
+                                        int phaseIdx,
+                                        int compIdx)
+    {
+        // TODO!
+        DUNE_THROW(Dune::NotImplemented, "Diffusion coefficients");
+    };
+
+    /*!
+     * \brief Given a phase's composition, temperature and pressure,
+     *        return the binary diffusion coefficient for components
+     *        \f$i\f$ and \f$j\f$ in this phase.
+     */
+    static Scalar computeBinaryDiffCoeff(MutableParameters &params, 
+                                         int phaseIdx,
+                                         int compIIdx,
+                                         int compJIdx)
+                                  
+    {
+        params.updateMeanMolarMass(phaseIdx);
+        if (compIIdx > compJIdx)
+            std::swap(compIIdx, compJIdx);
+
+#ifndef NDEBUG
+        if (compIIdx == compJIdx ||
+            phaseIdx > SP::numPhases - 1 ||
+            compJIdx > SP::numComponents - 1)
+        {
+            DUNE_THROW(Dune::InvalidStateException,
+                       "Binary diffusion coefficient of components "
+                       << compIIdx << " and " << compJIdx
+                       << " in phase " << phaseIdx << " is undefined!\n");
+        }
+#endif
+
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);       
+
+        switch (phaseIdx) {
+        case SP::lPhaseIdx:
+            switch (compIIdx) {
+            case SP::H2OIdx:
+                switch (compJIdx) {
+                case SP::N2Idx: return BinaryCoeff::H2O_N2::liquidDiffCoeff(T, p);
+                }
+            default:
+                DUNE_THROW(Dune::InvalidStateException,
+                           "Binary diffusion coefficients of trace "
+                           "substances in liquid phase is undefined!\n");
+            }
+        case SP::gPhaseIdx:
+            switch (compIIdx) {
+            case SP::H2OIdx:
+                switch (compJIdx) {
+                case SP::N2Idx: return BinaryCoeff::H2O_N2::gasDiffCoeff(T, p);
+                }
+            }
+        }
+
+        DUNE_THROW(Dune::InvalidStateException,
+                   "Binary diffusion coefficient of components "
+                   << compIIdx << " and " << compJIdx
+                   << " in phase " << phaseIdx << " is undefined!\n");
+    };
+
+    static Scalar binaryDiffCoeff(MutableParameters &params, 
+                                  int phaseIdx,
+                                  int compIIdx,
+                                  int compJIdx)
+        DUNE_DEPRECATED // use computeBinaryDiffCoeff()
+    {
+        return computeBinaryDiffCoeff(params, 
+                                      phaseIdx,
+                                      compIIdx,
+                                      compJIdx);
+    }
+
+    /*!
+     * \brief Given a phase's composition, temperature, pressure and
+     *        density, calculate its specific enthalpy [J/kg].
+     */
+    static Scalar computeEnthalpy(MutableParameters &params, 
+                                  int phaseIdx)
+    {
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+        Valgrind::CheckDefined(T);
+        Valgrind::CheckDefined(p);
+        if (phaseIdx == SP::lPhaseIdx) {
+            Scalar cN2 = params.molarity(SP::lPhaseIdx, SP::N2Idx);
+            Scalar pN2 = SP::N2::gasPressure(T, cN2*SP::N2::molarMass());
+
+            Scalar XH2O = params.massFrac(SP::lPhaseIdx, SP::H2OIdx);
+            Scalar XN2 = params.massFrac(SP::lPhaseIdx, SP::N2Idx);
+            
+            // TODO: correct way to deal with the solutes???
+            return 
+                (XH2O*SP::H2O::liquidEnthalpy(T, p) +
+                 XN2*SP::N2::gasEnthalpy(T, pN2))
+                /
+                (XH2O + XN2);
+        }
+        else {
+            Scalar cH2O = params.molarity(SP::gPhaseIdx, SP::H2OIdx);
+            Scalar cN2 = params.molarity(SP::gPhaseIdx, SP::N2Idx);
+
+            // assume ideal gas
+            Scalar pH2O = SP::H2O::gasPressure(T, cH2O*SP::H2O::molarMass());
+            Scalar pN2 = SP::N2::gasPressure(T, cN2*SP::H2O::molarMass());
+
+            Scalar XH2O = params.massFrac(SP::gPhaseIdx, SP::H2OIdx);
+            Scalar XN2 = params.massFrac(SP::gPhaseIdx, SP::N2Idx);          
+            Scalar result = 0;
+            result += XH2O*SP::H2O::gasEnthalpy(T, pH2O);
+            result += XN2*SP::N2::gasEnthalpy(T, pN2);
+            result /= XH2O + XN2;
+
+            return result;
+        }
+    };
+
+    /*!
+     * \brief Given a phase's composition, temperature, pressure and
+     *        density, calculate its specific internal energy [J/kg].
+     */
+    static Scalar computeInternalEnergy(MutableParameters &params, 
+                                        int phaseIdx)
+    {
+        params.updateMeanMolarMass(phaseIdx);
+        Scalar T = params.temperature(phaseIdx);
+        Scalar p = params.pressure(phaseIdx);
+        Scalar rho = params.density(phaseIdx);
+        return
+            computeEnthalpy(params, phaseIdx) -
+            p/rho;
+    }
+};
+
+} // end namepace
+
+#endif
diff --git a/dumux/material/new_fluidsystems/spe5fluidsystem.hh b/dumux/material/new_fluidsystems/spe5fluidsystem.hh
new file mode 100644
index 0000000000000000000000000000000000000000..57ffcf5c701eb90146037fbd7461f0c709609ec4
--- /dev/null
+++ b/dumux/material/new_fluidsystems/spe5fluidsystem.hh
@@ -0,0 +1,347 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief The mixing rule for the oil and the gas phases of the SPE5 problem.
+ *
+ * This problem comprises \f$H_2O\f$, \f$C_1\f$, \f$C_3\f$, \f$C_6\f$,
+ * \f$C_10\f$, \f$C_15\f$ and \f$C_20\f$ as components.
+ *
+ * See:
+ *
+ * J.E. Killough, et al.: Fifth Comparative Solution Project:
+ * Evaluation of Miscible Flood Simulators, Ninth SPE Symposium on
+ * Reservoir Simulation, 1987
+ */
+#ifndef DUMUX_SPE5_FLUID_SYSTEM_HH
+#define DUMUX_SPE5_FLUID_SYSTEM_HH
+
+#include "dumux/common/spline.hh"
+#include "spe5/spe5staticparameters.hh"
+#include "spe5/spe5mutableparameters.hh"
+#include "spe5/spe5pengrobinsonparams.hh"
+#include "../eos/pengrobinsonmixture.hh"
+
+namespace Dumux
+{
+/*!
+ * \brief The fluid system for the SPE-5 benchmark problem.
+ *
+ * This problem comprises \f$H_2O\f$, \f$C_1\f$, \f$C_3\f$, \f$C_6\f$,
+ * \f$C_10\f$, \f$C_15\f$ and \f$C_20\f$ as components.
+ *
+ * See:
+ *
+ * J.E. Killough, et al.: Fifth Comparative Solution Project:
+ * Evaluation of Miscible Flood Simulators, Ninth SPE Symposium on
+ * Reservoir Simulation, 1987
+ */
+template <class Scalar>
+class Spe5FluidSystem
+{
+public:
+    typedef Dumux::Spe5StaticParameters<Scalar> StaticParameters;
+    typedef Dumux::Spe5MutableParameters<Scalar> MutableParameters;
+
+private:
+    typedef typename Dumux::PengRobinsonMixture<Scalar, StaticParameters> PengRobinsonMixture;
+    typedef typename Dumux::PengRobinson<Scalar> PengRobinson;
+
+public:
+    // copy number of phases and components from the static parameters
+    enum { numPhases = StaticParameters::numPhases };
+    enum { numComponents = StaticParameters::numComponents };
+
+    // copy phase indices from the static parameters
+    enum {
+        wPhaseIdx = StaticParameters::wPhaseIdx,
+        oPhaseIdx = StaticParameters::oPhaseIdx,
+        gPhaseIdx = StaticParameters::gPhaseIdx
+    };
+
+    // copy component indices from the static parameters
+    enum {
+        H2OIdx = StaticParameters::H2OIdx,
+        C1Idx = StaticParameters::C1Idx,
+        C3Idx = StaticParameters::C3Idx,
+        C6Idx = StaticParameters::C6Idx,
+        C10Idx = StaticParameters::C10Idx,
+        C15Idx = StaticParameters::C15Idx,
+        C20Idx = StaticParameters::C20Idx,
+    };
+
+    // copy the component types from the static parameters
+    typedef typename StaticParameters::H2O H2O;
+
+    /*!
+     * \brief Initialize the fluid system's static parameters
+     */
+    static void init()
+    {
+    }
+
+    /*!
+     * \brief Returns true if and only if a fluid phase is assumed to
+     *        be an ideal mixture.
+     *
+     * We define an ideal mixture as a fluid phase where the fugacity
+     * coefficients of all components times the pressure of the phase
+     * are indepent on the fluid composition. This assumtion is true
+     * if Henry's law and Rault's law apply. If you are unsure what
+     * this function should return, it is safe to return false. The
+     * only damage done will be (slightly) increased computation times
+     * in some cases.
+     */
+    static bool isIdealMixture(int phaseIdx)
+    {
+        // always use the reference oil for the fugacity coefficents,
+        // so they cannot be dependent on composition and they the
+        // phases thus always an ideal mixture
+        return phaseIdx == wPhaseIdx;
+    }
+
+    /*!
+     * \brief Return the human readable name of a component
+     */
+    static const char *componentName(int compIdx)
+    {
+        assert(0 <= compIdx  && compIdx <= numComponents);
+        return StaticParameters::componentName(compIdx);
+    }
+
+    /*!
+     * \brief Return the human readable name of a phase
+     */
+    static const char *phaseName(int phaseIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= numPhases);
+        return StaticParameters::phaseName(phaseIdx);
+    }
+
+    /*!
+     * \brief Return the molar mass [kg/mol] of a component
+     */
+    static Scalar molarMass(int compIdx)
+    {
+        assert(0 <= compIdx  && compIdx <= numComponents);
+        return StaticParameters::molarMass(compIdx);
+    }
+    
+    /*!
+     * \brief Calculate the molar volume [m^3/mol] of a fluid phase
+     */
+    static Scalar computeMolarVolume(MutableParameters &params, 
+                                     int phaseIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= numPhases);
+
+        params.update(phaseIdx);
+        return params.molarVolume(phaseIdx);
+    };
+
+    /*!
+     * \brief Calculate the fugacity of a component in a fluid phase
+     *        [Pa]
+     *
+     * The components chemical \f$mu_\kappa\f$ potential is connected
+     * to the component's fugacity \f$f_\kappa\f$ by the relation
+     *
+     * \f[ \mu_\kappa = R T_\alpha \mathrm{ln} \frac{f_\kappa}{p_\alpha} \f]
+     *
+     * where \f$p_\alpha\f$ and \f$T_\alpha\f$ are the fluid phase'
+     * pressure and temperature.
+     */
+    static Scalar computeFugacity(MutableParameters &params,
+                                  int phaseIdx, 
+                                  int compIdx)
+    {
+        params.update(phaseIdx);
+        return 
+            params.moleFrac(phaseIdx, compIdx) *
+            params.pressure(phaseIdx) *
+            computeFugacityCoeff(params, phaseIdx, compIdx);
+    };
+
+    /*!
+     * \brief Calculate the fugacity coefficient [Pa] of an individual
+     *        component in a fluid phase
+     *
+     * The fugacity coefficient \f$\phi_\kappa\f$ is connected to the
+     * fugacity \f$f_\kappa\f$ and the component's molarity
+     * \f$x_\kappa\f$ by means of the relation
+     *
+     * \f[ f_\kappa = \phi_\kappa * x_{\kappa} \f]
+     */
+    static Scalar computeFugacityCoeff(MutableParameters &params,
+                                       int phaseIdx, 
+                                       int compIdx)
+    {
+//        const Scalar phi_g[numComponents] = {0.315214, 0.86048, 0.378601, 0.12922, 0.0320002, 0.00813658, 0.00174178 };
+//        const Scalar phi_o[numComponents] = {0.0633375, 1.73469, 0.19746, 0.0147604, 0.000630321, 2.48063e-05, 7.74427e-07 };
+//        const Scalar pRefOil = 1.5e+07;
+
+        assert(0 <= phaseIdx  && phaseIdx <= numPhases);
+        assert(0 <= compIdx  && compIdx <= numComponents);
+
+        params.update(phaseIdx);
+        switch (phaseIdx) {
+        case gPhaseIdx:
+        case oPhaseIdx: {
+            params.update(phaseIdx);             
+            Scalar phi = PengRobinsonMixture::computeFugacityCoeff(params,
+                                                                   phaseIdx, 
+                                                                   compIdx);
+            return phi;
+        }
+        case wPhaseIdx:
+            return 
+                henryCoeffWater_(compIdx, params.temperature(wPhaseIdx))
+                /
+                params.pressure(wPhaseIdx);
+        default: DUNE_THROW(Dune::InvalidStateException, "Unhandled phase index " << phaseIdx);
+        }
+    }
+    
+    /*
+    static Scalar evalTable_(const Scalar *y, Scalar p)
+    {
+        Scalar tmp = pIdx_(p);
+        int pIdx = static_cast<int>(tmp);
+
+        Scalar p1 = (pIdx + 0) * (pMax_ - pMin_)/Scalar(numEntries_) + pMin_;
+        Scalar p2 = (pIdx + 1) * (pMax_ - pMin_)/Scalar(numEntries_) + pMin_;
+        
+#if 0
+        Scalar alpha = tmp - pIdx;
+        return y[pIdx]*(1 - alpha) + y[pIdx + 1]*alpha; 
+#else
+        Scalar pPrimeLeft =  (y[pIdx + 1] - y[pIdx - 1])/( 2*(pMax_ - pMin_)/numEntries_ );
+        Scalar pPrimeRight =  (y[pIdx + 2] - y[pIdx]    )/( 2*(pMax_ - pMin_)/numEntries_ );
+        Spline<Scalar> sp(p1, p2,
+                          y[pIdx], y[pIdx + 1],
+                          pPrimeLeft, pPrimeRight);
+        return sp.eval(p);
+#endif
+    }
+    */
+
+    /*!
+     * \brief Calculate the dynamic viscosity of a fluid phase [Pa*s]
+     */
+    static Scalar computeViscosity(MutableParameters &params,
+                                   int phaseIdx)
+    {
+        assert(0 <= phaseIdx  && phaseIdx <= numPhases);
+        params.update(phaseIdx);
+        
+        switch (phaseIdx) {
+        case gPhaseIdx: {
+            // given by SPE-5 in table on page 64. we use a constant
+            // viscosity, though...
+            return 0.0170e-2 * 0.1; 
+        }
+        case wPhaseIdx: 
+            // given by SPE-5: 0.7 centi-Poise  = 0.0007 Pa s
+            return 0.7e-2 * 0.1;
+        case oPhaseIdx: {
+            // given by SPE-5 in table on page 64. we use a constant
+            // viscosity, though...
+            return 0.208e-2 * 0.1; 
+        }
+        default: DUNE_THROW(Dune::InvalidStateException, "Unhandled phase index " << phaseIdx);
+        }
+    };
+
+    /*!
+     * \brief Calculate the binary molecular diffusion coefficient for
+     *        a component in a fluid phase [mol^2 * s / (kg*m^3)]
+     *
+     * Molecular diffusion of a compoent $\kappa$ is caused by a
+     * gradient of the chemical potential and follows the law
+     *
+     * \f[ J = - D \grad mu_\kappa \f] 
+     *
+     * where \f$\mu_\kappa\$ is the component's chemical potential,
+     * \f$D\f$ is the diffusion coefficient and \f$J\f$ is the
+     * diffusive flux. \f$mu_\kappa\f$ is connected to the component's
+     * fugacity \f$f_\kappa\f$ by the relation
+     *
+     * \f[ \mu_\kappa = R T_\alpha \mathrm{ln} \frac{f_\kappa}{p_\alpha} \f]
+     *
+     * where \f$p_\alpha\f$ and \f$T_\alpha\f$ are the fluid phase'
+     * pressure and temperature.
+     */
+    static Scalar computeDiffusionCoeff(MutableParameters &params, 
+                                        int phaseIdx,
+                                        int compIdx)
+    {
+        // TODO!
+        DUNE_THROW(Dune::NotImplemented, "Diffusion coefficients");
+    };
+
+    /*!
+     * \brief Given a phase's composition, temperature and pressure,
+     *        calculate its specific enthalpy [J/kg].
+     */
+    static Scalar computeEnthalpy(MutableParameters &params, 
+                                  int phaseIdx)
+    {
+        // TODO!
+        DUNE_THROW(Dune::NotImplemented, "Enthalpies");
+    };
+
+    /*!
+     * \brief Given a phase's composition, temperature and pressure,
+     *        calculate its specific internal energy [J/kg].
+     */
+    static Scalar internalEnergy(MutableParameters &params, 
+                                 int phaseIdx)
+    {
+        // TODO!
+        DUNE_THROW(Dune::NotImplemented, "Enthalpies");
+    };
+
+private:   
+    static Scalar henryCoeffWater_(int compIdx, Scalar temperature)
+    {
+        // use henry's law for the solutes and the vapor pressure for
+        // the solvent.
+        switch (compIdx) {
+        case H2OIdx: return H2O::vaporPressure(temperature);
+            
+            // the values of the Henry constant for the solutes have
+            // been computed using the Peng-Robinson equation of state
+            // (-> slope of the component's fugacity function at
+            // almost 100% water content)
+        case C1Idx: return 5.57601e+09;
+        case C3Idx: return 1.89465e+10;
+        case C6Idx: return 5.58969e+12;
+        case C10Idx: return 4.31947e+17;
+        case C15Idx: return 4.27283e+28;
+        case C20Idx: return 3.39438e+36;
+        default: DUNE_THROW(Dune::InvalidStateException, "Unknown component index " << compIdx);
+        }
+    };
+};
+
+} // end namepace
+
+#endif
diff --git a/test/boxmodels/Makefile.am b/test/boxmodels/Makefile.am
index 8c3650936ee7f1e0ea9876976400e1fd2b645f62..bcebc872c57a4ace2ab7ce7452f4161db679cfd5 100644
--- a/test/boxmodels/Makefile.am
+++ b/test/boxmodels/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = 1p 1p2c 2p 2p2c 2p2cni 2pni richards 
+SUBDIRS = 1p 1p2c 2p 2p2c 2p2cni 2pni MpNc richards 
 
 EXTRA_DIST = CMakeLists.txt
 
diff --git a/test/boxmodels/MpNc/CMakeLists.txt b/test/boxmodels/MpNc/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ad33076f533a6d95cc564f69aa8f8df7f55defbc
--- /dev/null
+++ b/test/boxmodels/MpNc/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_definitions(-DYASPGRID -DENABLE_ALBERTA -DENABLE_ALUGRID -DENABLE_UG)
+
+# build target for the twophase-twocomponent test problem
+ADD_EXECUTABLE("test_2p2c" test_2p2c.cc)
+TARGET_LINK_LIBRARIES("test_2p2c" ${DumuxLinkLibraries})
+
+# add required libraries and includes to the build flags 
+LINK_DIRECTORIES(${DumuxLinkDirectories})
+INCLUDE_DIRECTORIES(${DumuxIncludeDirectories})
+
+# make sure the grids are present in the build directory
+add_custom_command(TARGET "test_2p2c"
+                   POST_BUILD
+                   COMMAND ${CMAKE_COMMAND} -E
+                        copy_directory 
+                           "${CMAKE_CURRENT_SOURCE_DIR}/grids"
+                           "${CMAKE_CURRENT_BINARY_DIR}/grids")
+
diff --git a/test/boxmodels/MpNc/Makefile.am b/test/boxmodels/MpNc/Makefile.am
new file mode 100644
index 0000000000000000000000000000000000000000..5d397cf79edb9c4010fd0acfbc888648199d5c21
--- /dev/null
+++ b/test/boxmodels/MpNc/Makefile.am
@@ -0,0 +1,10 @@
+check_PROGRAMS = test_MpNc
+noinst_HEADERS = *.hh
+
+EXTRA_DIST=grids/*.dgf
+gridsdir=$(datadir)/dumux/grids
+grids_DATA=grids/*.dgf
+
+test_MpNc_SOURCES = test_MpNc.cc
+
+include $(top_srcdir)/am/global-rules
diff --git a/test/boxmodels/MpNc/obstacleproblem.hh b/test/boxmodels/MpNc/obstacleproblem.hh
new file mode 100644
index 0000000000000000000000000000000000000000..7df0e1748df45a7a8ed352e111d8ed0937c879e1
--- /dev/null
+++ b/test/boxmodels/MpNc/obstacleproblem.hh
@@ -0,0 +1,564 @@
+/*****************************************************************************
+ *   Copyright (C) 2008-2010 by Andreas Lauser                               *
+ *   Copyright (C) 2008-2009 by Klaus Mosthaf                                *
+ *   Copyright (C) 2008-2009 by Bernd Flemisch                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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
+ * \ingroup TwoPTwoNBoxProblems
+ *
+ * \brief Problem where water and gas is injected by means of a
+ *        dirchlet condition on the lower right of the domain which have to go
+ *        around an obstacle with \f$10^3\f$ lower permeability.
+ * \author Andreas Lauser, Klaus Mosthaf, Bernd Flemisch
+ */
+#ifndef DUMUX_OBSTACLEPROBLEM_HH
+#define DUMUX_OBSTACLEPROBLEM_HH
+
+#define USE_2P2C 0
+#define OBSTACLE_FIND_CONVERGENCE_RADIUS 0
+
+#include <dune/common/parametertreeparser.hh>
+
+#include <dune/grid/io/file/dgfparser/dgfug.hh>
+#include <dune/grid/io/file/dgfparser/dgfs.hh>
+#include <dune/grid/io/file/dgfparser/dgfyasp.hh>
+
+#if USE_2P2C
+#include <dumux/boxmodels/2p2c/2p2cmodel.hh>
+#else
+#include <dumux/boxmodels/MpNc/MpNcmodel.hh>
+#endif
+
+/*
+#include <dumux/material/fluidsystems/simple_h2o_n2_system.hh>
+#include <dumux/material/fluidsystems/simple_h2o_n2_tce_system.hh>
+#include <dumux/material/fluidsystems/h2o_n2_system.hh>
+#include <dumux/material/fluidsystems/h2o_n2_o2_system.hh>
+#include <dumux/material/fluidsystems/h2o_h2_o2_system.hh>
+#include <dumux/material/fluidsystems/h2o_h2_n2_o2_system.hh>
+*/
+
+#include <dumux/material/new_fluidsystems/h2on2fluidsystem.hh>
+
+#include "obstaclespatialparameters.hh"
+
+namespace Dumux
+{
+
+template <class TypeTag>
+class ObstacleProblem;
+
+namespace Properties
+{
+#if USE_2P2C
+NEW_TYPE_TAG(ObstacleProblem, INHERITS_FROM(BoxTwoPTwoC, ObstacleSpatialParameters));
+#else
+NEW_TYPE_TAG(ObstacleProblem, INHERITS_FROM(BoxMPNC, ObstacleSpatialParameters));
+#endif
+
+// Set the grid type
+SET_TYPE_PROP(ObstacleProblem, Grid, Dune::YaspGrid<2>);
+
+// Set the problem property
+SET_TYPE_PROP(ObstacleProblem,
+              Problem,
+              Dumux::ObstacleProblem<TypeTag>);
+
+
+// Set fluid configuration
+SET_PROP(ObstacleProblem, FluidSystem)
+{ private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+public:
+    typedef Dumux::H2ON2FluidSystem<Scalar> type;
+};
+//              Dumux::Simple_H2O_N2_TCE_System<TypeTag> );
+//Dumux::H2O_N2_System<TypeTag> );
+
+#if ! USE_2P2C
+// Enable smooth upwinding?
+SET_BOOL_PROP(ObstacleProblem, EnableSmoothUpwinding, false);
+
+// Enable molecular diffusion of the components?
+SET_BOOL_PROP(ObstacleProblem, EnableDiffusion, false);
+
+// Use the chopped Newton method?
+SET_BOOL_PROP(ObstacleProblem, NewtonEnableChop, true);
+#endif
+
+// Enable gravity
+SET_BOOL_PROP(ObstacleProblem, EnableGravity, true);
+
+// Write Newton convergence to disk?
+SET_BOOL_PROP(ObstacleProblem, NewtonWriteConvergence, false);
+
+// Use the line search strategy for the Newton update?
+SET_BOOL_PROP(ObstacleProblem, NewtonUseLineSearch, false);
+
+// Enable the re-use of the jacobian matrix whenever possible?
+SET_BOOL_PROP(ObstacleProblem, EnableJacobianRecycling, true);
+
+// Reassemble the jacobian matrix only where it changed?
+SET_BOOL_PROP(ObstacleProblem, EnablePartialReassemble, true);
+
+// use forward diffferences to approximate the partial derivatives
+SET_INT_PROP(ObstacleProblem, NumericDifferenceMethod, +1);
+}
+
+
+/*!
+ * \ingroup TwoPBoxProblems
+ * \brief Problem where liquid water is injected by means of a
+ *        dirchlet condition on the lower right of the domain which have to go
+ *        around an obstacle with \f$10^3\f$ lower permeability.
+ *
+ * The domain is sized 60m times 40m and consists of two media, a
+ * moderately permeable soil (\f$ K_0=10e-12 m^2\f$) and an obstacle
+ * at \f$[10; 20]m \times [0; 35]m \f$ with a lower permeablility of
+ * \f$ K_1=K_0/1000\f$.
+ *
+ * Initially the whole domain is filled by nitrogen, the temperature
+ * is \f$20\symbol{23}C\f$ at the whole domain. The gas pressure at
+ * the left side of the domain is 1 bar, at the right side it is 2 bar
+ * with a linear gradient in between.
+ *
+ * The boundary is no-flow except on the lower 10 meters of the left
+ * and the right boundary which is a Dirichlet condition with the same
+ * values as the initial condition.
+ */
+template <class TypeTag>
+class ObstacleProblem
+#if USE_2P2C
+    : public TwoPTwoCProblem<TypeTag>
+#else
+    : public MPNCProblem<TypeTag>
+#endif
+{
+    typedef ObstacleProblem<TypeTag>             ThisType;
+#if USE_2P2C
+    typedef TwoPTwoCProblem<TypeTag> ParentType;
+#else
+    typedef MPNCProblem<TypeTag> ParentType;
+#endif
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(PrimaryVariables)) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(BoundaryTypes)) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+    enum {
+        // Grid and world dimension
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld,
+        
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+        numComponents = GET_PROP_VALUE(TypeTag, PTAG(NumComponents)),
+
+        gPhaseIdx = FluidSystem::gPhaseIdx,
+        //oPhaseIdx = FluidSystem::oPhaseIdx,
+        lPhaseIdx = FluidSystem::lPhaseIdx,
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::Intersection Intersection;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef Dune::FieldVector<typename GridView::Grid::ctype, dimWorld> GlobalPosition;
+
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(TimeManager)) TimeManager;
+
+#if USE_2P2C
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(TwoPTwoCIndices)) Indices;
+
+#else // ! USE_2P2C
+    // copy some indices for convenience
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MPNCIndices)) Indices;
+    enum {
+        fug0Idx = Indices::fug0Idx,
+        S0Idx = Indices::S0Idx,
+        p0Idx = Indices::p0Idx,
+    };
+#endif // USE_2P2C
+public:
+    ObstacleProblem(TimeManager &timeManager, const GridView &gridView)
+        : ParentType(timeManager, gridView)
+    {
+        temperature_ = 273.15 + 25; // -> 25°C
+
+        // initialize the tables of the fluid system
+        Scalar Tmin = temperature_ - 1.0;
+        Scalar Tmax = temperature_ + 1.0;
+        int nT = 10;
+        Scalar pmin = 0.75 * 1e5;
+        Scalar pmax = 1.25 * 2e5;
+        int np = 1000;
+        FluidSystem::init(Tmin, Tmax, nT, pmin, pmax, np);
+    }
+
+    /*!
+     * \brief Called by Dumux::TimeManager in order to do a time
+     *        integration on the model.
+     */
+    void timeIntegration()
+    {
+#if !OBSTACLE_FIND_CONVERGENCE_RADIUS
+        if (GET_PROP_VALUE(TypeTag, PTAG(NewtonWriteConvergence)))
+            this->newtonController().setMaxSteps(40);
+        ParentType::timeIntegration();
+#else
+        std::cout << "Finding convergence radius\n";
+        this->newtonController().setVerbose(false);
+        this->newtonController().setMaxSteps(40);
+        this->newtonController().setTargetSteps(20);
+        Scalar successDt = 0.0;
+        const int maxFails = 10;
+        for (int i = 0; true; ++i) {
+            std::cout << "Try dt of " << this->timeManager().timeStepSize() << "\n";
+            std::cout.flush();
+
+            if (i == maxFails && this->gridView().comm().rank() == 0)
+                DUNE_THROW(Dune::MathError,
+                           "Newton solver didn't converge after "
+                           << maxFails
+                           << " timestep divisions. dt="
+                           << this->timeManager().timeStepSize());
+
+            if (this->model().update(this->newtonMethod(), 
+                                     this->newtonController()))
+            {
+                // sucessfull update. remember time step size
+                successDt = this->timeManager().timeStepSize();
+                this->model().updateFailed();
+                break;
+            }
+
+            if (i > 0 && this->gridView().comm().rank() == 0)
+                std::cout << "Newton solver did not converge. Retrying with time step of "
+                          << this->timeManager().timeStepSize() << "sec\n";
+            
+            // update failed
+            Scalar dt = this->timeManager().timeStepSize();
+            Scalar nextDt = dt / 2;
+            this->timeManager().setTimeStepSize(nextDt);
+            std::cout << "Failed for dt=" << dt << ". Try with half dt of " << nextDt << "\n";
+        }
+
+        // increase time step until the update fails
+        while (true)
+        {
+            if (!this->model().update(this->newtonMethod(),
+                                      this->newtonController()))
+                break;
+            
+            // sucessfull update. increase time step size
+            successDt = this->timeManager().timeStepSize();
+            Scalar nextDt = successDt*1.25;
+            this->timeManager().setTimeStepSize(nextDt);
+            if (this->timeManager().timeStepSize() < nextDt) {
+                std::cout << "End of simulation reached!\n";
+                break;
+            };
+            std::cout << "Increase dt to " << nextDt << "\n";
+            std::cout.flush();
+            this->model().updateFailed();
+        }
+        
+        // do a last update with the largest successful time step
+        this->newtonController().setVerbose(true);
+        this->timeManager().setTimeStepSize(successDt);
+        std::cout << "Convergence radius is " << successDt << "\n";
+        this->model().update(this->newtonMethod(), this->newtonController());
+#endif
+    }
+    
+    /*!
+     * \brief Called directly after the time integration.
+     */
+    void postTimeStep()
+    {
+        // Calculate storage terms of the individual phases
+        for (int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
+            PrimaryVariables phaseStorage;
+            this->model().globalPhaseStorage(phaseStorage, phaseIdx);
+
+            if (this->gridView().comm().rank() == 0) {
+                std::cout 
+                    <<"Storage in " 
+                    << FluidSystem::phaseName(phaseIdx)
+                    << "Phase: ["
+                    << phaseStorage
+                    << "]"
+                    << "\n";
+            }
+        }
+
+        // Calculate total storage terms 
+        PrimaryVariables storage;
+        this->model().globalStorage(storage);
+   
+        // Write mass balance information for rank 0
+        if (this->gridView().comm().rank() == 0) {
+            std::cout 
+                <<"Storage total: [" << storage << "]"
+                << "\n";
+        }        
+    }
+
+    /*!
+     * \name Problem parameters
+     */
+    // \{
+
+    /*!
+     * \brief The problem name.
+     *
+     * This is used as a prefix for files generated by the simulation.
+     */
+    const char *name() const
+    { return "obstacle"; }
+
+    /*!
+     * \brief Returns the temperature [K] within the domain.
+     */
+    Scalar temperature() const
+    { return temperature_; };
+
+    // \}
+
+    /*!
+     * \name Boundary conditions
+     */
+    // \{
+
+    /*!
+     * \brief Specifies which kind of boundary condition should be
+     *        used for which equation on a given boundary segment.
+     *
+     * \param values The boundary types for the conservation equations
+     * \param vertex The vertex for which the boundary type is set
+     */
+    void boundaryTypes(BoundaryTypes &values, const Vertex &vertex) const
+    {
+        const GlobalPosition globalPos = vertex.geometry().center();
+
+        if (onInlet_(globalPos) || onOutlet_(globalPos))
+            values.setAllDirichlet();
+        else
+            values.setAllNeumann();
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a dirichlet
+     *        boundary segment.
+     *
+     * \param values The dirichlet values for the primary variables
+     * \param vertex The vertex for which the boundary type is set
+     *
+     * For this method, the \a values parameter stores primary variables.
+     */
+    void dirichlet(PrimaryVariables &values, const Vertex &vertex) const
+    {
+        const GlobalPosition globalPos = vertex.geometry().center();
+
+        initial_(values, globalPos);
+    }
+
+    /*!
+     * \brief Evaluate the boundary conditions for a neumann
+     *        boundary segment.
+     *
+     * For this method, the \a values parameter stores the mass flux
+     * in normal direction of each component. Negative values mean
+     * influx.
+     */
+    void neumann(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvElemGeom,
+                 const Intersection &is,
+                 int scvIdx,
+                 int boundaryFaceIdx) const
+    { values = 0; }
+
+    // \}
+
+    /*!
+     * \name Volume terms
+     */
+    // \{
+
+    /*!
+     * \brief Evaluate the source term for all phases within a given
+     *        sub-control-volume.
+     *
+     * For this method, the \a values parameter stores the rate mass
+     * of a component is generated or annihilate per volume
+     * unit. Positive values mean that mass is created, negative ones
+     * mean that it vanishes.
+     */
+    void source(PrimaryVariables &values,
+                const Element &element,
+                const FVElementGeometry &fvElemGeom,
+                int scvIdx) const
+    {
+        values = Scalar(0.0);
+    }
+
+    /*!
+     * \brief Evaluate the initial value for a control volume.
+     *
+     * For this method, the \a values parameter stores primary
+     * variables.
+     */
+    void initial(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvElemGeom,
+                 int scvIdx) const
+    {
+        const GlobalPosition &globalPos = element.geometry().corner(scvIdx);
+
+        initial_(values, globalPos);
+        Valgrind::CheckDefined(values);
+    }
+
+    // \}
+
+    /*!
+     * \brief Write a restart file?
+     */
+    bool shouldWriteRestartFile() const 
+    {
+        return ParentType::shouldWriteRestartFile();
+    }
+
+    
+#if USE_2P2C
+    /*!
+     * \brief Return the initial phase state inside a control volume.
+     */
+   int initialPhasePresence(const Vertex &vert,
+                             int &globalIdx,
+                             const GlobalPosition &globalPos) const
+    {
+        if (onInlet_(globalPos))
+            return Indices::lPhaseOnly;
+        else
+            return Indices::gPhaseOnly;
+    };
+#endif
+
+private:
+    // the internal method for the initial condition
+    void initial_(PrimaryVariables &values,
+                  const GlobalPosition &globalPos) const
+    {
+        Scalar pg;
+        if (onInlet_(globalPos))
+            pg = 2e5;
+        else
+            pg = 1e5;
+
+
+#if USE_2P2C
+        values[Indices::plIdx] = pg;
+
+        if (onInlet_(globalPos))
+            values[Indices::SgOrXIdx] = 0.0; // X^a_w
+        else
+            values[Indices::SgOrXIdx] = 0.0; // X^w_g
+#else
+        if (onInlet_(globalPos)) {
+            // only liquid
+            Scalar S[numPhases];
+            Scalar p[numPhases];
+            Scalar xl[numComponents];
+            Scalar beta[numComponents];
+
+            p[gPhaseIdx] = pg;
+            p[lPhaseIdx] = pg;
+
+            S[lPhaseIdx] = 1.0;
+            S[gPhaseIdx] = 0.0;
+
+            xl[FluidSystem::H2OIdx]     = 1.0;
+            xl[FluidSystem::N2Idx]      = 0.0;
+            beta[FluidSystem::H2OIdx]   = FluidSystem::H2O::vaporPressure(temperature_);
+            beta[FluidSystem::N2Idx]    = Dumux::BinaryCoeff::H2O_N2::henry(temperature_);
+            
+            // assign the primary variables
+            for (int i = 0; i < numComponents; ++i)
+                values[fug0Idx + i] = xl[i]*beta[i];
+
+            for (int i = 0; i < numPhases - 1; ++i)
+                values[S0Idx + i] = S[i]; 
+
+            values[p0Idx] = p[0];
+        }
+        else {
+            // only gas
+            Scalar S[numPhases];
+            Scalar xg[numComponents];
+            Scalar p[numPhases];
+
+            S[lPhaseIdx] = 0.0;
+            S[gPhaseIdx] = 1.0;
+
+            p[lPhaseIdx] = pg;
+            p[gPhaseIdx] = pg;
+            
+            
+            xg[FluidSystem::H2OIdx] = 0.01;
+            xg[FluidSystem::N2Idx] = 0.99;
+            
+
+            // assign the primary variables
+            for (int i = 0; i < numComponents; ++i)
+                values[fug0Idx + i] = xg[i]*pg;
+
+            for (int i = 0; i < numPhases - 1; ++i)
+                values[S0Idx + i] = S[i]; 
+
+            values[p0Idx] = p[0];
+        }
+#endif // USE_2P2C
+    }
+
+    bool onInlet_(const GlobalPosition &globalPos) const
+    {
+        Scalar x = globalPos[0];
+        Scalar y = globalPos[1];
+        return x >= 60 - eps_ && y <= 10;
+    };
+
+    bool onOutlet_(const GlobalPosition &globalPos) const
+    {
+        Scalar x = globalPos[0];
+        Scalar y = globalPos[1];
+        return x < eps_ && y <= 10;
+    };
+
+    Scalar temperature_;
+    static constexpr Scalar eps_ = 1e-6;
+};
+} //end namespace
+
+#endif
diff --git a/test/boxmodels/MpNc/obstaclespatialparameters.hh b/test/boxmodels/MpNc/obstaclespatialparameters.hh
new file mode 100644
index 0000000000000000000000000000000000000000..f48e9d3202e0671d18b70caba21c553c4b48a5e6
--- /dev/null
+++ b/test/boxmodels/MpNc/obstaclespatialparameters.hh
@@ -0,0 +1,302 @@
+/*****************************************************************************
+ *   Copyright (C) 2008-2009 by Andreas Lauser                               *
+ *   Copyright (C) 2008-2009 by Klaus Mosthaf                                *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_OBSTACLE_SPATIAL_PARAMS_HH
+#define DUMUX_OBSTACLE_SPATIAL_PARAMS_HH
+
+#include <dumux/material/spatialparameters/boxspatialparameters.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/linearmaterial.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/regularizedlinearmaterial.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh>
+
+#if USE_2P2C
+#include <dumux/boxmodels/2p2c/2p2cmodel.hh>
+#else
+#include <dumux/boxmodels/MpNc/MpNcmodel.hh>
+#include <dumux/material/fluidmatrixinteractions/Mp/Mplinearmaterial.hh>
+#include <dumux/material/fluidmatrixinteractions/Mp/2padapter.hh>
+#endif
+
+namespace Dumux
+{
+
+//forward declaration
+template<class TypeTag>
+class ObstacleSpatialParameters;
+
+namespace Properties
+{
+// The spatial parameters TypeTag
+NEW_TYPE_TAG(ObstacleSpatialParameters);
+
+// Set the spatial parameters
+SET_TYPE_PROP(ObstacleSpatialParameters, SpatialParameters, Dumux::ObstacleSpatialParameters<TypeTag>);
+
+// Set the material Law
+SET_PROP(ObstacleSpatialParameters, MaterialLaw)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+    enum {
+        lPhaseIdx = FluidSystem::lPhaseIdx,
+        gPhaseIdx = FluidSystem::gPhaseIdx,
+    };
+    // define the material law
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    //    typedef RegularizedBrooksCorey<Scalar> EffMaterialLaw;
+        typedef RegularizedLinearMaterial<Scalar> EffMaterialLaw;
+        typedef EffToAbsLaw<EffMaterialLaw> TwoPMaterialLaw;
+public:
+#if USE_2P2C
+    typedef TwoPMaterialLaw type;
+#else
+    typedef TwoPAdapter<lPhaseIdx, TwoPMaterialLaw> type;
+#endif
+};
+}
+
+/**
+ * \brief Definition of the spatial params properties for the obstacle problem
+ *
+ */
+template<class TypeTag>
+class ObstacleSpatialParameters : public BoxSpatialParameters<TypeTag>
+{
+    typedef BoxSpatialParameters<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Grid)) Grid;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(GridView)) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(Scalar)) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(SolutionVector)) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(ElementVolumeVariables)) ElementVolumeVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluxVariables)) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FVElementGeometry)) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(FluidSystem)) FluidSystem;
+
+    typedef typename Grid::ctype CoordScalar;
+    enum {
+        dim=GridView::dimension,
+        dimWorld=GridView::dimensionworld,
+        numPhases = GET_PROP_VALUE(TypeTag, PTAG(NumPhases)),
+    };
+
+    enum {
+        lPhaseIdx = FluidSystem::lPhaseIdx,
+        gPhaseIdx = FluidSystem::gPhaseIdx,
+    };
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef Dune::FieldVector<CoordScalar,dimWorld> GlobalPosition;
+    typedef Dune::FieldVector<Scalar,dimWorld> Vector;
+
+public:
+    typedef typename GET_PROP_TYPE(TypeTag, PTAG(MaterialLaw)) MaterialLaw;
+    typedef typename MaterialLaw::Params MaterialLawParams;
+
+    ObstacleSpatialParameters(const GridView &gv)
+        : ParentType(gv)
+    {
+        // intrinsic permeabilities
+        coarseK_ = 1e-12;
+        fineK_ = 1e-15;
+
+        // the porosity
+        porosity_ = 0.3;        
+
+        // residual saturations
+        fineMaterialParams_.setSwr(0.0);
+        fineMaterialParams_.setSnr(0.0);
+        coarseMaterialParams_.setSwr(0.0);
+        coarseMaterialParams_.setSnr(0.0);
+
+        // parameters for the linear law, i.e. minimum and maximum
+        // pressures
+        fineMaterialParams_.setEntryPC(0.0);
+        coarseMaterialParams_.setEntryPC(0.0);
+        fineMaterialParams_.setMaxPC(0.0);
+        coarseMaterialParams_.setMaxPC(0.0);
+        
+        /*
+        // entry pressures for Brooks-Corey
+        fineMaterialParams_.setPe(5e3);
+        coarseMaterialParams_.setPe(1e3);
+
+        // Brooks-Corey shape parameters
+        fineMaterialParams_.setLambda(2);
+        coarseMaterialParams_.setLambda(2);
+        */
+    }
+
+    ~ObstacleSpatialParameters()
+    {}
+
+    /*!
+     * \brief Update the spatial parameters with the flow solution
+     *        after a timestep.
+     *
+     * \TODO call parameters
+     */
+    void update(const SolutionVector &globalSol)
+    {
+    };
+
+    /*!
+     * \brief Returns the intrinsic permeability tensor.
+     *
+     * \param element       The current finite element
+     * \param fvElemGeom    The current finite volume geometry of the element
+     * \param scvIdx        The index sub-control volume where the
+     *                      intrinsic permeability is given.
+     */
+    Scalar intrinsicPermeability(const Element &element,
+                                 const FVElementGeometry &fvElemGeom,
+                                 int scvIdx) const
+    {
+        if (isFineMaterial_(fvElemGeom.subContVol[scvIdx].global))
+            return fineK_;
+        return coarseK_;
+    }
+
+    /*!
+     * \brief Define the porosity \f$[-]\f$ of the soil
+     *
+     * \param vDat        The data defined on the sub-control volume
+     * \param element     The finite element
+     * \param fvElemGeom  The finite volume geometry
+     * \param scvIdx      The local index of the sub-control volume where
+     *                    the porosity needs to be defined
+     */
+    double porosity(const Element &element,
+                    const FVElementGeometry &fvElemGeom,
+                    int scvIdx) const
+    {
+        return porosity_;
+    }
+
+    /*!
+     * \brief Returns the heat capacity \f$[J/m^3 K]\f$ of the rock matrix.
+     *
+     * This is only required for non-isothermal models.
+     *
+     * \param element     The finite element
+     * \param fvElemGeom  The finite volume geometry
+     * \param scvIdx      The local index of the sub-control volume where
+     *                    the heat capacity needs to be defined
+     */
+    double heatCapacity(const Element &element,
+                        const FVElementGeometry &fvElemGeom,
+                        int scvIdx) const
+    {
+        return 790. ;  // specific heat capacity of granite [J / (kg K)]
+    }
+
+    /*!
+     * \brief Calculate the heat flux \f$[W/m^2]\f$ through the
+     *        rock matrix based on the temperature gradient \f$[K / m]\f$
+     *
+     * This is only required for non-isothermal models.
+     *
+     * \param heatFlux    The result vector
+     * \param tempGrad    The temperature gradient
+     * \param element     The current finite element
+     * \param fvElemGeom  The finite volume geometry of the current element
+     * \param scvfIdx     The local index of the sub-control volume face where
+     *                    the matrix heat flux should be calculated
+     */
+//    void matrixHeatFlux(Vector &heatFlux,
+//                        const FluxVariables &fluxDat,
+//                        const ElementVolumeVariables &vDat,
+//                        const Vector &tempGrad,
+//                        const Element &element,
+//                        const FVElementGeometry &fvElemGeom,
+//                        int scvfIdx) const
+//    {
+//        static const Scalar lWater = 0.6;   // [W / (m K ) ]
+//        static const Scalar lGranite = 2.8; // [W / (m K ) ]
+//
+//        // arithmetic mean of the liquid saturation and the porosity
+//        const int i = fvElemGeom.subContVolFace[scvfIdx].i;
+//        const int j = fvElemGeom.subContVolFace[scvfIdx].j;
+//        Scalar Sl = std::max(0.0, (vDat[i].saturation(lPhaseIdx) +
+//                                     vDat[j].saturation(lPhaseIdx)) / 2);
+//        Scalar poro = (porosity(element, fvElemGeom, i) +
+//                       porosity(element, fvElemGeom, j)) / 2;
+//
+//        Scalar lsat = pow(lGranite, (1-poro)) * pow(lWater, poro);
+//        Scalar ldry = pow(lGranite, (1-poro));
+//
+//        // the heat conductivity of the matrix. in general this is a
+//        // tensorial value, but we assume isotropic heat conductivity.
+//        Scalar heatCond = ldry + sqrt(Sl) * (ldry - lsat);
+//
+//        // the matrix heat flux is the negative temperature gradient
+//        // times the heat conductivity.
+//        heatFlux = tempGrad;
+//        heatFlux *= -heatCond;
+//    }
+
+    // return the brooks-corey context depending on the position
+    const MaterialLawParams& materialLawParams(const Element &element,
+                                                const FVElementGeometry &fvElemGeom,
+                                                int scvIdx) const
+    {
+        const GlobalPosition &pos = fvElemGeom.subContVol[scvIdx].global;
+        if (isFineMaterial_(pos))
+            return fineMaterialParams_;
+        else
+            return coarseMaterialParams_;
+    }
+
+    const Scalar & soilDensity(const Element &element,
+                                const FVElementGeometry &fvElemGeom,
+                                int scvIdx) const
+    {
+        return 2700. ; // density of granite [kg/m^3]
+    }
+
+    const Scalar & soilThermalConductivity(const Element &element,
+                                    const FVElementGeometry &fvElemGeom,
+                                    int scvIdx) const
+    {
+        return 2.8; // conductivity of granite [W / (m K ) ]
+    }
+
+private:
+    /*!
+     * \brief Returns whether a given global position is in the
+     *        fine-permeability region or not.
+     */
+    static bool isFineMaterial_(const GlobalPosition &pos)
+    {
+        return
+            10 <= pos[0] && pos[0] <= 20 &&
+            0 <= pos[1] && pos[1] <= 35;
+    };
+
+    Scalar coarseK_;
+    Scalar fineK_;
+    Scalar porosity_;
+    MaterialLawParams fineMaterialParams_;
+    MaterialLawParams coarseMaterialParams_;
+};
+
+}
+
+#endif
diff --git a/test/boxmodels/MpNc/test_MpNc.cc b/test/boxmodels/MpNc/test_MpNc.cc
new file mode 100644
index 0000000000000000000000000000000000000000..be92f454d02c69e44d879e9ebd64ad1b68fade2f
--- /dev/null
+++ b/test/boxmodels/MpNc/test_MpNc.cc
@@ -0,0 +1,31 @@
+/*****************************************************************************
+ *   Copyright (C) 2009-2010 by Andreas Lauser                               *
+ *   Institute of Hydraulic Engineering                                      *
+ *   University of Stuttgart, Germany                                        *
+ *   email: <givenname>.<name>@iws.uni-stuttgart.de                          *
+ *                                                                           *
+ *   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/>.   *
+ *****************************************************************************/
+#include "config.h"
+#include "obstacleproblem.hh"
+
+#include <dumux/common/start.hh>
+
+int main(int argc, char** argv)
+{
+    typedef TTAG(ObstacleProblem) TypeTag;
+    int ret = Dumux::startFromDGF<TypeTag>(argc, argv);
+    Dumux::Parameters::print<TypeTag>();
+    return ret;
+}