From 9c3ab5e1a43bff526fd6590c71f3b3150d29d4dc Mon Sep 17 00:00:00 2001
From: Klaus Mosthaf <klmos@env.dtu.dk>
Date: Wed, 29 Jan 2014 10:27:05 +0000
Subject: [PATCH] added 2cnistokes2p2cni test and adapted makefiles and
 configure

git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@12384 2fb0f335-1f38-0410-981e-8018bf24f1b0
---
 configure.ac                                  |   1 +
 .../2cnistokes2p2cnilocaloperator.hh          |   4 +-
 .../2cnistokes2p2cniproblem.hh                | 758 ++++++++++++++++++
 .../2cnistokes2p2cnispatialparams.hh          | 371 +++++++++
 .../2cnistokes2p2cni/2p2cnisubproblem.hh      | 675 ++++++++++++++++
 test/multidomain/2cnistokes2p2cni/Makefile.am |   5 +
 .../grids/interfacedomain.dgf                 |  15 +
 .../grids/test_2cnistokes2p2cni.dgf           |  17 +
 .../2cnistokes2p2cni/stokes2cnisubproblem.hh  | 592 ++++++++++++++
 .../2cnistokes2p2cni/test_2cnistokes2p2cni.cc | 279 +++++++
 .../test_2cnistokes2p2cni.input               | 193 +++++
 test/multidomain/Makefile.am                  |   3 +-
 12 files changed, 2910 insertions(+), 3 deletions(-)
 create mode 100644 test/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproblem.hh
 create mode 100644 test/multidomain/2cnistokes2p2cni/2cnistokes2p2cnispatialparams.hh
 create mode 100644 test/multidomain/2cnistokes2p2cni/2p2cnisubproblem.hh
 create mode 100644 test/multidomain/2cnistokes2p2cni/Makefile.am
 create mode 100644 test/multidomain/2cnistokes2p2cni/grids/interfacedomain.dgf
 create mode 100644 test/multidomain/2cnistokes2p2cni/grids/test_2cnistokes2p2cni.dgf
 create mode 100644 test/multidomain/2cnistokes2p2cni/stokes2cnisubproblem.hh
 create mode 100644 test/multidomain/2cnistokes2p2cni/test_2cnistokes2p2cni.cc
 create mode 100644 test/multidomain/2cnistokes2p2cni/test_2cnistokes2p2cni.input

diff --git a/configure.ac b/configure.ac
index e311465a31..10c58d3271 100644
--- a/configure.ac
+++ b/configure.ac
@@ -131,6 +131,7 @@ AC_CONFIG_FILES([dumux.pc
     test/material/tabulation/Makefile
     test/multidomain/Makefile
     test/multidomain/2cstokes2p2c/Makefile
+    test/multidomain/2cnistokes2p2cni/Makefile
     test/references/Makefile
     tutorial/Makefile
 ])
diff --git a/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh b/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh
index bdc7153fc4..7672bed006 100644
--- a/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh
+++ b/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh
@@ -26,8 +26,8 @@
 
 #include <dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh>
 
-#include <dumux/freeflow/stokesncni/stokesncnimodel.hh>
-#include <dumux/implicit/2p2cnicoupling/2p2cnicouplingmodel.hh>
+//#include <dumux/freeflow/stokesncni/stokesncnimodel.hh>
+//#include <dumux/implicit/2p2cnicoupling/2p2cnicouplingmodel.hh>
 
 namespace Dumux {
 
diff --git a/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproblem.hh b/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproblem.hh
new file mode 100644
index 0000000000..9c3ca6c470
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproblem.hh
@@ -0,0 +1,758 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/**
+ * @file
+ * \ingroup docme
+ * @brief  docme
+ */
+#ifndef DUMUX_2CNISTOKES2P2CNIPROBLEM_HH
+#define DUMUX_2CNISTOKES2P2CNIPROBLEM_HH
+
+#include <dune/grid/common/gridinfo.hh>
+#include <dune/grid/multidomaingrid.hh>
+#include <dune/grid/io/file/dgfparser.hh>
+
+#include <dumux/multidomain/common/multidomainproblem.hh>
+#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2cnewtoncontroller.hh>
+#include <dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh>
+//#include <dumux/linear/amgbackend.hh>
+#include <dumux/linear/seqsolverbackend.hh>
+#include <dumux/linear/pardisobackend.hh>
+
+#include "2cnistokes2p2cnispatialparams.hh"
+#include <dumux/material/fluidsystems/h2oairfluidsystem.hh>
+
+#include "stokes2cnisubproblem.hh"
+#include "2p2cnisubproblem.hh"
+
+namespace Dumux
+{
+template <class TypeTag>
+class TwoCNIStokesTwoPTwoCNIProblem;
+
+namespace Properties
+{
+NEW_TYPE_TAG(TwoCNIStokesTwoPTwoCNIProblem, INHERITS_FROM(MultiDomain));
+
+// Set the grid type
+SET_PROP(TwoCNIStokesTwoPTwoCNIProblem, Grid)
+{
+ public:
+#ifdef HAVE_UG
+    typedef typename Dune::UGGrid<2> type;
+#elif HAVE_ALUGRID
+    typedef typename Dune::ALUGrid<2, 2, Dune::cube, Dune::nonconforming> type;
+#endif
+};
+
+// Specify the multidomain gridview
+SET_PROP(TwoCNIStokesTwoPTwoCNIProblem, GridView)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
+ public:
+    typedef typename MDGrid::LeafGridView type;
+};
+
+// Set the global problem
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, Problem, TwoCNIStokesTwoPTwoCNIProblem<TypeTag>);
+
+// Set the two sub-problems of the global problem
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, SubDomain1TypeTag, TTAG(Stokes2cniSubProblem));
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, SubDomain2TypeTag, TTAG(TwoPTwoCNISubProblem));
+
+// Set the global problem in the context of the two sub-problems
+SET_TYPE_PROP(Stokes2cniSubProblem, MultiDomainTypeTag, TTAG(TwoCNIStokesTwoPTwoCNIProblem));
+SET_TYPE_PROP(TwoPTwoCNISubProblem, MultiDomainTypeTag, TTAG(TwoCNIStokesTwoPTwoCNIProblem));
+
+// Set the other sub-problem for each of the two sub-problems
+SET_TYPE_PROP(Stokes2cniSubProblem, OtherSubDomainTypeTag, TTAG(TwoPTwoCNISubProblem));
+SET_TYPE_PROP(TwoPTwoCNISubProblem, OtherSubDomainTypeTag, TTAG(Stokes2cniSubProblem));
+
+// Set the same spatial parameters for both sub-problems
+SET_PROP(Stokes2cniSubProblem, SpatialParams)
+{ typedef Dumux::TwoCNIStokesTwoPTwoCNISpatialParams<TypeTag> type; };
+SET_PROP(TwoPTwoCNISubProblem, SpatialParams)
+{ typedef Dumux::TwoCNIStokesTwoPTwoCNISpatialParams<TypeTag> type; };
+
+// Set the fluid system
+SET_PROP(TwoCNIStokesTwoPTwoCNIProblem, FluidSystem)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dumux::FluidSystems::H2OAir<Scalar,
+        Dumux::H2O<Scalar>,
+        /*useComplexrelations=*/true> type;
+};
+
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, JacobianAssembler, Dumux::MultiDomainAssembler<TypeTag>);
+
+// Set the local coupling operator
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, MultiDomainCouplingLocalOperator, 
+				Dumux::TwoCNIStokesTwoPTwoCNILocalOperator<TypeTag>);
+
+SET_PROP(TwoCNIStokesTwoPTwoCNIProblem, SolutionVector)
+{
+ private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridOperator) MDGridOperator;
+ public:
+    typedef typename MDGridOperator::Traits::Domain type;
+};
+
+// the newton controller from the TwoCStokesTwoPTwoC model is used
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, NewtonController, TwoCStokesTwoPTwoCNewtonController<TypeTag>);
+
+//SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, LinearSolver, SSORRestartedGMResBackend<TypeTag>);
+// if you do not have PARDISO, the SuperLU solver is used:
+#ifdef HAVE_PARDISO
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, LinearSolver, PardisoBackend<TypeTag>);
+#else
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNIProblem, LinearSolver, SuperLUBackend<TypeTag>);
+#endif // HAVE_PARDISO
+
+
+// set this to one here (must fit to the structure of the coupled matrix which has block length 1)
+SET_INT_PROP(TwoCNIStokesTwoPTwoCNIProblem, NumEq, 1);
+
+// Write the solutions of individual newton iterations?
+SET_BOOL_PROP(TwoCNIStokesTwoPTwoCNIProblem, NewtonWriteConvergence, false);
+}
+
+/*!
+ * \brief The problem class for the coupling of a non-isothermal two-component Stokes (stokes2cni)
+ *        and a non-isothermal two-phase two-component Darcy model (2p2cni).
+ *
+ *        The problem class for the coupling of a non-isothermal two-component Stokes (stokes2cni)
+ *        and a non-isothermal two-phase two-component Darcy model (2p2cni).
+ *        It uses the 2p2cniCoupling model and the Stokes2cnicoupling model and provides
+ *        the problem specifications for common parameters of the two submodels.
+ *        The initial and boundary conditions of the submodels are specified in the two subproblems,
+ *        2p2cnisubproblem.hh and stokes2cnisubproblem.hh, which are accessible via the coupled problem.
+ */
+template <class TypeTag = TTAG(TwoCNIStokesTwoPTwoCNIProblem) >
+class TwoCNIStokesTwoPTwoCNIProblem : public MultiDomainProblem<TypeTag>
+{
+    template<int dim>
+    struct VertexLayout
+    {
+        bool contains(Dune::GeometryType geomtype)
+        { return geomtype.dim() == 0; }
+    };
+
+    typedef TwoCNIStokesTwoPTwoCNIProblem<TypeTag> ThisType;
+    typedef MultiDomainProblem<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) Stokes2cniTypeTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TwoPTwoCNITypeTag;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, Problem) Stokes2cniSubProblem;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, Problem) TwoPTwoCNISubProblem;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, GridView) Stokes2cniGridView;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, GridView) TwoPTwoCNIGridView;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, PrimaryVariables) Stokes2cniPrimaryVariables;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, PrimaryVariables) TwoPTwoCNIPrimaryVariables;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, ElementSolutionVector) ElementSolutionVector1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, ElementSolutionVector) ElementSolutionVector2;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, ElementVolumeVariables) ElementVolumeVariables1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, ElementVolumeVariables) ElementVolumeVariables2;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, FluxVariables) BoundaryVariables1;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, FVElementGeometry) FVElementGeometry1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, FVElementGeometry) FVElementGeometry2;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Grid) HostGrid;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
+    typedef typename MDGrid::LeafGridView MDGridView;
+    typedef typename MDGrid::SubDomainGrid SDGrid;
+
+    typedef typename MDGrid::Traits::template Codim<0>::Entity MDElement;
+    typedef typename MDGrid::Traits::template Codim<0>::EntityPointer MDElementPointer;
+    typedef typename Stokes2cniGridView::template Codim<0>::Entity SDElement1;
+    typedef typename TwoPTwoCNIGridView::template Codim<0>::Entity SDElement2;
+    typedef typename SDGrid::Traits::template Codim<0>::EntityPointer SDElementPointer;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, Indices) Stokes2cniIndices;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, Indices) TwoPTwoCNIIndices;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+    enum { dim = Stokes2cniGridView::dimension };
+    enum { // indices in the Stokes domain
+        momentumXIdx1 = Stokes2cniIndices::momentumXIdx, //!< Index of the x-component of the momentum balance
+        momentumYIdx1 = Stokes2cniIndices::momentumYIdx, //!< Index of the y-component of the momentum balance
+        momentumZIdx1 = Stokes2cniIndices::momentumZIdx, //!< Index of the z-component of the momentum balance
+        massBalanceIdx1 = Stokes2cniIndices::massBalanceIdx, //!< Index of the mass balance
+        transportEqIdx1 = Stokes2cniIndices::transportEqIdx, //!< Index of the transport equation
+        energyEqIdx1 = Stokes2cniIndices::energyEqIdx //!< Index of the transport equation
+    };
+    enum { // indices of the PVs in the Darcy domain
+        massBalanceIdx2 = TwoPTwoCNIIndices::pressureIdx,
+        switchIdx2 = TwoPTwoCNIIndices::switchIdx,
+        temperatureIdx2 = TwoPTwoCNIIndices::temperatureIdx
+    };
+    enum { // indices of the balance equations
+        contiTotalMassIdx2 = TwoPTwoCNIIndices::contiNEqIdx,
+        contiWEqIdx2 = TwoPTwoCNIIndices::contiWEqIdx,
+        energyEqIdx2 = TwoPTwoCNIIndices::energyEqIdx
+    };
+    enum { transportCompIdx1 = Stokes2cniIndices::transportCompIdx };
+    enum {
+        wCompIdx2 = TwoPTwoCNIIndices::wCompIdx,
+        nCompIdx2 = TwoPTwoCNIIndices::nCompIdx
+    };
+    enum { phaseIdx = GET_PROP_VALUE(Stokes2cniTypeTag, PhaseIdx) };
+    enum {
+        numEq1 = GET_PROP_VALUE(Stokes2cniTypeTag, NumEq),
+        numEq2 = GET_PROP_VALUE(TwoPTwoCNITypeTag, NumEq)
+    };
+
+    typedef Dune::FieldVector<Scalar, dim> GlobalPosition;
+    typedef Dune::FieldVector<Scalar, dim> FieldVector;
+
+    typedef typename MDGrid::template Codim<0>::LeafIterator ElementIterator;
+    typedef typename MDGrid::LeafSubDomainInterfaceIterator SDInterfaceIterator;
+
+    /*!
+     * \brief docme
+     *
+     * \param hostGrid docme
+     * \param timeManager The TimeManager which is used by the simulation
+     *
+     */
+public:
+    TwoCNIStokesTwoPTwoCNIProblem(MDGrid &mdGrid,
+    							  TimeManager &timeManager)
+        : ParentType(mdGrid, timeManager)
+    {
+        try
+        {
+            // define location of the interface
+            interface_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, InterfacePos);
+            noDarcyX_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Problem, NoDarcyX);
+            episodeLength_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, EpisodeLength);
+            initializationTime_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, InitTime);
+            dtInit_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, DtInitial);
+
+            // define output options
+            freqRestart_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, Output, FreqRestart);
+            freqOutput_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, Output, FreqOutput);
+            freqFluxOutput_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, Output, FreqFluxOutput);
+            freqVaporFluxOutput_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, Output, FreqVaporFluxOutput);
+        }
+        catch (Dumux::ParameterException &e) {
+            std::cerr << e << ". Abort!\n";
+            exit(1) ;
+        }
+        catch (...) {
+            std::cerr << "Unknown exception thrown!\n";
+            exit(1);
+        }
+
+        stokes2cni_ = this->sdID1();
+        twoPtwoCNI_ = this->sdID2();
+
+        initializeGrid();
+
+        // initialize the tables of the fluid system
+        FluidSystem::init(/*tempMin=*/273.15, /*tempMax=*/373.15, /*numTemp=*/200,
+                          /*pMin=*/1e3, /*pMax=*/2e5, /*numP=*/200);
+
+        if (initializationTime_ > 0.0)
+            this->timeManager().startNextEpisode(initializationTime_);
+        else
+            this->timeManager().startNextEpisode(episodeLength_);
+    }
+
+    ~TwoCNIStokesTwoPTwoCNIProblem()
+    {
+        fluxFile_.close();
+    };
+
+    //! \copydoc Dumux::CoupledProblem::init()
+    void init()
+    {
+        ParentType::init();
+
+        // plot the Pc-Sw curves, if requested
+        this->sdProblem2().spatialParams().plotMaterialLaw();
+
+        std::cout << "Writing flux data at interface\n";
+        if (this->timeManager().time() == 0)
+        {
+            fluxFile_.open("fluxes.out");
+            fluxFile_ << "time; flux1; advFlux1; diffFlux1; totalFlux1; energyFlux1; "
+            		"flux2; wPhaseFlux2; nPhaseFlux2; energyFlux2\n";
+            counter_ = 1;
+        }
+        else
+            fluxFile_.open("fluxes.out", std::ios_base::app);
+    }
+
+    /*!
+     * \brief docme
+     */
+    void initializeGrid()
+    {
+        MDGrid& mdGrid = this->mdGrid();
+        mdGrid.startSubDomainMarking();
+
+        // subdivide grid in two subdomains
+        ElementIterator eendit = mdGrid.template leafend<0>();
+        for (ElementIterator elementIt = mdGrid.template leafbegin<0>();
+             elementIt != eendit; ++elementIt)
+        {
+            // this is required for parallelization
+            // checks if element is within a partition
+            if (elementIt->partitionType() != Dune::InteriorEntity)
+                continue;
+
+            GlobalPosition globalPos = elementIt->geometry().center();
+
+            if (globalPos[1] > interface_)
+                mdGrid.addToSubDomain(stokes2cni_,*elementIt);
+            else
+                if(globalPos[0] > noDarcyX_)
+                    mdGrid.addToSubDomain(twoPtwoCNI_,*elementIt);
+        }
+        mdGrid.preUpdateSubDomains();
+        mdGrid.updateSubDomains();
+        mdGrid.postUpdateSubDomains();
+
+        gridinfo(this->sdGrid1());
+        gridinfo(this->sdGrid2());
+    }
+
+    //! \copydoc Dumux::CoupledProblem::postTimeStep()
+    void postTimeStep()
+    {
+        // call the postTimeStep function of the subproblems
+        this->sdProblem1().postTimeStep();
+        this->sdProblem2().postTimeStep();
+
+        if (shouldWriteFluxFile() || shouldWriteVaporFlux())
+        {
+            counter_ = this->sdProblem1().currentVTKFileNumber() + 1;
+
+            calculateFirstInterfaceFluxes();
+            calculateSecondInterfaceFluxes();
+        }
+    }
+
+    //! \copydoc Dumux::CoupledProblem::episodeEnd()
+    void episodeEnd()
+    {
+        this->timeManager().startNextEpisode(episodeLength_);
+        if (this->timeManager().time() <= initializationTime_ + dtInit_)
+		{
+        	std::cout << "setting timeStepSize to " << dtInit_ << std::endl;
+			this->timeManager().setTimeStepSize(dtInit_);
+		}
+    }
+
+    /*
+     * \brief Calculates fluxes and coupling terms at the interface for the Stokes model.
+     *        Flux output files are created and the summarized flux is written to a file.
+     */
+    void calculateFirstInterfaceFluxes()
+    {
+        const MDGrid& mdGrid = this->mdGrid();
+        ElementVolumeVariables1 elemVolVarsPrev1, elemVolVarsCur1;
+        Scalar sumVaporFluxes = 0.;
+        Scalar advectiveVaporFlux = 0.;
+        Scalar diffusiveVaporFlux = 0.;
+        Scalar sumEnergyFluxes = 0.;
+
+        // count number of elements to determine number of interface nodes
+        int numElements = 0;
+        const SDInterfaceIterator endIfIt = mdGrid.leafSubDomainInterfaceEnd(stokes2cni_, twoPtwoCNI_);
+        for (SDInterfaceIterator ifIt =
+                 mdGrid.leafSubDomainInterfaceBegin(stokes2cni_, twoPtwoCNI_); ifIt != endIfIt; ++ifIt)
+            numElements++;
+
+        const int numInterfaceVertices = numElements + 1;
+        std::vector<InterfaceFluxes<numEq1> > outputVector(numInterfaceVertices); // vector for the output of the fluxes
+        FVElementGeometry1 fvGeometry1;
+        int interfaceVertIdx = -1;
+
+        // loop over the element faces on the interface
+        for (SDInterfaceIterator ifIt =
+                 mdGrid.leafSubDomainInterfaceBegin(stokes2cni_, twoPtwoCNI_); ifIt != endIfIt; ++ifIt)
+        {
+            const int firstFaceIdx = ifIt->indexInFirstCell();
+            const MDElementPointer mdElementPointer1 = ifIt->firstCell(); // ATTENTION!!!
+            const MDElement& mdElement1 = *mdElementPointer1;     // Entity pointer has to be copied before.
+            const SDElementPointer sdElementPointer1 = this->sdElementPointer1(mdElement1);
+            const SDElement1& sdElement1 = *sdElementPointer1;
+            fvGeometry1.update(this->sdGridView1(), sdElement1);
+
+            const Dune::GenericReferenceElement<typename MDGrid::ctype,dim>& referenceElement1 =
+                Dune::GenericReferenceElements<typename MDGrid::ctype,dim>::general(mdElement1.type());
+            const int numVerticesOfFace = referenceElement1.size(firstFaceIdx, 1, dim);
+
+            // evaluate residual of the sub model without boundary conditions (stabilization is removed)
+            // the element volume variables are updated here
+            this->localResidual1().evalNoBoundary(sdElement1, fvGeometry1,
+                                                  elemVolVarsPrev1, elemVolVarsCur1);
+
+            for (int nodeInFace = 0; nodeInFace < numVerticesOfFace; nodeInFace++)
+            {
+                const int vertInElem1 = referenceElement1.subEntity(firstFaceIdx, 1, nodeInFace, dim);
+                const FieldVector& vertexGlobal = mdElement1.geometry().corner(vertInElem1);
+                const unsigned firstGlobalIdx = this->mdVertexMapper().map(stokes2cni_, mdElement1, vertInElem1, dim);
+                const ElementSolutionVector1& firstVertexDefect = this->localResidual1().residual();
+
+                // loop over all interface vertices to check if vertex id is already in stack
+                bool existing = false;
+                for (int interfaceVertex=0; interfaceVertex < numInterfaceVertices; ++interfaceVertex)
+                {
+                    if (firstGlobalIdx == outputVector[interfaceVertex].globalIdx)
+                    {
+                        existing = true;
+                        interfaceVertIdx = interfaceVertex;
+                        break;
+                    }
+                }
+
+                if (!existing)
+                    interfaceVertIdx++;
+
+                if (shouldWriteFluxFile()) // compute only if required
+                {
+                    outputVector[interfaceVertIdx].interfaceVertex = interfaceVertIdx;
+                    outputVector[interfaceVertIdx].globalIdx = firstGlobalIdx;
+                    outputVector[interfaceVertIdx].xCoord = vertexGlobal[0];
+                    outputVector[interfaceVertIdx].yCoord = vertexGlobal[1];
+                    outputVector[interfaceVertIdx].count += 1;
+                    for (int eqIdx=0; eqIdx < numEq1; ++eqIdx)
+                        outputVector[interfaceVertIdx].defect[eqIdx] +=
+                            firstVertexDefect[vertInElem1][eqIdx];
+                }
+
+                // compute summarized fluxes for output
+                if (shouldWriteVaporFlux())
+                {
+                    int boundaryFaceIdx =
+                        fvGeometry1.boundaryFaceIndex(firstFaceIdx, nodeInFace);
+
+                    const BoundaryVariables1 boundaryVars1(this->sdProblem1(),
+                                                           sdElement1,
+                                                           fvGeometry1,
+                                                           boundaryFaceIdx,
+                                                           elemVolVarsCur1,
+                                                           /*onBoundary=*/true);
+
+                    advectiveVaporFlux += computeAdvectiveVaporFluxes1(elemVolVarsCur1, boundaryVars1, vertInElem1);
+                    diffusiveVaporFlux += computeDiffusiveVaporFluxes1(elemVolVarsCur1, boundaryVars1, vertInElem1);
+                    sumVaporFluxes += firstVertexDefect[vertInElem1][transportEqIdx1];
+                    sumEnergyFluxes += firstVertexDefect[vertInElem1][energyEqIdx1];
+                }
+            }
+        } // end loop over element faces on interface
+
+        if (shouldWriteFluxFile())
+        {
+            std::cout << "Writing flux file\n";
+            char outputname[20];
+            sprintf(outputname, "%s%05d%s","fluxes1_", counter_,".out");
+            std::ofstream outfile(outputname, std::ios_base::out);
+            outfile << "Xcoord1 "
+                    << "totalFlux1 "
+                    << "componentFlux1 "
+                    << "heatFlux1 "
+                    << std::endl;
+            for (int interfaceVertIdx=0; interfaceVertIdx < numInterfaceVertices; interfaceVertIdx++)
+            {
+                if (outputVector[interfaceVertIdx].count > 2)
+                    std::cerr << "too often at one node!!";
+
+                if (outputVector[interfaceVertIdx].count==2)
+                    outfile << outputVector[interfaceVertIdx].xCoord << " "
+                            << outputVector[interfaceVertIdx].defect[massBalanceIdx1] << " " // total mass flux
+                            << outputVector[interfaceVertIdx].defect[transportEqIdx1] << " " // total flux of component
+                            << outputVector[interfaceVertIdx].defect[energyEqIdx1] << " " // total flux of heat
+                            << std::endl;
+            }
+            outfile.close();
+        }
+        if (shouldWriteVaporFlux())
+            fluxFile_ << this->timeManager().time() + this->timeManager().timeStepSize() << "; "
+                      << sumVaporFluxes << "; "
+                      << advectiveVaporFlux << "; "
+                      << diffusiveVaporFlux << "; "
+                      << advectiveVaporFlux-diffusiveVaporFlux << "; "
+                      << sumEnergyFluxes << "; ";
+    }
+
+    /*
+     * \brief Calculates fluxes and coupling terms at the interface for the Darcy model.
+     *        Flux output files are created and the summarized flux is written to a file.
+     */
+    void calculateSecondInterfaceFluxes()
+    {
+        const MDGrid& mdGrid = this->mdGrid();
+        ElementVolumeVariables2 elemVolVarsPrev2, elemVolVarsCur2;
+
+        Scalar sumVaporFluxes = 0.;
+        Scalar sumEnergyFluxes = 0.;
+        Scalar sumWaterFluxInGasPhase = 0.;
+
+        // count number of elements to determine number of interface nodes
+        int numElements = 0;
+        const SDInterfaceIterator endIfIt = mdGrid.leafSubDomainInterfaceEnd(stokes2cni_, twoPtwoCNI_);
+        for (SDInterfaceIterator ifIt =
+                 mdGrid.leafSubDomainInterfaceBegin(stokes2cni_, twoPtwoCNI_); ifIt != endIfIt; ++ifIt)
+            numElements++;
+
+        const int numInterfaceVertices = numElements + 1;
+        std::vector<InterfaceFluxes<numEq2> > outputVector(numInterfaceVertices); // vector for the output of the fluxes
+        FVElementGeometry2 fvGeometry2;
+        int interfaceVertIdx = -1;
+
+        // loop over the element faces on the interface
+        for (SDInterfaceIterator ifIt =
+                 mdGrid.leafSubDomainInterfaceBegin(stokes2cni_, twoPtwoCNI_); ifIt != endIfIt; ++ifIt)
+        {
+            const int secondFaceIdx = ifIt->indexInSecondCell();
+            const MDElementPointer mdElementPointer2 = ifIt->secondCell(); // ATTENTION!!!
+            const MDElement& mdElement2 = *mdElementPointer2;     // Entity pointer has to be copied before.
+            const SDElementPointer sdElementPointer2 = this->sdElementPointer2(mdElement2);
+            const SDElement2& sdElement2 = *sdElementPointer2;
+            fvGeometry2.update(this->sdGridView2(), sdElement2);
+
+            const Dune::GenericReferenceElement<typename MDGrid::ctype,dim>& referenceElement2 =
+                Dune::GenericReferenceElements<typename MDGrid::ctype,dim>::general(mdElement2.type());
+            const int numVerticesOfFace = referenceElement2.size(secondFaceIdx, 1, dim);
+
+            // evaluate residual of the sub model without boundary conditions
+            this->localResidual2().evalNoBoundary(sdElement2, fvGeometry2,
+                                                  elemVolVarsPrev2, elemVolVarsCur2);
+            // evaluate the vapor fluxes within each phase
+            this->localResidual2().evalPhaseFluxes();
+
+            for (int nodeInFace = 0; nodeInFace < numVerticesOfFace; nodeInFace++)
+            {
+                const int vertInElem2 = referenceElement2.subEntity(secondFaceIdx, 1, nodeInFace, dim);
+                const FieldVector& vertexGlobal = mdElement2.geometry().corner(vertInElem2);
+                const unsigned secondGlobalIdx = this->mdVertexMapper().map(twoPtwoCNI_, mdElement2, vertInElem2, dim);
+                const ElementSolutionVector2& secondVertexDefect = this->localResidual2().residual();
+
+                bool existing = false;
+                // loop over all interface vertices to check if vertex id is already in stack
+                for (int interfaceVertex=0; interfaceVertex < numInterfaceVertices; ++interfaceVertex)
+                {
+                    if (secondGlobalIdx == outputVector[interfaceVertex].globalIdx)
+                    {
+                        existing = true;
+                        interfaceVertIdx = interfaceVertex;
+                        break;
+                    }
+                }
+
+                if (!existing)
+                    interfaceVertIdx++;
+
+                if (shouldWriteFluxFile())
+                {
+                    outputVector[interfaceVertIdx].interfaceVertex = interfaceVertIdx;
+                    outputVector[interfaceVertIdx].globalIdx = secondGlobalIdx;
+                    outputVector[interfaceVertIdx].xCoord = vertexGlobal[0];
+                    outputVector[interfaceVertIdx].yCoord = vertexGlobal[1];
+                    for (int eqIdx=0; eqIdx < numEq2; ++eqIdx)
+                        outputVector[interfaceVertIdx].defect[eqIdx] += secondVertexDefect[vertInElem2][eqIdx];
+                    outputVector[interfaceVertIdx].count += 1;
+                }
+                if (shouldWriteVaporFlux())
+                {
+                    if (!existing) // add phase storage only once per vertex
+                        sumWaterFluxInGasPhase +=
+                            this->localResidual2().evalPhaseStorage(vertInElem2);
+
+                    sumVaporFluxes += secondVertexDefect[vertInElem2][contiWEqIdx2];
+                    sumWaterFluxInGasPhase +=
+                        this->localResidual2().elementFluxes(vertInElem2);
+                    sumEnergyFluxes += secondVertexDefect[vertInElem2][energyEqIdx2];
+
+                }
+            }
+        }
+
+        if (shouldWriteFluxFile())
+        {
+            char outputname[20];
+            sprintf(outputname, "%s%05d%s","fluxes2_", counter_,".out");
+            std::ofstream outfile(outputname, std::ios_base::out);
+            outfile << "Xcoord2 "
+                    << "totalFlux2 "
+                    << "componentFlux2 "
+                    << "heatFlux2 "
+                    << std::endl;
+
+            for (int interfaceVertIdx=0; interfaceVertIdx < numInterfaceVertices; interfaceVertIdx++)
+            {
+                if (outputVector[interfaceVertIdx].count > 2)
+                    std::cerr << "too often at one node!!";
+
+                if (outputVector[interfaceVertIdx].count==2)
+                    outfile << outputVector[interfaceVertIdx].xCoord << " "
+                            << outputVector[interfaceVertIdx].defect[contiTotalMassIdx2] << " " // total mass flux
+                            << outputVector[interfaceVertIdx].defect[contiWEqIdx2] << " " // total flux of component
+                            << outputVector[interfaceVertIdx].defect[energyEqIdx2] << " " // total heat flux
+                            << std::endl;
+            }
+            outfile.close();
+        }
+        if (shouldWriteVaporFlux()){
+            Scalar sumWaterFluxInLiquidPhase = sumVaporFluxes - sumWaterFluxInGasPhase;
+            fluxFile_ << sumVaporFluxes << "; "
+                      << sumWaterFluxInLiquidPhase << "; "
+                      << sumWaterFluxInGasPhase << "; "
+                      << sumEnergyFluxes
+                      << std::endl;
+        }
+    }
+
+    Scalar computeAdvectiveVaporFluxes1(const ElementVolumeVariables1& elemVolVars1,
+                                        const BoundaryVariables1& boundaryVars1,
+                                        int vertInElem1)
+    {
+        Scalar advFlux = elemVolVars1[vertInElem1].density() *
+            elemVolVars1[vertInElem1].fluidState().massFraction(phaseIdx, transportCompIdx1) *
+            boundaryVars1.normalVelocity();
+        return advFlux;
+    }
+
+    Scalar computeDiffusiveVaporFluxes1(const ElementVolumeVariables1& elemVolVars1,
+                                        const BoundaryVariables1& boundaryVars1,
+                                        int vertInElem1)
+    {
+        Scalar diffFlux = boundaryVars1.moleFractionGrad(transportCompIdx1) *
+            boundaryVars1.face().normal *
+            boundaryVars1.diffusionCoeff(transportCompIdx1) *
+            boundaryVars1.molarDensity() *
+            FluidSystem::molarMass(transportCompIdx1);
+        return diffFlux;
+    }
+
+    //! \copydoc Dumux::CoupledProblem::shouldWriteRestartFile()
+    bool shouldWriteRestartFile() const
+    {
+        if ((this->timeManager().timeStepIndex() > 0 &&
+             (this->timeManager().timeStepIndex() % freqRestart_ == 0))
+            // also write a restart file at the end of each episode
+            || this->timeManager().episodeWillBeOver())
+            return true;
+        return false;
+    }
+
+
+    //! \copydoc Dumux::CoupledProblem::shouldWriteOutput()
+    bool shouldWriteOutput() const
+    {
+        if (this->timeManager().timeStepIndex() % freqOutput_ == 0
+            || this->timeManager().episodeWillBeOver())
+            return true;
+        return false;
+    }
+
+    /*!
+     * \brief Returns true if a file with the fluxes across the
+     * free-flow -- porous-medium interface should be written.
+     */
+    bool shouldWriteFluxFile() const
+    {
+        if (this->timeManager().timeStepIndex() % freqFluxOutput_ == 0
+            || this->timeManager().episodeWillBeOver())
+            return true;
+        return false;
+    }
+
+    /*!
+     * \brief Returns true if the summarized vapor fluxes
+     *        across the free-flow -- porous-medium interface,
+     *        representing the evaporation rate (related to the
+     *        interface area), should be written.
+     */
+    bool shouldWriteVaporFlux() const
+    {
+        if (this->timeManager().timeStepIndex() % freqVaporFluxOutput_ == 0
+            || this->timeManager().episodeWillBeOver())
+            return true;
+        return false;
+
+    }
+
+    Stokes2cniSubProblem& stokes2cniProblem()
+    { return this->sdProblem1(); }
+    const Stokes2cniSubProblem& stokes2cniProblem() const
+    { return this->sdProblem1(); }
+
+    TwoPTwoCNISubProblem& twoPtwoCNIProblem()
+    { return this->sdProblem2(); }
+    const TwoPTwoCNISubProblem& twoPtwoCNIProblem() const
+    { return this->sdProblem2(); }
+
+private:
+    typename MDGrid::SubDomainType stokes2cni_;
+    typename MDGrid::SubDomainType twoPtwoCNI_;
+
+    unsigned counter_;
+    unsigned freqRestart_;
+    unsigned freqOutput_;
+    unsigned freqFluxOutput_;
+    unsigned freqVaporFluxOutput_;
+
+    Scalar interface_;
+    Scalar noDarcyX_;
+    Scalar episodeLength_;
+    Scalar initializationTime_;
+    Scalar dtInit_;
+
+    template <int numEq>
+    struct InterfaceFluxes
+    {
+        unsigned count;
+        unsigned interfaceVertex;
+        unsigned globalIdx;
+        Scalar xCoord;
+        Scalar yCoord;
+        Dune::FieldVector<Scalar, numEq> defect;
+
+        InterfaceFluxes()
+        {
+            count = 0;
+            interfaceVertex = 0;
+            globalIdx = 0;
+            xCoord = 0.0;
+            yCoord = 0.0;
+            defect = 0.0;
+        }
+    };
+    std::ofstream fluxFile_;
+};
+
+} //end namespace
+
+#endif
diff --git a/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cnispatialparams.hh b/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cnispatialparams.hh
new file mode 100644
index 0000000000..3c1973350b
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cnispatialparams.hh
@@ -0,0 +1,371 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+#ifndef DUMUX_TWOCNISTOKES2P2CNISPATIALPARAMS_HH
+#define DUMUX_TWOCNISTOKES2P2CNISPATIALPARAMS_HH
+
+#include <dune/grid/io/file/vtk/common.hh>
+
+#include <dumux/material/spatialparams/implicitspatialparams.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/regularizedvangenuchten.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/regularizedbrookscorey.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/efftoabslaw.hh>
+//#include <dumux/io/plotfluidmatrixlaw.hh>
+
+namespace Dumux
+{
+
+//forward declaration
+template<class TypeTag>
+class TwoCNIStokesTwoPTwoCNISpatialParams;
+
+namespace Properties
+{
+// The spatial parameters TypeTag
+NEW_TYPE_TAG(TwoCNIStokesTwoPTwoCNISpatialParams);
+
+// Set the spatial parameters
+SET_TYPE_PROP(TwoCNIStokesTwoPTwoCNISpatialParams, SpatialParams,
+        TwoCNIStokesTwoPTwoCNISpatialParams<TypeTag>);
+
+// Set the material Law
+SET_PROP(TwoCNIStokesTwoPTwoCNISpatialParams, MaterialLaw)
+{
+private:
+    // define the material law which is parameterized by effective
+    // saturations
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef RegularizedVanGenuchten<Scalar> EffMaterialLaw;
+public:
+    // define the material law parameterized by absolute saturations
+    typedef EffToAbsLaw<EffMaterialLaw> type;
+};
+}
+
+
+/*!
+ * \brief docme
+ */
+template<class TypeTag>
+class TwoCNIStokesTwoPTwoCNISpatialParams : public ImplicitSpatialParams<TypeTag>
+{
+    typedef ImplicitSpatialParams<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GridView::ctype CoordScalar;
+
+    enum {
+        dim=GridView::dimension,
+        dimWorld=GridView::dimensionworld
+    };
+
+    typedef Dune::FieldVector<CoordScalar,dim> LocalPosition;
+    typedef Dune::FieldVector<CoordScalar,dimWorld> GlobalPosition;
+    typedef Dune::FieldVector<CoordScalar,dimWorld> DimVector;
+
+    typedef typename GridView::IndexSet IndexSet;
+    typedef typename GridView::template Codim<0>::Iterator ElementIterator;
+    typedef typename GridView::template Codim<0>::Entity Element;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, FluxVariables) FluxVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+
+    typedef std::vector<Scalar> PermeabilityType;
+    typedef typename GET_PROP(TypeTag, ParameterTree) ParameterTree;
+    typedef typename GridView::template Codim<dim>::Iterator VertexIterator;
+
+public:
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename MaterialLaw::Params MaterialLawParams;
+    typedef std::vector<MaterialLawParams> MaterialLawParamsVector;
+
+    /*!
+     * \brief docme
+     *
+     * \param gridView The GridView which is used by the problem.
+     *
+     */
+    TwoCNIStokesTwoPTwoCNISpatialParams(const GridView& gridView)
+        : ParentType(gridView),
+          permeability_(gridView.size(dim), 0.0),
+          vanGenuchtenAlpha_(gridView.size(dim), 0.0),
+          indexSet_(gridView.indexSet())
+    {
+        try
+        {
+            soilType_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, SpatialParams, SoilType);
+            xMaterialInterface_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, MaterialInterfaceX);
+
+            // porosities
+            coarsePorosity_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, Porosity1);
+            mediumPorosity_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Porosity2);
+            finePorosity_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, Porosity3);
+
+            // intrinsic permeabilities
+            coarsePermeability_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, Permeability1);
+            mediumPermeability_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Permeability2);
+            finePermeability_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, Permeability3);
+
+            // thermal conductivity of the solid material
+            coarseLambdaSolid_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, LambdaSolid1);
+            mediumLambdaSolid_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, LambdaSolid2);
+            fineLambdaSolid_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, LambdaSolid3);
+
+            if (soilType_ != 0)
+            {
+                // residual saturations
+                coarseParams_.setSwr(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, Swr1));
+                coarseParams_.setSnr(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, Snr1));
+                mediumParams_.setSwr(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Swr2));
+                mediumParams_.setSnr(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Snr2));
+                fineParams_.setSwr(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, Swr3));
+                fineParams_.setSnr(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, Snr3));
+
+                // parameters for the vanGenuchten law
+                coarseParams_.setVgAlpha(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, VgAlpha1));
+                coarseParams_.setVgn(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, VgN1));
+                mediumParams_.setVgAlpha(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, VgAlpha2));
+                mediumParams_.setVgn(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, VgN2));
+                fineParams_.setVgAlpha(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, VgAlpha3));
+                fineParams_.setVgn(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, VgN3));
+            }
+        }
+        catch (Dumux::ParameterException &e) {
+            std::cerr << e << ". Abort!\n";
+            exit(1) ;
+        }
+        catch (...) {
+            std::cerr << "Unknown exception thrown!\n";
+            exit(1);
+        }
+    }
+
+    ~TwoCNIStokesTwoPTwoCNISpatialParams()
+    { }
+
+    /*!
+     * \brief Apply the intrinsic permeability tensor to a pressure
+     *        potential gradient.
+     *
+     * \param element       The current finite element
+     * \param fvGeometry    The current finite volume geometry of the element
+     * \param scvIdx       The index sub-control volume face where the
+     *                      intrinsic velocity ought to be calculated.
+     */
+    const Scalar intrinsicPermeability(const Element &element,
+                                 	   const FVElementGeometry &fvGeometry,
+                                 	   const int scvIdx) const
+    {
+		const GlobalPosition &globalPos = element.geometry().corner(scvIdx);
+
+		if (checkSoilType(globalPos) == 1)
+			return coarsePermeability_;
+		if (checkSoilType(globalPos) == 2)
+			return mediumPermeability_;
+		if (checkSoilType(globalPos) == 3)
+			return finePermeability_;
+		if (checkSoilType(globalPos) == 4)
+			return finePermeability_;
+		else
+			return mediumPermeability_;
+    }
+
+    //! \copydoc Dumux::ImplicitSpatialParamsOneP::porosity()
+    Scalar porosity(const Element &element,
+                    const FVElementGeometry &fvGeometry,
+                    const int scvIdx) const
+    {
+        const GlobalPosition &globalPos = element.geometry().corner(scvIdx);
+
+        if (checkSoilType(globalPos) == 1)
+            return coarsePorosity_;
+        if (checkSoilType(globalPos) == 2)
+            return mediumPorosity_;
+        if (checkSoilType(globalPos) == 3)
+            return finePorosity_;
+        else
+            return mediumPorosity_;
+    }
+
+
+    //! \copydoc Dumux::ImplicitSpatialParams::materialLawParams()
+    const MaterialLawParams& materialLawParams(const Element &element,
+                                               const FVElementGeometry &fvGeometry,
+                                               const int scvIdx) const
+    {
+		const GlobalPosition &globalPos = element.geometry().corner(scvIdx);
+		if (checkSoilType(globalPos)==1)
+			return coarseParams_;
+		if (checkSoilType(globalPos)==2)
+			return mediumParams_;
+		if (checkSoilType(globalPos)==3)
+			return fineParams_;
+//            if (checkSoilType(globalPos)==4)
+//                return leverettJParams_;
+		else
+			return mediumParams_;
+    }
+
+
+    /*!
+     * \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 fvGeometry The finite volume geometry
+     * \param scvIdx The local index of the sub-control volume where
+     *                    the heat capacity needs to be defined
+     */
+    Scalar heatCapacity(const Element &element,
+                        const FVElementGeometry &fvGeometry,
+                        const int scvIdx) const
+    {
+        return
+            // 830 for sand
+            790 // specific heat capacity of granite [J / (kg K)]
+            * 2700 // density of granite [kg/m^3]
+            * (1 - porosity(element, fvGeometry, scvIdx));
+    }
+
+    /*!
+     * \brief docme
+     *
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry
+     * \param scvIdx The local subcontrolvolume index
+     *
+     */
+    Scalar thermalConductivitySolid(const Element &element,
+                                    const FVElementGeometry &fvGeometry,
+                                    const int scvIdx) const
+    {
+        const GlobalPosition &pos = element.geometry().corner(scvIdx);
+
+        if (checkSoilType(pos) == 1)
+            return coarseLambdaSolid_;
+        if (checkSoilType(pos) == 2)
+            return mediumLambdaSolid_;
+        if (checkSoilType(pos) == 3)
+            return fineLambdaSolid_;
+        else
+            return mediumLambdaSolid_;
+    }
+
+    /*!
+     * \brief docme
+     *
+     * \param pos The position of the boundary face's integration point in global coordinates
+     *
+     */
+    const unsigned checkSoilType(const GlobalPosition &pos) const
+    {
+
+// one soil, which can be chosen as runtime parameter:
+// 1: coarse
+// 2: medium
+// 3: fine
+// 4: LeverettJ (x < xMaterialInterface)
+		return soilType_;
+    }
+
+    // this is called from the coupled problem
+    // and creates a gnuplot output of the Pc-Sw curve
+    /*!
+     * \brief docme
+     */
+    void plotMaterialLaw()
+    {
+//        if (soilType_ == 0)
+//        {
+//            std::cout << "Material law plot not possible for heterogeneous media!\n";
+//            return;
+//        }
+//        if (GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, bool, SpatialParams.Coarse, PlotMaterialLaw1))
+//        {
+//            PlotFluidMatrixLaw<MaterialLaw> coarseFluidMatrixLaw_;
+//            coarseFluidMatrixLaw_.plotpC(coarseParams_,
+//                    GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, Swr1),
+//                    1.0 - GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Coarse, Snr1),
+//                    "pcSw_coarse");
+//        }
+//        if (GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, bool, SpatialParams.Medium, PlotMaterialLaw2))
+//        {
+//            PlotFluidMatrixLaw<MaterialLaw> mediumFluidMatrixLaw_;
+//            mediumFluidMatrixLaw_.plotpC(mediumParams_,
+//                    GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Swr2),
+//                    1.0 - GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Snr2),
+//                    "pcSw_medium");
+//            PlotFluidMatrixLaw<MaterialLaw> mediumFluidMatrixLaw2_;
+//            mediumFluidMatrixLaw_.plotkrw(mediumParams_,
+//                    GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Swr2),
+//                    1.0 - GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Snr2));
+//            PlotFluidMatrixLaw<MaterialLaw> mediumFluidMatrixLaw3_;
+//            mediumFluidMatrixLaw_.plotkrn(mediumParams_,
+//                    GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Swr2),
+//                    1.0 - GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Snr2));
+//        }
+//        if (GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, bool, SpatialParams.Fine, PlotMaterialLaw3))
+//        {
+//            PlotFluidMatrixLaw<MaterialLaw> fineFluidMatrixLaw_;
+//            fineFluidMatrixLaw_.plotpC(fineParams_,
+//                    GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, Swr3),
+//                    1.0 - GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Fine, Snr3),
+//                    "pcSw_fine");
+//        }
+//        if (GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, bool, SpatialParams.LeverettJ, PlotMaterialLawJ))
+//        {
+//            PlotFluidMatrixLaw<MaterialLaw> leverettJFluidMatrixLaw_;
+//            leverettJFluidMatrixLaw_.plotpC(leverettJParams_,
+//                    GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Swr2),
+//                    1.0 - GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Snr2),
+//                    "pcSw_leverett");
+//        }
+    }
+
+private:
+
+    unsigned soilType_;
+
+    Scalar coarsePermeability_;
+    Scalar mediumPermeability_;
+    Scalar finePermeability_;
+
+    Scalar coarsePorosity_;
+    Scalar mediumPorosity_;
+    Scalar finePorosity_;
+
+    Scalar coarseLambdaSolid_;
+    Scalar mediumLambdaSolid_;
+    Scalar fineLambdaSolid_;
+
+    Scalar xMaterialInterface_;
+    MaterialLawParamsVector materialLawParams_;
+    PermeabilityType permeability_;
+    PermeabilityType vanGenuchtenAlpha_;
+    const IndexSet& indexSet_;
+
+    MaterialLawParams coarseParams_;
+    MaterialLawParams mediumParams_;
+    MaterialLawParams fineParams_;
+};
+
+} // end namespace
+#endif
+
diff --git a/test/multidomain/2cnistokes2p2cni/2p2cnisubproblem.hh b/test/multidomain/2cnistokes2p2cni/2p2cnisubproblem.hh
new file mode 100644
index 0000000000..772e1988c8
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/2p2cnisubproblem.hh
@@ -0,0 +1,675 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief Porous-medium subproblem with coupling at the top boundary.
+ */
+#ifndef DUMUX_2P2CNISUB_PROBLEM_HH
+#define DUMUX_2P2CNISUB_PROBLEM_HH
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <dumux/implicit/common/implicitporousmediaproblem.hh>
+#include <dumux/implicit/2p2cni/2p2cnimodel.hh>
+#include <dumux/multidomain/couplinglocalresiduals/2p2cnicouplinglocalresidual.hh>
+#include <dumux/multidomain/common/subdomainpropertydefaults.hh>
+#include <dumux/multidomain/common/multidomainlocaloperator.hh>
+#include <dumux/material/fluidmatrixinteractions/2p/thermalconductivitysomerton.hh>
+#include <dune/pdelab/finiteelementmap/conformingconstraints.hh>
+
+#include "2cnistokes2p2cniproblem.hh"
+
+namespace Dumux
+{
+template <class TypeTag>
+class TwoPTwoCNISubProblem;
+
+namespace Properties
+{
+NEW_TYPE_TAG(TwoPTwoCNISubProblem, 
+	INHERITS_FROM(BoxTwoPTwoCNI, SubDomain, TwoCNIStokesTwoPTwoCNISpatialParams));
+
+// Set the problem property
+SET_TYPE_PROP(TwoPTwoCNISubProblem, Problem, TwoPTwoCNISubProblem<TTAG(TwoPTwoCNISubProblem)>);
+
+//! Use the 2p2cni local jacobian operator for the 2p2cniCoupling model
+SET_TYPE_PROP(TwoPTwoCNISubProblem, LocalResidual, TwoPTwoCNICouplingLocalResidual<TypeTag>);
+
+// choose pn and Sw as primary variables
+SET_INT_PROP(TwoPTwoCNISubProblem, Formulation, TwoPTwoCFormulation::pnsw);
+
+// the gas component balance (air) is replaced by the total mass balance
+SET_PROP(TwoPTwoCNISubProblem, ReplaceCompEqIdx)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    static const int value = Indices::contiNEqIdx;
+};
+
+// Set the model parameter group for the TypeTag
+//SET_PROP(TwoPTwoCNISubProblem, ModelParameterGroup)
+//{ static const char *value() { return "PM"; }; };
+
+// set the constraints for multidomain / pdelab
+SET_TYPE_PROP(TwoPTwoCNISubProblem, Constraints,
+        Dune::PDELab::NonoverlappingConformingDirichletConstraints);
+
+// set the grid operator
+SET_PROP(TwoPTwoCNISubProblem, GridOperator)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, ConstraintsTrafo) ConstraintsTrafo;
+    typedef typename GET_PROP_TYPE(TypeTag, GridFunctionSpace) GridFunctionSpace;
+    typedef Dumux::PDELab::MultiDomainLocalOperator<TypeTag> LocalOperator;
+
+    enum{numEq = GET_PROP_VALUE(TypeTag, NumEq)};
+
+public:
+    typedef Dune::PDELab::GridOperator<GridFunctionSpace,
+            GridFunctionSpace, LocalOperator,
+            Dune::PDELab::ISTLBCRSMatrixBackend<numEq, numEq>,
+            Scalar, Scalar, Scalar,
+            ConstraintsTrafo,
+            ConstraintsTrafo,
+            true> type;
+};
+
+// the fluidsystem is set in the coupled problem
+SET_PROP(TwoPTwoCNISubProblem, FluidSystem)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainTypeTag) CoupledTypeTag;
+    typedef typename GET_PROP_TYPE(CoupledTypeTag, FluidSystem) FluidSystem;
+public:
+    typedef FluidSystem type;
+};
+
+
+//! Somerton is used as model to compute the effective thermal heat conductivity
+SET_PROP(TwoPTwoCNISubProblem, ThermalConductivityModel)
+{ private :
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+  public:
+    typedef ThermalConductivitySomerton<Scalar> type;
+};
+
+// use formulation based on mass fractions
+SET_BOOL_PROP(TwoPTwoCNISubProblem, UseMoles, false);
+
+// enable/disable velocity output
+SET_BOOL_PROP(TwoPTwoCNISubProblem, VtkAddVelocity, true);
+
+// Enable gravity
+SET_BOOL_PROP(TwoPTwoCNISubProblem, ProblemEnableGravity, true);
+}
+
+
+template <class TypeTag = TTAG(TwoPTwoCNISubProblem) >
+class TwoPTwoCNISubProblem : public ImplicitPorousMediaProblem<TypeTag>
+{
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GridView::Grid Grid;
+
+    typedef TwoPTwoCNISubProblem<TypeTag> ThisType;
+    typedef ImplicitPorousMediaProblem<TypeTag> ParentType;
+
+    // copy some indices for convenience
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+
+    // the type tag of the coupled problem
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainTypeTag) CoupledTypeTag;
+
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+    enum { numPhases = GET_PROP_VALUE(TypeTag, NumPhases) };
+    enum { numComponents = GET_PROP_VALUE(TypeTag, NumComponents) };
+    enum { // the equation indices
+        contiTotalMassIdx = Indices::contiNEqIdx,
+        contiWEqIdx = Indices::contiWEqIdx,
+        energyEqIdx = Indices::energyEqIdx
+    };
+    enum { // the indices of the primary variables
+		pNIdx = Indices::pressureIdx,
+        sWIdx = Indices::switchIdx,
+        temperatureIdx = Indices::temperatureIdx
+    };
+    enum { // the indices for the phase presence
+        wCompIdx = Indices::wCompIdx,
+        nCompIdx = Indices::nCompIdx
+    };
+	enum { // the indices for the phase presence
+        wPhaseOnly = Indices::wPhaseOnly,
+        nPhaseOnly = Indices::nPhaseOnly,
+        bothPhases = Indices::bothPhases
+    };
+    enum {
+        wPhaseIdx = Indices::wPhaseIdx,
+        nPhaseIdx = Indices::nPhaseIdx
+    };
+    enum { // grid and world dimension
+        dim = GridView::dimension,
+        dimWorld = GridView::dimensionworld
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::Intersection Intersection;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLawParams) MaterialLawParams;
+//    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+
+    // only required for radiation
+    typedef typename GET_PROP_TYPE(TypeTag, ElementVolumeVariables) ElementVolumeVariables;
+    //////////////
+
+    typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition;
+
+    /*!
+     * \brief docme
+     *
+     * \param timeManager The TimeManager which is used by the simulation
+     * \param gridView The simulation's idea about physical space
+     *
+     */
+public:
+    TwoPTwoCNISubProblem(TimeManager &timeManager, const GridView &gridView)
+        : ParentType(timeManager, gridView)
+    {
+        try
+        {
+            Scalar noDarcyX = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Problem, NoDarcyX);
+            Scalar xMin = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, XMin);
+
+            bboxMin_[0] = std::max(xMin,noDarcyX);
+    		bboxMax_[0] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, XMax);
+
+    		bboxMin_[1] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, YMin);
+    		bboxMax_[1] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, InterfacePos);
+
+    		runUpDistanceX_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Problem, RunUpDistanceX); // first part of the interface without coupling
+            xMaterialInterface_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, MaterialInterfaceX);
+    		initializationTime_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, InitTime);
+
+            refTemperature_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, PorousMedium, RefTemperaturePM);
+            refPressure_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, PorousMedium, RefPressurePM);
+            initialSw1_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, PorousMedium, InitialSw1);
+            initialSw2_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, PorousMedium, InitialSw2);
+
+//            porosity_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams.Medium, Porosity2);
+
+            freqMassOutput_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, Output, FreqMassOutput);
+
+            storageLastTimestep_ = Scalar(0);
+            lastMassOutputTime_ = Scalar(0);
+
+            outfile.open("evaporation.out");
+            outfile << "time; massChange; evaporationRate; energyChange; massH2O" << std::endl;
+        }
+        catch (Dumux::ParameterException &e) {
+            std::cerr << e << ". Abort!\n";
+            exit(1) ;
+        }
+        catch (...) {
+            std::cerr << "Unknown exception thrown!\n";
+            exit(1);
+        }
+    }
+
+    ~TwoPTwoCNISubProblem()
+    {
+        outfile.close();
+    }
+
+    /*!
+     * \name Problem parameters
+     */
+    // \{
+
+    //! \copydoc Dumux::ImplicitProblem::name()
+    const std::string &name() const
+    { return GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, std::string, Vtk, NamePM); }
+
+    //! \copydoc Dumux::ImplicitProblem::init()
+    void init()
+    {
+        // set the initial condition of the model
+        ParentType::init();
+
+        this->model().globalStorage(storageLastTimestep_);
+
+        const int blModel = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, FreeFlow, UseBoundaryLayerModel);
+        std::cout << "Using boundary layer model " << blModel << std::endl;
+    }
+
+    // \}
+
+    /*!
+     * \name Boundary conditions
+     */
+    // \{
+
+    //! \copydoc Dumux::ImplicitProblem::boundaryTypes()
+    void boundaryTypes(BoundaryTypes &values, const Vertex &vertex) const
+    {
+        const GlobalPosition globalPos = vertex.geometry().center();
+        Scalar time = this->timeManager().time();
+
+        values.setAllNeumann();
+
+        if (onLowerBoundary_(globalPos))
+        {
+//        	values.setAllDirichlet();
+//        	values.setDirichlet(pressureIdx, contiTotalMassIdx);
+        	values.setDirichlet(temperatureIdx, energyEqIdx);
+        }
+
+        if (onUpperBoundary_(globalPos))
+        {
+            if (time > initializationTime_)
+            {
+                if (globalPos[0] > runUpDistanceX_ - eps_)
+                {
+                    values.setAllCouplingInflow();
+                }
+                else
+                    values.setAllNeumann();
+            }
+            else
+            {
+//                values.setAllDirichlet();
+                values.setAllNeumann();
+            }
+        }
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::dirichlet()
+    void dirichlet(PrimaryVariables &values, const Vertex &vertex) const
+    {
+        const GlobalPosition globalPos = vertex.geometry().center();
+
+        initial_(values, globalPos);
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::neumann()
+    void neumann(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const Intersection &is,
+                 const int scvIdx,
+                 const int boundaryFaceIdx) const
+    {
+        values = 0.;
+    }
+
+    // \}
+
+    /*!
+     * \name Volume terms
+     */
+    // \{
+    //! \copydoc Dumux::ImplicitProblem::solDependentSource()
+    void solDependentSource(PrimaryVariables &values,
+            		 const Element &element,
+            		 const FVElementGeometry &fvGeometry,
+            		 const int scvIdx,
+            		 const ElementVolumeVariables &elemVolVars) const
+    {
+        values = 0;
+//        const Scalar time = this->timeManager().time();
+//        const GlobalPosition &globalPos = element.geometry().corner(scvIdx);
+//
+//		const Scalar temperatureOut = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefTemperature);
+//
+////		const Scalar S = variationSun_(0);                       //Solar irradiance (Yamanaka 1998)
+//		const Scalar sigma = 5.671e-8;                             //Boltzmann-Constant
+//		const Scalar e_a = atmosphericEmissivity();                //atmosphere emissivity (Brutsaert 1982)
+//		const Scalar e_s = surfaceEmissivity_(elemVolVars, scvIdx);
+//		const Scalar a = albedo_(elemVolVars, scvIdx);
+//		const Scalar T_a = 298.15;//variationT_a_(6);                       //atmosphere Temperature (Yamanaka 1998)
+//		const Scalar T_s = elemVolVars[scvIdx].temperature();      //surface Temperature
+//
+//		const Scalar vertexPosition = 0.249248;//1.0; //GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Problem, InterfacePos);
+//
+//          //For d depth with b cells!!
+////		Scalar radiation = S*(1.0-a)+
+//		Scalar radiation = sigma*e_s*(e_a*std::pow(T_a,4.0)-(std::pow(T_s,4.0)));  //Equation from Novak 2010
+//
+//		if (time > initializationTime_
+//				&& globalPos[1] > (vertexPosition - 0.00002)
+//				&& globalPos[1] < (vertexPosition + 0.00002))
+//		  values[energyEqIdx] += radiation/cellHeight_();
+    }
+
+
+    //! \copydoc Dumux::ImplicitProblem::initial()
+    void initial(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const int scvIdx) const
+    {
+        const GlobalPosition &globalPos = element.geometry().corner(scvIdx);
+
+        values = 0.;
+
+        initial_(values, globalPos);
+    }
+
+    /*!
+     * \brief Return the initial phase state inside a control volume.
+     *
+     * \param vert The vertex
+     * \param globalIdx The index of the global vertex
+     * \param globalPos The global position
+     */
+    int initialPhasePresence(const Vertex &vert,
+                             const int &globalIdx,
+                             const GlobalPosition &globalPos) const
+    {
+        return bothPhases;
+    }
+
+
+//    /*!
+//     * \brief docme
+//     */
+//    Scalar globalRadiation()
+//    {
+//        FVElementGeometry fvGeometry;
+//        ElementVolumeVariables elemVolVars;
+//        Scalar source = 0;
+//        PrimaryVariables values(0);
+//
+//        ElementIterator elemIt = this->gridView().template begin<0>();
+//        const ElementIterator elemEndIt = this->gridView().template end<0>();
+//        for (elemIt = this->gridView().template begin<0>(); elemIt != elemEndIt; ++elemIt)
+//        {
+//            if(elemIt->partitionType() == Dune::InteriorEntity)
+//            {
+//                fvGeometry.update(this->gridView(), *elemIt);
+//                elemVolVars.update(*this, *elemIt, fvGeometry, false);
+//
+//                for (int scvIdx = 0; scvIdx < elemIt->template count<dim>(); ++scvIdx)
+//
+//                {
+//                    boxSDSource(values,
+//                                 *elemIt,
+//                                 fvGeometry,
+//                                 scvIdx,
+//                                 elemVolVars);
+//                    Valgrind::CheckDefined(values);
+//
+//                    // thickness of the domain, for 2D usually 1m
+//                    Scalar extrusionFactor =
+//                        elemVolVars[scvIdx].extrusionFactor();
+//                    values[energyEqIdx] *= fvGeometry.subContVol[scvIdx].volume * extrusionFactor;
+//
+//                    source += values[energyEqIdx];
+//                }
+//            }
+//        }
+//
+//        if (this->gridView().comm().size() > 1)
+//            source = this->gridView().comm().sum(source);
+//
+//        return source;
+//    }
+
+    //! \copydoc Dumux::ImplicitProblem::postTimeStep()
+    void postTimeStep()
+    {
+        // Calculate masses
+        PrimaryVariables storage;
+
+        this->model().globalStorage(storage);
+        const Scalar time = this->timeManager().time() +  this->timeManager().timeStepSize();
+
+        // Write mass balance information for rank 0
+        if (this->gridView().comm().rank() == 0)
+        {
+            if (this->timeManager().timeStepIndex() % freqMassOutput_ == 0
+                    || this->timeManager().episodeWillBeOver())
+            {
+                PrimaryVariables evaporationRate(0.);
+                evaporationRate = storageLastTimestep_ - storage;
+
+                assert(time - lastMassOutputTime_ != 0);
+                evaporationRate /= (time - lastMassOutputTime_);
+                // 2d: interface length has to be accounted for
+                // in order to obtain kg/m²s
+                evaporationRate /= (bboxMax_[0]-bboxMin_[0]);
+
+                std::cout << "TotalMass: " << storage[contiTotalMassIdx]
+                          << " MassH2O: " << storage[contiWEqIdx]
+                          << " IntEnergy: " << storage[energyEqIdx]
+                          << " EvaporationRate: " << evaporationRate[contiWEqIdx]
+                          << " Time: " << time <<std::endl;
+                if (this->timeManager().time() != 0.)
+                    outfile << time <<
+							"; " << evaporationRate[contiTotalMassIdx] <<
+                            "; " << evaporationRate[contiWEqIdx] <<
+                            "; " << evaporationRate[energyEqIdx] <<
+                            "; " << storage[contiWEqIdx] <<
+                            std::endl;
+
+                storageLastTimestep_ = storage;
+                lastMassOutputTime_ = time;
+            }
+        }
+    }
+
+    /*!
+     * \brief Determine if we are on a corner of the grid
+     *
+     * \param globalPos The global position
+     *
+     */
+    bool isCornerPoint(const GlobalPosition &globalPos)
+    {
+        return ((onLeftBoundary_(globalPos) && onLowerBoundary_(globalPos)) ||
+            (onLeftBoundary_(globalPos) && onUpperBoundary_(globalPos)) ||
+            (onRightBoundary_(globalPos) && onLowerBoundary_(globalPos)) ||
+            (onRightBoundary_(globalPos) && onUpperBoundary_(globalPos)));
+    }
+
+    // required in case of mortar coupling
+    // otherwise it should return false
+    /*!
+     * \brief docme
+     *
+     * \param global Pos The global position
+     *
+     */
+    bool isInterfaceCornerPoint(const GlobalPosition &globalPos) const
+    { return false; }
+
+    // \}
+
+private:
+    // internal method for the initial condition (reused for the
+    // dirichlet conditions!)
+
+    void initial_(PrimaryVariables &values,
+                  const GlobalPosition &globalPos) const
+    {
+        //TODO: call density from fluidsystem
+//        const MaterialLawParams &materialParams =
+//            this->spatialParams().materialLawParams(globalPos);
+//        Scalar pC = MaterialLaw::pC(materialParams, initialSw1_);
+
+        values[pNIdx] = refPressure_
+                + 1000.*this->gravity()[1]*(globalPos[1]-bboxMax_[1]);
+//                + pC;
+
+        if (globalPos[0] < xMaterialInterface_)
+		     values[sWIdx] = initialSw1_;
+	     else
+	         values[sWIdx] = initialSw2_;
+        values[temperatureIdx] = refTemperature_;
+        //        if (onUpperBoundary_(globalPos) && onLeftBoundary_(globalPos))
+//        {
+//            values[sWIdx] = 0.99e-4;
+//            values[temperatureIdx] = 283.55;
+//        }
+
+//    	values[pNIdx] = 1e5*(2.0 - globalPos[0]);
+//    	if (onLeftBoundary_(globalPos))
+//    		values[sWIdx] = 0.9e-4;
+//    	else
+//    		values[sWIdx] = 1e-4;
+//        values[temperatureIdx] = 283.15;
+    }
+
+    /// RADIATION stuff
+//    const Scalar albedo_(const ElementVolumeVariables &elemVolVars, const int scvIdx) const                                     //albedo
+//    {
+//  	  if (elemVolVars[scvIdx].saturation(wPhaseIdx)*porosity_ > 0.3)
+//  		  return 0.075;
+//  	  if (0.04 <= elemVolVars[scvIdx].saturation(wPhaseIdx)*porosity_ &&
+//  			elemVolVars[scvIdx].saturation(wPhaseIdx)*porosity_ <= 0.3)
+//  		  return 0.1846-0.3654*elemVolVars[scvIdx].saturation(wPhaseIdx)*porosity_;
+//  	  if (elemVolVars[scvIdx].saturation(wPhaseIdx)*porosity_ > 0.4)
+//  		  return 0.17;
+//	  return 0.17;
+//    }
+//
+//    const Scalar surfaceEmissivity_(const ElementVolumeVariables &elemVolVars, const int scvIdx) const                                    //surface emissivity
+//    {
+//  	  if (elemVolVars[scvIdx].saturation(wPhaseIdx)*porosity_ < 0.3)
+//  			return 0.93+0.1333*elemVolVars[scvIdx].saturation(wPhaseIdx)*porosity_;
+//  	  if (elemVolVars[scvIdx].saturation(wPhaseIdx)*porosity_ >= 0.3)
+//  		    return 0.97;
+//  	  return 0.;
+//    }
+//
+//    //to simulate the Solar irradiance for a number of days (definable in the input file)
+//    const Scalar variationSun_(const Scalar value) const
+//    {
+//	  const Scalar time = this->timeManager().time() + this->timeManager().timeStepSize();
+//	  const Scalar days = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, days);
+//
+//	  Scalar solar = 0;
+//	  for (int n=0; n<days; ++n)
+//	  {
+//		  if (time > 21600 + n*86400 && time < 64800 + n*86400)
+//			  solar = cos(2*M_PI*((time+43200)/(86400))) * value;
+//	  }
+//	  return solar;
+//	}
+//
+//    //to simulate the atmospheric Temperature for a number of days (definable in the input file)
+//    const Scalar variationT_a_(const Scalar value) const
+//	{
+//    	const Scalar time = this->timeManager().time() + this->timeManager().timeStepSize();
+//    	const Scalar T = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefTemperature);
+//    	{
+//			  return T+cos(2*M_PI*((time+36000)/(86400))) * value;
+//    	}
+//    	std::cerr << "error with T_a at time " << time << std::endl;
+//	}
+//
+//    //to calculate the atmospheric Emissivity depending on the Temperature near the Surface
+//    const Scalar atmosphericEmissivity() const
+//    {
+//    	const Scalar T_a = variationT_a_(6);
+//
+//      	return 1.24*std::pow((((Dumux::H2O<Scalar>::vaporPressure(T_a)/100)/T_a)),(1.0/7.0));
+//    }
+//
+//    const Scalar cellHeight_() const
+//    {
+//    	return 0.0004575;
+//    }
+    /////////
+
+// TODO: what should be used as reference mass fraction??
+//	void updateFluidStateForBC_(FluidState& fluidState) const
+//	{
+//		for (unsigned phaseIdx=0; phaseIdx<numPhases; ++phaseIdx)
+//		{
+//			fluidState.setTemperature(refTemperature_);
+//			fluidState.setPressure(phaseIdx, refPressure_);
+//
+//			Scalar massFraction[numComponents];
+//			massFraction[wCompIdx] = refMassfrac_;
+//			massFraction[nCompIdx] = 1 - massFraction[wCompIdx];
+//
+//			// calculate average molar mass of the gas phase
+//			Scalar M1 = FluidSystem::molarMass(wCompIdx);
+//			Scalar M2 = FluidSystem::molarMass(nCompIdx);
+//			Scalar X2 = massFraction[nCompIdx];
+//			Scalar massToMoleDenominator = M2 + X2*(M1 - M2);
+//
+//			fluidState.setMoleFraction(phaseIdx, wCompIdx, massFraction[wCompIdx]*M2/massToMoleDenominator);
+//			fluidState.setMoleFraction(phaseIdx, nCompIdx, massFraction[nCompIdx]*M1/massToMoleDenominator);
+//		}
+//	}
+
+
+    bool onLeftBoundary_(const GlobalPosition &globalPos) const
+    { return globalPos[0] < bboxMin_[0] + eps_; }
+
+    bool onRightBoundary_(const GlobalPosition &globalPos) const
+    { return globalPos[0] > bboxMax_[0] - eps_; }
+
+    bool onLowerBoundary_(const GlobalPosition &globalPos) const
+    { return globalPos[1] < bboxMin_[1] + eps_; }
+
+    bool onUpperBoundary_(const GlobalPosition &globalPos) const
+    { return globalPos[1] > bboxMax_[1] - eps_; }
+
+    bool onBoundary_(const GlobalPosition &globalPos) const
+    {
+    	return (onLeftBoundary_(globalPos) || onRightBoundary_(globalPos)
+    			|| onLowerBoundary_(globalPos) || onUpperBoundary_(globalPos));
+    }
+
+    static constexpr Scalar eps_ = 1e-8;
+    GlobalPosition bboxMin_;
+    GlobalPosition bboxMax_;
+    Scalar xMaterialInterface_;
+
+    int freqMassOutput_;
+
+    PrimaryVariables storageLastTimestep_;
+    Scalar lastMassOutputTime_;
+
+    Scalar refTemperature_;
+    Scalar refPressure_;
+    Scalar initialSw1_;
+    Scalar initialSw2_;
+
+//    Scalar porosity_;
+    Scalar runUpDistanceX_;
+    Scalar initializationTime_;
+    std::ofstream outfile;
+};
+} //end namespace
+
+#endif
diff --git a/test/multidomain/2cnistokes2p2cni/Makefile.am b/test/multidomain/2cnistokes2p2cni/Makefile.am
new file mode 100644
index 0000000000..e6520df3f3
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/Makefile.am
@@ -0,0 +1,5 @@
+# tests where program to build and program to run are equal
+check_PROGRAMS = test_2cnistokes2p2cni
+test_2cnistokes2p2cni_SOURCES = test_2cnistokes2p2cni.cc
+
+include $(top_srcdir)/am/global-rules
diff --git a/test/multidomain/2cnistokes2p2cni/grids/interfacedomain.dgf b/test/multidomain/2cnistokes2p2cni/grids/interfacedomain.dgf
new file mode 100644
index 0000000000..b0290172cb
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/grids/interfacedomain.dgf
@@ -0,0 +1,15 @@
+DGF
+Interval
+0 0   % first corner
+0.25 0.5   % second corner
+1 1   % 1 cells in x and 1 in y direction
+# 
+
+Cube 
+0 1 2 3
+# 
+
+BOUNDARYDOMAIN
+default 1    % all boundaries have id 1
+#BOUNDARYDOMAIN
+# unitcube.dgf 
diff --git a/test/multidomain/2cnistokes2p2cni/grids/test_2cnistokes2p2cni.dgf b/test/multidomain/2cnistokes2p2cni/grids/test_2cnistokes2p2cni.dgf
new file mode 100644
index 0000000000..f13c8f14e2
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/grids/test_2cnistokes2p2cni.dgf
@@ -0,0 +1,17 @@
+DGF
+Interval
+0 0   % first corner 
+0.25 0.5   % second corner
+20 64 % cells in x and y direction
+#
+GridParameter
+overlap 0 
+periodic 
+closure green
+copies none
+heapsize 500
+
+BOUNDARYDOMAIN
+default 1    % all boundaries have id 1
+#BOUNDARYDOMAIN
+# unitcube.dgf 
diff --git a/test/multidomain/2cnistokes2p2cni/stokes2cnisubproblem.hh b/test/multidomain/2cnistokes2p2cni/stokes2cnisubproblem.hh
new file mode 100644
index 0000000000..3602c2837e
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/stokes2cnisubproblem.hh
@@ -0,0 +1,592 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/**
+ * @file
+ * \ingroup Stokes2cniProblems
+ * @brief  Definition of a non-isothermal compositional Stokes problem
+ * @author Klaus Mosthaf
+ */
+#ifndef DUMUX_STOKES2CNI_SUBPROBLEM_HH
+#define DUMUX_STOKES2CNI_SUBPROBLEM_HH
+
+#include <dune/pdelab/finiteelementmap/conformingconstraints.hh>
+
+#include <dumux/freeflow/stokesncni/stokesncnimodel.hh>
+#include <dumux/multidomain/couplinglocalresiduals/stokesncnicouplinglocalresidual.hh>
+#include <dumux/multidomain/common/subdomainpropertydefaults.hh>
+
+namespace Dumux
+{
+
+template <class TypeTag>
+class Stokes2cniSubProblem;
+
+//////////
+// Specify the properties for the Stokes problem
+//////////
+namespace Properties
+{
+NEW_TYPE_TAG(Stokes2cniSubProblem, 
+	INHERITS_FROM(BoxStokesncni, SubDomain, TwoCNIStokesTwoPTwoCNISpatialParams));
+
+//SET_PROP(Stokes2cniSubProblem, ModelParameterGroup)
+//{ static const char *value() { return "FF"; }; };
+
+// Set the problem property
+SET_TYPE_PROP(Stokes2cniSubProblem, Problem, Dumux::Stokes2cniSubProblem<TypeTag>);
+
+//! Use the Stokes2cniCouplingLocalResidual for the computation of the local residual in the Stokes domain
+SET_TYPE_PROP(Stokes2cniSubProblem, LocalResidual, StokesncniCouplingLocalResidual<TypeTag>);
+
+//! Set the property for the material parameters by extracting it from the material law
+SET_PROP(Stokes2cniSubProblem, MaterialLawParams)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MaterialLaw) MaterialLaw;
+public:
+    typedef typename MaterialLaw::Params type;
+};
+
+SET_TYPE_PROP(Stokes2cniSubProblem, Constraints,
+		Dune::PDELab::NonoverlappingConformingDirichletConstraints);
+
+// set the grid operator
+SET_PROP(Stokes2cniSubProblem, GridOperator)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, ConstraintsTrafo) ConstraintsTrafo;
+    typedef typename GET_PROP_TYPE(TypeTag, GridFunctionSpace) GridFunctionSpace;
+    typedef Dumux::PDELab::MultiDomainLocalOperator<TypeTag> LocalOperator;
+
+    enum{numEq = GET_PROP_VALUE(TypeTag, NumEq)};
+public:
+    typedef Dune::PDELab::GridOperator<GridFunctionSpace,
+            GridFunctionSpace, LocalOperator,
+            Dune::PDELab::ISTLBCRSMatrixBackend<numEq, numEq>,
+            Scalar, Scalar, Scalar,
+            ConstraintsTrafo, ConstraintsTrafo,
+            true> type;
+};
+
+SET_PROP(Stokes2cniSubProblem, FluidSystem)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainTypeTag) CoupledTypeTag;
+    typedef typename GET_PROP_TYPE(CoupledTypeTag, FluidSystem) FluidSystem;
+public:
+    typedef FluidSystem type;
+};
+
+// use formulation based on mass fractions
+SET_BOOL_PROP(Stokes2cniSubProblem, UseMoles, false);
+
+// Disable gravity in the Stokes domain
+SET_BOOL_PROP(Stokes2cniSubProblem, ProblemEnableGravity, false);
+
+// switch inertia term on or off
+SET_BOOL_PROP(Stokes2cniSubProblem, EnableNavierStokes, false);
+}
+
+/*!
+ * \ingroup Stokes2cniBoxProblems
+ * \brief Stokes2cni problem with air flowing
+ *        from the left to the right.
+ *
+ * The stokes subdomain is sized 1m times 1m. The boundary conditions for the momentum balances
+ * are all set to Dirichlet. The mass balance receives
+ * outflow bcs, which are replaced in the localresidual by the sum
+ * of the two momentum balances. In the middle of the right boundary,
+ * one vertex receives Dirichlet bcs, to set the pressure level.
+ *
+ * This sub problem uses the \ref Stokes2cniModel. It is part of the 2cnistokes2p2cni model and
+ * is combined with the 2p2cnisubproblem for the Darcy domain.
+ *
+ */
+template <class TypeTag>
+class Stokes2cniSubProblem : public StokesProblem<TypeTag>
+{
+    typedef Stokes2cniSubProblem<TypeTag> ThisType;
+    typedef StokesProblem<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+
+    // soil parameters for beavers & joseph
+    typedef typename GET_PROP_TYPE(TypeTag, SpatialParams) SpatialParams;
+
+    enum {
+        // Number of equations and grid dimension
+        numEq = GET_PROP_VALUE(TypeTag, NumEq),
+        dim = GridView::dimension
+    };
+    typedef typename GET_PROP_TYPE(TypeTag, Indices) Indices;
+    enum {
+        // equation indices
+        massBalanceIdx = Indices::massBalanceIdx,
+        momentumXIdx = Indices::momentumXIdx, //!< Index of the x-component of the momentum balance
+        momentumYIdx = Indices::momentumYIdx, //!< Index of the y-component of the momentum balance
+        momentumZIdx = Indices::momentumZIdx, //!< Index of the z-component of the momentum balance
+        transportEqIdx = Indices::transportEqIdx, //!< Index of the transport equation (massfraction)
+        energyEqIdx =    Indices::energyEqIdx     //!< Index of the energy equation (temperature)
+    };
+    enum { // primary variable indices
+        pressureIdx = Indices::pressureIdx,
+        velocityXIdx = Indices::velocityXIdx,
+        velocityYIdx = Indices::velocityYIdx,
+        velocityZIdx = Indices::velocityZIdx,
+        massOrMoleFracIdx = Indices::massOrMoleFracIdx,
+        temperatureIdx = Indices::temperatureIdx
+    };
+    enum { phaseIdx = Indices::phaseIdx };
+    enum { numComponents = Indices::numComponents };
+    enum {
+        transportCompIdx = Indices::transportCompIdx, //!< water component index
+        phaseCompIdx = Indices::phaseCompIdx          //!< air component index
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, PrimaryVariables) PrimaryVariables;
+    typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes;
+
+    typedef typename GridView::template Codim<0>::Entity Element;
+    typedef typename GridView::template Codim<dim>::Entity Vertex;
+    typedef typename GridView::ctype CoordScalar;
+    typedef typename GridView::Intersection Intersection;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FVElementGeometry) FVElementGeometry;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TypeTag, FluidState) FluidState;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef Dune::FieldVector<CoordScalar, dim> GlobalPosition;
+
+    /*!
+     * \brief docme
+     */
+public:
+    Stokes2cniSubProblem(TimeManager &timeManager, const GridView &gridView)
+        : ParentType(timeManager, gridView),
+          spatialParams_(gridView)
+    {
+        try
+        {
+            bboxMin_[0] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, XMin);
+            bboxMax_[0] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, XMax);
+            bboxMin_[1] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, InterfacePos);
+            bboxMax_[1] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, YMax);
+
+            refTemperature_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefTemperature);
+            refPressure_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefPressure);
+            refMassfrac_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefMassfrac);
+            vxMax_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, VxMax);
+            bjSlipVel_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, BeaversJosephSlipVel);
+
+            sinusVelVar_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, SinusVelVar);
+            sinusPVar_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, SinusPVar);
+            sinusTVar_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, SinusTVar);
+            sinusXVar_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, SinusXVar);
+
+            xMaterialInterface_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, MaterialInterfaceX);
+            runUpDistanceX_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Problem, RunUpDistanceX); // first part of the interface without coupling
+            initializationTime_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, InitTime);
+
+            alphaBJ_ = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, SpatialParams, AlphaBJ);
+        }
+        catch (Dumux::ParameterException &e) {
+            std::cerr << e << ". Abort!\n";
+            exit(1) ;
+        }
+        catch (...) {
+            std::cerr << "Unknown exception thrown!\n";
+            exit(1);
+        }
+    }
+
+    /*!
+     * \name Problem parameters
+     */
+    // \{
+
+    //! \copydoc Dumux::ImplicitProblem::name()
+    const std::string &name() const
+    { return GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, std::string, Vtk, NameFF); }
+
+    // \}
+
+    /*!
+     * \name Boundary conditions
+     */
+    // \{
+
+    //! \copydoc Dumux::ImplicitProblem::boundaryTypes()
+    void boundaryTypes(BoundaryTypes &values, const Vertex &vertex) const
+    {
+        const GlobalPosition &globalPos = vertex.geometry().center();
+        const Scalar time = this->timeManager().time();
+
+        values.setAllDirichlet();
+
+        if (onUpperBoundary_(globalPos))
+        {
+            values.setNeumann(transportEqIdx);
+            values.setNeumann(energyEqIdx);
+        }
+
+		// Left inflow boundaries should be Neumann, otherwise the
+		// evaporative fluxes are much more grid dependent
+        if (onLeftBoundary_(globalPos))
+        {
+            values.setNeumann(transportEqIdx);
+            values.setNeumann(energyEqIdx);
+
+            if (onUpperBoundary_(globalPos)) // corner point
+                values.setAllDirichlet();
+        }
+
+        if (onRightBoundary_(globalPos))
+        {
+            values.setAllOutflow();
+
+            if (onUpperBoundary_(globalPos)) // corner point
+                values.setAllDirichlet();
+        }
+
+        if (onLowerBoundary_(globalPos))
+        {
+            values.setAllDirichlet();
+            if (!onLeftBoundary_(globalPos)) // is this required?
+            {
+                values.setNeumann(transportEqIdx);
+                values.setNeumann(energyEqIdx);
+            }
+
+            if (globalPos[0] > runUpDistanceX_-eps_ && time > initializationTime_)
+            {
+                values.setAllCouplingOutflow();
+//                values.setCouplingInflow(energyEqIdx);
+            }
+        }
+
+        // the mass balance has to be of type outflow
+        // it does not get a coupling condition, since pn is a condition for stokes
+        values.setOutflow(massBalanceIdx);
+
+        // set pressure at one point, do NOT specify this
+        // if the Darcy domain has a Dirichlet condition for pressure
+        if (onRightBoundary_(globalPos))
+        {
+            if (time > initializationTime_)
+                values.setDirichlet(pressureIdx, massBalanceIdx);
+            else
+                if (!onLowerBoundary_(globalPos) && !onUpperBoundary_(globalPos))
+                    values.setDirichlet(pressureIdx, massBalanceIdx);
+        }
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::dirichlet()
+    void dirichlet(PrimaryVariables &values, const Vertex &vertex) const
+    {
+        const GlobalPosition globalPos = vertex.geometry().center();
+
+//        initial_(values, globalPos);
+        values = 0.0;
+
+        FluidState fluidState;
+        updateFluidStateForBC_(fluidState);
+
+        const Scalar density =
+                FluidSystem::density(fluidState, phaseIdx);
+
+        values[velocityXIdx] = xVelocity_(globalPos);
+        values[velocityYIdx] = 0.0;
+        values[pressureIdx] = refPressure()  +
+                density*this->gravity()[1]*(globalPos[1] - bboxMin_[1]);
+        values[massOrMoleFracIdx] = refMassfrac();
+        values[temperatureIdx] = refTemperature();
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::neumann()
+    void neumann(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const Intersection &is,
+                 const int scvIdx,
+                 const int boundaryFaceIdx) const
+    {
+        const GlobalPosition &globalPos =
+                fvGeometry.boundaryFace[boundaryFaceIdx].ipGlobal;
+
+        values = 0.;
+
+        FluidState fluidState;
+        updateFluidStateForBC_(fluidState);
+
+        const Scalar density =
+                FluidSystem::density(fluidState, phaseIdx);
+        const Scalar enthalpy =
+                FluidSystem::enthalpy(fluidState, phaseIdx);
+        const Scalar xVelocity = xVelocity_(globalPos);
+
+        if (onLeftBoundary_(globalPos)
+                && globalPos[1] > bboxMin_[1] && globalPos[1] < bboxMax_[1])
+        {
+            values[transportEqIdx] = -xVelocity*density*refMassfrac();
+            values[energyEqIdx] = -xVelocity*density*enthalpy;
+        }
+    }
+
+    /*!
+     * \brief Evaluate the Beavers-Joseph coefficient
+     *        at the center of a given intersection
+     *
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry
+     * \param is The intersection between element and boundary
+     * \param scvIdx The local subcontrolvolume index
+     * \param boundaryFaceIdx The index of the boundary face
+     *
+     * \return Beavers-Joseph coefficient
+     */
+    Scalar beaversJosephCoeff(const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const Intersection &is,
+                 const int scvIdx,
+                 const int boundaryFaceIdx) const
+    {
+        const GlobalPosition &globalPos =
+                fvGeometry.boundaryFace[boundaryFaceIdx].ipGlobal;
+
+        if (onLowerBoundary_(globalPos))
+            return alphaBJ_;
+        else
+            return 0.0;
+    }
+
+    /*!
+     * \brief Evaluate the intrinsic permeability
+     *        at the corner of a given element
+     *
+     * \param element The finite element
+     * \param fvGeometry The finite-volume geometry
+     * \param scvIdx The local subcontrolvolume index
+     *
+     * \return permeability in x-direction
+     */
+    Scalar permeability(const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const int scvIdx) const
+    {
+        return spatialParams_.intrinsicPermeability(element,
+                                                    fvGeometry,
+                                                    scvIdx);
+    }
+
+    // \}
+
+    //! \copydoc Dumux::ImplicitProblem::source()
+    void source(PrimaryVariables &values,
+                const Element &element,
+                const FVElementGeometry &fvGeometry,
+                const int scvIdx) const
+    {
+        // ATTENTION: The source term of the mass balance has to be chosen as
+        // div (q_momentum) in the problem file
+        values = Scalar(0);
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::initial()
+    void initial(PrimaryVariables &values,
+                 const Element &element,
+                 const FVElementGeometry &fvGeometry,
+                 const int scvIdx) const
+    {
+        const GlobalPosition &globalPos
+            = element.geometry().corner(scvIdx);
+
+        initial_(values, globalPos);
+    }
+    // \}
+
+    /*!
+     * \brief Determine if we are on a corner of the grid
+     *
+     * \param global Pos The global position
+     *
+     */
+    bool isCornerPoint(const GlobalPosition &globalPos)
+    {
+        if ((onLeftBoundary_(globalPos) && onLowerBoundary_(globalPos)) ||
+            (onLeftBoundary_(globalPos) && onUpperBoundary_(globalPos)) ||
+            (onRightBoundary_(globalPos) && onLowerBoundary_(globalPos)) ||
+            (onRightBoundary_(globalPos) && onUpperBoundary_(globalPos)))
+            return true;
+        else
+            return false;
+    }
+
+    // required in case of mortar coupling
+    // otherwise it should return false
+    /*!
+     * \brief docme
+     *
+     * \param global Pos The global position
+     *
+     */
+    bool isInterfaceCornerPoint(const GlobalPosition &globalPos) const
+    { return false; }
+
+    /*!
+     * \brief Returns the spatial parameters object.
+     */
+    SpatialParams &spatialParams()
+    { return spatialParams_; }
+    const SpatialParams &spatialParams() const
+    { return spatialParams_; }
+
+    const Scalar refTemperature() const
+    { return refTemperature_+ diurnalVariation_(sinusTVar_); }
+
+    const Scalar refMassfrac() const
+    { return refMassfrac_ + diurnalVariation_(sinusXVar_); }
+
+    const Scalar refPressure() const
+    { return refPressure_ + diurnalVariation_(sinusPVar_); }
+
+private:
+    // internal method for the initial condition (reused for the
+    // dirichlet conditions!)
+
+
+    void initial_(PrimaryVariables &values,
+                  const GlobalPosition &globalPos) const
+    {
+        FluidState fluidState;
+        updateFluidStateForBC_(fluidState);
+
+        const Scalar density =
+                FluidSystem::density(fluidState, phaseIdx);
+
+        values[velocityXIdx] = xVelocity_(globalPos);
+        values[velocityYIdx] = 0.;
+
+        values[pressureIdx] = refPressure()
+                + density*this->gravity()[1]*(globalPos[1] - bboxMin_[1]);
+        values[massOrMoleFracIdx] = refMassfrac();
+        values[temperatureIdx] = refTemperature();
+    }
+
+
+    const Scalar xVelocity_(const GlobalPosition &globalPos) const
+    {
+        const Scalar vmax = vxMax_ + hourlyVariation_(sinusVelVar_);
+//        const Scalar relativeHeight = (globalPos[1]-bboxMin_[1])/height_();
+        // linear profile
+//        return vmax*relativeHeight + bjSlipVel_; // BJ slip velocity is added as sqrt(Kxx)
+	      // parabolic profile
+        return  4*vmax*(globalPos[1] - bboxMin_[1])*(bboxMax_[1] - globalPos[1])
+                / (height_()*height_()) + bjSlipVel_;
+//        Scalar tempVel = (globalPos[1] - bboxMin_[1])/height_();
+//        return vmax*tempVel*tempVel + bjSlipVel_;
+        // logarithmic profile
+//        return 0.1*vmax*log((relativeHeight+1e-3)/1e-3) + bjSlipVel_;
+    }
+
+
+    void updateFluidStateForBC_(FluidState& fluidState) const
+    {
+        fluidState.setTemperature(refTemperature());
+        fluidState.setPressure(phaseIdx, refPressure());
+
+        Scalar massFraction[numComponents];
+        massFraction[transportCompIdx] = refMassfrac();
+        massFraction[phaseCompIdx] = 1 - massFraction[transportCompIdx];
+
+        // calculate average molar mass of the gas phase
+        Scalar M1 = FluidSystem::molarMass(transportCompIdx);
+        Scalar M2 = FluidSystem::molarMass(phaseCompIdx);
+        Scalar X2 = massFraction[phaseCompIdx];
+        Scalar massToMoleDenominator = M2 + X2*(M1 - M2);
+
+        fluidState.setMoleFraction(phaseIdx, transportCompIdx, massFraction[transportCompIdx]*M2/massToMoleDenominator);
+        fluidState.setMoleFraction(phaseIdx, phaseCompIdx, massFraction[phaseCompIdx]*M1/massToMoleDenominator);
+    }
+
+
+    const Scalar diurnalVariation_(const Scalar value) const
+    {
+        const Scalar time = this->timeManager().time() + this->timeManager().timeStepSize();
+        return sin(2*M_PI*time/86400) * value;
+    }
+
+
+    const Scalar hourlyVariation_(const Scalar value) const
+    {
+        const Scalar time = this->timeManager().time();
+        return sin(2*M_PI*time/3600) * value;
+    }
+
+    bool onLeftBoundary_(const GlobalPosition &globalPos) const
+    { return globalPos[0] < bboxMin_[0] + eps_; }
+
+    bool onRightBoundary_(const GlobalPosition &globalPos) const
+    { return globalPos[0] > bboxMax_[0] - eps_; }
+
+    bool onLowerBoundary_(const GlobalPosition &globalPos) const
+    { return globalPos[1] < bboxMin_[1] + eps_; }
+
+    bool onUpperBoundary_(const GlobalPosition &globalPos) const
+    { return globalPos[1] > bboxMax_[1] - eps_; }
+
+    bool onBoundary_(const GlobalPosition &globalPos) const
+    {
+        return (onLeftBoundary_(globalPos) || onRightBoundary_(globalPos)
+                || onLowerBoundary_(globalPos) || onUpperBoundary_(globalPos));
+    }
+
+    const Scalar height_() const
+    { return bboxMax_[1] - bboxMin_[1]; }
+
+    // spatial parameters
+    SpatialParams spatialParams_;
+
+    static constexpr Scalar eps_ = 1e-8;
+
+    GlobalPosition bboxMin_;
+    GlobalPosition bboxMax_;
+
+    Scalar refPressure_;
+    Scalar refTemperature_;
+    Scalar refMassfrac_;
+
+    Scalar vxMax_;
+    Scalar bjSlipVel_;
+    Scalar alphaBJ_;
+
+    Scalar sinusVelVar_;
+    Scalar sinusPVar_;
+    Scalar sinusTVar_;
+    Scalar sinusXVar_;
+
+    Scalar xMaterialInterface_;
+    Scalar runUpDistanceX_;
+    Scalar initializationTime_;
+};
+} //end namespace
+
+#endif
diff --git a/test/multidomain/2cnistokes2p2cni/test_2cnistokes2p2cni.cc b/test/multidomain/2cnistokes2p2cni/test_2cnistokes2p2cni.cc
new file mode 100644
index 0000000000..5230301847
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/test_2cnistokes2p2cni.cc
@@ -0,0 +1,279 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ *
+ * \brief test for the coupled 2cni-Stokes and 2p2cni-Darcy model
+ */
+#include "config.h"
+#include <iostream>
+#include <boost/format.hpp>
+
+#include <dune/common/version.hh>
+#if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 3)
+#include <dune/common/parallel/mpihelper.hh>
+#else
+#include <dune/common/mpihelper.hh>
+#endif
+
+#include <dune/common/parametertreeparser.hh>
+#include <dumux/io/interfacemeshcreator.hh>
+
+#include "2cnistokes2p2cniproblem.hh"
+
+
+/*!
+ * \brief Print a usage string for simulations.
+ *
+ * \param progname The name of the executable
+ */
+void printUsage(const char *progName)
+{
+    std::cout << "usage: " << progName
+            << " [--restart restartTime] -parameterFile test_2cnistokes2p2cni.input\n";
+    exit(1);
+}
+
+template <class TypeTag>
+int start_(int argc,
+           char **argv)
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
+    typedef typename GET_PROP_TYPE(TypeTag, GridCreator) GridCreator;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+
+//    typedef Dune::GridPtr<Grid> GridPointer;
+
+    ////////////////////////////////////////////////////////////
+    // Load the input parameters
+    ////////////////////////////////////////////////////////////
+
+    typedef typename GET_PROP(TypeTag, ParameterTree) ParameterTree;
+    Dune::ParameterTreeParser::readOptions(argc, argv, ParameterTree::tree());
+
+    if (ParameterTree::tree().hasKey("parameterFile") or argc==1)
+    {
+        // read input file, but do not overwrite options specified
+        // on the command line, since the latter have precedence.
+        std::string inputFileName ;
+        if(argc==1) // if there are no arguments given (and there is a file ./<programname>.input) we use it as input file
+        {
+            std::cout<< "\nNo parameter file given. \n"
+                     << "Defaulting to '"
+                     << argv[0]
+                     << ".input' for input file.\n";
+            inputFileName = argv[0];
+            inputFileName += ".input";
+        }
+        else
+            inputFileName = GET_RUNTIME_PARAM(TypeTag, std::string, parameterFile); // otherwise we read from the command line
+
+        std::ifstream parameterFile;
+
+        // check whether the parameter file exists.
+        parameterFile.open(inputFileName.c_str());
+        if (not parameterFile.is_open()){
+            std::cout<< "\n\t -> Could not open file"
+                     << inputFileName
+                     << ". <- \n\n\n\n";
+            printUsage(argv[0]);
+            return 1;
+        }
+        parameterFile.close();
+
+        Dune::ParameterTreeParser::readINITree(inputFileName,
+                                               ParameterTree::tree(),
+                                               /*overwrite=*/false);
+    }
+
+    // initialize MPI, finalize is done automatically on exit
+    static Dune::MPIHelper& mpiHelper = Dune::MPIHelper::instance(argc, argv);
+
+    // define the problem dimensions
+    const int dim=2;
+
+    // deal with the restart stuff
+    int argIdx = 1;
+    bool restart = false;
+    double tStart = 0.0;
+    if (argc > 1 && std::string("--restart") == argv[argIdx])
+    {
+        restart = true;
+        ++argIdx;
+
+        std::istringstream(argv[argIdx++]) >> tStart;
+    }
+
+    std::string dgfFileName;
+    Scalar dt, tEnd;
+    Dune::FieldVector<int, dim> nElements;
+    Scalar interfacePos, gradingFactor;
+    int gridRefinement;
+    bool useInterfaceMeshCreator;
+
+    try
+    {
+    	dgfFileName = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, std::string, Grid, File);
+    	dt = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, DtInitial);
+    	tEnd = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, TimeManager, TEnd);
+	    nElements[0] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, Grid, CellsX);
+    	if (dim>1) nElements[1] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, Grid, CellsY);
+    	if (dim==3) nElements[2] = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, int, Grid, CellsZ);
+    	interfacePos = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, InterfacePos);
+    	gradingFactor = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, Grading);
+    	gridRefinement = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, Grid, Refinement);
+    	useInterfaceMeshCreator = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, bool, Grid, UseInterfaceMeshCreator);
+    }
+    catch (Dumux::ParameterException &e) {
+        std::cerr << e << ". Abort!\n";
+        exit(1) ;
+    }
+    catch (...) {
+        std::cerr << "Unknown exception thrown!\n";
+        exit(1);
+    }
+    std::cout << "Starting with timestep size = " << dt << "s, simulation end = " << tEnd << "s\n";
+
+    if (useInterfaceMeshCreator)
+    {
+        Dumux::InterfaceMeshCreator<Grid> interfaceMeshCreator;
+        GridCreator::gridPtr() = interfaceMeshCreator.create(dgfFileName, nElements, interfacePos, gradingFactor);
+    }
+    else
+    {
+        // try to create a grid (from the given grid file)
+        try { GridCreator::makeGrid(); }
+        catch (...) {
+            std::string usageMessage = "\n\t -> Creation of the grid failed! <- \n\n\n\n";
+//            usageMessage += usageTextBlock();
+//            usage(argv[0], usageMessage);
+            throw;
+        }
+    }
+
+    if (gridRefinement)
+    	GridCreator::grid().globalRefine(gridRefinement);
+
+    if (mpiHelper.size() > 1) {
+        if (!Dune::Capabilities::isParallel<Grid>::v) {
+            std::cerr << "WARNING: THE PROGRAM IS STARTED USING MPI, BUT THE GRID IMPLEMENTATION\n"
+                      << "         YOU HAVE CHOSEN IS NOT PARALLEL!\n";
+        }
+    	GridCreator::loadBalance();
+    }
+
+    // Instantiate the time manager
+    TimeManager timeManager;
+
+    // instantiate coupled problem
+    Dune::shared_ptr<MDGrid> mdGrid_ = Dune::make_shared<MDGrid> (GridCreator::grid());
+
+    Problem problem(*mdGrid_,
+                    timeManager);
+
+    Dumux::Parameters::print<TypeTag>();
+
+    // run the simulation
+    timeManager.init(problem,
+                     tStart, // initial time
+                     dt, // initial time step
+                     tEnd, // final time
+                     restart);
+
+    // print all properties
+    Dumux::Properties::print<TypeTag>();
+
+    timeManager.run();
+
+    return 0;
+}
+
+/*!
+ * \ingroup Start
+ *
+ * \brief Provides a main function which reads in parameters from the
+ *        command line and a parameter file.
+ *
+ *        In this function only the differentiation between debugger
+ *        or not is made.
+ *
+ * \tparam TypeTag  The type tag of the problem which needs to be solved
+ *
+ * \param argc  The number of command line arguments of the program
+ * \param argv  The contents of the command line arguments of the program
+ * \param usage Callback function for printing the usage message
+ */
+template <class TypeTag>
+int start(int argc,
+          char **argv)
+{
+    try {
+        return start_<TypeTag>(argc, argv);
+    }
+    catch (Dumux::ParameterException &e)
+    {
+       std::cerr << e << ". Abort!\n";
+       printUsage(argv[0]);
+       return 1;
+    }
+    catch (Dune::Exception &e) {
+        std::cerr << "Dune reported error: " << e << std::endl;
+        return 2;
+    }
+    catch (...) {
+        std::cerr << "Unknown exception thrown!\n";
+        return 3;
+    }
+}
+
+//
+///*!
+// * \brief Print a usage string for simulations using
+// *        Dumux::startFromDGF() as their main() function.
+// *
+// * \param progname The name of the executable
+// */
+//void printUsage(const char *progname)
+//{
+//    std::cout << boost::format(
+//        "usage: %s [options]\n"
+//        "\n"
+//        "Options starting with a lowercase letter must be specified somewhere,\n"
+//        "options beginning with an uppercase letter do have fallback values.\n"
+//        "Some important options include:\n"
+//        "  -Help                         Print this usage message and quit\n"
+//        "  -tEnd time                    Time [s] of the simulation's end\n"
+//        "  -dtInitial time               Initial time step size [s]\n"
+//        "  -parameterFile parameter file A INI file with options\n"
+//        "  -Restart time                 Restart a previous run from a DRS file\n"
+//        "  -PrintParams (true|false)     Print the parameters used at the end of the simulation\n"
+//        "  -CellsX n                     Number of cells in x direction\n"
+//        "  -CellsY n                     Number of cells in y direction\n"
+//        "  -Newton.RelTolerance value    Tolerated relative error for the Newton solver\n"
+//        )%progname;
+//}
+
+int main(int argc, char** argv)
+{
+    typedef TTAG(TwoCNIStokesTwoPTwoCNIProblem) ProblemTypeTag;
+    return start<ProblemTypeTag>(argc, argv);//, usage);
+}
diff --git a/test/multidomain/2cnistokes2p2cni/test_2cnistokes2p2cni.input b/test/multidomain/2cnistokes2p2cni/test_2cnistokes2p2cni.input
new file mode 100644
index 0000000000..7b736ca114
--- /dev/null
+++ b/test/multidomain/2cnistokes2p2cni/test_2cnistokes2p2cni.input
@@ -0,0 +1,193 @@
+#############################################################
+#Configuration file for test_2cnistokes2p2cni
+#############################################################
+
+#############################################################
+#General conditions: Problem, TimeManager, Vtk, Grid
+#############################################################
+
+#############################################################
+[Problem]
+#############################################################
+#First part of the interface, where it is not coupled;
+#set to zero or negative if not desired
+RunUpDistanceX = 0.0 # 0.06, has to be larger than NoDarcyX !?
+NoDarcyX = 0.0 # 0.05
+
+#############################################################
+[TimeManager]
+#############################################################
+#Initial and maximum time-step size
+DtInitial = 5e-1 
+MaxTimeStepSize = 360
+
+#Initialization time without coupling
+#set to zero or negative if not desired
+InitTime = 864 
+
+#Simulation end
+TEnd = 0.864e6
+
+#Define the length of an episode (for output)
+EpisodeLength = 43200
+
+#############################################################
+[Vtk]
+#############################################################
+#Names for VTK output
+NameFF = stokes2cni
+NamePM = 2p2cni
+AddVelocity = 1 
+
+#############################################################
+[Grid]
+#############################################################
+UseInterfaceMeshCreator = true
+
+#Name of the dgf file (grid)
+File = grids/interfacedomain.dgf
+#File = grids/test_2cnistokes2p2cni.dgf
+Refinement = 0
+
+#Number of elements in x-, y-, z-direction
+CellsX = 30
+CellsY = 62
+CellsZ = 1
+#Grading and refinement of the mesh
+Grading = 1.13
+
+#Extend of entire domain
+XMin = 0.0
+XMax = 0.25
+YMin = 0.0
+YMax = 0.5
+
+#Vertical position of coupling interface
+InterfacePos = 0.25
+
+#############################################################
+[Output]
+#############################################################
+#Frequency of restart file, flux and VTK output
+FreqRestart = 1000      # how often restart files are written out 
+FreqOutput = 50         # frequency of VTK output
+FreqMassOutput = 2      # frequency of mass and evaporation rate output (Darcy)
+FreqFluxOutput = 1000   # frequency of detailed flux output
+FreqVaporFluxOutput = 2 # frequency of summarized flux output
+
+#############################################################
+[Stokes]
+#############################################################
+StabilizationAlpha = -1.0
+
+#############################################################
+[FreeFlow]
+#############################################################
+RefPressure = 1e5
+RefTemperature = 298.15
+RefMassfrac = 0.008
+VxMax = 3.5
+BeaversJosephSlipVel = 0.00134
+ExponentMTC = 0.0 # 1./6., Mass transfer coefficient for S^MTC
+UseBoundaryLayerModel = 0 # integer, 0 for no boundary layer model, 1 for Blasius, 2 for turbulent BL, 9 for constant thickness
+BoundaryLayerOffset = 0.00 # For BL model like Blasius, determines a virtual run-up distance for the flow
+ConstThickness = 0.0016 # for a constant BL thickness, use BL model 3
+MassTransferModel = 0 # 0 for none, 1 for power law, 2 for Schluender model
+
+SinusVelVar = 0.0 	# hourly velocity variation
+SinusPVar = 0.0 	# diurnal pressure variation
+SinusTVar = 0.0 	# diurnal temperature variation
+SinusXVar = 0.0 	# diurnal variation of the vapor concentration (massfraction)
+
+#############################################################
+[PorousMedium]
+#############################################################
+RefPressurePM = 1e5
+RefTemperaturePM = 298.15
+InitialSw1 = 0.98
+InitialSw2 = 0.98
+CharPoreRadius = 1e-4
+PlotFluidProperties = false
+
+#############################################################
+[SpatialParams]
+#############################################################
+MaterialInterfaceX = -100.0
+AlphaBJ = 1.0
+
+# for homogeneous setups (0 for heterogeneous):
+SoilType = 2
+# threshold of the linearization of the capillary pressure curve
+RegularizationThreshold = 1e-2
+
+# GStat stuff, only required for SoilType=0
+GenerateNewPermeability = true
+GStatControlFileName = gstatControl_2D.txt
+GStatInputFileName = gstatInput.txt
+PermeabilityInputFileName = permeab.dat
+
+### SoilType = 1 ### (Zurich coarse, MUSIS sand)
+[SpatialParams.Coarse]
+Permeability1 = 7.0e-10 #Kozeny-Carman; 1.387e-11 measured?
+Porosity1 = 0.44
+Swr1 = 0.005
+Snr1 = 0.01
+VgAlpha1 = 8.74e-4 
+VgN1 = 3.35
+PlotMaterialLaw1 = false
+LambdaSolid1 = 5.26
+
+Pentry1 = 1012
+BCLambda1 = 3.277
+
+### SoilType = 2 ### (Zurich fine)
+[SpatialParams.Medium]
+Permeability2 = 2.65e-10
+Porosity2 = 0.41
+Swr2 = 0.005
+Snr2 = 0.01
+VgAlpha2 = 6.371e-4
+VgN2 = 8.0 # before: 6.9
+PlotMaterialLaw2 = false
+LambdaSolid2 = 5.26
+
+Pentry2 = 1357
+BCLambda2 = 6.960
+
+### SoilType = 4 ### (Zurich fine)
+[SpatialParams.LeverettJ]
+PermeabilityJ = 1.0e-09
+PorosityJ = 0.41
+PlotMaterialLawJ = false
+
+### SoilType = 3 ### (Colorado)
+[SpatialParams.Fine]
+Permeability3 = 1.06e-10
+Porosity3 = 0.334
+Swr3 = 0.028
+Snr3 = 0.01
+VgAlpha3 = 5.81e-4
+VgN3 = 17.8
+PlotMaterialLaw3 = false
+LambdaSolid3 = 5.26
+
+Pentry3 = 1012
+BCLambda3 = 3.277
+
+#############################################################
+[Newton]
+#############################################################
+RelTolerance = 1e-5
+TargetSteps = 8
+MaxSteps = 12
+WriteConvergence = false 
+MaxTimeStepDivisions = 20 # should be in group Implicit
+
+#############################################################
+[LinearSolver]
+#############################################################
+ResidualReduction = 1e-9
+Verbosity = 0
+MaxIterations = 200
+#GMResRestart = 100
+#PreconditionerIterations = 2
diff --git a/test/multidomain/Makefile.am b/test/multidomain/Makefile.am
index 08f06370a2..2db4fddc7f 100644
--- a/test/multidomain/Makefile.am
+++ b/test/multidomain/Makefile.am
@@ -1,5 +1,6 @@
 SUBDIRS = \
-  2cstokes2p2c
+  2cstokes2p2c \
+  2cnistokes2p2cni
 
 EXTRA_DIST = CMakeLists.txt
 
-- 
GitLab