From 54518cec5e9ea5f0f47d63529a61ddfaed29582e Mon Sep 17 00:00:00 2001
From: Bernd Flemisch <bernd@iws.uni-stuttgart.de>
Date: Thu, 21 Jan 2016 09:30:42 +0100
Subject: [PATCH] [folder structure] rename files in dumux/multidomain, adapt
 includes

---
 .../2cnistokes2p2cnilocaloperator.hh          |  541 +--------
 .../2cnistokes2p2cniproperties.hh             |   58 +-
 .../2cnistokes2p2cnipropertydefaults.hh       |   46 +-
 .../2cnistokes2p2cni/localoperator.hh         |  539 +++++++++
 .../2cnistokes2p2cni/properties.hh            |   58 +
 .../2cnistokes2p2cni/propertydefaults.hh      |   46 +
 .../2cstokes2p2c/2cstokes2p2clocaloperator.hh | 1010 +----------------
 .../2cstokes2p2cnewtoncontroller.hh           |   70 +-
 .../2cstokes2p2c/2cstokes2p2cproperties.hh    |   60 +-
 .../2cstokes2p2cpropertydefaults.hh           |   66 +-
 .../multidomain/2cstokes2p2c/localoperator.hh | 1008 ++++++++++++++++
 .../2cstokes2p2c/newtoncontroller.hh          |   68 ++
 dumux/multidomain/2cstokes2p2c/properties.hh  |   60 +
 .../2cstokes2p2c/propertydefaults.hh          |   66 ++
 dumux/multidomain/common/assembler.hh         |  218 ++++
 dumux/multidomain/common/convergencewriter.hh |  150 +++
 dumux/multidomain/common/localoperator.hh     |  134 +++
 dumux/multidomain/common/model.hh             |  335 ++++++
 .../common/multidomainassembler.hh            |  220 +---
 .../common/multidomainconvergencewriter.hh    |  152 +--
 .../common/multidomainlocaloperator.hh        |  136 +--
 dumux/multidomain/common/multidomainmodel.hh  |  337 +-----
 .../common/multidomainnewtoncontroller.hh     |  312 +----
 .../multidomain/common/multidomainproblem.hh  |  451 +-------
 .../common/multidomainproperties.hh           |  115 +-
 .../common/multidomainpropertydefaults.hh     |  258 +----
 dumux/multidomain/common/newtoncontroller.hh  |  312 +++++
 dumux/multidomain/common/problem.hh           |  449 ++++++++
 dumux/multidomain/common/properties.hh        |  113 ++
 dumux/multidomain/common/propertydefaults.hh  |  255 +++++
 dumux/multidomain/common/splitandmerge.hh     |    2 +-
 .../common/subdomainpropertydefaults.hh       |    4 +-
 .../2cnistokes2p2cniproblem.hh                |    6 +-
 .../2cnistokes2p2cni/2p2cnisubproblem.hh      |    2 +-
 .../2cnizeroeq2p2cniproblem.hh                |    6 +-
 .../2cnizeroeq2p2cni/2p2cnisubproblem.hh      |    2 +-
 .../2cstokes2p2c/2cstokes2p2cproblem.hh       |    6 +-
 .../2cstokes2p2c/2p2csubproblem.hh            |    2 +-
 .../2czeroeq2p2c/2czeroeq2p2cproblem.hh       |    6 +-
 .../2czeroeq2p2c/2p2csubproblem.hh            |    2 +-
 40 files changed, 3900 insertions(+), 3781 deletions(-)
 create mode 100644 dumux/multidomain/2cnistokes2p2cni/localoperator.hh
 create mode 100644 dumux/multidomain/2cnistokes2p2cni/properties.hh
 create mode 100644 dumux/multidomain/2cnistokes2p2cni/propertydefaults.hh
 create mode 100644 dumux/multidomain/2cstokes2p2c/localoperator.hh
 create mode 100644 dumux/multidomain/2cstokes2p2c/newtoncontroller.hh
 create mode 100644 dumux/multidomain/2cstokes2p2c/properties.hh
 create mode 100644 dumux/multidomain/2cstokes2p2c/propertydefaults.hh
 create mode 100644 dumux/multidomain/common/assembler.hh
 create mode 100644 dumux/multidomain/common/convergencewriter.hh
 create mode 100644 dumux/multidomain/common/localoperator.hh
 create mode 100644 dumux/multidomain/common/model.hh
 create mode 100644 dumux/multidomain/common/newtoncontroller.hh
 create mode 100644 dumux/multidomain/common/problem.hh
 create mode 100644 dumux/multidomain/common/properties.hh
 create mode 100644 dumux/multidomain/common/propertydefaults.hh

diff --git a/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh b/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh
index dcefe47184..cc15559ac8 100644
--- a/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh
+++ b/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh
@@ -1,539 +1,8 @@
-// -*- 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 This local operator extends the 2cstokes2p2clocaloperator
- *        by non-isothermal conditions.
- */
-#ifndef DUMUX_TWOCNISTOKES2P2CNILOCALOPERATOR_HH
-#define DUMUX_TWOCNISTOKES2P2CNILOCALOPERATOR_HH
+#ifndef DUMUX_TWOCNISTOKES2P2CNILOCALOPERATOR_HH_OLD
+#define DUMUX_TWOCNISTOKES2P2CNILOCALOPERATOR_HH_OLD
 
-#include <dune/common/deprecated.hh>
+#warning this header is deprecated, use dumux/multidomain/2cnistokes2p2cni/localoperator.hh instead
 
-#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh>
+#include <dumux/multidomain/2cnistokes2p2cni/localoperator.hh>
 
-namespace Dumux {
-
-/*!
- * \ingroup TwoPTwoCNIStokesTwoCNIModel
- * \ingroup TwoPTwoCNIZeroEqTwoCNIModel
- * \brief The extension of the local operator for the coupling of a two-component Stokes model
- *        and a two-phase two-component Darcy model for non-isothermal conditions.
- *
- * This model implements the coupling between a free-flow model
- * and a porous-medium flow model under non-isothermal conditions.
- * Here the coupling conditions for the individual balance are presented:
- *
- * The total mass balance equation:
- * \f[
- *  \left[
- *    \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{ff}
- *  = -\left[
- *      \left( \varrho_\textrm{g} \boldsymbol{v}_\textrm{g}
- *             + \varrho_\textrm{l} \boldsymbol{v}_\textrm{l} \right) \cdot \boldsymbol{n}
- *    \right]^\textrm{pm}
- * \f]
- * in which \f$n\f$ represents a vector normal to the interface pointing outside of
- * the specified subdomain.
- *
- * The momentum balance (tangential), which corresponds to the Beavers-Jospeh Saffman condition:
- * \f[
- *  \left[
- *   \left( {\boldsymbol{v}}_\textrm{g}
- *          + \frac{\sqrt{\left(\boldsymbol{K} \boldsymbol{t}_i \right) \cdot \boldsymbol{t}_i}}
- *                 {\alpha_\textrm{BJ} \mu_\textrm{g}} \boldsymbol{{\tau}}_\textrm{t} \boldsymbol{n}
- *          \right) \cdot \boldsymbol{t}_i
- *  \right]^\textrm{ff}
- *  = 0
- * \f]
- * with
- * \f$
- * \boldsymbol{{\tau}_\textrm{t}} = \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right]
- *                                  \nabla \left( \boldsymbol{v}_\textrm{g}
- *                                                + \boldsymbol{v}_\textrm{g}^\intercal \right)
- * \f$
- * in which the eddy viscosity \f$ \mu_\textrm{g,t} = 0 \f$ for the Stokes equation.
- *
- * The momentum balance (normal):
- * \f[
- *  \left[
- *    \left(
- *      \left\lbrace
- *        \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} {\boldsymbol{v}}_\textrm{g}^\intercal
- *        - \boldsymbol{{\tau}}_\textrm{t}
- *        + {p}_\textrm{g} \boldsymbol{I}
- *      \right\rbrace \boldsymbol{n}
- *    \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{ff}
- *  = p_\textrm{g}^\textrm{pm}
- * \f]
- *
- * The component mass balance equation (continuity of fluxes):
- * \f[
- *  \left[
- *    \left(
- *      \varrho_\textrm{g} {X}^\kappa_\textrm{g} {\boldsymbol{v}}_\textrm{g}
- *      - {\boldsymbol{j}}^\kappa_\textrm{g,ff,t,diff}
- *    \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{ff}
- *  = -\left[
- *    \left(
- *      \varrho_\textrm{g} X^\kappa_\textrm{g} \boldsymbol{v}_\textrm{g}
- *      - \boldsymbol{j}^\kappa_\textrm{g,pm,diff}
- *      + \varrho_\textrm{l} \boldsymbol{v}_\textrm{l} X^\kappa_\textrm{l}
- *      - \boldsymbol{j}^\kappa_\textrm{l,pm,diff}
- *    \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{pm}
- *  = 0
- * \f]
- * in which the diffusive fluxes \f$ j_\textrm{diff} \f$ are the diffusive fluxes as
- * they are implemented in the individual subdomain models.
- *
- * The component mass balance equation (continuity of mass/ mole fractions):
- * \f[
- *  \left[ {X}^{\kappa}_\textrm{g} \right]^\textrm{ff}
- *  = \left[ X^{\kappa}_\textrm{g} \right]^\textrm{pm}
- * \f]
- *
- * The energy balance equation (continuity of fluxes):
- * \f[
- *  \left[
- *    \left(
- *      \varrho_\textrm{g} {h}_\textrm{g} {\boldsymbol{v}}_\textrm{g}
- *      - {h}^\textrm{a}_\textrm{g} {\boldsymbol{j}}^\textrm{a}_\textrm{g,ff,t,diff}
- *      - {h}^\textrm{w}_\textrm{g} {\boldsymbol{j}}^\textrm{w}_\textrm{g,ff,t,diff}
- *      - \left( \lambda_\textrm{g} + \lambda_\textrm{g,t} \right) \nabla {T}
- *    \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{ff}
- *  = -\left[
- *       \left(
- *         \varrho_\textrm{g} h_\textrm{g} \boldsymbol{v}_\textrm{g}
- *         + \varrho_\textrm{l} h_\textrm{l} \boldsymbol{v}_\textrm{l}
- *         - \lambda_\textrm{pm} \nabla T
- *      \right) \cdot \boldsymbol{n}
- *    \right]^\textrm{pm}
- * \f]
- *
- * The energy balance equation (continuity of temperature):
- * \f[
- *  \left[ {T} \right]^\textrm{ff}
- *  = \left[ T \right]^\textrm{pm}
- * \f]
- *
- * This is discretized by a fully-coupled vertex-centered finite volume
- * (box) scheme in space and by the implicit Euler method in time.
- */
-template<class TypeTag>
-class TwoCNIStokesTwoPTwoCNILocalOperator :
-        public TwoCStokesTwoPTwoCLocalOperator<TypeTag>
-{
-public:
-    typedef TwoCStokesTwoPTwoCLocalOperator<TypeTag> ParentType;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) GlobalProblem;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) Stokes2cniTypeTag;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TwoPTwoCNITypeTag;
-
-    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
-
-    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, FluxVariables) BoundaryVariables1;
-    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, FluxVariables) BoundaryVariables2;
-
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
-
-    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, GridView) Stokes2cniGridView;
-    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, GridView) TwoPTwoCNIGridView;
-    typedef typename Stokes2cniGridView::template Codim<0>::Entity SDElement1;
-    typedef typename TwoPTwoCNIGridView::template Codim<0>::Entity SDElement2;
-
-    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, Indices) Stokes2cniIndices;
-    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, Indices) TwoPTwoCNIIndices;
-
-    enum {
-        dimWorld = MDGrid::dimensionworld
-    };
-
-    // Stokes
-    enum { numComponents1 = Stokes2cniIndices::numComponents };
-    enum { // equation indices
-        energyEqIdx1 = Stokes2cniIndices::energyEqIdx             //!< Index of the energy balance equation
-    };
-    enum { // component indices
-        transportCompIdx1 = Stokes2cniIndices::transportCompIdx,  //!< Index of transported component
-        phaseCompIdx1 = Stokes2cniIndices::phaseCompIdx           //!< Index of main component of the phase
-    };
-
-    // Darcy
-    enum { numPhases2 = GET_PROP_VALUE(TwoPTwoCNITypeTag, NumPhases) };
-    enum { // equation indices
-        energyEqIdx2 = TwoPTwoCNIIndices::energyEqIdx      //!< Index of the energy balance equation
-    };
-    enum { // phase indices
-        wPhaseIdx2 = TwoPTwoCNIIndices::wPhaseIdx,          //!< Index for the liquid phase
-        nPhaseIdx2 = TwoPTwoCNIIndices::nPhaseIdx           //!< Index for the gas phase
-    };
-
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename MDGrid::ctype CoordScalar;
-    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
-
-    // multidomain flags
-    static const bool doAlphaCoupling = true;
-    static const bool doPatternCoupling = true;
-
-    TwoCNIStokesTwoPTwoCNILocalOperator(GlobalProblem& globalProblem)
-        : ParentType(globalProblem)
-    { }
-
-public:
-    //! \copydoc Dumux::TwoCStokesTwoPTwoCLocalOperator::evalCoupling()
-    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
-    void evalCoupling(const LFSU1& lfsu1, const LFSU2& lfsu2,
-                      const int vertInElem1, const int vertInElem2,
-                      const SDElement1& sdElement1, const SDElement2& sdElement2,
-                      const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
-                      const CParams &cParams,
-                      RES1& couplingRes1, RES2& couplingRes2) const
-    {
-        // evaluate coupling of mass and momentum balances
-        ParentType::evalCoupling(lfsu1, lfsu2,
-                                 vertInElem1, vertInElem2,
-                                 sdElement1, sdElement2,
-                                 boundaryVars1, boundaryVars2,
-                                 cParams,
-                                 couplingRes1, couplingRes2);
-
-        const GlobalPosition& globalPos1 = cParams.fvGeometry1.subContVol[vertInElem1].global;
-        const GlobalPosition& globalPos2 = cParams.fvGeometry2.subContVol[vertInElem2].global;
-
-        // ENERGY Balance
-        // Neumann-like conditions
-        if (cParams.boundaryTypes1.isCouplingNeumann(energyEqIdx1))
-        {
-            if (this->globalProblem().sdProblem2().isCornerPoint(globalPos2))
-            {
-                // convective energy flux (enthalpy is mass based, mass flux also needed for useMoles)
-                Scalar convectiveFlux = 0.0;
-                for (int phaseIdx=0; phaseIdx<numPhases2; ++phaseIdx)
-                {
-                    convectiveFlux -= boundaryVars2.volumeFlux(phaseIdx)
-                                      * cParams.elemVolVarsCur2[vertInElem2].density(phaseIdx)
-                                      * cParams.elemVolVarsCur2[vertInElem2].enthalpy(phaseIdx);
-                }
-
-                // conductive energy flux
-                Scalar conductiveFlux = boundaryVars2.normalMatrixHeatFlux();
-
-                couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
-                                        -(convectiveFlux - conductiveFlux));
-            }
-            else
-            {
-                couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
-                                        this->globalProblem().localResidual2().residual(vertInElem2)[energyEqIdx2]);
-            }
-        }
-        if (cParams.boundaryTypes2.isCouplingNeumann(energyEqIdx2))
-        {
-            const GlobalPosition& bfNormal1 = boundaryVars1.face().normal;
-            // only enter here, if a boundary layer model is used for the computation of the diffusive fluxes
-            if (ParentType::blModel_)
-            {
-                // convective energy flux (enthalpy is mass based, mass flux also needed for useMoles)
-                Scalar convectiveFlux = boundaryVars1.normalVelocity()
-                                        * cParams.elemVolVarsCur1[vertInElem1].density()
-                                        * cParams.elemVolVarsCur1[vertInElem1].enthalpy();
-
-                // conductive energy flux
-                Scalar conductiveFlux = bfNormal1.two_norm()
-                                        * evalBoundaryLayerTemperatureGradient(cParams, vertInElem1)
-                                        * (boundaryVars1.thermalConductivity()
-                                           + boundaryVars1.thermalEddyConductivity());
-
-                // enthalpy transported by diffusive fluxes
-                Scalar sumDiffusiveFluxes = 0.0;
-                Scalar sumDiffusiveEnergyFlux = 0.0;
-                for (int compIdx=0; compIdx < numComponents1; compIdx++)
-                {
-                    if (compIdx != phaseCompIdx1)
-                    {
-                        Scalar diffusiveFlux = bfNormal1.two_norm()
-                                               * ParentType::evalBoundaryLayerConcentrationGradient(cParams, vertInElem1)
-                                               * (boundaryVars1.diffusionCoeff(compIdx)
-                                                  + boundaryVars1.eddyDiffusivity())
-                                               * boundaryVars1.molarDensity()
-                                               * ParentType::evalMassTransferCoefficient(cParams, vertInElem1, vertInElem2);
-                        sumDiffusiveFluxes += diffusiveFlux;
-                        sumDiffusiveEnergyFlux += diffusiveFlux
-                                                  * boundaryVars1.componentEnthalpy(compIdx)
-                                                  * FluidSystem::molarMass(compIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]
-                    }
-                }
-                sumDiffusiveEnergyFlux -= sumDiffusiveFluxes
-                                          * boundaryVars1.componentEnthalpy(phaseCompIdx1)
-                                          * FluidSystem::molarMass(phaseCompIdx1);
-
-                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
-                                        -(convectiveFlux - sumDiffusiveEnergyFlux - conductiveFlux));
-            }
-            else if (this->globalProblem().sdProblem1().isCornerPoint(globalPos1))
-            {
-                // convective energy flux (enthalpy is mass based, mass flux also needed for useMoles)
-                Scalar convectiveFlux = boundaryVars1.normalVelocity()
-                                        * cParams.elemVolVarsCur1[vertInElem1].density()
-                                        * cParams.elemVolVarsCur1[vertInElem1].enthalpy();
-
-                // conductive energy flux
-                Scalar conductiveFlux = bfNormal1
-                                        * boundaryVars1.temperatureGrad()
-                                        * (boundaryVars1.thermalConductivity()
-                                           + boundaryVars1.thermalEddyConductivity());
-
-                // enthalpy transported by diffusive fluxes
-                Scalar sumDiffusiveFluxes = 0.0;
-                Scalar sumDiffusiveEnergyFlux = 0.0;
-                for (int compIdx=0; compIdx < numComponents1; compIdx++)
-                {
-                    if (compIdx != phaseCompIdx1)
-                    {
-                        Scalar diffusiveFlux = bfNormal1
-                                               * boundaryVars1.moleFractionGrad(compIdx)
-                                               * (boundaryVars1.diffusionCoeff(compIdx)
-                                                  + boundaryVars1.eddyDiffusivity())
-                                               * boundaryVars1.molarDensity();
-                        sumDiffusiveFluxes += diffusiveFlux;
-                        sumDiffusiveEnergyFlux += diffusiveFlux
-                                                  * boundaryVars1.componentEnthalpy(compIdx)
-                                                  * FluidSystem::molarMass(compIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]
-                    }
-                }
-                sumDiffusiveEnergyFlux -= sumDiffusiveFluxes
-                                          * boundaryVars1.componentEnthalpy(phaseCompIdx1)
-                                          * FluidSystem::molarMass(phaseCompIdx1);
-
-                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
-                                        -(convectiveFlux - sumDiffusiveEnergyFlux - conductiveFlux));
-            }
-            else
-            {
-                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
-                                        this->globalProblem().localResidual1().residual(vertInElem1)[energyEqIdx1]);
-            }
-        }
-
-        // Dirichlet-like conditions
-        if (cParams.boundaryTypes1.isCouplingDirichlet(energyEqIdx1))
-        {
-            // set residualStokes[energyIdx1] = T in stokesncnicouplinglocalresidual.hh
-            couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
-                                    -cParams.elemVolVarsCur2[vertInElem2].temperature());
-        }
-
-        if (cParams.boundaryTypes2.isCouplingDirichlet(energyEqIdx2))
-        {
-            // set residualDarcy[energyEqIdx2] = T in 2p2cnicouplinglocalresidual.hh
-            couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
-                                    -cParams.elemVolVarsCur1[vertInElem1].temperature());
-        }
-    }
-
-    //! \copydoc Dumux::TwoCStokesTwoPTwoCLocalOperator::evalCoupling12()
-    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
-    DUNE_DEPRECATED_MSG("evalCoupling12() is deprecated. Use evalCoupling() instead.")
-    void evalCoupling12(const LFSU1& lfsu1, const LFSU2& lfsu2,
-                        const int vertInElem1, const int vertInElem2,
-                        const SDElement1& sdElement1, const SDElement2& sdElement2,
-                        const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
-                        const CParams &cParams,
-                        RES1& couplingRes1, RES2& couplingRes2) const
-    {
-        const GlobalPosition& globalPos1 = cParams.fvGeometry1.subContVol[vertInElem1].global;
-        const GlobalPosition& bfNormal1 = boundaryVars1.face().normal;
-        const Scalar normalMassFlux1 = boundaryVars1.normalVelocity() *
-            cParams.elemVolVarsCur1[vertInElem1].density();
-        GlobalProblem& globalProblem = this->globalProblem();
-
-        // evaluate coupling of mass and momentum balances
-        ParentType::evalCoupling12(lfsu1, lfsu2,
-                                   vertInElem1, vertInElem2,
-                                   sdElement1, sdElement2,
-                                   boundaryVars1, boundaryVars2,
-                                   cParams,
-                                   couplingRes1, couplingRes2);
-
-        if (cParams.boundaryTypes2.isCouplingNeumann(energyEqIdx2))
-        {
-            // only enter here, if a boundary layer model is used for the computation of the diffusive fluxes
-            if (ParentType::blModel_)
-            {
-                // convective energy flux
-                const Scalar convectiveFlux = normalMassFlux1
-                                              * cParams.elemVolVarsCur1[vertInElem1].enthalpy();
-
-                // enthalpy transported by diffusive fluxes
-                // multiply the diffusive flux with the mass transfer coefficient
-                static_assert(numComponents1 == 2,
-                              "This coupling condition is only implemented for two components.");
-                Scalar diffusiveEnergyFlux = 0.0;
-                Scalar diffusiveFlux = bfNormal1.two_norm()
-                                       * ParentType::evalBoundaryLayerConcentrationGradient(cParams, vertInElem1)
-                                       * (boundaryVars1.diffusionCoeff(transportCompIdx1)
-                                          + boundaryVars1.eddyDiffusivity())
-                                       * boundaryVars1.molarDensity()
-                                       * ParentType::evalMassTransferCoefficient(cParams, vertInElem1, vertInElem2);
-
-                diffusiveEnergyFlux += diffusiveFlux * FluidSystem::molarMass(transportCompIdx1)
-                                       * boundaryVars1.componentEnthalpy(transportCompIdx1);
-                diffusiveEnergyFlux -= diffusiveFlux * FluidSystem::molarMass(phaseCompIdx1)
-                                       * boundaryVars1.componentEnthalpy(phaseCompIdx1);
-
-                // conductive transported energy
-                const Scalar conductiveFlux = bfNormal1.two_norm()
-                                              * evalBoundaryLayerTemperatureGradient(cParams, vertInElem1)
-                                              * (boundaryVars1.thermalConductivity()
-                                                 + boundaryVars1.thermalEddyConductivity());
-
-                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
-                                        -(convectiveFlux - diffusiveEnergyFlux - conductiveFlux));
-            }
-            else if (globalProblem.sdProblem1().isCornerPoint(globalPos1))
-            {
-                const Scalar convectiveFlux =
-                    normalMassFlux1 *
-                    cParams.elemVolVarsCur1[vertInElem1].enthalpy();
-                const Scalar conductiveFlux =
-                    bfNormal1 *
-                    boundaryVars1.temperatureGrad() *
-                    (boundaryVars1.thermalConductivity() + boundaryVars1.thermalEddyConductivity());
-                Scalar sumDiffusiveFluxes = 0.0;
-                Scalar sumDiffusiveEnergyFlux = 0.0;
-                for (int compIdx=0; compIdx < numComponents1; compIdx++)
-                {
-                    if (compIdx != phaseCompIdx1)
-                    {
-                        Scalar diffusiveFlux = boundaryVars1.moleFractionGrad(compIdx)
-                                               * boundaryVars1.face().normal
-                                               *(boundaryVars1.diffusionCoeff(compIdx) + boundaryVars1.eddyDiffusivity())
-                                               * boundaryVars1.molarDensity();
-                        sumDiffusiveFluxes += diffusiveFlux;
-                        sumDiffusiveEnergyFlux += diffusiveFlux
-                                                  * boundaryVars1.componentEnthalpy(compIdx)
-                                                  * FluidSystem::molarMass(compIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]
-                    }
-                }
-                sumDiffusiveEnergyFlux -= sumDiffusiveFluxes * boundaryVars1.componentEnthalpy(phaseCompIdx1)
-                                          * FluidSystem::molarMass(phaseCompIdx1);
-                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
-                                        -(convectiveFlux - sumDiffusiveEnergyFlux - conductiveFlux));
-            }
-            else
-            {
-                // the energy flux from the Stokes domain
-                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
-                                        globalProblem.localResidual1().residual(vertInElem1)[energyEqIdx1]);
-            }
-        }
-        if (cParams.boundaryTypes2.isCouplingDirichlet(energyEqIdx2))
-        {
-            // set residualDarcy[energyEqIdx2] = T in 2p2cnilocalresidual.hh
-            couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
-                                    -cParams.elemVolVarsCur1[vertInElem1].temperature());
-        }
-    }
-
-    //! \copydoc Dumux::TwoCStokesTwoPTwoCLocalOperator::evalCoupling21()
-    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
-    DUNE_DEPRECATED_MSG("evalCoupling21() is deprecated. Use evalCoupling() instead.")
-    void evalCoupling21(const LFSU1& lfsu1, const LFSU2& lfsu2,
-                        const int vertInElem1, const int vertInElem2,
-                        const SDElement1& sdElement1, const SDElement2& sdElement2,
-                        const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
-                        const CParams &cParams,
-                        RES1& couplingRes1, RES2& couplingRes2) const
-    {
-        GlobalProblem& globalProblem = this->globalProblem();
-
-        // evaluate coupling of mass and momentum balances
-        ParentType::evalCoupling21(lfsu1, lfsu2,
-                                   vertInElem1, vertInElem2,
-                                   sdElement1, sdElement2,
-                                   boundaryVars1, boundaryVars2,
-                                   cParams,
-                                   couplingRes1, couplingRes2);
-
-        const GlobalPosition& globalPos2 = cParams.fvGeometry2.subContVol[vertInElem2].global;
-        GlobalPosition normalMassFlux2(0.);
-
-        // velocity*normal*area*rho
-        // mass flux is needed for both (mass/mole) formulation, as the enthalpy is mass based
-        for (int phaseIdx=0; phaseIdx<numPhases2; ++phaseIdx)
-            normalMassFlux2[phaseIdx] = -boundaryVars2.volumeFlux(phaseIdx)*
-                cParams.elemVolVarsCur2[vertInElem2].density(phaseIdx);
-
-        if (cParams.boundaryTypes1.isCouplingDirichlet(energyEqIdx1))
-        {
-            // set residualStokes[energyIdx1] = T in stokes2cnilocalresidual.hh
-            couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
-                                    -cParams.elemVolVarsCur2[vertInElem2].temperature());
-        }
-        if (cParams.boundaryTypes1.isCouplingNeumann(energyEqIdx1))
-        {
-            if (globalProblem.sdProblem2().isCornerPoint(globalPos2))
-            {
-                const Scalar convectiveFlux = normalMassFlux2[nPhaseIdx2] *
-                    cParams.elemVolVarsCur2[vertInElem2].enthalpy(nPhaseIdx2)
-                    +
-                    normalMassFlux2[wPhaseIdx2] *
-                    cParams.elemVolVarsCur2[vertInElem2].enthalpy(wPhaseIdx2);
-                const Scalar conductiveFlux = boundaryVars2.normalMatrixHeatFlux();
-
-                couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
-                                        -(convectiveFlux - conductiveFlux));
-            }
-            else
-            {
-                couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
-                                        globalProblem.localResidual2().residual(vertInElem2)[energyEqIdx2]);
-            }
-        }
-    }
-
-    /*!
-     * \brief Returns the temperature gradient through the boundary layer
-     *
-     * \todo This function could be moved to a more model specific place, because
-     *       of its runtime parameters.
-     *
-     * \param cParams a parameter container
-     * \param scvIdx1 The local index of the sub-control volume of the Stokes domain
-     */
-    template<typename CParams>
-    Scalar evalBoundaryLayerTemperatureGradient(CParams cParams, const int scvIdx) const
-    {
-        const Scalar temperatureOut = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefTemperature);
-        Scalar normalTemperatureGrad = cParams.elemVolVarsCur1[scvIdx].temperature()
-                                       - temperatureOut;
-        return normalTemperatureGrad
-               / ParentType::evalBoundaryLayerModel(cParams, scvIdx).thermalBoundaryLayerThickness();
-    }
-};
-} // end namespace Dumux
-
-#endif // DUMUX_TWOCNISTOKES2P2CNILOCALOPERATOR_HH
+#endif
diff --git a/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproperties.hh b/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproperties.hh
index 7c888bcfa1..b3f5ec4389 100644
--- a/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproperties.hh
+++ b/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproperties.hh
@@ -1,58 +1,8 @@
-// -*- 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 Properties
- * \ingroup ImplicitProperties
- * \ingroup MultidomainModel
- *
- * \brief Defines the properties required for the coupled 2cnistokes2p2cni model.
- */
+#ifndef DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTIES_HH_OLD
+#define DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTIES_HH_OLD
 
-#ifndef DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTIES_HH
-#define DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTIES_HH
-
-#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh>
-
-namespace Dumux
-{
-
-////////////////////////////////
-// properties
-////////////////////////////////
-namespace Properties
-{
-
-//////////////////////////////////////////////////////////////////
-// Type tags
-//////////////////////////////////////////////////////////////////
-
-//! The type tags for the coupled 2cnistokes2p2cni model
-NEW_TYPE_TAG(TwoCNIStokesTwoPTwoCNI, INHERITS_FROM(TwoCStokesTwoPTwoC));
-
-//////////////////////////////////////////////////////////////////
-// Property tags
-//////////////////////////////////////////////////////////////////
-
-} // end namespace properties
-
-} // end namespace Dumux
+#warning this header is deprecated, use dumux/multidomain/2cnistokes2p2cni/properties.hh instead
 
+#include <dumux/multidomain/2cnistokes2p2cni/properties.hh>
 
 #endif
diff --git a/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnipropertydefaults.hh b/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnipropertydefaults.hh
index d84e2d64c9..7765c8de8c 100644
--- a/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnipropertydefaults.hh
+++ b/dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnipropertydefaults.hh
@@ -1,46 +1,8 @@
-// -*- 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 Properties
- * \ingroup ImplicitProperties
- * \ingroup MultidomainModel
- *
- * \brief Defines default values for the properties required by the
- *        coupled 2cnistokes2p2cni model.
- */
-#ifndef DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTY_DEFAULTS_HH
-#define DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTY_DEFAULTS_HH
+#ifndef DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTY_DEFAULTS_HH_OLD
+#define DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTY_DEFAULTS_HH_OLD
 
-#include "2cnistokes2p2cniproperties.hh"
+#warning this header is deprecated, use dumux/multidomain/2cnistokes2p2cni/propertydefaults.hh instead
 
-namespace Dumux
-{
-namespace Properties
-{
-//////////////////////////////////////////////////////////////////
-// Property defaults
-//////////////////////////////////////////////////////////////////
-
-
-} // end namespace properties
-
-} // end namespace Dumux
+#include <dumux/multidomain/2cnistokes2p2cni/propertydefaults.hh>
 
 #endif
diff --git a/dumux/multidomain/2cnistokes2p2cni/localoperator.hh b/dumux/multidomain/2cnistokes2p2cni/localoperator.hh
new file mode 100644
index 0000000000..b033201b00
--- /dev/null
+++ b/dumux/multidomain/2cnistokes2p2cni/localoperator.hh
@@ -0,0 +1,539 @@
+// -*- 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 This local operator extends the 2cstokes2p2clocaloperator
+ *        by non-isothermal conditions.
+ */
+#ifndef DUMUX_TWOCNISTOKES2P2CNILOCALOPERATOR_HH
+#define DUMUX_TWOCNISTOKES2P2CNILOCALOPERATOR_HH
+
+#include <dune/common/deprecated.hh>
+
+#include <dumux/multidomain/2cstokes2p2c/localoperator.hh>
+
+namespace Dumux {
+
+/*!
+ * \ingroup TwoPTwoCNIStokesTwoCNIModel
+ * \ingroup TwoPTwoCNIZeroEqTwoCNIModel
+ * \brief The extension of the local operator for the coupling of a two-component Stokes model
+ *        and a two-phase two-component Darcy model for non-isothermal conditions.
+ *
+ * This model implements the coupling between a free-flow model
+ * and a porous-medium flow model under non-isothermal conditions.
+ * Here the coupling conditions for the individual balance are presented:
+ *
+ * The total mass balance equation:
+ * \f[
+ *  \left[
+ *    \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{ff}
+ *  = -\left[
+ *      \left( \varrho_\textrm{g} \boldsymbol{v}_\textrm{g}
+ *             + \varrho_\textrm{l} \boldsymbol{v}_\textrm{l} \right) \cdot \boldsymbol{n}
+ *    \right]^\textrm{pm}
+ * \f]
+ * in which \f$n\f$ represents a vector normal to the interface pointing outside of
+ * the specified subdomain.
+ *
+ * The momentum balance (tangential), which corresponds to the Beavers-Jospeh Saffman condition:
+ * \f[
+ *  \left[
+ *   \left( {\boldsymbol{v}}_\textrm{g}
+ *          + \frac{\sqrt{\left(\boldsymbol{K} \boldsymbol{t}_i \right) \cdot \boldsymbol{t}_i}}
+ *                 {\alpha_\textrm{BJ} \mu_\textrm{g}} \boldsymbol{{\tau}}_\textrm{t} \boldsymbol{n}
+ *          \right) \cdot \boldsymbol{t}_i
+ *  \right]^\textrm{ff}
+ *  = 0
+ * \f]
+ * with
+ * \f$
+ * \boldsymbol{{\tau}_\textrm{t}} = \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right]
+ *                                  \nabla \left( \boldsymbol{v}_\textrm{g}
+ *                                                + \boldsymbol{v}_\textrm{g}^\intercal \right)
+ * \f$
+ * in which the eddy viscosity \f$ \mu_\textrm{g,t} = 0 \f$ for the Stokes equation.
+ *
+ * The momentum balance (normal):
+ * \f[
+ *  \left[
+ *    \left(
+ *      \left\lbrace
+ *        \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} {\boldsymbol{v}}_\textrm{g}^\intercal
+ *        - \boldsymbol{{\tau}}_\textrm{t}
+ *        + {p}_\textrm{g} \boldsymbol{I}
+ *      \right\rbrace \boldsymbol{n}
+ *    \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{ff}
+ *  = p_\textrm{g}^\textrm{pm}
+ * \f]
+ *
+ * The component mass balance equation (continuity of fluxes):
+ * \f[
+ *  \left[
+ *    \left(
+ *      \varrho_\textrm{g} {X}^\kappa_\textrm{g} {\boldsymbol{v}}_\textrm{g}
+ *      - {\boldsymbol{j}}^\kappa_\textrm{g,ff,t,diff}
+ *    \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{ff}
+ *  = -\left[
+ *    \left(
+ *      \varrho_\textrm{g} X^\kappa_\textrm{g} \boldsymbol{v}_\textrm{g}
+ *      - \boldsymbol{j}^\kappa_\textrm{g,pm,diff}
+ *      + \varrho_\textrm{l} \boldsymbol{v}_\textrm{l} X^\kappa_\textrm{l}
+ *      - \boldsymbol{j}^\kappa_\textrm{l,pm,diff}
+ *    \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{pm}
+ *  = 0
+ * \f]
+ * in which the diffusive fluxes \f$ j_\textrm{diff} \f$ are the diffusive fluxes as
+ * they are implemented in the individual subdomain models.
+ *
+ * The component mass balance equation (continuity of mass/ mole fractions):
+ * \f[
+ *  \left[ {X}^{\kappa}_\textrm{g} \right]^\textrm{ff}
+ *  = \left[ X^{\kappa}_\textrm{g} \right]^\textrm{pm}
+ * \f]
+ *
+ * The energy balance equation (continuity of fluxes):
+ * \f[
+ *  \left[
+ *    \left(
+ *      \varrho_\textrm{g} {h}_\textrm{g} {\boldsymbol{v}}_\textrm{g}
+ *      - {h}^\textrm{a}_\textrm{g} {\boldsymbol{j}}^\textrm{a}_\textrm{g,ff,t,diff}
+ *      - {h}^\textrm{w}_\textrm{g} {\boldsymbol{j}}^\textrm{w}_\textrm{g,ff,t,diff}
+ *      - \left( \lambda_\textrm{g} + \lambda_\textrm{g,t} \right) \nabla {T}
+ *    \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{ff}
+ *  = -\left[
+ *       \left(
+ *         \varrho_\textrm{g} h_\textrm{g} \boldsymbol{v}_\textrm{g}
+ *         + \varrho_\textrm{l} h_\textrm{l} \boldsymbol{v}_\textrm{l}
+ *         - \lambda_\textrm{pm} \nabla T
+ *      \right) \cdot \boldsymbol{n}
+ *    \right]^\textrm{pm}
+ * \f]
+ *
+ * The energy balance equation (continuity of temperature):
+ * \f[
+ *  \left[ {T} \right]^\textrm{ff}
+ *  = \left[ T \right]^\textrm{pm}
+ * \f]
+ *
+ * This is discretized by a fully-coupled vertex-centered finite volume
+ * (box) scheme in space and by the implicit Euler method in time.
+ */
+template<class TypeTag>
+class TwoCNIStokesTwoPTwoCNILocalOperator :
+        public TwoCStokesTwoPTwoCLocalOperator<TypeTag>
+{
+public:
+    typedef TwoCStokesTwoPTwoCLocalOperator<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) GlobalProblem;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) Stokes2cniTypeTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TwoPTwoCNITypeTag;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, FluxVariables) BoundaryVariables1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, FluxVariables) BoundaryVariables2;
+
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, GridView) Stokes2cniGridView;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, GridView) TwoPTwoCNIGridView;
+    typedef typename Stokes2cniGridView::template Codim<0>::Entity SDElement1;
+    typedef typename TwoPTwoCNIGridView::template Codim<0>::Entity SDElement2;
+
+    typedef typename GET_PROP_TYPE(Stokes2cniTypeTag, Indices) Stokes2cniIndices;
+    typedef typename GET_PROP_TYPE(TwoPTwoCNITypeTag, Indices) TwoPTwoCNIIndices;
+
+    enum {
+        dimWorld = MDGrid::dimensionworld
+    };
+
+    // Stokes
+    enum { numComponents1 = Stokes2cniIndices::numComponents };
+    enum { // equation indices
+        energyEqIdx1 = Stokes2cniIndices::energyEqIdx             //!< Index of the energy balance equation
+    };
+    enum { // component indices
+        transportCompIdx1 = Stokes2cniIndices::transportCompIdx,  //!< Index of transported component
+        phaseCompIdx1 = Stokes2cniIndices::phaseCompIdx           //!< Index of main component of the phase
+    };
+
+    // Darcy
+    enum { numPhases2 = GET_PROP_VALUE(TwoPTwoCNITypeTag, NumPhases) };
+    enum { // equation indices
+        energyEqIdx2 = TwoPTwoCNIIndices::energyEqIdx      //!< Index of the energy balance equation
+    };
+    enum { // phase indices
+        wPhaseIdx2 = TwoPTwoCNIIndices::wPhaseIdx,          //!< Index for the liquid phase
+        nPhaseIdx2 = TwoPTwoCNIIndices::nPhaseIdx           //!< Index for the gas phase
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename MDGrid::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+
+    // multidomain flags
+    static const bool doAlphaCoupling = true;
+    static const bool doPatternCoupling = true;
+
+    TwoCNIStokesTwoPTwoCNILocalOperator(GlobalProblem& globalProblem)
+        : ParentType(globalProblem)
+    { }
+
+public:
+    //! \copydoc Dumux::TwoCStokesTwoPTwoCLocalOperator::evalCoupling()
+    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
+    void evalCoupling(const LFSU1& lfsu1, const LFSU2& lfsu2,
+                      const int vertInElem1, const int vertInElem2,
+                      const SDElement1& sdElement1, const SDElement2& sdElement2,
+                      const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
+                      const CParams &cParams,
+                      RES1& couplingRes1, RES2& couplingRes2) const
+    {
+        // evaluate coupling of mass and momentum balances
+        ParentType::evalCoupling(lfsu1, lfsu2,
+                                 vertInElem1, vertInElem2,
+                                 sdElement1, sdElement2,
+                                 boundaryVars1, boundaryVars2,
+                                 cParams,
+                                 couplingRes1, couplingRes2);
+
+        const GlobalPosition& globalPos1 = cParams.fvGeometry1.subContVol[vertInElem1].global;
+        const GlobalPosition& globalPos2 = cParams.fvGeometry2.subContVol[vertInElem2].global;
+
+        // ENERGY Balance
+        // Neumann-like conditions
+        if (cParams.boundaryTypes1.isCouplingNeumann(energyEqIdx1))
+        {
+            if (this->globalProblem().sdProblem2().isCornerPoint(globalPos2))
+            {
+                // convective energy flux (enthalpy is mass based, mass flux also needed for useMoles)
+                Scalar convectiveFlux = 0.0;
+                for (int phaseIdx=0; phaseIdx<numPhases2; ++phaseIdx)
+                {
+                    convectiveFlux -= boundaryVars2.volumeFlux(phaseIdx)
+                                      * cParams.elemVolVarsCur2[vertInElem2].density(phaseIdx)
+                                      * cParams.elemVolVarsCur2[vertInElem2].enthalpy(phaseIdx);
+                }
+
+                // conductive energy flux
+                Scalar conductiveFlux = boundaryVars2.normalMatrixHeatFlux();
+
+                couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
+                                        -(convectiveFlux - conductiveFlux));
+            }
+            else
+            {
+                couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
+                                        this->globalProblem().localResidual2().residual(vertInElem2)[energyEqIdx2]);
+            }
+        }
+        if (cParams.boundaryTypes2.isCouplingNeumann(energyEqIdx2))
+        {
+            const GlobalPosition& bfNormal1 = boundaryVars1.face().normal;
+            // only enter here, if a boundary layer model is used for the computation of the diffusive fluxes
+            if (ParentType::blModel_)
+            {
+                // convective energy flux (enthalpy is mass based, mass flux also needed for useMoles)
+                Scalar convectiveFlux = boundaryVars1.normalVelocity()
+                                        * cParams.elemVolVarsCur1[vertInElem1].density()
+                                        * cParams.elemVolVarsCur1[vertInElem1].enthalpy();
+
+                // conductive energy flux
+                Scalar conductiveFlux = bfNormal1.two_norm()
+                                        * evalBoundaryLayerTemperatureGradient(cParams, vertInElem1)
+                                        * (boundaryVars1.thermalConductivity()
+                                           + boundaryVars1.thermalEddyConductivity());
+
+                // enthalpy transported by diffusive fluxes
+                Scalar sumDiffusiveFluxes = 0.0;
+                Scalar sumDiffusiveEnergyFlux = 0.0;
+                for (int compIdx=0; compIdx < numComponents1; compIdx++)
+                {
+                    if (compIdx != phaseCompIdx1)
+                    {
+                        Scalar diffusiveFlux = bfNormal1.two_norm()
+                                               * ParentType::evalBoundaryLayerConcentrationGradient(cParams, vertInElem1)
+                                               * (boundaryVars1.diffusionCoeff(compIdx)
+                                                  + boundaryVars1.eddyDiffusivity())
+                                               * boundaryVars1.molarDensity()
+                                               * ParentType::evalMassTransferCoefficient(cParams, vertInElem1, vertInElem2);
+                        sumDiffusiveFluxes += diffusiveFlux;
+                        sumDiffusiveEnergyFlux += diffusiveFlux
+                                                  * boundaryVars1.componentEnthalpy(compIdx)
+                                                  * FluidSystem::molarMass(compIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]
+                    }
+                }
+                sumDiffusiveEnergyFlux -= sumDiffusiveFluxes
+                                          * boundaryVars1.componentEnthalpy(phaseCompIdx1)
+                                          * FluidSystem::molarMass(phaseCompIdx1);
+
+                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
+                                        -(convectiveFlux - sumDiffusiveEnergyFlux - conductiveFlux));
+            }
+            else if (this->globalProblem().sdProblem1().isCornerPoint(globalPos1))
+            {
+                // convective energy flux (enthalpy is mass based, mass flux also needed for useMoles)
+                Scalar convectiveFlux = boundaryVars1.normalVelocity()
+                                        * cParams.elemVolVarsCur1[vertInElem1].density()
+                                        * cParams.elemVolVarsCur1[vertInElem1].enthalpy();
+
+                // conductive energy flux
+                Scalar conductiveFlux = bfNormal1
+                                        * boundaryVars1.temperatureGrad()
+                                        * (boundaryVars1.thermalConductivity()
+                                           + boundaryVars1.thermalEddyConductivity());
+
+                // enthalpy transported by diffusive fluxes
+                Scalar sumDiffusiveFluxes = 0.0;
+                Scalar sumDiffusiveEnergyFlux = 0.0;
+                for (int compIdx=0; compIdx < numComponents1; compIdx++)
+                {
+                    if (compIdx != phaseCompIdx1)
+                    {
+                        Scalar diffusiveFlux = bfNormal1
+                                               * boundaryVars1.moleFractionGrad(compIdx)
+                                               * (boundaryVars1.diffusionCoeff(compIdx)
+                                                  + boundaryVars1.eddyDiffusivity())
+                                               * boundaryVars1.molarDensity();
+                        sumDiffusiveFluxes += diffusiveFlux;
+                        sumDiffusiveEnergyFlux += diffusiveFlux
+                                                  * boundaryVars1.componentEnthalpy(compIdx)
+                                                  * FluidSystem::molarMass(compIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]
+                    }
+                }
+                sumDiffusiveEnergyFlux -= sumDiffusiveFluxes
+                                          * boundaryVars1.componentEnthalpy(phaseCompIdx1)
+                                          * FluidSystem::molarMass(phaseCompIdx1);
+
+                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
+                                        -(convectiveFlux - sumDiffusiveEnergyFlux - conductiveFlux));
+            }
+            else
+            {
+                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
+                                        this->globalProblem().localResidual1().residual(vertInElem1)[energyEqIdx1]);
+            }
+        }
+
+        // Dirichlet-like conditions
+        if (cParams.boundaryTypes1.isCouplingDirichlet(energyEqIdx1))
+        {
+            // set residualStokes[energyIdx1] = T in stokesncnicouplinglocalresidual.hh
+            couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
+                                    -cParams.elemVolVarsCur2[vertInElem2].temperature());
+        }
+
+        if (cParams.boundaryTypes2.isCouplingDirichlet(energyEqIdx2))
+        {
+            // set residualDarcy[energyEqIdx2] = T in 2p2cnicouplinglocalresidual.hh
+            couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
+                                    -cParams.elemVolVarsCur1[vertInElem1].temperature());
+        }
+    }
+
+    //! \copydoc Dumux::TwoCStokesTwoPTwoCLocalOperator::evalCoupling12()
+    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
+    DUNE_DEPRECATED_MSG("evalCoupling12() is deprecated. Use evalCoupling() instead.")
+    void evalCoupling12(const LFSU1& lfsu1, const LFSU2& lfsu2,
+                        const int vertInElem1, const int vertInElem2,
+                        const SDElement1& sdElement1, const SDElement2& sdElement2,
+                        const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
+                        const CParams &cParams,
+                        RES1& couplingRes1, RES2& couplingRes2) const
+    {
+        const GlobalPosition& globalPos1 = cParams.fvGeometry1.subContVol[vertInElem1].global;
+        const GlobalPosition& bfNormal1 = boundaryVars1.face().normal;
+        const Scalar normalMassFlux1 = boundaryVars1.normalVelocity() *
+            cParams.elemVolVarsCur1[vertInElem1].density();
+        GlobalProblem& globalProblem = this->globalProblem();
+
+        // evaluate coupling of mass and momentum balances
+        ParentType::evalCoupling12(lfsu1, lfsu2,
+                                   vertInElem1, vertInElem2,
+                                   sdElement1, sdElement2,
+                                   boundaryVars1, boundaryVars2,
+                                   cParams,
+                                   couplingRes1, couplingRes2);
+
+        if (cParams.boundaryTypes2.isCouplingNeumann(energyEqIdx2))
+        {
+            // only enter here, if a boundary layer model is used for the computation of the diffusive fluxes
+            if (ParentType::blModel_)
+            {
+                // convective energy flux
+                const Scalar convectiveFlux = normalMassFlux1
+                                              * cParams.elemVolVarsCur1[vertInElem1].enthalpy();
+
+                // enthalpy transported by diffusive fluxes
+                // multiply the diffusive flux with the mass transfer coefficient
+                static_assert(numComponents1 == 2,
+                              "This coupling condition is only implemented for two components.");
+                Scalar diffusiveEnergyFlux = 0.0;
+                Scalar diffusiveFlux = bfNormal1.two_norm()
+                                       * ParentType::evalBoundaryLayerConcentrationGradient(cParams, vertInElem1)
+                                       * (boundaryVars1.diffusionCoeff(transportCompIdx1)
+                                          + boundaryVars1.eddyDiffusivity())
+                                       * boundaryVars1.molarDensity()
+                                       * ParentType::evalMassTransferCoefficient(cParams, vertInElem1, vertInElem2);
+
+                diffusiveEnergyFlux += diffusiveFlux * FluidSystem::molarMass(transportCompIdx1)
+                                       * boundaryVars1.componentEnthalpy(transportCompIdx1);
+                diffusiveEnergyFlux -= diffusiveFlux * FluidSystem::molarMass(phaseCompIdx1)
+                                       * boundaryVars1.componentEnthalpy(phaseCompIdx1);
+
+                // conductive transported energy
+                const Scalar conductiveFlux = bfNormal1.two_norm()
+                                              * evalBoundaryLayerTemperatureGradient(cParams, vertInElem1)
+                                              * (boundaryVars1.thermalConductivity()
+                                                 + boundaryVars1.thermalEddyConductivity());
+
+                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
+                                        -(convectiveFlux - diffusiveEnergyFlux - conductiveFlux));
+            }
+            else if (globalProblem.sdProblem1().isCornerPoint(globalPos1))
+            {
+                const Scalar convectiveFlux =
+                    normalMassFlux1 *
+                    cParams.elemVolVarsCur1[vertInElem1].enthalpy();
+                const Scalar conductiveFlux =
+                    bfNormal1 *
+                    boundaryVars1.temperatureGrad() *
+                    (boundaryVars1.thermalConductivity() + boundaryVars1.thermalEddyConductivity());
+                Scalar sumDiffusiveFluxes = 0.0;
+                Scalar sumDiffusiveEnergyFlux = 0.0;
+                for (int compIdx=0; compIdx < numComponents1; compIdx++)
+                {
+                    if (compIdx != phaseCompIdx1)
+                    {
+                        Scalar diffusiveFlux = boundaryVars1.moleFractionGrad(compIdx)
+                                               * boundaryVars1.face().normal
+                                               *(boundaryVars1.diffusionCoeff(compIdx) + boundaryVars1.eddyDiffusivity())
+                                               * boundaryVars1.molarDensity();
+                        sumDiffusiveFluxes += diffusiveFlux;
+                        sumDiffusiveEnergyFlux += diffusiveFlux
+                                                  * boundaryVars1.componentEnthalpy(compIdx)
+                                                  * FluidSystem::molarMass(compIdx); // Multiplied by molarMass [kg/mol] to convert from [mol/m^3 s] to [kg/m^3 s]
+                    }
+                }
+                sumDiffusiveEnergyFlux -= sumDiffusiveFluxes * boundaryVars1.componentEnthalpy(phaseCompIdx1)
+                                          * FluidSystem::molarMass(phaseCompIdx1);
+                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
+                                        -(convectiveFlux - sumDiffusiveEnergyFlux - conductiveFlux));
+            }
+            else
+            {
+                // the energy flux from the Stokes domain
+                couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
+                                        globalProblem.localResidual1().residual(vertInElem1)[energyEqIdx1]);
+            }
+        }
+        if (cParams.boundaryTypes2.isCouplingDirichlet(energyEqIdx2))
+        {
+            // set residualDarcy[energyEqIdx2] = T in 2p2cnilocalresidual.hh
+            couplingRes2.accumulate(lfsu2.child(energyEqIdx2), vertInElem2,
+                                    -cParams.elemVolVarsCur1[vertInElem1].temperature());
+        }
+    }
+
+    //! \copydoc Dumux::TwoCStokesTwoPTwoCLocalOperator::evalCoupling21()
+    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
+    DUNE_DEPRECATED_MSG("evalCoupling21() is deprecated. Use evalCoupling() instead.")
+    void evalCoupling21(const LFSU1& lfsu1, const LFSU2& lfsu2,
+                        const int vertInElem1, const int vertInElem2,
+                        const SDElement1& sdElement1, const SDElement2& sdElement2,
+                        const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
+                        const CParams &cParams,
+                        RES1& couplingRes1, RES2& couplingRes2) const
+    {
+        GlobalProblem& globalProblem = this->globalProblem();
+
+        // evaluate coupling of mass and momentum balances
+        ParentType::evalCoupling21(lfsu1, lfsu2,
+                                   vertInElem1, vertInElem2,
+                                   sdElement1, sdElement2,
+                                   boundaryVars1, boundaryVars2,
+                                   cParams,
+                                   couplingRes1, couplingRes2);
+
+        const GlobalPosition& globalPos2 = cParams.fvGeometry2.subContVol[vertInElem2].global;
+        GlobalPosition normalMassFlux2(0.);
+
+        // velocity*normal*area*rho
+        // mass flux is needed for both (mass/mole) formulation, as the enthalpy is mass based
+        for (int phaseIdx=0; phaseIdx<numPhases2; ++phaseIdx)
+            normalMassFlux2[phaseIdx] = -boundaryVars2.volumeFlux(phaseIdx)*
+                cParams.elemVolVarsCur2[vertInElem2].density(phaseIdx);
+
+        if (cParams.boundaryTypes1.isCouplingDirichlet(energyEqIdx1))
+        {
+            // set residualStokes[energyIdx1] = T in stokes2cnilocalresidual.hh
+            couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
+                                    -cParams.elemVolVarsCur2[vertInElem2].temperature());
+        }
+        if (cParams.boundaryTypes1.isCouplingNeumann(energyEqIdx1))
+        {
+            if (globalProblem.sdProblem2().isCornerPoint(globalPos2))
+            {
+                const Scalar convectiveFlux = normalMassFlux2[nPhaseIdx2] *
+                    cParams.elemVolVarsCur2[vertInElem2].enthalpy(nPhaseIdx2)
+                    +
+                    normalMassFlux2[wPhaseIdx2] *
+                    cParams.elemVolVarsCur2[vertInElem2].enthalpy(wPhaseIdx2);
+                const Scalar conductiveFlux = boundaryVars2.normalMatrixHeatFlux();
+
+                couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
+                                        -(convectiveFlux - conductiveFlux));
+            }
+            else
+            {
+                couplingRes1.accumulate(lfsu1.child(energyEqIdx1), vertInElem1,
+                                        globalProblem.localResidual2().residual(vertInElem2)[energyEqIdx2]);
+            }
+        }
+    }
+
+    /*!
+     * \brief Returns the temperature gradient through the boundary layer
+     *
+     * \todo This function could be moved to a more model specific place, because
+     *       of its runtime parameters.
+     *
+     * \param cParams a parameter container
+     * \param scvIdx1 The local index of the sub-control volume of the Stokes domain
+     */
+    template<typename CParams>
+    Scalar evalBoundaryLayerTemperatureGradient(CParams cParams, const int scvIdx) const
+    {
+        const Scalar temperatureOut = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefTemperature);
+        Scalar normalTemperatureGrad = cParams.elemVolVarsCur1[scvIdx].temperature()
+                                       - temperatureOut;
+        return normalTemperatureGrad
+               / ParentType::evalBoundaryLayerModel(cParams, scvIdx).thermalBoundaryLayerThickness();
+    }
+};
+} // end namespace Dumux
+
+#endif // DUMUX_TWOCNISTOKES2P2CNILOCALOPERATOR_HH
diff --git a/dumux/multidomain/2cnistokes2p2cni/properties.hh b/dumux/multidomain/2cnistokes2p2cni/properties.hh
new file mode 100644
index 0000000000..5bc41ce38f
--- /dev/null
+++ b/dumux/multidomain/2cnistokes2p2cni/properties.hh
@@ -0,0 +1,58 @@
+// -*- 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 Properties
+ * \ingroup ImplicitProperties
+ * \ingroup MultidomainModel
+ *
+ * \brief Defines the properties required for the coupled 2cnistokes2p2cni model.
+ */
+
+#ifndef DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTIES_HH
+#define DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTIES_HH
+
+#include <dumux/multidomain/2cstokes2p2c/propertydefaults.hh>
+
+namespace Dumux
+{
+
+////////////////////////////////
+// properties
+////////////////////////////////
+namespace Properties
+{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tags for the coupled 2cnistokes2p2cni model
+NEW_TYPE_TAG(TwoCNIStokesTwoPTwoCNI, INHERITS_FROM(TwoCStokesTwoPTwoC));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+} // end namespace properties
+
+} // end namespace Dumux
+
+
+#endif
diff --git a/dumux/multidomain/2cnistokes2p2cni/propertydefaults.hh b/dumux/multidomain/2cnistokes2p2cni/propertydefaults.hh
new file mode 100644
index 0000000000..704d8a6110
--- /dev/null
+++ b/dumux/multidomain/2cnistokes2p2cni/propertydefaults.hh
@@ -0,0 +1,46 @@
+// -*- 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 Properties
+ * \ingroup ImplicitProperties
+ * \ingroup MultidomainModel
+ *
+ * \brief Defines default values for the properties required by the
+ *        coupled 2cnistokes2p2cni model.
+ */
+#ifndef DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTY_DEFAULTS_HH
+#define DUMUX_TWOCNISTOKESTWOPTWOCNI_PROPERTY_DEFAULTS_HH
+
+#include "properties.hh"
+
+namespace Dumux
+{
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Property defaults
+//////////////////////////////////////////////////////////////////
+
+
+} // end namespace properties
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh b/dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh
index 6743259f8a..78aed87cd2 100644
--- a/dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh
+++ b/dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh
@@ -1,1008 +1,8 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \brief The local operator for the coupling of a two-component Stokes model
- *        and a two-phase two-component porous-medium model under isothermal conditions.
- */
-#ifndef DUMUX_2CSTOKES_2P2C_LOCALOPERATOR_HH
-#define DUMUX_2CSTOKES_2P2C_LOCALOPERATOR_HH
+#ifndef DUMUX_2CSTOKES_2P2C_LOCALOPERATOR_HH_OLD
+#define DUMUX_2CSTOKES_2P2C_LOCALOPERATOR_HH_OLD
 
-#include <iostream>
+#warning this header is deprecated, use dumux/multidomain/2cstokes2p2c/localoperator.hh instead
 
-#include <dune/common/deprecated.hh>
+#include <dumux/multidomain/2cstokes2p2c/localoperator.hh>
 
-#include <dune/pdelab/multidomain/couplingutilities.hh>
-#include <dune/pdelab/localoperator/pattern.hh>
-#include <dune/pdelab/localoperator/idefault.hh>
-
-#include <dumux/multidomain/common/multidomainproperties.hh>
-#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh>
-#include <dumux/freeflow/boundarylayermodel.hh>
-#include <dumux/freeflow/masstransfermodel.hh>
-#include <dumux/freeflow/stokesnc/model.hh>
-#include <dumux/porousmediumflow/2p2c/implicit/model.hh>
-
-
-namespace Dumux {
-
-/*!
- * \ingroup TwoPTwoCStokesTwoCModel
- * \ingroup TwoPTwoCZeroEqTwoCModel
- * \brief The local operator for the coupling of a two-component Stokes model
- *        and a two-phase two-component porous-medium model under isothermal conditions.
- *
- * This model implements the coupling between a free-flow model
- * and a porous-medium flow model under isothermal conditions.
- * Here the coupling conditions for the individual balance are presented:
- *
- * The total mass balance equation:
- * \f[
- *  \left[
- *    \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{ff}
- *  = -\left[
- *      \left( \varrho_\textrm{g} \boldsymbol{v}_\textrm{g}
- *             + \varrho_\textrm{l} \boldsymbol{v}_\textrm{l} \right) \cdot \boldsymbol{n}
- *    \right]^\textrm{pm}
- * \f]
- * in which \f$n\f$ represents a vector normal to the interface pointing outside of
- * the specified subdomain.
- *
- * The momentum balance (tangential), which corresponds to the Beavers-Jospeh Saffman condition:
- * \f[
- *  \left[
- *   \left( {\boldsymbol{v}}_\textrm{g}
- *          + \frac{\sqrt{\left(\boldsymbol{K} \boldsymbol{t}_i \right) \cdot \boldsymbol{t}_i}}
- *                 {\alpha_\textrm{BJ} \mu_\textrm{g}} \boldsymbol{{\tau}}_\textrm{t} \boldsymbol{n}
- *          \right) \cdot \boldsymbol{t}_i
- *  \right]^\textrm{ff}
- *  = 0
- * \f]
- * with
- * \f$
- * \boldsymbol{{\tau}_\textrm{t}} = \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right]
- *                                  \nabla \left( \boldsymbol{v}_\textrm{g}
- *                                                + \boldsymbol{v}_\textrm{g}^\intercal \right)
- * \f$
- * in which the eddy viscosity \f$ \mu_\textrm{g,t} = 0 \f$ for the Stokes equation.
- *
- * The momentum balance (normal):
- * \f[
- *  \left[
- *    \left(
- *      \left\lbrace
- *        \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} {\boldsymbol{v}}_\textrm{g}^\intercal
- *        - \boldsymbol{{\tau}}_\textrm{t}
- *        + {p}_\textrm{g} \boldsymbol{I}
- *      \right\rbrace \boldsymbol{n}
- *    \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{ff}
- *  = p_\textrm{g}^\textrm{pm}
- * \f]
- *
- * The component mass balance equation (continuity of fluxes):
- * \f[
- *  \left[
- *    \left(
- *      \varrho_\textrm{g} {X}^\kappa_\textrm{g} {\boldsymbol{v}}_\textrm{g}
- *      - {\boldsymbol{j}}^\kappa_\textrm{g,ff,t,diff}
- *    \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{ff}
- *  = -\left[
- *    \left(
- *      \varrho_\textrm{g} X^\kappa_\textrm{g} \boldsymbol{v}_\textrm{g}
- *      - \boldsymbol{j}^\kappa_\textrm{g,pm,diff}
- *      + \varrho_\textrm{l} \boldsymbol{v}_\textrm{l} X^\kappa_\textrm{l}
- *      - \boldsymbol{j}^\kappa_\textrm{l,pm,diff}
- *    \right) \cdot \boldsymbol{n}
- *  \right]^\textrm{pm}
- *  = 0
- * \f]
- * in which the diffusive fluxes \f$ j_\textrm{diff} \f$ are the diffusive fluxes as
- * they are implemented in the individual subdomain models.
- *
- * The component mass balance equation (continuity of mass/ mole fractions):
- * \f[
- *  \left[ {X}^{\kappa}_\textrm{g} \right]^\textrm{ff}
- *  = \left[ X^{\kappa}_\textrm{g} \right]^\textrm{pm}
- * \f]
- *
- * This is discretized by a fully-coupled vertex-centered finite volume
- * (box) scheme in space and by the implicit Euler method in time.
- */
-template<class TypeTag>
-class TwoCStokesTwoPTwoCLocalOperator :
-        public Dune::PDELab::MultiDomain::CouplingOperatorDefaultFlags,
-        public Dune::PDELab::MultiDomain::NumericalJacobianCoupling<TwoCStokesTwoPTwoCLocalOperator<TypeTag>>,
-        public Dune::PDELab::MultiDomain::FullCouplingPattern,
-        public Dune::PDELab::InstationaryLocalOperatorDefaultMethods<double>
-{
-public:
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) GlobalProblem;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCouplingLocalOperator) Implementation;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) Stokes2cTypeTag;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TwoPTwoCTypeTag;
-
-    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
-    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, SpatialParams) SpatialParams;
-
-    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, ElementVolumeVariables) ElementVolumeVariables1;
-    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, ElementVolumeVariables) ElementVolumeVariables2;
-
-    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, FluxVariables) BoundaryVariables1;
-    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, FluxVariables) BoundaryVariables2;
-
-    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, ElementBoundaryTypes) ElementBoundaryTypes1;
-    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, ElementBoundaryTypes) ElementBoundaryTypes2;
-
-    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, BoundaryTypes) BoundaryTypes1;
-    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, BoundaryTypes) BoundaryTypes2;
-
-    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, FVElementGeometry) FVElementGeometry1;
-    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, FVElementGeometry) FVElementGeometry2;
-
-    // Multidomain Grid types
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
-    typedef typename MDGrid::Traits::template Codim<0>::Entity MDElement;
-
-    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, GridView) Stokes2cGridView;
-    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, GridView) TwoPTwoCGridView;
-    typedef typename Stokes2cGridView::template Codim<0>::Entity SDElement1;
-    typedef typename TwoPTwoCGridView::template Codim<0>::Entity SDElement2;
-
-    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, Indices) Stokes2cIndices;
-    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, Indices) TwoPTwoCIndices;
-
-    enum {
-        dim = MDGrid::dimension,
-        dimWorld = MDGrid::dimensionworld
-    };
-
-    // Stokes
-    enum { numEq1 = GET_PROP_VALUE(Stokes2cTypeTag, NumEq) };
-    enum { numComponents1 = Stokes2cIndices::numComponents };
-    enum { // equation indices
-        momentumXIdx1 = Stokes2cIndices::momentumXIdx,         //!< Index of the x-component of the momentum balance
-        momentumYIdx1 = Stokes2cIndices::momentumYIdx,         //!< Index of the y-component of the momentum balance
-        momentumZIdx1 = Stokes2cIndices::momentumZIdx,         //!< Index of the z-component of the momentum balance
-        lastMomentumIdx1 = Stokes2cIndices::lastMomentumIdx,   //!< Index of the last component of the momentum balance
-        massBalanceIdx1 = Stokes2cIndices::massBalanceIdx,     //!< Index of the mass balance
-        transportEqIdx1 = Stokes2cIndices::transportEqIdx      //!< Index of the transport equation
-    };
-    enum { // component indices
-        transportCompIdx1 = Stokes2cIndices::transportCompIdx, //!< Index of transported component
-        phaseCompIdx1 = Stokes2cIndices::phaseCompIdx    //!< Index of main component of the phase
-    };
-
-    // Darcy
-    enum { numEq2 = GET_PROP_VALUE(TwoPTwoCTypeTag, NumEq) };
-    enum { numPhases2 = GET_PROP_VALUE(TwoPTwoCTypeTag, NumPhases) };
-    enum { // equation indices
-        contiWEqIdx2 = TwoPTwoCIndices::contiWEqIdx,     //!< Index of the continuity equation for water component
-        massBalanceIdx2 = TwoPTwoCIndices::contiNEqIdx   //!< Index of the total mass balance (if one component balance is replaced)
-    };
-    enum { // component indices
-        wCompIdx2 = TwoPTwoCIndices::wCompIdx,           //!< Index of the liquids main component
-        nCompIdx2 = TwoPTwoCIndices::nCompIdx            //!< Index of the main component of the gas
-    };
-    enum { // phase indices
-        wPhaseIdx2 = TwoPTwoCIndices::wPhaseIdx,         //!< Index for the liquid phase
-        nPhaseIdx2 = TwoPTwoCIndices::nPhaseIdx          //!< Index for the gas phase
-    };
-
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename MDGrid::ctype CoordScalar;
-    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
-
-    typedef typename Stokes2cGridView::template Codim<dim>::EntityPointer VertexPointer1;
-    typedef typename TwoPTwoCGridView::template Codim<dim>::EntityPointer VertexPointer2;
-
-    // multidomain flags
-    static const bool doAlphaCoupling = true;
-    static const bool doPatternCoupling = true;
-
-public:
-    //! \brief The constructor
-    TwoCStokesTwoPTwoCLocalOperator(GlobalProblem& globalProblem)
-        : globalProblem_(globalProblem)
-    {
-        static_assert(GET_PROP_VALUE(Stokes2cTypeTag, UseMoles) == GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
-                      "The coupling conditions is only implemented for same formulations (mass or mole) in both subdomains.");
-
-        blModel_ = GET_PARAM_FROM_GROUP(TypeTag, int, BoundaryLayer, Model);
-        massTransferModel_ = GET_PARAM_FROM_GROUP(TypeTag, int, MassTransfer, Model);
-
-        if (blModel_ != 0)
-            std::cout << "Using boundary layer model " << blModel_ << std::endl;
-        if (massTransferModel_ != 0)
-            std::cout << "Using mass transfer model " << massTransferModel_ << std::endl;
-    }
-
-    /*!
-     * \brief Do the coupling. The unknowns are transferred from dune-multidomain.
-     *        Based on them, a coupling residual is calculated and added at the
-     *        respective positions in the matrix.
-     *
-     * \param intersectionGeometry the geometry of the intersection
-     * \param lfsu1 local basis for the trial space of the Stokes domain
-     * \param unknowns1 the unknowns vector of the Stokes element (formatted according to PDELab)
-     * \param lfsv1 local basis for the test space of the Stokes domain
-     * \param lfsu2 local basis for the trail space of the Darcy domain
-     * \param unknowns2 the unknowns vector of the Darcy element (formatted according to PDELab)
-     * \param lfsv2 local basis for the test space of the Darcy domain
-     * \param couplingRes1 the coupling residual from the Stokes domain
-     * \param couplingRes2 the coupling residual from the Darcy domain
-     */
-    template<typename IntersectionGeom, typename LFSU1, typename LFSU2,
-             typename X, typename LFSV1, typename LFSV2,typename RES>
-    void alpha_coupling(const IntersectionGeom& intersectionGeometry,
-                        const LFSU1& lfsu1, const X& unknowns1, const LFSV1& lfsv1,
-                        const LFSU2& lfsu2, const X& unknowns2, const LFSV2& lfsv2,
-                        RES& couplingRes1, RES& couplingRes2) const
-    {
-        const MDElement& mdElement1 = intersectionGeometry.inside();
-        const MDElement& mdElement2 = intersectionGeometry.outside();
-
-        // the subodmain elements
-        const SDElement1& sdElement1 = globalProblem_.sdElementPointer1(mdElement1);
-        const SDElement2& sdElement2 = globalProblem_.sdElementPointer2(mdElement2);
-
-        // a container for the parameters on each side of the coupling interface (see below)
-        CParams cParams;
-
-        // update fvElementGeometry and the element volume variables
-        updateElemVolVars(lfsu1, lfsu2,
-                          unknowns1, unknowns2,
-                          sdElement1, sdElement2,
-                          cParams);
-
-        // first element
-        const int faceIdx1 = intersectionGeometry.indexInInside();
-        const Dune::ReferenceElement<typename MDGrid::ctype,dim>& referenceElement1 =
-            Dune::ReferenceElements<typename MDGrid::ctype,dim>::general(mdElement1.type());
-        const int numVerticesOfFace = referenceElement1.size(faceIdx1, 1, dim);
-
-        // second element
-        const int faceIdx2 = intersectionGeometry.indexInOutside();
-        const Dune::ReferenceElement<typename MDGrid::ctype,dim>& referenceElement2 =
-            Dune::ReferenceElements<typename MDGrid::ctype,dim>::general(mdElement2.type());
-
-        for (int vertexInFace = 0; vertexInFace < numVerticesOfFace; ++vertexInFace)
-        {
-            const int vertInElem1 = referenceElement1.subEntity(faceIdx1, 1, vertexInFace, dim);
-            const int vertInElem2 = referenceElement2.subEntity(faceIdx2, 1, vertexInFace, dim);
-
-            const int boundaryFaceIdx1 = cParams.fvGeometry1.boundaryFaceIndex(faceIdx1, vertexInFace);
-            const int boundaryFaceIdx2 = cParams.fvGeometry2.boundaryFaceIndex(faceIdx2, vertexInFace);
-
-            // obtain the boundary types
-            const VertexPointer1 vPtr1 = sdElement1.template subEntity<dim>(vertInElem1);
-            const VertexPointer2 vPtr2 = sdElement2.template subEntity<dim>(vertInElem2);
-
-            globalProblem_.sdProblem1().boundaryTypes(cParams.boundaryTypes1, vPtr1);
-            globalProblem_.sdProblem2().boundaryTypes(cParams.boundaryTypes2, vPtr2);
-
-            const BoundaryVariables1 boundaryVars1(globalProblem_.sdProblem1(),
-                                                   sdElement1,
-                                                   cParams.fvGeometry1,
-                                                   boundaryFaceIdx1,
-                                                   cParams.elemVolVarsCur1,
-                                                   /*onBoundary=*/true);
-            const BoundaryVariables2 boundaryVars2(globalProblem_.sdProblem2(),
-                                                   sdElement2,
-                                                   cParams.fvGeometry2,
-                                                   boundaryFaceIdx2,
-                                                   cParams.elemVolVarsCur2,
-                                                   /*onBoundary=*/true);
-
-            asImp_()->evalCoupling(lfsu1, lfsu2,
-                                   vertInElem1, vertInElem2,
-                                   sdElement1, sdElement2,
-                                   boundaryVars1, boundaryVars2,
-                                   cParams,
-                                   couplingRes1, couplingRes2);
-        }
-    }
-
-    /*!
-     * \brief Update the volume variables of the element and extract the unknowns from dune-pdelab vectors
-     *        and bring them into a form which fits to dumux.
-     *
-     * \param lfsu1 local basis for the trial space of the Stokes domain
-     * \param lfsu2 local basis for the trial space of the Darcy domain
-     * \param unknowns1 the unknowns vector of the Stokes element (formatted according to PDELab)
-     * \param unknowns2 the unknowns vector of the Darcy element (formatted according to PDELab)
-     * \param sdElement1 the element in the Stokes domain
-     * \param sdElement2 the element in the Darcy domain
-     * \param cParams a parameter container
-     */
-    template<typename LFSU1, typename LFSU2, typename X, typename CParams>
-    void updateElemVolVars(const LFSU1& lfsu1, const LFSU2& lfsu2,
-                           const X& unknowns1, const X& unknowns2,
-                           const SDElement1& sdElement1, const SDElement2& sdElement2,
-                           CParams &cParams) const
-    {
-        cParams.fvGeometry1.update(globalProblem_.sdGridView1(), sdElement1);
-        cParams.fvGeometry2.update(globalProblem_.sdGridView2(), sdElement2);
-
-        const int numVertsOfElem1 = sdElement1.subEntities(dim);
-        const int numVertsOfElem2 = sdElement2.subEntities(dim);
-
-        // bring the local unknowns x1 into a form that can be passed to elemVolVarsCur.update()
-        Dune::BlockVector<Dune::FieldVector<Scalar,1>> elementSol1(0.);
-        Dune::BlockVector<Dune::FieldVector<Scalar,1>> elementSol2(0.);
-        elementSol1.resize(unknowns1.size());
-        elementSol2.resize(unknowns2.size());
-
-        for (int idx=0; idx<numVertsOfElem1; ++idx)
-        {
-            for (int eqIdx1=0; eqIdx1<numEq1; ++eqIdx1)
-                elementSol1[eqIdx1*numVertsOfElem1+idx] = unknowns1(lfsu1.child(eqIdx1),idx);
-            for (int eqIdx2=0; eqIdx2<numEq2; ++eqIdx2)
-                elementSol2[eqIdx2*numVertsOfElem2+idx] = unknowns2(lfsu2.child(eqIdx2),idx);
-        }
-#if HAVE_VALGRIND
-        for (unsigned int i = 0; i < elementSol1.size(); i++)
-            Valgrind::CheckDefined(elementSol1[i]);
-        for (unsigned int i = 0; i < elementSol2.size(); i++)
-            Valgrind::CheckDefined(elementSol2[i]);
-#endif // HAVE_VALGRIND
-
-        cParams.elemVolVarsPrev1.update(globalProblem_.sdProblem1(),
-                                        sdElement1,
-                                        cParams.fvGeometry1,
-                                        true /* oldSol? */);
-        cParams.elemVolVarsCur1.updatePDELab(globalProblem_.sdProblem1(),
-                                             sdElement1,
-                                             cParams.fvGeometry1,
-                                             elementSol1);
-        cParams.elemVolVarsPrev2.update(globalProblem_.sdProblem2(),
-                                        sdElement2,
-                                        cParams.fvGeometry2,
-                                        true /* oldSol? */);
-        cParams.elemVolVarsCur2.updatePDELab(globalProblem_.sdProblem2(),
-                                             sdElement2,
-                                             cParams.fvGeometry2,
-                                             elementSol2);
-
-        ElementBoundaryTypes1 bcTypes1;
-        ElementBoundaryTypes2 bcTypes2;
-        bcTypes1.update(globalProblem_.sdProblem1(), sdElement1, cParams.fvGeometry1);
-        bcTypes2.update(globalProblem_.sdProblem2(), sdElement2, cParams.fvGeometry2);
-
-        globalProblem_.localResidual1().evalPDELab(sdElement1, cParams.fvGeometry1,
-                                                   cParams.elemVolVarsPrev1, cParams.elemVolVarsCur1,
-                                                   bcTypes1);
-        globalProblem_.localResidual2().evalPDELab(sdElement2, cParams.fvGeometry2,
-                                                   cParams.elemVolVarsPrev2, cParams.elemVolVarsCur2,
-                                                   bcTypes2);
-    }
-
-    /*!
-     * \brief Evaluation of the coupling between the Stokes (1) and Darcy (2).
-     *
-     * Dirichlet-like and Neumann-like conditions for the respective domain are evaluated.
-     *
-     * \param lfsu1 local basis for the trial space of the Stokes domain
-     * \param lfsu2 local basis for the trial space of the Darcy domain
-     * \param vertInElem1 local vertex index in element1
-     * \param vertInElem2 local vertex index in element2
-     * \param sdElement1 the element in the Stokes domain
-     * \param sdElement2 the element in the Darcy domain
-     * \param boundaryVars1 the boundary variables at the interface of the Stokes domain
-     * \param boundaryVars2 the boundary variables at the interface of the Darcy domain
-     * \param cParams a parameter container
-     * \param couplingRes1 the coupling residual from the Stokes domain
-     * \param couplingRes2 the coupling residual from the Darcy domain
-     */
-    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
-    void evalCoupling(const LFSU1& lfsu1, const LFSU2& lfsu2,
-                      const int vertInElem1, const int vertInElem2,
-                      const SDElement1& sdElement1, const SDElement2& sdElement2,
-                      const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
-                      const CParams &cParams,
-                      RES1& couplingRes1, RES2& couplingRes2) const
-    {
-        const GlobalPosition& globalPos1 = cParams.fvGeometry1.subContVol[vertInElem1].global;
-        const GlobalPosition& globalPos2 = cParams.fvGeometry2.subContVol[vertInElem2].global;
-
-        const GlobalPosition& bfNormal1 = boundaryVars1.face().normal;
-        const Scalar normalMassFlux1 = boundaryVars1.normalVelocity()
-                                       * cParams.elemVolVarsCur1[vertInElem1].density();
-
-        // MASS Balance
-        // Neumann-like conditions
-        if (cParams.boundaryTypes1.isCouplingNeumann(massBalanceIdx1))
-        {
-            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingNeumann(massBalanceIdx1) for the Stokes side is not implemented.");
-        }
-        if (cParams.boundaryTypes2.isCouplingNeumann(massBalanceIdx2))
-        {
-            static_assert(!GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
-                          "This coupling condition is only implemented for mass fraction formulation.");
-
-            if (globalProblem_.sdProblem1().isCornerPoint(globalPos1))
-            {
-                couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
-                                        -normalMassFlux1);
-            }
-            else
-            {
-                couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
-                                        globalProblem_.localResidual1().residual(vertInElem1)[massBalanceIdx1]);
-            }
-        }
-
-        // Dirichlet-like
-        if (cParams.boundaryTypes1.isCouplingDirichlet(massBalanceIdx1))
-        {
-            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingDirichlet(massBalanceIdx1) for the Stokes side is not implemented.");
-        }
-        if (cParams.boundaryTypes2.isCouplingDirichlet(massBalanceIdx2))
-        {
-            couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
-                                    globalProblem_.localResidual1().residual(vertInElem1)[momentumYIdx1]
-                                    -cParams.elemVolVarsCur1[vertInElem1].pressure());
-        }
-
-
-        // MOMENTUM_X Balance
-        SpatialParams spatialParams = globalProblem_.sdProblem2().spatialParams();
-        Scalar beaversJosephCoeff = spatialParams.beaversJosephCoeffAtPos(globalPos1);
-        assert(beaversJosephCoeff > 0);
-        beaversJosephCoeff /= std::sqrt(spatialParams.intrinsicPermeability(sdElement2, cParams.fvGeometry2, vertInElem2));
-
-        // Neumann-like conditions
-        if (cParams.boundaryTypes1.isCouplingNeumann(momentumXIdx1))
-        {
-            // v_tau = v - (v.n)n
-            const Scalar normalComp = boundaryVars1.velocity()*bfNormal1;
-            GlobalPosition normalV = bfNormal1;
-            normalV *= normalComp;
-            const GlobalPosition tangentialV = boundaryVars1.velocity() - normalV;
-
-            // Implementation as Neumann-like condition: (v.n)n
-            for (int dimIdx=0; dimIdx < dim; ++dimIdx)
-            {
-                couplingRes1.accumulate(lfsu1.child(momentumXIdx1), vertInElem1,
-                                        beaversJosephCoeff
-                                        * boundaryVars1.face().area
-                                        * tangentialV[dimIdx]
-                                        * (boundaryVars1.dynamicViscosity()
-                                          + boundaryVars1.dynamicEddyViscosity()));
-            }
-        }
-
-        // Dirichlet-like conditions
-        if (cParams.boundaryTypes1.isCouplingDirichlet(momentumXIdx1))
-        {
-            // NOTE: This boundary condition is not implemented anymore because curPrimaryVars_ is protected
-            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingNeumann(momentumXIdx1) on the Stokes side is not implemented anymore.");
-
-            // tangential component: vx = sqrt K /alpha * (grad v n(unity))t
-            // GlobalPosition tangentialVelGrad(0);
-            // boundaryVars1.velocityGrad().umv(elementUnitNormal, tangentialVelGrad);
-            // tangentialVelGrad /= -beaversJosephCoeff; // was - before
-            // this->residual_[vertInElem1][momentumXIdx1] =
-            //        tangentialVelGrad[momentumXIdx1] - globalProblem_.localResidual1().curPriVars_(vertInElem1)[momentumXIdx1]);
-        }
-
-
-        // MOMENTUM_Y Balance
-        // Neumann-like conditions
-        if (cParams.boundaryTypes1.isCouplingNeumann(momentumYIdx1))
-        {
-            // p*A as condition for free flow
-            // pressure correction is done in stokeslocalresidual.hh
-            couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
-                                    cParams.elemVolVarsCur2[vertInElem2].pressure(nPhaseIdx2) *
-                                    boundaryVars2.face().area);
-        }
-
-        // Dirichlet-like conditions
-        if (cParams.boundaryTypes1.isCouplingDirichlet(momentumYIdx1))
-        {
-            // v.n as Dirichlet-like condition for the Stokes domain
-            if (globalProblem_.sdProblem2().isCornerPoint(globalPos2))
-            {
-                Scalar sumNormalPhaseFluxes = 0.0;
-                for (int phaseIdx=0; phaseIdx<numPhases2; ++phaseIdx)
-                {
-                    sumNormalPhaseFluxes -= boundaryVars2.volumeFlux(phaseIdx)
-                                            * cParams.elemVolVarsCur2[vertInElem2].density(phaseIdx);
-                }
-                couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
-                                        -sumNormalPhaseFluxes
-                                        / cParams.elemVolVarsCur1[vertInElem1].density());
-            }
-            else
-            {
-                // set residualStokes[momentumYIdx1] = v_y in stokesnccouplinglocalresidual.hh
-                couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
-                                        globalProblem_.localResidual2().residual(vertInElem2)[massBalanceIdx2]
-                                        / cParams.elemVolVarsCur1[vertInElem1].density());
-            }
-        }
-
-
-        // COMPONENT Balance
-        // Neumann-like conditions
-        if (cParams.boundaryTypes1.isCouplingNeumann(transportEqIdx1))
-        {
-            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingNeumann(transportEqIdx1) is not implemented \
-                                              for the Stokes side for multicomponent systems.");
-        }
-        if (cParams.boundaryTypes2.isCouplingNeumann(contiWEqIdx2))
-        {
-            // only enter here, if a boundary layer model is used for the computation of the diffusive fluxes
-            if (blModel_)
-            {
-                Scalar advectiveFlux = normalMassFlux1
-                                       * cParams.elemVolVarsCur1[vertInElem1].massFraction(transportCompIdx1);
-
-                Scalar diffusiveFlux = bfNormal1.two_norm()
-                                       * evalBoundaryLayerConcentrationGradient(cParams, vertInElem1)
-                                       * (boundaryVars1.diffusionCoeff(transportCompIdx1)
-                                         + boundaryVars1.eddyDiffusivity())
-                                       * boundaryVars1.molarDensity()
-                                       * FluidSystem::molarMass(transportCompIdx1);
-
-                const Scalar massTransferCoeff = evalMassTransferCoefficient(cParams, vertInElem1, vertInElem2);
-
-                if (massTransferModel_ && globalProblem_.sdProblem1().isCornerPoint(globalPos1))
-                {
-                    Scalar diffusiveFluxAtCorner = bfNormal1
-                                                   * boundaryVars1.moleFractionGrad(transportCompIdx1)
-                                                   * (boundaryVars1.diffusionCoeff(transportCompIdx1)
-                                                      + boundaryVars1.eddyDiffusivity())
-                                                   * boundaryVars1.molarDensity()
-                                                   * FluidSystem::molarMass(transportCompIdx1);
-
-                    couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
-                                            -massTransferCoeff*(advectiveFlux - diffusiveFlux) -
-                                            (1.-massTransferCoeff)*(advectiveFlux - diffusiveFluxAtCorner));
-                }
-                else
-                {
-                    couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
-                                            -massTransferCoeff*(advectiveFlux - diffusiveFlux) +
-                                            (1.-massTransferCoeff)*globalProblem_.localResidual1().residual(vertInElem1)[transportEqIdx1]);
-                }
-            }
-            else if (globalProblem_.sdProblem1().isCornerPoint(globalPos1))
-            {
-                static_assert(!GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
-                              "This coupling condition is only implemented for mass fraction formulation.");
-
-                Scalar advectiveFlux = normalMassFlux1
-                                       * cParams.elemVolVarsCur1[vertInElem1].massFraction(transportCompIdx1);
-
-                Scalar diffusiveFlux = bfNormal1
-                                       * boundaryVars1.moleFractionGrad(transportCompIdx1)
-                                       * (boundaryVars1.diffusionCoeff(transportCompIdx1)
-                                          + boundaryVars1.eddyDiffusivity())
-                                       * boundaryVars1.molarDensity()
-                                       * FluidSystem::molarMass(transportCompIdx1);
-
-                couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
-                                        -(advectiveFlux - diffusiveFlux));
-            }
-            else
-            {
-                static_assert(GET_PROP_VALUE(Stokes2cTypeTag, UseMoles) == GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
-                              "This coupling condition is not implemented for different formulations (mass/mole) in the subdomains.");
-
-                // the component mass flux from the stokes domain
-                couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
-                                        globalProblem_.localResidual1().residual(vertInElem1)[transportEqIdx1]);
-            }
-        }
-
-        // Dirichlet-like conditions
-        if (cParams.boundaryTypes1.isCouplingDirichlet(transportEqIdx1))
-        {
-            static_assert(!GET_PROP_VALUE(Stokes2cTypeTag, UseMoles),
-                          "This coupling condition is only implemented for mass fraction formulation.");
-
-            // set residualStokes[transportEqIdx1] = x in stokesnccouplinglocalresidual.hh
-            // coupling residual is added to "real" residual
-            couplingRes1.accumulate(lfsu1.child(transportEqIdx1), vertInElem1,
-                                    -cParams.elemVolVarsCur2[vertInElem2].massFraction(nPhaseIdx2, wCompIdx2));
-        }
-        if (cParams.boundaryTypes2.isCouplingDirichlet(contiWEqIdx2))
-        {
-            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingDirichlet(contiWEqIdx2) is not implemented \
-                                              for the Darcy side for multicomponent systems.");
-        }
-    }
-
-    /*!
-     * \brief Evaluation of the coupling from Stokes (1) to Darcy (2).
-     *
-     * \param lfsu1 local basis for the trial space of the Stokes domain
-     * \param lfsu2 local basis for the trial space of the Darcy domain
-     * \param vertInElem1 local vertex index in element1
-     * \param vertInElem2 local vertex index in element2
-     * \param sdElement1 the element in the Stokes domain
-     * \param sdElement2 the element in the Darcy domain
-     * \param boundaryVars1 the boundary variables at the interface of the Stokes domain
-     * \param boundaryVars2 the boundary variables at the interface of the Darcy domain
-     * \param cParams a parameter container
-     * \param couplingRes1 the coupling residual from the Stokes domain
-     * \param couplingRes2 the coupling residual from the Darcy domain
-     */
-    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
-    DUNE_DEPRECATED_MSG("evalCoupling12() is deprecated. Use evalCoupling() instead.")
-    void evalCoupling12(const LFSU1& lfsu1, const LFSU2& lfsu2,
-                        const int vertInElem1, const int vertInElem2,
-                        const SDElement1& sdElement1, const SDElement2& sdElement2,
-                        const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
-                        const CParams &cParams,
-                        RES1& couplingRes1, RES2& couplingRes2) const
-    {
-        const GlobalPosition& globalPos1 = cParams.fvGeometry1.subContVol[vertInElem1].global;
-        const GlobalPosition& bfNormal1 = boundaryVars1.face().normal;
-
-        const Scalar normalMassFlux = boundaryVars1.normalVelocity() *
-            cParams.elemVolVarsCur1[vertInElem1].density();
-
-        //rho*v*n as NEUMANN condition for porous medium (set, if B&J defined as NEUMANN condition)
-        if (cParams.boundaryTypes2.isCouplingNeumann(massBalanceIdx2))
-        {
-            static_assert(!GET_PROP_VALUE(Stokes2cTypeTag, UseMoles),
-                          "This coupling condition is only implemented for mass fraction formulation.");
-
-            if (globalProblem_.sdProblem1().isCornerPoint(globalPos1))
-            {
-                couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
-                                        -normalMassFlux);
-            }
-            else
-            {
-                couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
-                                        globalProblem_.localResidual1().residual(vertInElem1)[massBalanceIdx1]);
-            }
-        }
-        if (cParams.boundaryTypes2.isCouplingDirichlet(massBalanceIdx2))
-        {
-            couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
-                                    globalProblem_.localResidual1().residual(vertInElem1)[momentumYIdx1]
-                                    -cParams.elemVolVarsCur1[vertInElem1].pressure());
-        }
-
-        if (cParams.boundaryTypes2.isCouplingNeumann(contiWEqIdx2))
-        {
-            // only enter here, if a boundary layer model is used for the computation of the diffusive fluxes
-            if (blModel_)
-            {
-                const Scalar diffusiveFlux =
-                    bfNormal1.two_norm()
-                    * evalBoundaryLayerConcentrationGradient(cParams, vertInElem1)
-                    * (boundaryVars1.diffusionCoeff(transportCompIdx1)
-                       + boundaryVars1.eddyDiffusivity())
-                    * boundaryVars1.molarDensity()
-                    * FluidSystem::molarMass(transportCompIdx1);
-
-                Scalar advectiveFlux = normalMassFlux * cParams.elemVolVarsCur1[vertInElem1].massFraction(transportCompIdx1);
-
-                const Scalar massTransferCoeff = evalMassTransferCoefficient(cParams, vertInElem1, vertInElem2);
-
-                if (globalProblem_.sdProblem1().isCornerPoint(globalPos1) && massTransferModel_)
-                {
-                    const Scalar diffusiveFluxAtCorner =
-                        bfNormal1 *
-                        boundaryVars1.moleFractionGrad(transportCompIdx1) *
-                        (boundaryVars1.diffusionCoeff(transportCompIdx1) + boundaryVars1.eddyDiffusivity()) *
-                        boundaryVars1.molarDensity() *
-                        FluidSystem::molarMass(transportCompIdx1);
-
-                    couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
-                                            -massTransferCoeff*(advectiveFlux - diffusiveFlux) -
-                                            (1.-massTransferCoeff)*(advectiveFlux - diffusiveFluxAtCorner));
-                }
-                else
-                {
-                    couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
-                                            -massTransferCoeff*(advectiveFlux - diffusiveFlux) +
-                                            (1.-massTransferCoeff)*globalProblem_.localResidual1().residual(vertInElem1)[transportEqIdx1]);
-                }
-            }
-            else if (globalProblem_.sdProblem1().isCornerPoint(globalPos1))
-            {
-                static_assert(!GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
-                              "This coupling condition is only implemented for mass fraction formulation.");
-
-                const Scalar advectiveFlux =
-                    normalMassFlux *
-                    cParams.elemVolVarsCur1[vertInElem1].massFraction(transportCompIdx1);
-                const Scalar diffusiveFlux =
-                    bfNormal1 *
-                    boundaryVars1.moleFractionGrad(transportCompIdx1) *
-                    (boundaryVars1.diffusionCoeff(transportCompIdx1) + boundaryVars1.eddyDiffusivity()) *
-                    boundaryVars1.molarDensity() *
-                    FluidSystem::molarMass(transportCompIdx1);
-
-                couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
-                                        -(advectiveFlux - diffusiveFlux));
-            }
-            else
-            {
-                static_assert(GET_PROP_VALUE(Stokes2cTypeTag, UseMoles) == GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
-                              "This coupling condition is not implemented dor different formulations (mass/mole) in the subdomains.");
-
-                // the component mass flux from the stokes domain
-                couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
-                                        globalProblem_.localResidual1().residual(vertInElem1)[transportEqIdx1]);
-            }
-        }
-        if (cParams.boundaryTypes2.isCouplingDirichlet(contiWEqIdx2))
-        {
-            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingDirichlet(contiWEqIdx2) is not implemented for the Darcy side.");
-        }
-    }
-
-    /*!
-     * \brief Evaluation of the coupling from Darcy (2) to Stokes (1).
-     *
-     * \param lfsu1 local basis for the trial space of the Stokes domain
-     * \param lfsu2 local basis for the trial space of the Darcy domain
-     * \param vertInElem1 local vertex index in element1
-     * \param vertInElem2 local vertex index in element2
-     * \param sdElement1 the element in the Stokes domain
-     * \param sdElement2 the element in the Darcy domain
-     * \param boundaryVars1 the boundary variables at the interface of the Stokes domain
-     * \param boundaryVars2 the boundary variables at the interface of the Darcy domain
-     * \param cParams a parameter container
-     * \param couplingRes1 the coupling residual from the Stokes domain
-     * \param couplingRes2 the coupling residual from the Darcy domain
-     */
-    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
-    DUNE_DEPRECATED_MSG("evalCoupling21() is deprecated. Use evalCoupling() instead.")
-    void evalCoupling21(const LFSU1& lfsu1, const LFSU2& lfsu2,
-                        const int vertInElem1, const int vertInElem2,
-                        const SDElement1& sdElement1, const SDElement2& sdElement2,
-                        const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
-                        const CParams &cParams,
-                        RES1& couplingRes1, RES2& couplingRes2) const
-    {
-        const GlobalPosition& globalPos2 = cParams.fvGeometry2.subContVol[vertInElem2].global;
-        GlobalPosition normalFlux2(0.);
-
-        // velocity*normal*area*rho
-        for (int phaseIdx=0; phaseIdx<numPhases2; ++phaseIdx)
-            normalFlux2[phaseIdx] = -boundaryVars2.volumeFlux(phaseIdx)*
-                cParams.elemVolVarsCur2[vertInElem2].density(phaseIdx);
-
-        //p*n as NEUMANN condition for free flow (set, if B&J defined as NEUMANN condition)
-        if (cParams.boundaryTypes1.isCouplingDirichlet(momentumYIdx1))
-        {
-            //p*A*n as NEUMANN condition for free flow (set, if B&J defined as NEUMANN condition)
-            //pressure correction in stokeslocalresidual.hh
-            couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
-                                    cParams.elemVolVarsCur2[vertInElem2].pressure(nPhaseIdx2) *
-                                    boundaryVars2.face().area);
-        }
-        if (cParams.boundaryTypes1.isCouplingNeumann(momentumYIdx1))
-        {
-            // v.n as Dirichlet-like condition for the Stokes domain
-            // set residualStokes[momentumYIdx1] = vy in stokeslocalresidual.hh
-            if (globalProblem_.sdProblem2().isCornerPoint(globalPos2))
-            {
-                couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
-                                        -((normalFlux2[nPhaseIdx2] + normalFlux2[wPhaseIdx2])
-                                          / cParams.elemVolVarsCur1[vertInElem1].density()));
-            }
-            else
-            {
-                // v.n as DIRICHLET condition for the Stokes domain (negative sign!)
-                couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
-                                        globalProblem_.localResidual2().residual(vertInElem2)[massBalanceIdx2]
-                                        / cParams.elemVolVarsCur1[vertInElem1].density());
-            }
-        }
-
-        typedef typename GET_PROP_TYPE(Stokes2cTypeTag, SpatialParams) SpatialParams1;
-        SpatialParams1 spatialParams = globalProblem_.sdProblem1().spatialParams();
-        const GlobalPosition& globalPos = cParams.fvGeometry1.subContVol[vertInElem1].global;
-        Scalar beaversJosephCoeff = spatialParams.beaversJosephCoeffAtPos(globalPos);
-        assert(beaversJosephCoeff > 0);
-
-        const Scalar Kxx = spatialParams.intrinsicPermeability(sdElement1, cParams.fvGeometry1,
-                                                               vertInElem1);
-
-        beaversJosephCoeff /= std::sqrt(Kxx);
-        const GlobalPosition& elementUnitNormal = boundaryVars1.face().normal;
-
-        // Implementation as Neumann-like condition: (v.n)n
-        if (cParams.boundaryTypes1.isCouplingDirichlet(momentumXIdx1))
-        {
-            const Scalar normalComp = boundaryVars1.velocity()*elementUnitNormal;
-            GlobalPosition normalV = elementUnitNormal;
-            normalV *= normalComp; // v*n*n
-
-            // v_tau = v - (v.n)n
-            const GlobalPosition tangentialV = boundaryVars1.velocity() - normalV;
-            const Scalar boundaryFaceArea = boundaryVars1.face().area;
-
-            for (int dimIdx=0; dimIdx < dim; ++dimIdx)
-            {
-                couplingRes1.accumulate(lfsu1.child(momentumXIdx1), vertInElem1,
-                                        beaversJosephCoeff
-                                        * boundaryFaceArea
-                                        * tangentialV[dimIdx]
-                                        * (boundaryVars1.dynamicViscosity()
-                                          + boundaryVars1.dynamicEddyViscosity()));
-            }
-        }
-        // Implementation as Dirichlet-like condition
-        // tangential component: vx = sqrt K /alpha * (grad v n(unity))t
-        if (cParams.boundaryTypes1.isCouplingNeumann(momentumXIdx1))
-        {
-            DUNE_THROW(Dune::NotImplemented, "The boundary conditionisCouplingNeumann(momentumXIdx1) on the Stokes side is not implemented anymore.");
-            // GlobalPosition tangentialVelGrad(0);
-            // boundaryVars1.velocityGrad().umv(elementUnitNormal, tangentialVelGrad);
-            // tangentialVelGrad /= -beaversJosephCoeff; // was - before
-            // couplingRes1.accumulate(lfsu1.child(momentumXIdx1), vertInElem1,
-            // this->residual_[vertInElem1][momentumXIdx1] =
-            //        tangentialVelGrad[momentumXIdx1] - globalProblem_.localResidual1().curPriVars_(vertInElem1)[momentumXIdx1]);
-        }
-
-        //coupling residual is added to "real" residual
-        //here each node is passed twice, hence only half of the dirichlet condition has to be set
-        if (cParams.boundaryTypes1.isCouplingDirichlet(transportEqIdx1))
-        {
-            // set residualStokes[transportEqIdx1] = x in stokes2clocalresidual.hh
-
-
-            static_assert(!GET_PROP_VALUE(Stokes2cTypeTag, UseMoles),
-                          "This coupling condition is only implemented for mass fraction formulation.");
-
-            couplingRes1.accumulate(lfsu1.child(transportEqIdx1), vertInElem1,
-                                    -cParams.elemVolVarsCur2[vertInElem2].massFraction(nPhaseIdx2, wCompIdx2));
-        }
-        if (cParams.boundaryTypes1.isCouplingNeumann(transportEqIdx1))
-        {
-            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingNeumann(transportEqIdx1) is not implemented for the Stokes side.");
-        }
-    }
-
-    /*!
-     * \brief Returns a BoundaryLayerModel object
-     *
-     * This function is reused in Child LocalOperators and used for extracting
-     * the respective boundary layer thickness.<br>
-     * \todo This function could be moved to a more model specific place, because
-     *       of its runtime parameters.
-     *
-     * \param cParams a parameter container
-     * \param scvIdx1 The local index of the sub-control volume of the Stokes domain
-     */
-    template<typename CParams>
-    BoundaryLayerModel<TypeTag> evalBoundaryLayerModel(CParams cParams, const int scvIdx1) const
-    {
-        // current position + additional virtual runup distance
-        const Scalar distance = cParams.fvGeometry1.subContVol[scvIdx1].global[0]
-                                + GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, Offset);
-        BoundaryLayerModel<TypeTag> boundaryLayerModel(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefVelocity),
-                                                       distance,
-                                                       cParams.elemVolVarsCur1[scvIdx1].kinematicViscosity(),
-                                                       blModel_);
-        if (blModel_ == 1)
-            boundaryLayerModel.setConstThickness(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, ConstThickness));
-        if (blModel_ >= 4)
-            boundaryLayerModel.setYPlus(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, YPlus));
-        if (blModel_ >= 5)
-            boundaryLayerModel.setRoughnessLength(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, RoughnessLength));
-        if (blModel_ == 7)
-            boundaryLayerModel.setHydraulicDiameter(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, HydraulicDiameter));
-
-        return boundaryLayerModel;
-    }
-
-    /*!
-     * \brief Returns the concentration gradient through the boundary layer
-     *
-     * \todo This function could be moved to a more model specific place, because
-     *       of its runtime parameters.
-     *
-     * \param cParams a parameter container
-     * \param scvIdx1 The local index of the sub-control volume of the Stokes domain
-     */
-    template<typename CParams>
-    Scalar evalBoundaryLayerConcentrationGradient(CParams cParams, const int scvIdx1) const
-    {
-        static_assert(numComponents1 == 2,
-                      "This coupling condition is only implemented for two components.");
-        Scalar massFractionOut = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefMassfrac);
-        Scalar M1 = FluidSystem::molarMass(transportCompIdx1);
-        Scalar M2 = FluidSystem::molarMass(phaseCompIdx1);
-        Scalar X2 = 1.0 - massFractionOut;
-        Scalar massToMoleDenominator = M2 + X2*(M1 - M2);
-        Scalar moleFractionOut = massFractionOut * M2 /massToMoleDenominator;
-
-        Scalar normalMoleFracGrad = cParams.elemVolVarsCur1[scvIdx1].moleFraction(transportCompIdx1)
-                                    - moleFractionOut;
-        return normalMoleFracGrad / evalBoundaryLayerModel(cParams, scvIdx1).massBoundaryLayerThickness();
-    }
-
-    /*!
-     * \brief Returns the mass transfer coefficient
-     *
-     * This function is reused in Child LocalOperators.
-     * \todo This function could be moved to a more model specific place, because
-     *       of its runtime parameters.
-     *
-     * \param cParams a parameter container
-     * \param scvIdx1 The local index of the sub-control volume of the Stokes domain
-     * \param scvIdx1 The local index of the sub-control volume of the Darcy domain
-     */
-    template<typename CParams>
-    Scalar evalMassTransferCoefficient(CParams cParams, const int scvIdx1, const int scvIdx2) const
-    {
-        MassTransferModel<TypeTag> massTransferModel(cParams.elemVolVarsCur2[scvIdx2].saturation(wPhaseIdx2),
-                                                     cParams.elemVolVarsCur2[scvIdx2].porosity(),
-                                                     evalBoundaryLayerModel(cParams, scvIdx1).massBoundaryLayerThickness(),
-                                                     massTransferModel_);
-        if (massTransferModel_ == 1)
-            massTransferModel.setMassTransferCoeff(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, MassTransfer, Coefficient));
-        if (massTransferModel_ == 2 || massTransferModel_ == 4)
-            massTransferModel.setCharPoreRadius(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, MassTransfer, CharPoreRadius));
-        if (massTransferModel_ == 3)
-            massTransferModel.setCapillaryPressure(cParams.elemVolVarsCur2[scvIdx2].capillaryPressure());
-
-        return massTransferModel.massTransferCoefficient();
-    }
-
- protected:
-    GlobalProblem& globalProblem() const
-    { return globalProblem_; }
-
-    Implementation *asImp_()
-    { return static_cast<Implementation *> (this); }
-    const Implementation *asImp_() const
-    { return static_cast<const Implementation *> (this); }
-
-    unsigned int blModel_;
-    unsigned int massTransferModel_;
-
- private:
-    /*!
-     * \brief A struct that contains data of the FF and PM including boundary types,
-     *        volume variables in both subdomains and geometric information
-     */
-    struct CParams
-    {
-        BoundaryTypes1 boundaryTypes1;
-        BoundaryTypes2 boundaryTypes2;
-        ElementVolumeVariables1 elemVolVarsPrev1;
-        ElementVolumeVariables1 elemVolVarsCur1;
-        ElementVolumeVariables2 elemVolVarsPrev2;
-        ElementVolumeVariables2 elemVolVarsCur2;
-        FVElementGeometry1 fvGeometry1;
-        FVElementGeometry2 fvGeometry2;
-    };
-
-    GlobalProblem& globalProblem_;
-};
-
-} // end namespace Dumux
-
-#endif // DUMUX_2CSTOKES_2P2C_LOCALOPERATOR_HH
+#endif
diff --git a/dumux/multidomain/2cstokes2p2c/2cstokes2p2cnewtoncontroller.hh b/dumux/multidomain/2cstokes2p2c/2cstokes2p2cnewtoncontroller.hh
index 779d9975fd..38be033319 100644
--- a/dumux/multidomain/2cstokes2p2c/2cstokes2p2cnewtoncontroller.hh
+++ b/dumux/multidomain/2cstokes2p2c/2cstokes2p2cnewtoncontroller.hh
@@ -1,68 +1,8 @@
-// -*- 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 Reference implementation of a Newton controller for the coupling of a two-component Stokes model
- *        and a two-phase two-component porous-medium model under isothermal conditions.
- */
-#ifndef DUMUX_2CSTOKES_2P2C_NEWTON_CONTROLLER_HH
-#define DUMUX_2CSTOKES_2P2C_NEWTON_CONTROLLER_HH
+#ifndef DUMUX_2CSTOKES_2P2C_NEWTON_CONTROLLER_HH_OLD
+#define DUMUX_2CSTOKES_2P2C_NEWTON_CONTROLLER_HH_OLD
 
-#include <dumux/multidomain/common/multidomainnewtoncontroller.hh>
+#warning this header is deprecated, use dumux/multidomain/2cstokes2p2c/newtoncontroller.hh instead
 
-namespace Dumux
-{
+#include <dumux/multidomain/2cstokes2p2c/newtoncontroller.hh>
 
-/*!
- * \ingroup Newton
- * \ingroup TwoPTwoCStokesTwoCModel
- * \ingroup TwoPTwoCZeroEqTwoCModel
- * \brief Implementation of a Newton controller for the coupling of a two-component Stokes model
- *        and a two-phase two-component porous-medium model under isothermal conditions.
- *
- * The Newton controller ensures that the updateStaticData routine is called
- * in the porous-medium sub-problem
- */
-template <class TypeTag>
-class TwoCStokesTwoPTwoCNewtonController : public MultiDomainNewtonController<TypeTag>
-{
-    typedef MultiDomainNewtonController<TypeTag> ParentType;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-
-public:
-    //! \brief The constructor
-    TwoCStokesTwoPTwoCNewtonController(const Problem &problem)
-        : ParentType(problem)
-    {  }
-
-    //! \copydoc Dumux::NewtonController::newtonEndStep()
-    void newtonEndStep(SolutionVector &uCurrentIter, SolutionVector &uLastIter)
-    {
-        ParentType::newtonEndStep(uCurrentIter, uLastIter);
-
-        this->model_().sdModel2().updateStaticData(this->model_().sdModel2().curSol(),
-                                                   this->model_().sdModel2().prevSol());
-    }
-};
-
-} // namespace Dumux
-
-#endif // DUMUX_2CSTOKES_2P2C_NEWTON_CONTROLLER_HH
+#endif
diff --git a/dumux/multidomain/2cstokes2p2c/2cstokes2p2cproperties.hh b/dumux/multidomain/2cstokes2p2c/2cstokes2p2cproperties.hh
index d5f99a43ad..d4d4755c05 100644
--- a/dumux/multidomain/2cstokes2p2c/2cstokes2p2cproperties.hh
+++ b/dumux/multidomain/2cstokes2p2c/2cstokes2p2cproperties.hh
@@ -1,60 +1,8 @@
-// -*- 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 Properties
- * \ingroup ImplicitProperties
- * \ingroup MultidomainModel
- *
- * \brief Defines the properties required for the coupled 2cstokes2p2c model.
- */
+#ifndef DUMUX_TWOCSTOKESTWOPTWOC_PROPERTIES_HH_OLD
+#define DUMUX_TWOCSTOKESTWOPTWOC_PROPERTIES_HH_OLD
 
-#ifndef DUMUX_TWOCSTOKESTWOPTWOC_PROPERTIES_HH
-#define DUMUX_TWOCSTOKESTWOPTWOC_PROPERTIES_HH
-
-#include <dumux/multidomain/common/multidomainpropertydefaults.hh>
-
-namespace Dumux
-{
-
-////////////////////////////////
-// properties
-////////////////////////////////
-namespace Properties
-{
-
-//////////////////////////////////////////////////////////////////
-// Type tags
-//////////////////////////////////////////////////////////////////
-
-//! The type tags for the coupled 2cstokes2p2c model
-NEW_TYPE_TAG(TwoCStokesTwoPTwoC, INHERITS_FROM(MultiDomain));
-
-//////////////////////////////////////////////////////////////////
-// Property tags
-//////////////////////////////////////////////////////////////////
-NEW_PROP_TAG(BoundaryLayerModel); //!< Type of the used boundary layer model
-NEW_PROP_TAG(MassTransferModel); //!< Type of the used mass transfer model
-
-} // end namespace properties
-
-} // end namespace Dumux
+#warning this header is deprecated, use dumux/multidomain/2cstokes2p2c/properties.hh instead
 
+#include <dumux/multidomain/2cstokes2p2c/properties.hh>
 
 #endif
diff --git a/dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh b/dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh
index ac2fe046b6..be664a6531 100644
--- a/dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh
+++ b/dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh
@@ -1,66 +1,8 @@
-// -*- 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 Properties
- * \ingroup ImplicitProperties
- * \ingroup MultidomainModel
- *
- * \brief Defines default values for the properties required by the
- *        coupled 2cstokes2p2c model.
- */
-#ifndef DUMUX_TWOCSTOKESTWOPTWOC_PROPERTY_DEFAULTS_HH
-#define DUMUX_TWOCSTOKESTWOPTWOC_PROPERTY_DEFAULTS_HH
+#ifndef DUMUX_TWOCSTOKESTWOPTWOC_PROPERTY_DEFAULTS_HH_OLD
+#define DUMUX_TWOCSTOKESTWOPTWOC_PROPERTY_DEFAULTS_HH_OLD
 
-#include "2cstokes2p2cproperties.hh"
-#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2cnewtoncontroller.hh>
+#warning this header is deprecated, use dumux/multidomain/2cstokes2p2c/propertydefaults.hh instead
 
-namespace Dumux
-{
-namespace Properties
-{
-//////////////////////////////////////////////////////////////////
-// Property defaults
-//////////////////////////////////////////////////////////////////
-
-// Specify the multidomain gridview
-SET_TYPE_PROP(TwoCStokesTwoPTwoC, GridView,
-              typename GET_PROP_TYPE(TypeTag, MultiDomainGrid)::LeafGridView);
-
-// Specify the type of the used solution vector
-SET_TYPE_PROP(TwoCStokesTwoPTwoC, SolutionVector,
-              typename GET_PROP_TYPE(TypeTag, MultiDomainGridOperator)::Traits::Domain);
-
-// Specif the used Newton controller
-SET_TYPE_PROP(TwoCStokesTwoPTwoC, NewtonController, Dumux::TwoCStokesTwoPTwoCNewtonController<TypeTag>);
-
-// Set this to one here (must fit to the structure of the coupled matrix which has block length 1)
-SET_INT_PROP(TwoCStokesTwoPTwoC, NumEq, 1);
-
-// Specify the used boundary layer model
-SET_INT_PROP(TwoCStokesTwoPTwoC, BoundaryLayerModel, 0);
-
-// Specify the used mass transfer model
-SET_INT_PROP(TwoCStokesTwoPTwoC, MassTransferModel, 0);
-
-} // end namespace properties
-
-} // end namespace Dumux
+#include <dumux/multidomain/2cstokes2p2c/propertydefaults.hh>
 
 #endif
diff --git a/dumux/multidomain/2cstokes2p2c/localoperator.hh b/dumux/multidomain/2cstokes2p2c/localoperator.hh
new file mode 100644
index 0000000000..b1ad103c9f
--- /dev/null
+++ b/dumux/multidomain/2cstokes2p2c/localoperator.hh
@@ -0,0 +1,1008 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief The local operator for the coupling of a two-component Stokes model
+ *        and a two-phase two-component porous-medium model under isothermal conditions.
+ */
+#ifndef DUMUX_2CSTOKES_2P2C_LOCALOPERATOR_HH
+#define DUMUX_2CSTOKES_2P2C_LOCALOPERATOR_HH
+
+#include <iostream>
+
+#include <dune/common/deprecated.hh>
+
+#include <dune/pdelab/multidomain/couplingutilities.hh>
+#include <dune/pdelab/localoperator/pattern.hh>
+#include <dune/pdelab/localoperator/idefault.hh>
+
+#include <dumux/multidomain/common/properties.hh>
+#include <dumux/multidomain/2cstokes2p2c/propertydefaults.hh>
+#include <dumux/freeflow/boundarylayermodel.hh>
+#include <dumux/freeflow/masstransfermodel.hh>
+#include <dumux/freeflow/stokesnc/model.hh>
+#include <dumux/porousmediumflow/2p2c/implicit/model.hh>
+
+
+namespace Dumux {
+
+/*!
+ * \ingroup TwoPTwoCStokesTwoCModel
+ * \ingroup TwoPTwoCZeroEqTwoCModel
+ * \brief The local operator for the coupling of a two-component Stokes model
+ *        and a two-phase two-component porous-medium model under isothermal conditions.
+ *
+ * This model implements the coupling between a free-flow model
+ * and a porous-medium flow model under isothermal conditions.
+ * Here the coupling conditions for the individual balance are presented:
+ *
+ * The total mass balance equation:
+ * \f[
+ *  \left[
+ *    \left( \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{ff}
+ *  = -\left[
+ *      \left( \varrho_\textrm{g} \boldsymbol{v}_\textrm{g}
+ *             + \varrho_\textrm{l} \boldsymbol{v}_\textrm{l} \right) \cdot \boldsymbol{n}
+ *    \right]^\textrm{pm}
+ * \f]
+ * in which \f$n\f$ represents a vector normal to the interface pointing outside of
+ * the specified subdomain.
+ *
+ * The momentum balance (tangential), which corresponds to the Beavers-Jospeh Saffman condition:
+ * \f[
+ *  \left[
+ *   \left( {\boldsymbol{v}}_\textrm{g}
+ *          + \frac{\sqrt{\left(\boldsymbol{K} \boldsymbol{t}_i \right) \cdot \boldsymbol{t}_i}}
+ *                 {\alpha_\textrm{BJ} \mu_\textrm{g}} \boldsymbol{{\tau}}_\textrm{t} \boldsymbol{n}
+ *          \right) \cdot \boldsymbol{t}_i
+ *  \right]^\textrm{ff}
+ *  = 0
+ * \f]
+ * with
+ * \f$
+ * \boldsymbol{{\tau}_\textrm{t}} = \left[ \mu_\textrm{g} + \mu_\textrm{g,t} \right]
+ *                                  \nabla \left( \boldsymbol{v}_\textrm{g}
+ *                                                + \boldsymbol{v}_\textrm{g}^\intercal \right)
+ * \f$
+ * in which the eddy viscosity \f$ \mu_\textrm{g,t} = 0 \f$ for the Stokes equation.
+ *
+ * The momentum balance (normal):
+ * \f[
+ *  \left[
+ *    \left(
+ *      \left\lbrace
+ *        \varrho_\textrm{g} {\boldsymbol{v}}_\textrm{g} {\boldsymbol{v}}_\textrm{g}^\intercal
+ *        - \boldsymbol{{\tau}}_\textrm{t}
+ *        + {p}_\textrm{g} \boldsymbol{I}
+ *      \right\rbrace \boldsymbol{n}
+ *    \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{ff}
+ *  = p_\textrm{g}^\textrm{pm}
+ * \f]
+ *
+ * The component mass balance equation (continuity of fluxes):
+ * \f[
+ *  \left[
+ *    \left(
+ *      \varrho_\textrm{g} {X}^\kappa_\textrm{g} {\boldsymbol{v}}_\textrm{g}
+ *      - {\boldsymbol{j}}^\kappa_\textrm{g,ff,t,diff}
+ *    \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{ff}
+ *  = -\left[
+ *    \left(
+ *      \varrho_\textrm{g} X^\kappa_\textrm{g} \boldsymbol{v}_\textrm{g}
+ *      - \boldsymbol{j}^\kappa_\textrm{g,pm,diff}
+ *      + \varrho_\textrm{l} \boldsymbol{v}_\textrm{l} X^\kappa_\textrm{l}
+ *      - \boldsymbol{j}^\kappa_\textrm{l,pm,diff}
+ *    \right) \cdot \boldsymbol{n}
+ *  \right]^\textrm{pm}
+ *  = 0
+ * \f]
+ * in which the diffusive fluxes \f$ j_\textrm{diff} \f$ are the diffusive fluxes as
+ * they are implemented in the individual subdomain models.
+ *
+ * The component mass balance equation (continuity of mass/ mole fractions):
+ * \f[
+ *  \left[ {X}^{\kappa}_\textrm{g} \right]^\textrm{ff}
+ *  = \left[ X^{\kappa}_\textrm{g} \right]^\textrm{pm}
+ * \f]
+ *
+ * This is discretized by a fully-coupled vertex-centered finite volume
+ * (box) scheme in space and by the implicit Euler method in time.
+ */
+template<class TypeTag>
+class TwoCStokesTwoPTwoCLocalOperator :
+        public Dune::PDELab::MultiDomain::CouplingOperatorDefaultFlags,
+        public Dune::PDELab::MultiDomain::NumericalJacobianCoupling<TwoCStokesTwoPTwoCLocalOperator<TypeTag>>,
+        public Dune::PDELab::MultiDomain::FullCouplingPattern,
+        public Dune::PDELab::InstationaryLocalOperatorDefaultMethods<double>
+{
+public:
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) GlobalProblem;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCouplingLocalOperator) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) Stokes2cTypeTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TwoPTwoCTypeTag;
+
+    typedef typename GET_PROP_TYPE(TypeTag, FluidSystem) FluidSystem;
+    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, SpatialParams) SpatialParams;
+
+    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, ElementVolumeVariables) ElementVolumeVariables1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, ElementVolumeVariables) ElementVolumeVariables2;
+
+    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, FluxVariables) BoundaryVariables1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, FluxVariables) BoundaryVariables2;
+
+    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, ElementBoundaryTypes) ElementBoundaryTypes1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, ElementBoundaryTypes) ElementBoundaryTypes2;
+
+    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, BoundaryTypes) BoundaryTypes1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, BoundaryTypes) BoundaryTypes2;
+
+    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, FVElementGeometry) FVElementGeometry1;
+    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, FVElementGeometry) FVElementGeometry2;
+
+    // Multidomain Grid types
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
+    typedef typename MDGrid::Traits::template Codim<0>::Entity MDElement;
+
+    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, GridView) Stokes2cGridView;
+    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, GridView) TwoPTwoCGridView;
+    typedef typename Stokes2cGridView::template Codim<0>::Entity SDElement1;
+    typedef typename TwoPTwoCGridView::template Codim<0>::Entity SDElement2;
+
+    typedef typename GET_PROP_TYPE(Stokes2cTypeTag, Indices) Stokes2cIndices;
+    typedef typename GET_PROP_TYPE(TwoPTwoCTypeTag, Indices) TwoPTwoCIndices;
+
+    enum {
+        dim = MDGrid::dimension,
+        dimWorld = MDGrid::dimensionworld
+    };
+
+    // Stokes
+    enum { numEq1 = GET_PROP_VALUE(Stokes2cTypeTag, NumEq) };
+    enum { numComponents1 = Stokes2cIndices::numComponents };
+    enum { // equation indices
+        momentumXIdx1 = Stokes2cIndices::momentumXIdx,         //!< Index of the x-component of the momentum balance
+        momentumYIdx1 = Stokes2cIndices::momentumYIdx,         //!< Index of the y-component of the momentum balance
+        momentumZIdx1 = Stokes2cIndices::momentumZIdx,         //!< Index of the z-component of the momentum balance
+        lastMomentumIdx1 = Stokes2cIndices::lastMomentumIdx,   //!< Index of the last component of the momentum balance
+        massBalanceIdx1 = Stokes2cIndices::massBalanceIdx,     //!< Index of the mass balance
+        transportEqIdx1 = Stokes2cIndices::transportEqIdx      //!< Index of the transport equation
+    };
+    enum { // component indices
+        transportCompIdx1 = Stokes2cIndices::transportCompIdx, //!< Index of transported component
+        phaseCompIdx1 = Stokes2cIndices::phaseCompIdx    //!< Index of main component of the phase
+    };
+
+    // Darcy
+    enum { numEq2 = GET_PROP_VALUE(TwoPTwoCTypeTag, NumEq) };
+    enum { numPhases2 = GET_PROP_VALUE(TwoPTwoCTypeTag, NumPhases) };
+    enum { // equation indices
+        contiWEqIdx2 = TwoPTwoCIndices::contiWEqIdx,     //!< Index of the continuity equation for water component
+        massBalanceIdx2 = TwoPTwoCIndices::contiNEqIdx   //!< Index of the total mass balance (if one component balance is replaced)
+    };
+    enum { // component indices
+        wCompIdx2 = TwoPTwoCIndices::wCompIdx,           //!< Index of the liquids main component
+        nCompIdx2 = TwoPTwoCIndices::nCompIdx            //!< Index of the main component of the gas
+    };
+    enum { // phase indices
+        wPhaseIdx2 = TwoPTwoCIndices::wPhaseIdx,         //!< Index for the liquid phase
+        nPhaseIdx2 = TwoPTwoCIndices::nPhaseIdx          //!< Index for the gas phase
+    };
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename MDGrid::ctype CoordScalar;
+    typedef Dune::FieldVector<CoordScalar, dimWorld> GlobalPosition;
+
+    typedef typename Stokes2cGridView::template Codim<dim>::EntityPointer VertexPointer1;
+    typedef typename TwoPTwoCGridView::template Codim<dim>::EntityPointer VertexPointer2;
+
+    // multidomain flags
+    static const bool doAlphaCoupling = true;
+    static const bool doPatternCoupling = true;
+
+public:
+    //! \brief The constructor
+    TwoCStokesTwoPTwoCLocalOperator(GlobalProblem& globalProblem)
+        : globalProblem_(globalProblem)
+    {
+        static_assert(GET_PROP_VALUE(Stokes2cTypeTag, UseMoles) == GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
+                      "The coupling conditions is only implemented for same formulations (mass or mole) in both subdomains.");
+
+        blModel_ = GET_PARAM_FROM_GROUP(TypeTag, int, BoundaryLayer, Model);
+        massTransferModel_ = GET_PARAM_FROM_GROUP(TypeTag, int, MassTransfer, Model);
+
+        if (blModel_ != 0)
+            std::cout << "Using boundary layer model " << blModel_ << std::endl;
+        if (massTransferModel_ != 0)
+            std::cout << "Using mass transfer model " << massTransferModel_ << std::endl;
+    }
+
+    /*!
+     * \brief Do the coupling. The unknowns are transferred from dune-multidomain.
+     *        Based on them, a coupling residual is calculated and added at the
+     *        respective positions in the matrix.
+     *
+     * \param intersectionGeometry the geometry of the intersection
+     * \param lfsu1 local basis for the trial space of the Stokes domain
+     * \param unknowns1 the unknowns vector of the Stokes element (formatted according to PDELab)
+     * \param lfsv1 local basis for the test space of the Stokes domain
+     * \param lfsu2 local basis for the trail space of the Darcy domain
+     * \param unknowns2 the unknowns vector of the Darcy element (formatted according to PDELab)
+     * \param lfsv2 local basis for the test space of the Darcy domain
+     * \param couplingRes1 the coupling residual from the Stokes domain
+     * \param couplingRes2 the coupling residual from the Darcy domain
+     */
+    template<typename IntersectionGeom, typename LFSU1, typename LFSU2,
+             typename X, typename LFSV1, typename LFSV2,typename RES>
+    void alpha_coupling(const IntersectionGeom& intersectionGeometry,
+                        const LFSU1& lfsu1, const X& unknowns1, const LFSV1& lfsv1,
+                        const LFSU2& lfsu2, const X& unknowns2, const LFSV2& lfsv2,
+                        RES& couplingRes1, RES& couplingRes2) const
+    {
+        const MDElement& mdElement1 = intersectionGeometry.inside();
+        const MDElement& mdElement2 = intersectionGeometry.outside();
+
+        // the subodmain elements
+        const SDElement1& sdElement1 = globalProblem_.sdElementPointer1(mdElement1);
+        const SDElement2& sdElement2 = globalProblem_.sdElementPointer2(mdElement2);
+
+        // a container for the parameters on each side of the coupling interface (see below)
+        CParams cParams;
+
+        // update fvElementGeometry and the element volume variables
+        updateElemVolVars(lfsu1, lfsu2,
+                          unknowns1, unknowns2,
+                          sdElement1, sdElement2,
+                          cParams);
+
+        // first element
+        const int faceIdx1 = intersectionGeometry.indexInInside();
+        const Dune::ReferenceElement<typename MDGrid::ctype,dim>& referenceElement1 =
+            Dune::ReferenceElements<typename MDGrid::ctype,dim>::general(mdElement1.type());
+        const int numVerticesOfFace = referenceElement1.size(faceIdx1, 1, dim);
+
+        // second element
+        const int faceIdx2 = intersectionGeometry.indexInOutside();
+        const Dune::ReferenceElement<typename MDGrid::ctype,dim>& referenceElement2 =
+            Dune::ReferenceElements<typename MDGrid::ctype,dim>::general(mdElement2.type());
+
+        for (int vertexInFace = 0; vertexInFace < numVerticesOfFace; ++vertexInFace)
+        {
+            const int vertInElem1 = referenceElement1.subEntity(faceIdx1, 1, vertexInFace, dim);
+            const int vertInElem2 = referenceElement2.subEntity(faceIdx2, 1, vertexInFace, dim);
+
+            const int boundaryFaceIdx1 = cParams.fvGeometry1.boundaryFaceIndex(faceIdx1, vertexInFace);
+            const int boundaryFaceIdx2 = cParams.fvGeometry2.boundaryFaceIndex(faceIdx2, vertexInFace);
+
+            // obtain the boundary types
+            const VertexPointer1 vPtr1 = sdElement1.template subEntity<dim>(vertInElem1);
+            const VertexPointer2 vPtr2 = sdElement2.template subEntity<dim>(vertInElem2);
+
+            globalProblem_.sdProblem1().boundaryTypes(cParams.boundaryTypes1, vPtr1);
+            globalProblem_.sdProblem2().boundaryTypes(cParams.boundaryTypes2, vPtr2);
+
+            const BoundaryVariables1 boundaryVars1(globalProblem_.sdProblem1(),
+                                                   sdElement1,
+                                                   cParams.fvGeometry1,
+                                                   boundaryFaceIdx1,
+                                                   cParams.elemVolVarsCur1,
+                                                   /*onBoundary=*/true);
+            const BoundaryVariables2 boundaryVars2(globalProblem_.sdProblem2(),
+                                                   sdElement2,
+                                                   cParams.fvGeometry2,
+                                                   boundaryFaceIdx2,
+                                                   cParams.elemVolVarsCur2,
+                                                   /*onBoundary=*/true);
+
+            asImp_()->evalCoupling(lfsu1, lfsu2,
+                                   vertInElem1, vertInElem2,
+                                   sdElement1, sdElement2,
+                                   boundaryVars1, boundaryVars2,
+                                   cParams,
+                                   couplingRes1, couplingRes2);
+        }
+    }
+
+    /*!
+     * \brief Update the volume variables of the element and extract the unknowns from dune-pdelab vectors
+     *        and bring them into a form which fits to dumux.
+     *
+     * \param lfsu1 local basis for the trial space of the Stokes domain
+     * \param lfsu2 local basis for the trial space of the Darcy domain
+     * \param unknowns1 the unknowns vector of the Stokes element (formatted according to PDELab)
+     * \param unknowns2 the unknowns vector of the Darcy element (formatted according to PDELab)
+     * \param sdElement1 the element in the Stokes domain
+     * \param sdElement2 the element in the Darcy domain
+     * \param cParams a parameter container
+     */
+    template<typename LFSU1, typename LFSU2, typename X, typename CParams>
+    void updateElemVolVars(const LFSU1& lfsu1, const LFSU2& lfsu2,
+                           const X& unknowns1, const X& unknowns2,
+                           const SDElement1& sdElement1, const SDElement2& sdElement2,
+                           CParams &cParams) const
+    {
+        cParams.fvGeometry1.update(globalProblem_.sdGridView1(), sdElement1);
+        cParams.fvGeometry2.update(globalProblem_.sdGridView2(), sdElement2);
+
+        const int numVertsOfElem1 = sdElement1.subEntities(dim);
+        const int numVertsOfElem2 = sdElement2.subEntities(dim);
+
+        // bring the local unknowns x1 into a form that can be passed to elemVolVarsCur.update()
+        Dune::BlockVector<Dune::FieldVector<Scalar,1>> elementSol1(0.);
+        Dune::BlockVector<Dune::FieldVector<Scalar,1>> elementSol2(0.);
+        elementSol1.resize(unknowns1.size());
+        elementSol2.resize(unknowns2.size());
+
+        for (int idx=0; idx<numVertsOfElem1; ++idx)
+        {
+            for (int eqIdx1=0; eqIdx1<numEq1; ++eqIdx1)
+                elementSol1[eqIdx1*numVertsOfElem1+idx] = unknowns1(lfsu1.child(eqIdx1),idx);
+            for (int eqIdx2=0; eqIdx2<numEq2; ++eqIdx2)
+                elementSol2[eqIdx2*numVertsOfElem2+idx] = unknowns2(lfsu2.child(eqIdx2),idx);
+        }
+#if HAVE_VALGRIND
+        for (unsigned int i = 0; i < elementSol1.size(); i++)
+            Valgrind::CheckDefined(elementSol1[i]);
+        for (unsigned int i = 0; i < elementSol2.size(); i++)
+            Valgrind::CheckDefined(elementSol2[i]);
+#endif // HAVE_VALGRIND
+
+        cParams.elemVolVarsPrev1.update(globalProblem_.sdProblem1(),
+                                        sdElement1,
+                                        cParams.fvGeometry1,
+                                        true /* oldSol? */);
+        cParams.elemVolVarsCur1.updatePDELab(globalProblem_.sdProblem1(),
+                                             sdElement1,
+                                             cParams.fvGeometry1,
+                                             elementSol1);
+        cParams.elemVolVarsPrev2.update(globalProblem_.sdProblem2(),
+                                        sdElement2,
+                                        cParams.fvGeometry2,
+                                        true /* oldSol? */);
+        cParams.elemVolVarsCur2.updatePDELab(globalProblem_.sdProblem2(),
+                                             sdElement2,
+                                             cParams.fvGeometry2,
+                                             elementSol2);
+
+        ElementBoundaryTypes1 bcTypes1;
+        ElementBoundaryTypes2 bcTypes2;
+        bcTypes1.update(globalProblem_.sdProblem1(), sdElement1, cParams.fvGeometry1);
+        bcTypes2.update(globalProblem_.sdProblem2(), sdElement2, cParams.fvGeometry2);
+
+        globalProblem_.localResidual1().evalPDELab(sdElement1, cParams.fvGeometry1,
+                                                   cParams.elemVolVarsPrev1, cParams.elemVolVarsCur1,
+                                                   bcTypes1);
+        globalProblem_.localResidual2().evalPDELab(sdElement2, cParams.fvGeometry2,
+                                                   cParams.elemVolVarsPrev2, cParams.elemVolVarsCur2,
+                                                   bcTypes2);
+    }
+
+    /*!
+     * \brief Evaluation of the coupling between the Stokes (1) and Darcy (2).
+     *
+     * Dirichlet-like and Neumann-like conditions for the respective domain are evaluated.
+     *
+     * \param lfsu1 local basis for the trial space of the Stokes domain
+     * \param lfsu2 local basis for the trial space of the Darcy domain
+     * \param vertInElem1 local vertex index in element1
+     * \param vertInElem2 local vertex index in element2
+     * \param sdElement1 the element in the Stokes domain
+     * \param sdElement2 the element in the Darcy domain
+     * \param boundaryVars1 the boundary variables at the interface of the Stokes domain
+     * \param boundaryVars2 the boundary variables at the interface of the Darcy domain
+     * \param cParams a parameter container
+     * \param couplingRes1 the coupling residual from the Stokes domain
+     * \param couplingRes2 the coupling residual from the Darcy domain
+     */
+    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
+    void evalCoupling(const LFSU1& lfsu1, const LFSU2& lfsu2,
+                      const int vertInElem1, const int vertInElem2,
+                      const SDElement1& sdElement1, const SDElement2& sdElement2,
+                      const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
+                      const CParams &cParams,
+                      RES1& couplingRes1, RES2& couplingRes2) const
+    {
+        const GlobalPosition& globalPos1 = cParams.fvGeometry1.subContVol[vertInElem1].global;
+        const GlobalPosition& globalPos2 = cParams.fvGeometry2.subContVol[vertInElem2].global;
+
+        const GlobalPosition& bfNormal1 = boundaryVars1.face().normal;
+        const Scalar normalMassFlux1 = boundaryVars1.normalVelocity()
+                                       * cParams.elemVolVarsCur1[vertInElem1].density();
+
+        // MASS Balance
+        // Neumann-like conditions
+        if (cParams.boundaryTypes1.isCouplingNeumann(massBalanceIdx1))
+        {
+            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingNeumann(massBalanceIdx1) for the Stokes side is not implemented.");
+        }
+        if (cParams.boundaryTypes2.isCouplingNeumann(massBalanceIdx2))
+        {
+            static_assert(!GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
+                          "This coupling condition is only implemented for mass fraction formulation.");
+
+            if (globalProblem_.sdProblem1().isCornerPoint(globalPos1))
+            {
+                couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
+                                        -normalMassFlux1);
+            }
+            else
+            {
+                couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
+                                        globalProblem_.localResidual1().residual(vertInElem1)[massBalanceIdx1]);
+            }
+        }
+
+        // Dirichlet-like
+        if (cParams.boundaryTypes1.isCouplingDirichlet(massBalanceIdx1))
+        {
+            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingDirichlet(massBalanceIdx1) for the Stokes side is not implemented.");
+        }
+        if (cParams.boundaryTypes2.isCouplingDirichlet(massBalanceIdx2))
+        {
+            couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
+                                    globalProblem_.localResidual1().residual(vertInElem1)[momentumYIdx1]
+                                    -cParams.elemVolVarsCur1[vertInElem1].pressure());
+        }
+
+
+        // MOMENTUM_X Balance
+        SpatialParams spatialParams = globalProblem_.sdProblem2().spatialParams();
+        Scalar beaversJosephCoeff = spatialParams.beaversJosephCoeffAtPos(globalPos1);
+        assert(beaversJosephCoeff > 0);
+        beaversJosephCoeff /= std::sqrt(spatialParams.intrinsicPermeability(sdElement2, cParams.fvGeometry2, vertInElem2));
+
+        // Neumann-like conditions
+        if (cParams.boundaryTypes1.isCouplingNeumann(momentumXIdx1))
+        {
+            // v_tau = v - (v.n)n
+            const Scalar normalComp = boundaryVars1.velocity()*bfNormal1;
+            GlobalPosition normalV = bfNormal1;
+            normalV *= normalComp;
+            const GlobalPosition tangentialV = boundaryVars1.velocity() - normalV;
+
+            // Implementation as Neumann-like condition: (v.n)n
+            for (int dimIdx=0; dimIdx < dim; ++dimIdx)
+            {
+                couplingRes1.accumulate(lfsu1.child(momentumXIdx1), vertInElem1,
+                                        beaversJosephCoeff
+                                        * boundaryVars1.face().area
+                                        * tangentialV[dimIdx]
+                                        * (boundaryVars1.dynamicViscosity()
+                                          + boundaryVars1.dynamicEddyViscosity()));
+            }
+        }
+
+        // Dirichlet-like conditions
+        if (cParams.boundaryTypes1.isCouplingDirichlet(momentumXIdx1))
+        {
+            // NOTE: This boundary condition is not implemented anymore because curPrimaryVars_ is protected
+            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingNeumann(momentumXIdx1) on the Stokes side is not implemented anymore.");
+
+            // tangential component: vx = sqrt K /alpha * (grad v n(unity))t
+            // GlobalPosition tangentialVelGrad(0);
+            // boundaryVars1.velocityGrad().umv(elementUnitNormal, tangentialVelGrad);
+            // tangentialVelGrad /= -beaversJosephCoeff; // was - before
+            // this->residual_[vertInElem1][momentumXIdx1] =
+            //        tangentialVelGrad[momentumXIdx1] - globalProblem_.localResidual1().curPriVars_(vertInElem1)[momentumXIdx1]);
+        }
+
+
+        // MOMENTUM_Y Balance
+        // Neumann-like conditions
+        if (cParams.boundaryTypes1.isCouplingNeumann(momentumYIdx1))
+        {
+            // p*A as condition for free flow
+            // pressure correction is done in stokeslocalresidual.hh
+            couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
+                                    cParams.elemVolVarsCur2[vertInElem2].pressure(nPhaseIdx2) *
+                                    boundaryVars2.face().area);
+        }
+
+        // Dirichlet-like conditions
+        if (cParams.boundaryTypes1.isCouplingDirichlet(momentumYIdx1))
+        {
+            // v.n as Dirichlet-like condition for the Stokes domain
+            if (globalProblem_.sdProblem2().isCornerPoint(globalPos2))
+            {
+                Scalar sumNormalPhaseFluxes = 0.0;
+                for (int phaseIdx=0; phaseIdx<numPhases2; ++phaseIdx)
+                {
+                    sumNormalPhaseFluxes -= boundaryVars2.volumeFlux(phaseIdx)
+                                            * cParams.elemVolVarsCur2[vertInElem2].density(phaseIdx);
+                }
+                couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
+                                        -sumNormalPhaseFluxes
+                                        / cParams.elemVolVarsCur1[vertInElem1].density());
+            }
+            else
+            {
+                // set residualStokes[momentumYIdx1] = v_y in stokesnccouplinglocalresidual.hh
+                couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
+                                        globalProblem_.localResidual2().residual(vertInElem2)[massBalanceIdx2]
+                                        / cParams.elemVolVarsCur1[vertInElem1].density());
+            }
+        }
+
+
+        // COMPONENT Balance
+        // Neumann-like conditions
+        if (cParams.boundaryTypes1.isCouplingNeumann(transportEqIdx1))
+        {
+            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingNeumann(transportEqIdx1) is not implemented \
+                                              for the Stokes side for multicomponent systems.");
+        }
+        if (cParams.boundaryTypes2.isCouplingNeumann(contiWEqIdx2))
+        {
+            // only enter here, if a boundary layer model is used for the computation of the diffusive fluxes
+            if (blModel_)
+            {
+                Scalar advectiveFlux = normalMassFlux1
+                                       * cParams.elemVolVarsCur1[vertInElem1].massFraction(transportCompIdx1);
+
+                Scalar diffusiveFlux = bfNormal1.two_norm()
+                                       * evalBoundaryLayerConcentrationGradient(cParams, vertInElem1)
+                                       * (boundaryVars1.diffusionCoeff(transportCompIdx1)
+                                         + boundaryVars1.eddyDiffusivity())
+                                       * boundaryVars1.molarDensity()
+                                       * FluidSystem::molarMass(transportCompIdx1);
+
+                const Scalar massTransferCoeff = evalMassTransferCoefficient(cParams, vertInElem1, vertInElem2);
+
+                if (massTransferModel_ && globalProblem_.sdProblem1().isCornerPoint(globalPos1))
+                {
+                    Scalar diffusiveFluxAtCorner = bfNormal1
+                                                   * boundaryVars1.moleFractionGrad(transportCompIdx1)
+                                                   * (boundaryVars1.diffusionCoeff(transportCompIdx1)
+                                                      + boundaryVars1.eddyDiffusivity())
+                                                   * boundaryVars1.molarDensity()
+                                                   * FluidSystem::molarMass(transportCompIdx1);
+
+                    couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
+                                            -massTransferCoeff*(advectiveFlux - diffusiveFlux) -
+                                            (1.-massTransferCoeff)*(advectiveFlux - diffusiveFluxAtCorner));
+                }
+                else
+                {
+                    couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
+                                            -massTransferCoeff*(advectiveFlux - diffusiveFlux) +
+                                            (1.-massTransferCoeff)*globalProblem_.localResidual1().residual(vertInElem1)[transportEqIdx1]);
+                }
+            }
+            else if (globalProblem_.sdProblem1().isCornerPoint(globalPos1))
+            {
+                static_assert(!GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
+                              "This coupling condition is only implemented for mass fraction formulation.");
+
+                Scalar advectiveFlux = normalMassFlux1
+                                       * cParams.elemVolVarsCur1[vertInElem1].massFraction(transportCompIdx1);
+
+                Scalar diffusiveFlux = bfNormal1
+                                       * boundaryVars1.moleFractionGrad(transportCompIdx1)
+                                       * (boundaryVars1.diffusionCoeff(transportCompIdx1)
+                                          + boundaryVars1.eddyDiffusivity())
+                                       * boundaryVars1.molarDensity()
+                                       * FluidSystem::molarMass(transportCompIdx1);
+
+                couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
+                                        -(advectiveFlux - diffusiveFlux));
+            }
+            else
+            {
+                static_assert(GET_PROP_VALUE(Stokes2cTypeTag, UseMoles) == GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
+                              "This coupling condition is not implemented for different formulations (mass/mole) in the subdomains.");
+
+                // the component mass flux from the stokes domain
+                couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
+                                        globalProblem_.localResidual1().residual(vertInElem1)[transportEqIdx1]);
+            }
+        }
+
+        // Dirichlet-like conditions
+        if (cParams.boundaryTypes1.isCouplingDirichlet(transportEqIdx1))
+        {
+            static_assert(!GET_PROP_VALUE(Stokes2cTypeTag, UseMoles),
+                          "This coupling condition is only implemented for mass fraction formulation.");
+
+            // set residualStokes[transportEqIdx1] = x in stokesnccouplinglocalresidual.hh
+            // coupling residual is added to "real" residual
+            couplingRes1.accumulate(lfsu1.child(transportEqIdx1), vertInElem1,
+                                    -cParams.elemVolVarsCur2[vertInElem2].massFraction(nPhaseIdx2, wCompIdx2));
+        }
+        if (cParams.boundaryTypes2.isCouplingDirichlet(contiWEqIdx2))
+        {
+            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingDirichlet(contiWEqIdx2) is not implemented \
+                                              for the Darcy side for multicomponent systems.");
+        }
+    }
+
+    /*!
+     * \brief Evaluation of the coupling from Stokes (1) to Darcy (2).
+     *
+     * \param lfsu1 local basis for the trial space of the Stokes domain
+     * \param lfsu2 local basis for the trial space of the Darcy domain
+     * \param vertInElem1 local vertex index in element1
+     * \param vertInElem2 local vertex index in element2
+     * \param sdElement1 the element in the Stokes domain
+     * \param sdElement2 the element in the Darcy domain
+     * \param boundaryVars1 the boundary variables at the interface of the Stokes domain
+     * \param boundaryVars2 the boundary variables at the interface of the Darcy domain
+     * \param cParams a parameter container
+     * \param couplingRes1 the coupling residual from the Stokes domain
+     * \param couplingRes2 the coupling residual from the Darcy domain
+     */
+    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
+    DUNE_DEPRECATED_MSG("evalCoupling12() is deprecated. Use evalCoupling() instead.")
+    void evalCoupling12(const LFSU1& lfsu1, const LFSU2& lfsu2,
+                        const int vertInElem1, const int vertInElem2,
+                        const SDElement1& sdElement1, const SDElement2& sdElement2,
+                        const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
+                        const CParams &cParams,
+                        RES1& couplingRes1, RES2& couplingRes2) const
+    {
+        const GlobalPosition& globalPos1 = cParams.fvGeometry1.subContVol[vertInElem1].global;
+        const GlobalPosition& bfNormal1 = boundaryVars1.face().normal;
+
+        const Scalar normalMassFlux = boundaryVars1.normalVelocity() *
+            cParams.elemVolVarsCur1[vertInElem1].density();
+
+        //rho*v*n as NEUMANN condition for porous medium (set, if B&J defined as NEUMANN condition)
+        if (cParams.boundaryTypes2.isCouplingNeumann(massBalanceIdx2))
+        {
+            static_assert(!GET_PROP_VALUE(Stokes2cTypeTag, UseMoles),
+                          "This coupling condition is only implemented for mass fraction formulation.");
+
+            if (globalProblem_.sdProblem1().isCornerPoint(globalPos1))
+            {
+                couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
+                                        -normalMassFlux);
+            }
+            else
+            {
+                couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
+                                        globalProblem_.localResidual1().residual(vertInElem1)[massBalanceIdx1]);
+            }
+        }
+        if (cParams.boundaryTypes2.isCouplingDirichlet(massBalanceIdx2))
+        {
+            couplingRes2.accumulate(lfsu2.child(massBalanceIdx2), vertInElem2,
+                                    globalProblem_.localResidual1().residual(vertInElem1)[momentumYIdx1]
+                                    -cParams.elemVolVarsCur1[vertInElem1].pressure());
+        }
+
+        if (cParams.boundaryTypes2.isCouplingNeumann(contiWEqIdx2))
+        {
+            // only enter here, if a boundary layer model is used for the computation of the diffusive fluxes
+            if (blModel_)
+            {
+                const Scalar diffusiveFlux =
+                    bfNormal1.two_norm()
+                    * evalBoundaryLayerConcentrationGradient(cParams, vertInElem1)
+                    * (boundaryVars1.diffusionCoeff(transportCompIdx1)
+                       + boundaryVars1.eddyDiffusivity())
+                    * boundaryVars1.molarDensity()
+                    * FluidSystem::molarMass(transportCompIdx1);
+
+                Scalar advectiveFlux = normalMassFlux * cParams.elemVolVarsCur1[vertInElem1].massFraction(transportCompIdx1);
+
+                const Scalar massTransferCoeff = evalMassTransferCoefficient(cParams, vertInElem1, vertInElem2);
+
+                if (globalProblem_.sdProblem1().isCornerPoint(globalPos1) && massTransferModel_)
+                {
+                    const Scalar diffusiveFluxAtCorner =
+                        bfNormal1 *
+                        boundaryVars1.moleFractionGrad(transportCompIdx1) *
+                        (boundaryVars1.diffusionCoeff(transportCompIdx1) + boundaryVars1.eddyDiffusivity()) *
+                        boundaryVars1.molarDensity() *
+                        FluidSystem::molarMass(transportCompIdx1);
+
+                    couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
+                                            -massTransferCoeff*(advectiveFlux - diffusiveFlux) -
+                                            (1.-massTransferCoeff)*(advectiveFlux - diffusiveFluxAtCorner));
+                }
+                else
+                {
+                    couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
+                                            -massTransferCoeff*(advectiveFlux - diffusiveFlux) +
+                                            (1.-massTransferCoeff)*globalProblem_.localResidual1().residual(vertInElem1)[transportEqIdx1]);
+                }
+            }
+            else if (globalProblem_.sdProblem1().isCornerPoint(globalPos1))
+            {
+                static_assert(!GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
+                              "This coupling condition is only implemented for mass fraction formulation.");
+
+                const Scalar advectiveFlux =
+                    normalMassFlux *
+                    cParams.elemVolVarsCur1[vertInElem1].massFraction(transportCompIdx1);
+                const Scalar diffusiveFlux =
+                    bfNormal1 *
+                    boundaryVars1.moleFractionGrad(transportCompIdx1) *
+                    (boundaryVars1.diffusionCoeff(transportCompIdx1) + boundaryVars1.eddyDiffusivity()) *
+                    boundaryVars1.molarDensity() *
+                    FluidSystem::molarMass(transportCompIdx1);
+
+                couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
+                                        -(advectiveFlux - diffusiveFlux));
+            }
+            else
+            {
+                static_assert(GET_PROP_VALUE(Stokes2cTypeTag, UseMoles) == GET_PROP_VALUE(TwoPTwoCTypeTag, UseMoles),
+                              "This coupling condition is not implemented dor different formulations (mass/mole) in the subdomains.");
+
+                // the component mass flux from the stokes domain
+                couplingRes2.accumulate(lfsu2.child(contiWEqIdx2), vertInElem2,
+                                        globalProblem_.localResidual1().residual(vertInElem1)[transportEqIdx1]);
+            }
+        }
+        if (cParams.boundaryTypes2.isCouplingDirichlet(contiWEqIdx2))
+        {
+            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingDirichlet(contiWEqIdx2) is not implemented for the Darcy side.");
+        }
+    }
+
+    /*!
+     * \brief Evaluation of the coupling from Darcy (2) to Stokes (1).
+     *
+     * \param lfsu1 local basis for the trial space of the Stokes domain
+     * \param lfsu2 local basis for the trial space of the Darcy domain
+     * \param vertInElem1 local vertex index in element1
+     * \param vertInElem2 local vertex index in element2
+     * \param sdElement1 the element in the Stokes domain
+     * \param sdElement2 the element in the Darcy domain
+     * \param boundaryVars1 the boundary variables at the interface of the Stokes domain
+     * \param boundaryVars2 the boundary variables at the interface of the Darcy domain
+     * \param cParams a parameter container
+     * \param couplingRes1 the coupling residual from the Stokes domain
+     * \param couplingRes2 the coupling residual from the Darcy domain
+     */
+    template<typename LFSU1, typename LFSU2, typename RES1, typename RES2, typename CParams>
+    DUNE_DEPRECATED_MSG("evalCoupling21() is deprecated. Use evalCoupling() instead.")
+    void evalCoupling21(const LFSU1& lfsu1, const LFSU2& lfsu2,
+                        const int vertInElem1, const int vertInElem2,
+                        const SDElement1& sdElement1, const SDElement2& sdElement2,
+                        const BoundaryVariables1& boundaryVars1, const BoundaryVariables2& boundaryVars2,
+                        const CParams &cParams,
+                        RES1& couplingRes1, RES2& couplingRes2) const
+    {
+        const GlobalPosition& globalPos2 = cParams.fvGeometry2.subContVol[vertInElem2].global;
+        GlobalPosition normalFlux2(0.);
+
+        // velocity*normal*area*rho
+        for (int phaseIdx=0; phaseIdx<numPhases2; ++phaseIdx)
+            normalFlux2[phaseIdx] = -boundaryVars2.volumeFlux(phaseIdx)*
+                cParams.elemVolVarsCur2[vertInElem2].density(phaseIdx);
+
+        //p*n as NEUMANN condition for free flow (set, if B&J defined as NEUMANN condition)
+        if (cParams.boundaryTypes1.isCouplingDirichlet(momentumYIdx1))
+        {
+            //p*A*n as NEUMANN condition for free flow (set, if B&J defined as NEUMANN condition)
+            //pressure correction in stokeslocalresidual.hh
+            couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
+                                    cParams.elemVolVarsCur2[vertInElem2].pressure(nPhaseIdx2) *
+                                    boundaryVars2.face().area);
+        }
+        if (cParams.boundaryTypes1.isCouplingNeumann(momentumYIdx1))
+        {
+            // v.n as Dirichlet-like condition for the Stokes domain
+            // set residualStokes[momentumYIdx1] = vy in stokeslocalresidual.hh
+            if (globalProblem_.sdProblem2().isCornerPoint(globalPos2))
+            {
+                couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
+                                        -((normalFlux2[nPhaseIdx2] + normalFlux2[wPhaseIdx2])
+                                          / cParams.elemVolVarsCur1[vertInElem1].density()));
+            }
+            else
+            {
+                // v.n as DIRICHLET condition for the Stokes domain (negative sign!)
+                couplingRes1.accumulate(lfsu1.child(momentumYIdx1), vertInElem1,
+                                        globalProblem_.localResidual2().residual(vertInElem2)[massBalanceIdx2]
+                                        / cParams.elemVolVarsCur1[vertInElem1].density());
+            }
+        }
+
+        typedef typename GET_PROP_TYPE(Stokes2cTypeTag, SpatialParams) SpatialParams1;
+        SpatialParams1 spatialParams = globalProblem_.sdProblem1().spatialParams();
+        const GlobalPosition& globalPos = cParams.fvGeometry1.subContVol[vertInElem1].global;
+        Scalar beaversJosephCoeff = spatialParams.beaversJosephCoeffAtPos(globalPos);
+        assert(beaversJosephCoeff > 0);
+
+        const Scalar Kxx = spatialParams.intrinsicPermeability(sdElement1, cParams.fvGeometry1,
+                                                               vertInElem1);
+
+        beaversJosephCoeff /= std::sqrt(Kxx);
+        const GlobalPosition& elementUnitNormal = boundaryVars1.face().normal;
+
+        // Implementation as Neumann-like condition: (v.n)n
+        if (cParams.boundaryTypes1.isCouplingDirichlet(momentumXIdx1))
+        {
+            const Scalar normalComp = boundaryVars1.velocity()*elementUnitNormal;
+            GlobalPosition normalV = elementUnitNormal;
+            normalV *= normalComp; // v*n*n
+
+            // v_tau = v - (v.n)n
+            const GlobalPosition tangentialV = boundaryVars1.velocity() - normalV;
+            const Scalar boundaryFaceArea = boundaryVars1.face().area;
+
+            for (int dimIdx=0; dimIdx < dim; ++dimIdx)
+            {
+                couplingRes1.accumulate(lfsu1.child(momentumXIdx1), vertInElem1,
+                                        beaversJosephCoeff
+                                        * boundaryFaceArea
+                                        * tangentialV[dimIdx]
+                                        * (boundaryVars1.dynamicViscosity()
+                                          + boundaryVars1.dynamicEddyViscosity()));
+            }
+        }
+        // Implementation as Dirichlet-like condition
+        // tangential component: vx = sqrt K /alpha * (grad v n(unity))t
+        if (cParams.boundaryTypes1.isCouplingNeumann(momentumXIdx1))
+        {
+            DUNE_THROW(Dune::NotImplemented, "The boundary conditionisCouplingNeumann(momentumXIdx1) on the Stokes side is not implemented anymore.");
+            // GlobalPosition tangentialVelGrad(0);
+            // boundaryVars1.velocityGrad().umv(elementUnitNormal, tangentialVelGrad);
+            // tangentialVelGrad /= -beaversJosephCoeff; // was - before
+            // couplingRes1.accumulate(lfsu1.child(momentumXIdx1), vertInElem1,
+            // this->residual_[vertInElem1][momentumXIdx1] =
+            //        tangentialVelGrad[momentumXIdx1] - globalProblem_.localResidual1().curPriVars_(vertInElem1)[momentumXIdx1]);
+        }
+
+        //coupling residual is added to "real" residual
+        //here each node is passed twice, hence only half of the dirichlet condition has to be set
+        if (cParams.boundaryTypes1.isCouplingDirichlet(transportEqIdx1))
+        {
+            // set residualStokes[transportEqIdx1] = x in stokes2clocalresidual.hh
+
+
+            static_assert(!GET_PROP_VALUE(Stokes2cTypeTag, UseMoles),
+                          "This coupling condition is only implemented for mass fraction formulation.");
+
+            couplingRes1.accumulate(lfsu1.child(transportEqIdx1), vertInElem1,
+                                    -cParams.elemVolVarsCur2[vertInElem2].massFraction(nPhaseIdx2, wCompIdx2));
+        }
+        if (cParams.boundaryTypes1.isCouplingNeumann(transportEqIdx1))
+        {
+            DUNE_THROW(Dune::NotImplemented, "The boundary condition isCouplingNeumann(transportEqIdx1) is not implemented for the Stokes side.");
+        }
+    }
+
+    /*!
+     * \brief Returns a BoundaryLayerModel object
+     *
+     * This function is reused in Child LocalOperators and used for extracting
+     * the respective boundary layer thickness.<br>
+     * \todo This function could be moved to a more model specific place, because
+     *       of its runtime parameters.
+     *
+     * \param cParams a parameter container
+     * \param scvIdx1 The local index of the sub-control volume of the Stokes domain
+     */
+    template<typename CParams>
+    BoundaryLayerModel<TypeTag> evalBoundaryLayerModel(CParams cParams, const int scvIdx1) const
+    {
+        // current position + additional virtual runup distance
+        const Scalar distance = cParams.fvGeometry1.subContVol[scvIdx1].global[0]
+                                + GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, Offset);
+        BoundaryLayerModel<TypeTag> boundaryLayerModel(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefVelocity),
+                                                       distance,
+                                                       cParams.elemVolVarsCur1[scvIdx1].kinematicViscosity(),
+                                                       blModel_);
+        if (blModel_ == 1)
+            boundaryLayerModel.setConstThickness(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, ConstThickness));
+        if (blModel_ >= 4)
+            boundaryLayerModel.setYPlus(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, YPlus));
+        if (blModel_ >= 5)
+            boundaryLayerModel.setRoughnessLength(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, RoughnessLength));
+        if (blModel_ == 7)
+            boundaryLayerModel.setHydraulicDiameter(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, BoundaryLayer, HydraulicDiameter));
+
+        return boundaryLayerModel;
+    }
+
+    /*!
+     * \brief Returns the concentration gradient through the boundary layer
+     *
+     * \todo This function could be moved to a more model specific place, because
+     *       of its runtime parameters.
+     *
+     * \param cParams a parameter container
+     * \param scvIdx1 The local index of the sub-control volume of the Stokes domain
+     */
+    template<typename CParams>
+    Scalar evalBoundaryLayerConcentrationGradient(CParams cParams, const int scvIdx1) const
+    {
+        static_assert(numComponents1 == 2,
+                      "This coupling condition is only implemented for two components.");
+        Scalar massFractionOut = GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, FreeFlow, RefMassfrac);
+        Scalar M1 = FluidSystem::molarMass(transportCompIdx1);
+        Scalar M2 = FluidSystem::molarMass(phaseCompIdx1);
+        Scalar X2 = 1.0 - massFractionOut;
+        Scalar massToMoleDenominator = M2 + X2*(M1 - M2);
+        Scalar moleFractionOut = massFractionOut * M2 /massToMoleDenominator;
+
+        Scalar normalMoleFracGrad = cParams.elemVolVarsCur1[scvIdx1].moleFraction(transportCompIdx1)
+                                    - moleFractionOut;
+        return normalMoleFracGrad / evalBoundaryLayerModel(cParams, scvIdx1).massBoundaryLayerThickness();
+    }
+
+    /*!
+     * \brief Returns the mass transfer coefficient
+     *
+     * This function is reused in Child LocalOperators.
+     * \todo This function could be moved to a more model specific place, because
+     *       of its runtime parameters.
+     *
+     * \param cParams a parameter container
+     * \param scvIdx1 The local index of the sub-control volume of the Stokes domain
+     * \param scvIdx1 The local index of the sub-control volume of the Darcy domain
+     */
+    template<typename CParams>
+    Scalar evalMassTransferCoefficient(CParams cParams, const int scvIdx1, const int scvIdx2) const
+    {
+        MassTransferModel<TypeTag> massTransferModel(cParams.elemVolVarsCur2[scvIdx2].saturation(wPhaseIdx2),
+                                                     cParams.elemVolVarsCur2[scvIdx2].porosity(),
+                                                     evalBoundaryLayerModel(cParams, scvIdx1).massBoundaryLayerThickness(),
+                                                     massTransferModel_);
+        if (massTransferModel_ == 1)
+            massTransferModel.setMassTransferCoeff(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, MassTransfer, Coefficient));
+        if (massTransferModel_ == 2 || massTransferModel_ == 4)
+            massTransferModel.setCharPoreRadius(GET_RUNTIME_PARAM_FROM_GROUP(TypeTag, Scalar, MassTransfer, CharPoreRadius));
+        if (massTransferModel_ == 3)
+            massTransferModel.setCapillaryPressure(cParams.elemVolVarsCur2[scvIdx2].capillaryPressure());
+
+        return massTransferModel.massTransferCoefficient();
+    }
+
+ protected:
+    GlobalProblem& globalProblem() const
+    { return globalProblem_; }
+
+    Implementation *asImp_()
+    { return static_cast<Implementation *> (this); }
+    const Implementation *asImp_() const
+    { return static_cast<const Implementation *> (this); }
+
+    unsigned int blModel_;
+    unsigned int massTransferModel_;
+
+ private:
+    /*!
+     * \brief A struct that contains data of the FF and PM including boundary types,
+     *        volume variables in both subdomains and geometric information
+     */
+    struct CParams
+    {
+        BoundaryTypes1 boundaryTypes1;
+        BoundaryTypes2 boundaryTypes2;
+        ElementVolumeVariables1 elemVolVarsPrev1;
+        ElementVolumeVariables1 elemVolVarsCur1;
+        ElementVolumeVariables2 elemVolVarsPrev2;
+        ElementVolumeVariables2 elemVolVarsCur2;
+        FVElementGeometry1 fvGeometry1;
+        FVElementGeometry2 fvGeometry2;
+    };
+
+    GlobalProblem& globalProblem_;
+};
+
+} // end namespace Dumux
+
+#endif // DUMUX_2CSTOKES_2P2C_LOCALOPERATOR_HH
diff --git a/dumux/multidomain/2cstokes2p2c/newtoncontroller.hh b/dumux/multidomain/2cstokes2p2c/newtoncontroller.hh
new file mode 100644
index 0000000000..712cf33479
--- /dev/null
+++ b/dumux/multidomain/2cstokes2p2c/newtoncontroller.hh
@@ -0,0 +1,68 @@
+// -*- 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 Reference implementation of a Newton controller for the coupling of a two-component Stokes model
+ *        and a two-phase two-component porous-medium model under isothermal conditions.
+ */
+#ifndef DUMUX_2CSTOKES_2P2C_NEWTON_CONTROLLER_HH
+#define DUMUX_2CSTOKES_2P2C_NEWTON_CONTROLLER_HH
+
+#include <dumux/multidomain/common/newtoncontroller.hh>
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup Newton
+ * \ingroup TwoPTwoCStokesTwoCModel
+ * \ingroup TwoPTwoCZeroEqTwoCModel
+ * \brief Implementation of a Newton controller for the coupling of a two-component Stokes model
+ *        and a two-phase two-component porous-medium model under isothermal conditions.
+ *
+ * The Newton controller ensures that the updateStaticData routine is called
+ * in the porous-medium sub-problem
+ */
+template <class TypeTag>
+class TwoCStokesTwoPTwoCNewtonController : public MultiDomainNewtonController<TypeTag>
+{
+    typedef MultiDomainNewtonController<TypeTag> ParentType;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+public:
+    //! \brief The constructor
+    TwoCStokesTwoPTwoCNewtonController(const Problem &problem)
+        : ParentType(problem)
+    {  }
+
+    //! \copydoc Dumux::NewtonController::newtonEndStep()
+    void newtonEndStep(SolutionVector &uCurrentIter, SolutionVector &uLastIter)
+    {
+        ParentType::newtonEndStep(uCurrentIter, uLastIter);
+
+        this->model_().sdModel2().updateStaticData(this->model_().sdModel2().curSol(),
+                                                   this->model_().sdModel2().prevSol());
+    }
+};
+
+} // namespace Dumux
+
+#endif // DUMUX_2CSTOKES_2P2C_NEWTON_CONTROLLER_HH
diff --git a/dumux/multidomain/2cstokes2p2c/properties.hh b/dumux/multidomain/2cstokes2p2c/properties.hh
new file mode 100644
index 0000000000..6ca47f6bce
--- /dev/null
+++ b/dumux/multidomain/2cstokes2p2c/properties.hh
@@ -0,0 +1,60 @@
+// -*- 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 Properties
+ * \ingroup ImplicitProperties
+ * \ingroup MultidomainModel
+ *
+ * \brief Defines the properties required for the coupled 2cstokes2p2c model.
+ */
+
+#ifndef DUMUX_TWOCSTOKESTWOPTWOC_PROPERTIES_HH
+#define DUMUX_TWOCSTOKESTWOPTWOC_PROPERTIES_HH
+
+#include <dumux/multidomain/common/propertydefaults.hh>
+
+namespace Dumux
+{
+
+////////////////////////////////
+// properties
+////////////////////////////////
+namespace Properties
+{
+
+//////////////////////////////////////////////////////////////////
+// Type tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tags for the coupled 2cstokes2p2c model
+NEW_TYPE_TAG(TwoCStokesTwoPTwoC, INHERITS_FROM(MultiDomain));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+NEW_PROP_TAG(BoundaryLayerModel); //!< Type of the used boundary layer model
+NEW_PROP_TAG(MassTransferModel); //!< Type of the used mass transfer model
+
+} // end namespace properties
+
+} // end namespace Dumux
+
+
+#endif
diff --git a/dumux/multidomain/2cstokes2p2c/propertydefaults.hh b/dumux/multidomain/2cstokes2p2c/propertydefaults.hh
new file mode 100644
index 0000000000..51816bd4ee
--- /dev/null
+++ b/dumux/multidomain/2cstokes2p2c/propertydefaults.hh
@@ -0,0 +1,66 @@
+// -*- 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 Properties
+ * \ingroup ImplicitProperties
+ * \ingroup MultidomainModel
+ *
+ * \brief Defines default values for the properties required by the
+ *        coupled 2cstokes2p2c model.
+ */
+#ifndef DUMUX_TWOCSTOKESTWOPTWOC_PROPERTY_DEFAULTS_HH
+#define DUMUX_TWOCSTOKESTWOPTWOC_PROPERTY_DEFAULTS_HH
+
+#include "properties.hh"
+#include "newtoncontroller.hh"
+
+namespace Dumux
+{
+namespace Properties
+{
+//////////////////////////////////////////////////////////////////
+// Property defaults
+//////////////////////////////////////////////////////////////////
+
+// Specify the multidomain gridview
+SET_TYPE_PROP(TwoCStokesTwoPTwoC, GridView,
+              typename GET_PROP_TYPE(TypeTag, MultiDomainGrid)::LeafGridView);
+
+// Specify the type of the used solution vector
+SET_TYPE_PROP(TwoCStokesTwoPTwoC, SolutionVector,
+              typename GET_PROP_TYPE(TypeTag, MultiDomainGridOperator)::Traits::Domain);
+
+// Specif the used Newton controller
+SET_TYPE_PROP(TwoCStokesTwoPTwoC, NewtonController, Dumux::TwoCStokesTwoPTwoCNewtonController<TypeTag>);
+
+// Set this to one here (must fit to the structure of the coupled matrix which has block length 1)
+SET_INT_PROP(TwoCStokesTwoPTwoC, NumEq, 1);
+
+// Specify the used boundary layer model
+SET_INT_PROP(TwoCStokesTwoPTwoC, BoundaryLayerModel, 0);
+
+// Specify the used mass transfer model
+SET_INT_PROP(TwoCStokesTwoPTwoC, MassTransferModel, 0);
+
+} // end namespace properties
+
+} // end namespace Dumux
+
+#endif
diff --git a/dumux/multidomain/common/assembler.hh b/dumux/multidomain/common/assembler.hh
new file mode 100644
index 0000000000..d4bfe93cf4
--- /dev/null
+++ b/dumux/multidomain/common/assembler.hh
@@ -0,0 +1,218 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief An assembler for the global Jacobian matrix for multidomain models.
+ */
+
+#ifndef DUMUX_MULTIDOMAIN_ASSEMBLER_HH
+#define DUMUX_MULTIDOMAIN_ASSEMBLER_HH
+
+#include <dune/pdelab/constraints/common/constraintsparameters.hh>
+#include <dune/pdelab/multidomain/constraints.hh>
+
+#include "properties.hh"
+#include "propertydefaults.hh"
+
+namespace Dumux {
+
+/*!
+ * \ingroup MultidomainModel
+ * \brief An assembler for the global Jacobian matrix for multidomain models.
+ */
+template<class TypeTag>
+class MultiDomainAssembler
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, Problem) SubDomainProblem1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, Problem) SubDomainProblem2;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, LocalFEMSpace) FEM1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, LocalFEMSpace) FEM2;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, ScalarGridFunctionSpace) ScalarGridFunctionSpace1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, ScalarGridFunctionSpace) ScalarGridFunctionSpace2;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, GridFunctionSpace) GridFunctionSpace1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, GridFunctionSpace) GridFunctionSpace2;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, LocalOperator) LocalOperator1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, LocalOperator) LocalOperator2;
+
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MultiDomainGridFunctionSpace;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCondition) MultiDomainCondition;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem1) MultiDomainSubProblem1;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem2) MultiDomainSubProblem2;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCouplingLocalOperator) MultiDomainCouplingLocalOperator;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCoupling) MultiDomainCoupling;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainConstraintsTrafo) MultiDomainConstraintsTrafo;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridOperator) MultiDomainGridOperator;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix;
+
+    // copying the jacobian assembler is not a good idea
+    MultiDomainAssembler(const MultiDomainAssembler &);
+
+public:
+    //! \brief The constructor
+    MultiDomainAssembler()
+    {
+        globalProblem_ = 0;
+        sdProblem1_= 0;
+        sdProblem2_= 0;
+    }
+
+    //! \brief The destructor
+    ~MultiDomainAssembler()
+    { }
+
+    //! \copydoc ImplicitAssembler::init()
+    void init(Problem& problem)
+    {
+        globalProblem_ = &problem;
+        sdProblem1_ = &globalProblem_->sdProblem1();
+        sdProblem2_ = &globalProblem_->sdProblem2();
+
+        fem1_ = std::make_shared<FEM1>(globalProblem_->sdGridView1());
+        fem2_ = std::make_shared<FEM2>(globalProblem_->sdGridView2());
+
+        scalarGridFunctionSpace1_ = std::make_shared<ScalarGridFunctionSpace1>(globalProblem_->sdGridView1(),
+                                                                                *fem1_);
+        scalarGridFunctionSpace2_ = std::make_shared<ScalarGridFunctionSpace2>(globalProblem_->sdGridView2(),
+                                                                                *fem2_);
+
+        gridFunctionSpace1_ = std::make_shared<GridFunctionSpace1>(*scalarGridFunctionSpace1_);
+        gridFunctionSpace2_ = std::make_shared<GridFunctionSpace2>(*scalarGridFunctionSpace2_);
+
+        mdGridFunctionSpace_ = std::make_shared<MultiDomainGridFunctionSpace>(globalProblem_->mdGrid(),
+                                                                               *gridFunctionSpace1_,
+                                                                               *gridFunctionSpace2_);
+
+        localOperator1_ = std::make_shared<LocalOperator1>(sdProblem1_->model());
+        localOperator2_ = std::make_shared<LocalOperator2>(sdProblem2_->model());
+
+        condition1_ = std::make_shared<MultiDomainCondition>(0);
+        condition2_ = std::make_shared<MultiDomainCondition>(1);
+
+        mdSubProblem1_ = std::make_shared<MultiDomainSubProblem1>(*localOperator1_, *condition1_);
+        mdSubProblem2_ = std::make_shared<MultiDomainSubProblem2>(*localOperator2_, *condition2_);
+
+        couplingLocalOperator_ = std::make_shared<MultiDomainCouplingLocalOperator>(*globalProblem_);
+        mdCoupling_ = std::make_shared<MultiDomainCoupling>(*mdSubProblem1_, *mdSubProblem2_, *couplingLocalOperator_);
+
+        constraintsTrafo_ = std::make_shared<MultiDomainConstraintsTrafo>();
+
+        mdGridOperator_ = std::make_shared<MultiDomainGridOperator>(*mdGridFunctionSpace_, *mdGridFunctionSpace_,
+                                                                     *constraintsTrafo_, *constraintsTrafo_,
+                                                                     *mdSubProblem1_, *mdSubProblem2_, *mdCoupling_);
+
+        matrix_ = std::make_shared<JacobianMatrix>(*mdGridOperator_);
+        residual_ = std::make_shared<SolutionVector>(*mdGridFunctionSpace_);
+    }
+
+    //! \copydoc ImplicitAssembler::assemble()
+    void assemble()
+    {
+        // assemble the matrix
+        *matrix_ = 0;
+        mdGridOperator_->jacobian(globalProblem_->model().curSol(), *matrix_);
+
+        // calculate the global residual
+        *residual_ = 0;
+        mdGridOperator_->residual(globalProblem_->model().curSol(), *residual_);
+    }
+
+    //! \copydoc ImplicitAssembler::reassembleAll()
+    void reassembleAll()
+    { }
+
+    //! \copydoc ImplicitAssembler::matrix()
+    const JacobianMatrix &matrix() const
+    { return *matrix_; }
+    JacobianMatrix &matrix()
+    { return *matrix_; }
+
+    //! \copydoc ImplicitAssembler::residual()
+    const SolutionVector &residual() const
+    { return *residual_; }
+    SolutionVector &residual()
+    { return *residual_; }
+
+    /*!
+     * \brief Return constant reference to the multidomain gridfunctionspace
+     */
+    MultiDomainGridFunctionSpace &gridFunctionSpace() const
+    { return *mdGridFunctionSpace_; }
+
+    /*!
+     * \brief Return constant reference to the multidomain gridfunctionspace
+     */
+    MultiDomainGridFunctionSpace &mdGridFunctionSpace() const
+    { return *mdGridFunctionSpace_; }
+
+    /*!
+     * \brief Return the multidomain constraints transformation
+     */
+    MultiDomainConstraintsTrafo &constraintsTrafo() const
+    { return *constraintsTrafo_; }
+
+private:
+    Problem *globalProblem_;
+    SubDomainProblem1 *sdProblem1_;
+    SubDomainProblem2 *sdProblem2_;
+
+    std::shared_ptr<FEM1> fem1_;
+    std::shared_ptr<FEM2> fem2_;
+
+    std::shared_ptr<ScalarGridFunctionSpace1> scalarGridFunctionSpace1_;
+    std::shared_ptr<ScalarGridFunctionSpace2> scalarGridFunctionSpace2_;
+
+    std::shared_ptr<GridFunctionSpace1> gridFunctionSpace1_;
+    std::shared_ptr<GridFunctionSpace2> gridFunctionSpace2_;
+    std::shared_ptr<MultiDomainGridFunctionSpace> mdGridFunctionSpace_;
+
+    std::shared_ptr<LocalOperator1> localOperator1_;
+    std::shared_ptr<LocalOperator2> localOperator2_;
+
+    std::shared_ptr<MultiDomainCondition> condition1_;
+    std::shared_ptr<MultiDomainCondition> condition2_;
+
+    std::shared_ptr<MultiDomainSubProblem1> mdSubProblem1_;
+    std::shared_ptr<MultiDomainSubProblem2> mdSubProblem2_;
+
+    std::shared_ptr<MultiDomainCouplingLocalOperator> couplingLocalOperator_;
+    std::shared_ptr<MultiDomainCoupling> mdCoupling_;
+
+    std::shared_ptr<MultiDomainConstraintsTrafo> constraintsTrafo_;
+    std::shared_ptr<MultiDomainGridOperator> mdGridOperator_;
+
+    std::shared_ptr<JacobianMatrix> matrix_;
+
+    std::shared_ptr<SolutionVector> residual_;
+};
+
+} // namespace Dumux
+
+#endif // DUMUX_MULTIDOMAIN_ASSEMBLER_HH
diff --git a/dumux/multidomain/common/convergencewriter.hh b/dumux/multidomain/common/convergencewriter.hh
new file mode 100644
index 0000000000..a06aef4710
--- /dev/null
+++ b/dumux/multidomain/common/convergencewriter.hh
@@ -0,0 +1,150 @@
+// -*- 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 Reference implementation of a newton convergence writer for coupled problems.
+*/
+#ifndef DUMUX_MULTIDOMAIN_CONVERGENCEWRITER_HH
+#define DUMUX_MULTIDOMAIN_CONVERGENCEWRITER_HH
+
+#include <dune/grid/multidomaingrid.hh>
+#include <dune/pdelab/backend/istlsolverbackend.hh>
+
+#include <dumux/io/vtkmultiwriter.hh>
+
+#include "splitandmerge.hh"
+#include "newtoncontroller.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MultidomainModel
+ * \brief Writes the intermediate solutions during
+ *        the Newton scheme
+ */
+template <class TypeTag>
+struct MultiDomainConvergenceWriter
+{
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, SplitAndMerge) SplitAndMerge;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, GridView) GridView1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, GridView) GridView2;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, SolutionVector) SolutionVector1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, SolutionVector) SolutionVector2;
+
+    typedef Dumux::VtkMultiWriter<GridView1> VtkMultiWriter1;
+    typedef Dumux::VtkMultiWriter<GridView2> VtkMultiWriter2;
+
+    /*!
+    * \brief The constructor
+    * \param ctl The newton controller
+    */
+    MultiDomainConvergenceWriter(NewtonController &ctl)
+        : ctl_(ctl)
+    {
+        timeStepIndex_ = 0;
+        iteration_ = 0;
+        vtkMultiWriter1_ = 0;
+        vtkMultiWriter2_ = 0;
+    }
+
+    /*!
+     * \brief Start and advance in time
+     */
+    void beginTimestep()
+    {
+        ++timeStepIndex_;
+        iteration_ = 0;
+    }
+
+    /*!
+     * \brief Start and advance one iteration
+     *
+     * \param gridView1 The grid view of sub problem 1
+     * \param gridView2 The grid view of sub problem 2
+     */
+    void beginIteration(const GridView1 &gridView1,
+                        const GridView2 &gridView2)
+    {
+        ++ iteration_;
+        if (!vtkMultiWriter1_)
+            vtkMultiWriter1_ = std::make_shared<VtkMultiWriter2>(gridView1, "convergence1");
+        vtkMultiWriter1_->beginWrite(timeStepIndex_ + iteration_ / 100.0);
+
+        if (!vtkMultiWriter2_)
+            vtkMultiWriter2_ = std::make_shared<VtkMultiWriter2>(gridView2, "convergence2");
+        vtkMultiWriter2_->beginWrite(timeStepIndex_ + iteration_ / 100.0);
+    }
+
+    /*!
+     * \brief Write convergence to vtk
+     *
+     * \param uLastIter The solution of the last iteration
+     * \param deltaU The delta as calculated from solving the linear
+     *               system of equations. This parameter also stores
+     *               the updated solution.
+     */
+    void writeFields(const SolutionVector &uLastIter,
+                     const SolutionVector &deltaU)
+    {
+          SolutionVector1 uLastIter1(ctl_.method().model().sdModel1().curSol());
+          SolutionVector2 uLastIter2(ctl_.method().model().sdModel2().curSol());
+          SolutionVector1 deltaU1(uLastIter1);
+          SolutionVector2 deltaU2(uLastIter2);
+
+          SplitAndMerge::splitSolVector(uLastIter, uLastIter1, uLastIter2);
+          SplitAndMerge::splitSolVector(deltaU, deltaU1, deltaU2);
+
+          std::cout << "\nWriting convergence file of current Newton iteration\n";
+          ctl_.method().model().sdModel1().addConvergenceVtkFields(*vtkMultiWriter1_, uLastIter1, deltaU1);
+          ctl_.method().model().sdModel2().addConvergenceVtkFields(*vtkMultiWriter2_, uLastIter2, deltaU2);
+    }
+
+    //! \brief End of iteration
+    void endIteration()
+    {
+        vtkMultiWriter1_->endWrite();
+        vtkMultiWriter2_->endWrite();
+    }
+
+    //! \brief End of time step
+    void endTimestep()
+    {
+        iteration_ = 0;
+    }
+
+private:
+    int timeStepIndex_;
+    int iteration_;
+    std::shared_ptr<VtkMultiWriter1> vtkMultiWriter1_;
+    std::shared_ptr<VtkMultiWriter2> vtkMultiWriter2_;
+    NewtonController &ctl_;
+};
+
+} // namespace Dumux
+
+#endif // DUMUX_MULTIDOMAIN_CONVERGENCEWRITER_HH
diff --git a/dumux/multidomain/common/localoperator.hh b/dumux/multidomain/common/localoperator.hh
new file mode 100644
index 0000000000..84bf4a0eab
--- /dev/null
+++ b/dumux/multidomain/common/localoperator.hh
@@ -0,0 +1,134 @@
+// -*- 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 Local operator base class for multidomain problems
+ */
+
+#ifndef DUMUX_MULTIDOMAIN_LOCAL_OPERATOR_HH
+#define DUMUX_MULTIDOMAIN_LOCAL_OPERATOR_HH
+
+#include<dune/pdelab/localoperator/pattern.hh>
+#include<dune/pdelab/localoperator/flags.hh>
+
+#include <dumux/implicit/box/properties.hh>
+
+namespace Dumux {
+
+namespace PDELab {
+
+/*!
+ * \ingroup MultidomainModel
+ * \brief Local operator base class for multidomain problems
+ */
+template<class TypeTag>
+class MultiDomainLocalOperator
+ : public Dune::PDELab::FullVolumePattern,
+   public Dune::PDELab::LocalOperatorDefaultFlags
+{
+    // copying the local operator for PDELab is not a good idea
+    MultiDomainLocalOperator(const MultiDomainLocalOperator &);
+
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+
+    enum{numEq = GET_PROP_VALUE(TypeTag, NumEq)};
+
+public:
+    // pattern assembly flags
+    enum { doPatternVolume = true };
+
+    // residual assembly flags
+    enum { doAlphaVolume = true };
+
+    //! \brief The constructor
+    MultiDomainLocalOperator(Model &model)
+    : model_(model)
+    {}
+
+    /*!
+     * \brief Volume integral depending on test and ansatz functions
+     *
+     * \tparam EG Element geometry
+     * \tparam LFSU Local function space for ansatz functions
+     * \tparam X Coefficient vector
+     * \tparam LFSV Local function space for test functions
+     * \tparam R Residual vector
+     *
+     * \param eg Element geometry
+     * \param lfsu Local functions space for ansatz functions
+     * \param x Coefficient vector
+     * \param lfsv Local function space for test functions
+     * \param r Residual vector
+     */
+    template<typename EG, typename LFSU, typename X, typename LFSV, typename R>
+    void alpha_volume (const EG& eg, const LFSU& lfsu, const X& x,
+                       const LFSV& lfsv, R& r) const
+    {
+        typedef typename LFSU::Traits::SizeType size_type;
+
+        model_.localResidual().eval(model_.gridView().grid().subDomainEntityPointer(eg.entity()));
+
+        int numVertices = x.size()/numEq;
+        for (size_type comp = 0; comp < r.size(); comp++)
+            r.accumulate(lfsv, comp, model_.localResidual().residual(comp%numVertices)[comp/numVertices]);
+    }
+
+    /*!
+     * \brief Jacobian of volume term
+     *
+     * \tparam EG Element geometry
+     * \tparam LFSU Local function space for ansatz functions
+     * \tparam X Coefficient vector
+     * \tparam LFSV Local function space for test functions
+     * \tparam M Matrix
+     *
+     * \param eg Element geometry
+     * \param lfsu Local functions space for ansatz functions
+     * \param x Coefficient vector
+     * \param lfsv Local function space for test functions
+     * \param mat Matrix
+     */
+    template<typename EG, typename LFSU, typename X, typename LFSV, typename M>
+    void jacobian_volume (const EG& eg,
+                          const LFSU& lfsu,
+                          const X& x,
+                          const LFSV& lfsv,
+                          M& mat) const
+    {
+        typedef typename LFSU::Traits::SizeType size_typeU;
+        typedef typename LFSV::Traits::SizeType size_typeV;
+
+        model_.localJacobian().assemble(model_.gridView().grid().subDomainEntityPointer(eg.entity()));
+
+        int numVertices = x.size()/numEq;
+        for (size_typeV j=0; j<lfsv.size(); j++) {
+            for (size_typeU i=0; i<lfsu.size(); i++) {
+                mat.accumulate(lfsv, i, lfsu, j, (model_.localJacobian().mat(i%numVertices,j%numVertices))[i/numVertices][j/numVertices]);
+            }
+        }
+    }
+
+private:
+    Model& model_;
+};
+
+} // namespace PDELab
+} // namespace Dumux
+
+#endif // DUMUX_MULTIDOMAIN_LOCAL_OPERATOR_HH
diff --git a/dumux/multidomain/common/model.hh b/dumux/multidomain/common/model.hh
new file mode 100644
index 0000000000..329d54fdda
--- /dev/null
+++ b/dumux/multidomain/common/model.hh
@@ -0,0 +1,335 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
+/*****************************************************************************
+ *   See the file COPYING for full copying permissions.                      *
+ *                                                                           *
+ *   This program is free software: you can redistribute it and/or modify    *
+ *   it under the terms of the GNU General Public License as published by    *
+ *   the Free Software Foundation, either version 2 of the License, or       *
+ *   (at your option) any later version.                                     *
+ *                                                                           *
+ *   This program is distributed in the hope that it will be useful,         *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
+ *   GNU General Public License for more details.                            *
+ *                                                                           *
+ *   You should have received a copy of the GNU General Public License       *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ *****************************************************************************/
+/*!
+ * \file
+ * \brief The base class of models which consist of two arbitrary
+ *        sub-models which are coupled
+ */
+
+#ifndef DUMUX_MULTIDOMAIN_MODEL_HH
+#define DUMUX_MULTIDOMAIN_MODEL_HH
+
+#include <dune/common/deprecated.hh>
+
+#include "properties.hh"
+#include "propertydefaults.hh"
+#include "problem.hh"
+#include "convergencewriter.hh"
+#include "newtoncontroller.hh"
+
+namespace Dumux
+{
+/*!
+ * \ingroup MultidomainModel
+ * \brief The base class of models which consist of two arbitrary
+ *        sub-models which are coupled
+ */
+template<class TypeTag>
+class MultiDomainModel
+{
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, Problem) SubDomainProblem1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, Problem) SubDomainProblem2;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, Model) SubDomainModel1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, Model) SubDomainModel2;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SplitAndMerge) SplitAndMerge;
+
+    enum {
+        numEq1 = GET_PROP_VALUE(TypeTag, NumEq1),
+        numEq2 = GET_PROP_VALUE(TypeTag, NumEq2)
+    };
+
+public:
+    /*!
+     * \brief Apply the initial conditions to the model.
+     *
+     * \param problem The problem
+     */
+    void init(Problem &problem)
+    {
+        problem_ = &problem;
+
+        // the two sub models have already been initialized by the
+        // sub-problems!
+        jacAsm_ = std::make_shared<JacobianAssembler>();
+        jacAsm_->init(problem);
+
+        uCur_ = std::make_shared<SolutionVector>(jacAsm_->gridFunctionSpace());
+        uPrev_ = std::make_shared<SolutionVector>(jacAsm_->gridFunctionSpace());
+
+        *uCur_= 0;
+        *uPrev_= 0;
+
+        SplitAndMerge::mergeSolVectors(sdModel1().curSol(),
+                                       sdModel2().curSol(),
+                                       *uCur_);
+        SplitAndMerge::mergeSolVectors(sdModel1().prevSol(),
+                                       sdModel2().prevSol(),
+                                       *uPrev_);
+    }
+
+    /*!
+     * \brief Reference to the current solution as a block vector.
+     */
+    SolutionVector &curSol()
+    { return *uCur_; }
+
+    //! \brief \copydoc curSol()
+    const SolutionVector &curSol() const
+    { return *uCur_; }
+
+    /*!
+     * \brief Reference to the previous solution as a block vector.
+     */
+    SolutionVector &prevSol()
+    { return *uPrev_; }
+
+    //! \brief \copydoc prevSol()
+    const SolutionVector &prevSol() const
+    { return *uPrev_; }
+
+    /*!
+     * \brief Returns the operator assembler for the global jacobian of
+     *        the problem.
+     */
+    JacobianAssembler &jacobianAssembler()
+    { return *jacAsm_; }
+
+    //! \brief \copydoc jacobianAssembler()
+    const JacobianAssembler &jacobianAssembler() const
+    { return *jacAsm_; }
+
+    /*!
+     * \brief A reference to the problem on which the model is applied.
+     */
+    Problem &problem()
+    { return *problem_; }
+
+    //! \brief \copydoc problem()
+    const Problem &problem() const
+    { return *problem_; }
+
+    /*!
+     * \brief A reference to the problem on which the model is applied.
+     */
+    SubDomainProblem1 &sdProblem1()
+    { return problem().sdProblem1(); }
+
+    //! \brief \copydoc sdProblem1()
+    const SubDomainProblem1 &sdProblem1() const
+    { return problem().sdProblem1(); }
+
+    /*!
+     * \brief A reference to the problem on which the model is applied.
+     */
+    SubDomainProblem2 &sdProblem2()
+    { return problem().sdProblem2(); }
+
+    //! \brief \copydoc sdProblem2()
+    const SubDomainProblem2 &sdProblem2() const
+    { return problem().sdProblem2(); }
+
+    /*!
+     * \brief A reference to the first sub-problem's model.
+     */
+    SubDomainModel1 &sdModel1()
+    { return sdProblem1().model(); }
+
+    //! \brief \copydoc sdModel1()
+    const SubDomainModel1 &sdModel1() const
+    { return sdProblem1().model(); }
+
+    /*!
+     * \brief A reference to the second sub-problem's model.
+     */
+    SubDomainModel2 &sdModel2()
+    { return sdProblem2().model(); }
+
+    //! \brief \copydoc sdModel2()
+    const SubDomainModel2 &sdModel2() const
+    { return sdProblem2().model(); }
+
+    //! \copydoc Dumux::ImplicitModel::update()
+    bool update(NewtonMethod &solver,
+                NewtonController &controller)
+    {
+#if HAVE_VALGRIND
+        for (size_t i = 0; i < curSol().base().size(); ++i)
+            Valgrind::CheckDefined(curSol().base()[i]);
+#endif // HAVE_VALGRIND
+
+        asImp_().updateBegin();
+
+        bool converged = solver.execute(controller);
+        if (!converged)
+            asImp_().updateFailed();
+        else
+            asImp_().updateSuccessful();
+
+#if HAVE_VALGRIND
+        for (size_t i = 0; i < curSol().base().size(); ++i) {
+            Valgrind::CheckDefined(curSol().base()[i]);
+        }
+#endif // HAVE_VALGRIND
+
+        return converged;
+    }
+
+
+    //! \copydoc Dumux::ImplicitModel::checkPlausibility()
+    void checkPlausibility() const
+    { }
+
+    //! \copydoc Dumux::ImplicitModel::updateBegin()
+    void updateBegin()
+    {
+        sdModel1().updateBegin();
+        sdModel2().updateBegin();
+
+        SplitAndMerge::mergeSolVectors(sdModel1().curSol(), sdModel2().curSol(), *uCur_);
+    }
+
+    //! \copydoc Dumux::ImplicitModel::updateSuccessful()
+    void updateSuccessful()
+    {
+        sdModel1().updateSuccessful();
+        sdModel2().updateSuccessful();
+    }
+
+    /*!
+     * \brief Called by the problem if a timeintegration was
+     *        successful, post processing of the solution is done and the
+     *        result has been written to disk.
+     *
+     * This should perpare the model for the next time integration.
+     * Note, that the advanceTimeLevel() methods of the sub-models
+     * have already been called by the individual sub problems...
+     */
+    void advanceTimeLevel()
+    {
+        // merge the two sub-vectors together
+        SplitAndMerge::mergeSolVectors(sdModel1().curSol(), sdModel2().curSol(), *uCur_);
+        SplitAndMerge::mergeSolVectors(sdModel1().prevSol(), sdModel2().prevSol(), *uPrev_);
+    }
+
+    //! \copydoc Dumux::ImplicitModel::updateFailed()
+    void updateFailed()
+    {
+        sdModel1().updateFailed();
+        sdModel2().updateFailed();
+
+        // merge the two sub-vectors together
+        SplitAndMerge::mergeSolVectors(sdModel1().curSol(), sdModel2().curSol(), *uCur_);
+    }
+
+     /*!
+      * \brief Called by the update() method if a try was
+      *         unsuccessful. This is primary a hook which the
+      *         actual model can overload.
+      */
+    void updateFailedTry()
+    {
+        sdModel1().updateFailedTry();
+        sdModel2().updateFailedTry();
+
+        // merge the two sub-vectors together
+        SplitAndMerge::mergeSolVectors(sdModel1().curSol(), sdModel2().curSol(), *uCur_);
+    }
+
+    /*!
+     * \brief Calculate the global residual.
+     *
+     * \param globResidual The global residual
+     *
+     * The global deflection of the balance equation from zero.
+     */
+    void evalGlobalResidual(SolutionVector &globResidual)
+    {
+        DUNE_THROW(Dune::NotImplemented, "");
+    }
+
+    //! \copydoc Dumux::ImplicitModel::serialize()
+    template <class Restarter>
+    void serialize(Restarter &res)
+    {
+        sdProblem1().serialize(res);
+        sdProblem2().serialize(res);
+    }
+
+    //! \copydoc Dumux::ImplicitModel::deserialize()
+    template <class Restarter>
+    void deserialize(Restarter &res)
+    {
+        sdProblem1().deserialize(res);
+        sdProblem2().deserialize(res);
+        wasRestarted_ = true;
+    }
+
+    /*!
+     * \brief Returns the number of global degrees of freedoms (DOFs)
+     */
+    DUNE_DEPRECATED_MSG("numDofs() is deprecated.")
+    size_t numDofs() const
+    {
+        return sdModel1().numDofs()*numEq1 + sdModel2().numDofs()*numEq2;
+    }
+
+    //! \copydoc Dumux::ImplicitModel::resetJacobianAssembler()
+    void resetJacobianAssembler()
+    {
+        jacAsm_.template reset<JacobianAssembler>(0);
+        jacAsm_ = std::make_shared<JacobianAssembler>(asImp_(), problem());
+    }
+
+
+protected:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+    // the problem we want to solve. defines the constitutive
+    // relations, material laws, etc.
+    Problem *problem_;
+
+    // the jacobian assembler
+    std::shared_ptr<JacobianAssembler> jacAsm_;
+
+    // cur is the current solution, prev the solution of the previous
+    // time step
+    std::shared_ptr<SolutionVector> uCur_;
+    std::shared_ptr<SolutionVector> uPrev_;
+
+    bool wasRestarted_;
+};
+} // namespace Dumux
+
+#endif // DUMUX_MULTIDOMAIN_MODEL_HH
diff --git a/dumux/multidomain/common/multidomainassembler.hh b/dumux/multidomain/common/multidomainassembler.hh
index b43099f5dd..814bfa6810 100644
--- a/dumux/multidomain/common/multidomainassembler.hh
+++ b/dumux/multidomain/common/multidomainassembler.hh
@@ -1,218 +1,8 @@
-// -*- 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 An assembler for the global Jacobian matrix for multidomain models.
- */
+#ifndef DUMUX_MULTIDOMAIN_ASSEMBLER_HH_OLD
+#define DUMUX_MULTIDOMAIN_ASSEMBLER_HH_OLD
 
-#ifndef DUMUX_MULTIDOMAIN_ASSEMBLER_HH
-#define DUMUX_MULTIDOMAIN_ASSEMBLER_HH
+#warning this header is deprecated, use dumux/multidomain/common/assembler.hh instead
 
-#include <dune/pdelab/constraints/common/constraintsparameters.hh>
-#include <dune/pdelab/multidomain/constraints.hh>
+#include <dumux/multidomain/common/assembler.hh>
 
-#include "multidomainproperties.hh"
-#include "multidomainpropertydefaults.hh"
-
-namespace Dumux {
-
-/*!
- * \ingroup MultidomainModel
- * \brief An assembler for the global Jacobian matrix for multidomain models.
- */
-template<class TypeTag>
-class MultiDomainAssembler
-{
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, Problem) SubDomainProblem1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, Problem) SubDomainProblem2;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, LocalFEMSpace) FEM1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, LocalFEMSpace) FEM2;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, ScalarGridFunctionSpace) ScalarGridFunctionSpace1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, ScalarGridFunctionSpace) ScalarGridFunctionSpace2;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, GridFunctionSpace) GridFunctionSpace1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, GridFunctionSpace) GridFunctionSpace2;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, LocalOperator) LocalOperator1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, LocalOperator) LocalOperator2;
-
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MultiDomainGridFunctionSpace;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCondition) MultiDomainCondition;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem1) MultiDomainSubProblem1;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem2) MultiDomainSubProblem2;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCouplingLocalOperator) MultiDomainCouplingLocalOperator;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCoupling) MultiDomainCoupling;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainConstraintsTrafo) MultiDomainConstraintsTrafo;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridOperator) MultiDomainGridOperator;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-    typedef typename GET_PROP_TYPE(TypeTag, JacobianMatrix) JacobianMatrix;
-
-    // copying the jacobian assembler is not a good idea
-    MultiDomainAssembler(const MultiDomainAssembler &);
-
-public:
-    //! \brief The constructor
-    MultiDomainAssembler()
-    {
-        globalProblem_ = 0;
-        sdProblem1_= 0;
-        sdProblem2_= 0;
-    }
-
-    //! \brief The destructor
-    ~MultiDomainAssembler()
-    { }
-
-    //! \copydoc ImplicitAssembler::init()
-    void init(Problem& problem)
-    {
-        globalProblem_ = &problem;
-        sdProblem1_ = &globalProblem_->sdProblem1();
-        sdProblem2_ = &globalProblem_->sdProblem2();
-
-        fem1_ = std::make_shared<FEM1>(globalProblem_->sdGridView1());
-        fem2_ = std::make_shared<FEM2>(globalProblem_->sdGridView2());
-
-        scalarGridFunctionSpace1_ = std::make_shared<ScalarGridFunctionSpace1>(globalProblem_->sdGridView1(),
-                                                                                *fem1_);
-        scalarGridFunctionSpace2_ = std::make_shared<ScalarGridFunctionSpace2>(globalProblem_->sdGridView2(),
-                                                                                *fem2_);
-
-        gridFunctionSpace1_ = std::make_shared<GridFunctionSpace1>(*scalarGridFunctionSpace1_);
-        gridFunctionSpace2_ = std::make_shared<GridFunctionSpace2>(*scalarGridFunctionSpace2_);
-
-        mdGridFunctionSpace_ = std::make_shared<MultiDomainGridFunctionSpace>(globalProblem_->mdGrid(),
-                                                                               *gridFunctionSpace1_,
-                                                                               *gridFunctionSpace2_);
-
-        localOperator1_ = std::make_shared<LocalOperator1>(sdProblem1_->model());
-        localOperator2_ = std::make_shared<LocalOperator2>(sdProblem2_->model());
-
-        condition1_ = std::make_shared<MultiDomainCondition>(0);
-        condition2_ = std::make_shared<MultiDomainCondition>(1);
-
-        mdSubProblem1_ = std::make_shared<MultiDomainSubProblem1>(*localOperator1_, *condition1_);
-        mdSubProblem2_ = std::make_shared<MultiDomainSubProblem2>(*localOperator2_, *condition2_);
-
-        couplingLocalOperator_ = std::make_shared<MultiDomainCouplingLocalOperator>(*globalProblem_);
-        mdCoupling_ = std::make_shared<MultiDomainCoupling>(*mdSubProblem1_, *mdSubProblem2_, *couplingLocalOperator_);
-
-        constraintsTrafo_ = std::make_shared<MultiDomainConstraintsTrafo>();
-
-        mdGridOperator_ = std::make_shared<MultiDomainGridOperator>(*mdGridFunctionSpace_, *mdGridFunctionSpace_,
-                                                                     *constraintsTrafo_, *constraintsTrafo_,
-                                                                     *mdSubProblem1_, *mdSubProblem2_, *mdCoupling_);
-
-        matrix_ = std::make_shared<JacobianMatrix>(*mdGridOperator_);
-        residual_ = std::make_shared<SolutionVector>(*mdGridFunctionSpace_);
-    }
-
-    //! \copydoc ImplicitAssembler::assemble()
-    void assemble()
-    {
-        // assemble the matrix
-        *matrix_ = 0;
-        mdGridOperator_->jacobian(globalProblem_->model().curSol(), *matrix_);
-
-        // calculate the global residual
-        *residual_ = 0;
-        mdGridOperator_->residual(globalProblem_->model().curSol(), *residual_);
-    }
-
-    //! \copydoc ImplicitAssembler::reassembleAll()
-    void reassembleAll()
-    { }
-
-    //! \copydoc ImplicitAssembler::matrix()
-    const JacobianMatrix &matrix() const
-    { return *matrix_; }
-    JacobianMatrix &matrix()
-    { return *matrix_; }
-
-    //! \copydoc ImplicitAssembler::residual()
-    const SolutionVector &residual() const
-    { return *residual_; }
-    SolutionVector &residual()
-    { return *residual_; }
-
-    /*!
-     * \brief Return constant reference to the multidomain gridfunctionspace
-     */
-    MultiDomainGridFunctionSpace &gridFunctionSpace() const
-    { return *mdGridFunctionSpace_; }
-
-    /*!
-     * \brief Return constant reference to the multidomain gridfunctionspace
-     */
-    MultiDomainGridFunctionSpace &mdGridFunctionSpace() const
-    { return *mdGridFunctionSpace_; }
-
-    /*!
-     * \brief Return the multidomain constraints transformation
-     */
-    MultiDomainConstraintsTrafo &constraintsTrafo() const
-    { return *constraintsTrafo_; }
-
-private:
-    Problem *globalProblem_;
-    SubDomainProblem1 *sdProblem1_;
-    SubDomainProblem2 *sdProblem2_;
-
-    std::shared_ptr<FEM1> fem1_;
-    std::shared_ptr<FEM2> fem2_;
-
-    std::shared_ptr<ScalarGridFunctionSpace1> scalarGridFunctionSpace1_;
-    std::shared_ptr<ScalarGridFunctionSpace2> scalarGridFunctionSpace2_;
-
-    std::shared_ptr<GridFunctionSpace1> gridFunctionSpace1_;
-    std::shared_ptr<GridFunctionSpace2> gridFunctionSpace2_;
-    std::shared_ptr<MultiDomainGridFunctionSpace> mdGridFunctionSpace_;
-
-    std::shared_ptr<LocalOperator1> localOperator1_;
-    std::shared_ptr<LocalOperator2> localOperator2_;
-
-    std::shared_ptr<MultiDomainCondition> condition1_;
-    std::shared_ptr<MultiDomainCondition> condition2_;
-
-    std::shared_ptr<MultiDomainSubProblem1> mdSubProblem1_;
-    std::shared_ptr<MultiDomainSubProblem2> mdSubProblem2_;
-
-    std::shared_ptr<MultiDomainCouplingLocalOperator> couplingLocalOperator_;
-    std::shared_ptr<MultiDomainCoupling> mdCoupling_;
-
-    std::shared_ptr<MultiDomainConstraintsTrafo> constraintsTrafo_;
-    std::shared_ptr<MultiDomainGridOperator> mdGridOperator_;
-
-    std::shared_ptr<JacobianMatrix> matrix_;
-
-    std::shared_ptr<SolutionVector> residual_;
-};
-
-} // namespace Dumux
-
-#endif // DUMUX_MULTIDOMAIN_ASSEMBLER_HH
+#endif
diff --git a/dumux/multidomain/common/multidomainconvergencewriter.hh b/dumux/multidomain/common/multidomainconvergencewriter.hh
index 64d041c81c..a6a1671e08 100644
--- a/dumux/multidomain/common/multidomainconvergencewriter.hh
+++ b/dumux/multidomain/common/multidomainconvergencewriter.hh
@@ -1,150 +1,8 @@
-// -*- 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 Reference implementation of a newton convergence writer for coupled problems.
-*/
-#ifndef DUMUX_MULTIDOMAIN_CONVERGENCEWRITER_HH
-#define DUMUX_MULTIDOMAIN_CONVERGENCEWRITER_HH
+#ifndef DUMUX_MULTIDOMAIN_CONVERGENCEWRITER_HH_OLD
+#define DUMUX_MULTIDOMAIN_CONVERGENCEWRITER_HH_OLD
 
-#include <dune/grid/multidomaingrid.hh>
-#include <dune/pdelab/backend/istlsolverbackend.hh>
+#warning this header is deprecated, use dumux/multidomain/common/convergencewriter.hh instead
 
-#include <dumux/io/vtkmultiwriter.hh>
+#include <dumux/multidomain/common/convergencewriter.hh>
 
-#include "splitandmerge.hh"
-#include "multidomainnewtoncontroller.hh"
-
-namespace Dumux
-{
-/*!
- * \ingroup MultidomainModel
- * \brief Writes the intermediate solutions during
- *        the Newton scheme
- */
-template <class TypeTag>
-struct MultiDomainConvergenceWriter
-{
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-    typedef typename GET_PROP_TYPE(TypeTag, SplitAndMerge) SplitAndMerge;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, GridView) GridView1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, GridView) GridView2;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, SolutionVector) SolutionVector1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, SolutionVector) SolutionVector2;
-
-    typedef Dumux::VtkMultiWriter<GridView1> VtkMultiWriter1;
-    typedef Dumux::VtkMultiWriter<GridView2> VtkMultiWriter2;
-
-    /*!
-    * \brief The constructor
-    * \param ctl The newton controller
-    */
-    MultiDomainConvergenceWriter(NewtonController &ctl)
-        : ctl_(ctl)
-    {
-        timeStepIndex_ = 0;
-        iteration_ = 0;
-        vtkMultiWriter1_ = 0;
-        vtkMultiWriter2_ = 0;
-    }
-
-    /*!
-     * \brief Start and advance in time
-     */
-    void beginTimestep()
-    {
-        ++timeStepIndex_;
-        iteration_ = 0;
-    }
-
-    /*!
-     * \brief Start and advance one iteration
-     *
-     * \param gridView1 The grid view of sub problem 1
-     * \param gridView2 The grid view of sub problem 2
-     */
-    void beginIteration(const GridView1 &gridView1,
-                        const GridView2 &gridView2)
-    {
-        ++ iteration_;
-        if (!vtkMultiWriter1_)
-            vtkMultiWriter1_ = std::make_shared<VtkMultiWriter2>(gridView1, "convergence1");
-        vtkMultiWriter1_->beginWrite(timeStepIndex_ + iteration_ / 100.0);
-
-        if (!vtkMultiWriter2_)
-            vtkMultiWriter2_ = std::make_shared<VtkMultiWriter2>(gridView2, "convergence2");
-        vtkMultiWriter2_->beginWrite(timeStepIndex_ + iteration_ / 100.0);
-    }
-
-    /*!
-     * \brief Write convergence to vtk
-     *
-     * \param uLastIter The solution of the last iteration
-     * \param deltaU The delta as calculated from solving the linear
-     *               system of equations. This parameter also stores
-     *               the updated solution.
-     */
-    void writeFields(const SolutionVector &uLastIter,
-                     const SolutionVector &deltaU)
-    {
-          SolutionVector1 uLastIter1(ctl_.method().model().sdModel1().curSol());
-          SolutionVector2 uLastIter2(ctl_.method().model().sdModel2().curSol());
-          SolutionVector1 deltaU1(uLastIter1);
-          SolutionVector2 deltaU2(uLastIter2);
-
-          SplitAndMerge::splitSolVector(uLastIter, uLastIter1, uLastIter2);
-          SplitAndMerge::splitSolVector(deltaU, deltaU1, deltaU2);
-
-          std::cout << "\nWriting convergence file of current Newton iteration\n";
-          ctl_.method().model().sdModel1().addConvergenceVtkFields(*vtkMultiWriter1_, uLastIter1, deltaU1);
-          ctl_.method().model().sdModel2().addConvergenceVtkFields(*vtkMultiWriter2_, uLastIter2, deltaU2);
-    }
-
-    //! \brief End of iteration
-    void endIteration()
-    {
-        vtkMultiWriter1_->endWrite();
-        vtkMultiWriter2_->endWrite();
-    }
-
-    //! \brief End of time step
-    void endTimestep()
-    {
-        iteration_ = 0;
-    }
-
-private:
-    int timeStepIndex_;
-    int iteration_;
-    std::shared_ptr<VtkMultiWriter1> vtkMultiWriter1_;
-    std::shared_ptr<VtkMultiWriter2> vtkMultiWriter2_;
-    NewtonController &ctl_;
-};
-
-} // namespace Dumux
-
-#endif // DUMUX_MULTIDOMAIN_CONVERGENCEWRITER_HH
+#endif
diff --git a/dumux/multidomain/common/multidomainlocaloperator.hh b/dumux/multidomain/common/multidomainlocaloperator.hh
index 84bf4a0eab..2eb8c8572b 100644
--- a/dumux/multidomain/common/multidomainlocaloperator.hh
+++ b/dumux/multidomain/common/multidomainlocaloperator.hh
@@ -1,134 +1,8 @@
-// -*- 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 Local operator base class for multidomain problems
- */
+#ifndef DUMUX_MULTIDOMAIN_LOCAL_OPERATOR_HH_OLD
+#define DUMUX_MULTIDOMAIN_LOCAL_OPERATOR_HH_OLD
 
-#ifndef DUMUX_MULTIDOMAIN_LOCAL_OPERATOR_HH
-#define DUMUX_MULTIDOMAIN_LOCAL_OPERATOR_HH
+#warning this header is deprecated, use dumux/multidomain/common/localoperator.hh instead
 
-#include<dune/pdelab/localoperator/pattern.hh>
-#include<dune/pdelab/localoperator/flags.hh>
+#include <dumux/multidomain/common/localoperator.hh>
 
-#include <dumux/implicit/box/properties.hh>
-
-namespace Dumux {
-
-namespace PDELab {
-
-/*!
- * \ingroup MultidomainModel
- * \brief Local operator base class for multidomain problems
- */
-template<class TypeTag>
-class MultiDomainLocalOperator
- : public Dune::PDELab::FullVolumePattern,
-   public Dune::PDELab::LocalOperatorDefaultFlags
-{
-    // copying the local operator for PDELab is not a good idea
-    MultiDomainLocalOperator(const MultiDomainLocalOperator &);
-
-    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
-
-    enum{numEq = GET_PROP_VALUE(TypeTag, NumEq)};
-
-public:
-    // pattern assembly flags
-    enum { doPatternVolume = true };
-
-    // residual assembly flags
-    enum { doAlphaVolume = true };
-
-    //! \brief The constructor
-    MultiDomainLocalOperator(Model &model)
-    : model_(model)
-    {}
-
-    /*!
-     * \brief Volume integral depending on test and ansatz functions
-     *
-     * \tparam EG Element geometry
-     * \tparam LFSU Local function space for ansatz functions
-     * \tparam X Coefficient vector
-     * \tparam LFSV Local function space for test functions
-     * \tparam R Residual vector
-     *
-     * \param eg Element geometry
-     * \param lfsu Local functions space for ansatz functions
-     * \param x Coefficient vector
-     * \param lfsv Local function space for test functions
-     * \param r Residual vector
-     */
-    template<typename EG, typename LFSU, typename X, typename LFSV, typename R>
-    void alpha_volume (const EG& eg, const LFSU& lfsu, const X& x,
-                       const LFSV& lfsv, R& r) const
-    {
-        typedef typename LFSU::Traits::SizeType size_type;
-
-        model_.localResidual().eval(model_.gridView().grid().subDomainEntityPointer(eg.entity()));
-
-        int numVertices = x.size()/numEq;
-        for (size_type comp = 0; comp < r.size(); comp++)
-            r.accumulate(lfsv, comp, model_.localResidual().residual(comp%numVertices)[comp/numVertices]);
-    }
-
-    /*!
-     * \brief Jacobian of volume term
-     *
-     * \tparam EG Element geometry
-     * \tparam LFSU Local function space for ansatz functions
-     * \tparam X Coefficient vector
-     * \tparam LFSV Local function space for test functions
-     * \tparam M Matrix
-     *
-     * \param eg Element geometry
-     * \param lfsu Local functions space for ansatz functions
-     * \param x Coefficient vector
-     * \param lfsv Local function space for test functions
-     * \param mat Matrix
-     */
-    template<typename EG, typename LFSU, typename X, typename LFSV, typename M>
-    void jacobian_volume (const EG& eg,
-                          const LFSU& lfsu,
-                          const X& x,
-                          const LFSV& lfsv,
-                          M& mat) const
-    {
-        typedef typename LFSU::Traits::SizeType size_typeU;
-        typedef typename LFSV::Traits::SizeType size_typeV;
-
-        model_.localJacobian().assemble(model_.gridView().grid().subDomainEntityPointer(eg.entity()));
-
-        int numVertices = x.size()/numEq;
-        for (size_typeV j=0; j<lfsv.size(); j++) {
-            for (size_typeU i=0; i<lfsu.size(); i++) {
-                mat.accumulate(lfsv, i, lfsu, j, (model_.localJacobian().mat(i%numVertices,j%numVertices))[i/numVertices][j/numVertices]);
-            }
-        }
-    }
-
-private:
-    Model& model_;
-};
-
-} // namespace PDELab
-} // namespace Dumux
-
-#endif // DUMUX_MULTIDOMAIN_LOCAL_OPERATOR_HH
+#endif
diff --git a/dumux/multidomain/common/multidomainmodel.hh b/dumux/multidomain/common/multidomainmodel.hh
index bd206f0f69..f97f6031eb 100644
--- a/dumux/multidomain/common/multidomainmodel.hh
+++ b/dumux/multidomain/common/multidomainmodel.hh
@@ -1,335 +1,8 @@
-// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
-// vi: set et ts=4 sw=4 sts=4:
-/*****************************************************************************
- *   See the file COPYING for full copying permissions.                      *
- *                                                                           *
- *   This program is free software: you can redistribute it and/or modify    *
- *   it under the terms of the GNU General Public License as published by    *
- *   the Free Software Foundation, either version 2 of the License, or       *
- *   (at your option) any later version.                                     *
- *                                                                           *
- *   This program is distributed in the hope that it will be useful,         *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            *
- *   GNU General Public License for more details.                            *
- *                                                                           *
- *   You should have received a copy of the GNU General Public License       *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
- *****************************************************************************/
-/*!
- * \file
- * \brief The base class of models which consist of two arbitrary
- *        sub-models which are coupled
- */
+#ifndef DUMUX_MULTIDOMAIN_MODEL_HH_OLD
+#define DUMUX_MULTIDOMAIN_MODEL_HH_OLD
 
-#ifndef DUMUX_MULTIDOMAIN_MODEL_HH
-#define DUMUX_MULTIDOMAIN_MODEL_HH
+#warning this header is deprecated, use dumux/multidomain/common/model.hh instead
 
-#include <dune/common/deprecated.hh>
+#include <dumux/multidomain/common/model.hh>
 
-#include "multidomainproperties.hh"
-#include "multidomainpropertydefaults.hh"
-#include "multidomainproblem.hh"
-#include "multidomainconvergencewriter.hh"
-#include "multidomainnewtoncontroller.hh"
-
-namespace Dumux
-{
-/*!
- * \ingroup MultidomainModel
- * \brief The base class of models which consist of two arbitrary
- *        sub-models which are coupled
- */
-template<class TypeTag>
-class MultiDomainModel
-{
-    typedef typename GET_PROP_TYPE(TypeTag, Model) Implementation;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
-    typedef typename GET_PROP_TYPE(TypeTag, JacobianAssembler) JacobianAssembler;
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, Problem) SubDomainProblem1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, Problem) SubDomainProblem2;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, Model) SubDomainModel1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, Model) SubDomainModel2;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SplitAndMerge) SplitAndMerge;
-
-    enum {
-        numEq1 = GET_PROP_VALUE(TypeTag, NumEq1),
-        numEq2 = GET_PROP_VALUE(TypeTag, NumEq2)
-    };
-
-public:
-    /*!
-     * \brief Apply the initial conditions to the model.
-     *
-     * \param problem The problem
-     */
-    void init(Problem &problem)
-    {
-        problem_ = &problem;
-
-        // the two sub models have already been initialized by the
-        // sub-problems!
-        jacAsm_ = std::make_shared<JacobianAssembler>();
-        jacAsm_->init(problem);
-
-        uCur_ = std::make_shared<SolutionVector>(jacAsm_->gridFunctionSpace());
-        uPrev_ = std::make_shared<SolutionVector>(jacAsm_->gridFunctionSpace());
-
-        *uCur_= 0;
-        *uPrev_= 0;
-
-        SplitAndMerge::mergeSolVectors(sdModel1().curSol(),
-                                       sdModel2().curSol(),
-                                       *uCur_);
-        SplitAndMerge::mergeSolVectors(sdModel1().prevSol(),
-                                       sdModel2().prevSol(),
-                                       *uPrev_);
-    }
-
-    /*!
-     * \brief Reference to the current solution as a block vector.
-     */
-    SolutionVector &curSol()
-    { return *uCur_; }
-
-    //! \brief \copydoc curSol()
-    const SolutionVector &curSol() const
-    { return *uCur_; }
-
-    /*!
-     * \brief Reference to the previous solution as a block vector.
-     */
-    SolutionVector &prevSol()
-    { return *uPrev_; }
-
-    //! \brief \copydoc prevSol()
-    const SolutionVector &prevSol() const
-    { return *uPrev_; }
-
-    /*!
-     * \brief Returns the operator assembler for the global jacobian of
-     *        the problem.
-     */
-    JacobianAssembler &jacobianAssembler()
-    { return *jacAsm_; }
-
-    //! \brief \copydoc jacobianAssembler()
-    const JacobianAssembler &jacobianAssembler() const
-    { return *jacAsm_; }
-
-    /*!
-     * \brief A reference to the problem on which the model is applied.
-     */
-    Problem &problem()
-    { return *problem_; }
-
-    //! \brief \copydoc problem()
-    const Problem &problem() const
-    { return *problem_; }
-
-    /*!
-     * \brief A reference to the problem on which the model is applied.
-     */
-    SubDomainProblem1 &sdProblem1()
-    { return problem().sdProblem1(); }
-
-    //! \brief \copydoc sdProblem1()
-    const SubDomainProblem1 &sdProblem1() const
-    { return problem().sdProblem1(); }
-
-    /*!
-     * \brief A reference to the problem on which the model is applied.
-     */
-    SubDomainProblem2 &sdProblem2()
-    { return problem().sdProblem2(); }
-
-    //! \brief \copydoc sdProblem2()
-    const SubDomainProblem2 &sdProblem2() const
-    { return problem().sdProblem2(); }
-
-    /*!
-     * \brief A reference to the first sub-problem's model.
-     */
-    SubDomainModel1 &sdModel1()
-    { return sdProblem1().model(); }
-
-    //! \brief \copydoc sdModel1()
-    const SubDomainModel1 &sdModel1() const
-    { return sdProblem1().model(); }
-
-    /*!
-     * \brief A reference to the second sub-problem's model.
-     */
-    SubDomainModel2 &sdModel2()
-    { return sdProblem2().model(); }
-
-    //! \brief \copydoc sdModel2()
-    const SubDomainModel2 &sdModel2() const
-    { return sdProblem2().model(); }
-
-    //! \copydoc Dumux::ImplicitModel::update()
-    bool update(NewtonMethod &solver,
-                NewtonController &controller)
-    {
-#if HAVE_VALGRIND
-        for (size_t i = 0; i < curSol().base().size(); ++i)
-            Valgrind::CheckDefined(curSol().base()[i]);
-#endif // HAVE_VALGRIND
-
-        asImp_().updateBegin();
-
-        bool converged = solver.execute(controller);
-        if (!converged)
-            asImp_().updateFailed();
-        else
-            asImp_().updateSuccessful();
-
-#if HAVE_VALGRIND
-        for (size_t i = 0; i < curSol().base().size(); ++i) {
-            Valgrind::CheckDefined(curSol().base()[i]);
-        }
-#endif // HAVE_VALGRIND
-
-        return converged;
-    }
-
-
-    //! \copydoc Dumux::ImplicitModel::checkPlausibility()
-    void checkPlausibility() const
-    { }
-
-    //! \copydoc Dumux::ImplicitModel::updateBegin()
-    void updateBegin()
-    {
-        sdModel1().updateBegin();
-        sdModel2().updateBegin();
-
-        SplitAndMerge::mergeSolVectors(sdModel1().curSol(), sdModel2().curSol(), *uCur_);
-    }
-
-    //! \copydoc Dumux::ImplicitModel::updateSuccessful()
-    void updateSuccessful()
-    {
-        sdModel1().updateSuccessful();
-        sdModel2().updateSuccessful();
-    }
-
-    /*!
-     * \brief Called by the problem if a timeintegration was
-     *        successful, post processing of the solution is done and the
-     *        result has been written to disk.
-     *
-     * This should perpare the model for the next time integration.
-     * Note, that the advanceTimeLevel() methods of the sub-models
-     * have already been called by the individual sub problems...
-     */
-    void advanceTimeLevel()
-    {
-        // merge the two sub-vectors together
-        SplitAndMerge::mergeSolVectors(sdModel1().curSol(), sdModel2().curSol(), *uCur_);
-        SplitAndMerge::mergeSolVectors(sdModel1().prevSol(), sdModel2().prevSol(), *uPrev_);
-    }
-
-    //! \copydoc Dumux::ImplicitModel::updateFailed()
-    void updateFailed()
-    {
-        sdModel1().updateFailed();
-        sdModel2().updateFailed();
-
-        // merge the two sub-vectors together
-        SplitAndMerge::mergeSolVectors(sdModel1().curSol(), sdModel2().curSol(), *uCur_);
-    }
-
-     /*!
-      * \brief Called by the update() method if a try was
-      *         unsuccessful. This is primary a hook which the
-      *         actual model can overload.
-      */
-    void updateFailedTry()
-    {
-        sdModel1().updateFailedTry();
-        sdModel2().updateFailedTry();
-
-        // merge the two sub-vectors together
-        SplitAndMerge::mergeSolVectors(sdModel1().curSol(), sdModel2().curSol(), *uCur_);
-    }
-
-    /*!
-     * \brief Calculate the global residual.
-     *
-     * \param globResidual The global residual
-     *
-     * The global deflection of the balance equation from zero.
-     */
-    void evalGlobalResidual(SolutionVector &globResidual)
-    {
-        DUNE_THROW(Dune::NotImplemented, "");
-    }
-
-    //! \copydoc Dumux::ImplicitModel::serialize()
-    template <class Restarter>
-    void serialize(Restarter &res)
-    {
-        sdProblem1().serialize(res);
-        sdProblem2().serialize(res);
-    }
-
-    //! \copydoc Dumux::ImplicitModel::deserialize()
-    template <class Restarter>
-    void deserialize(Restarter &res)
-    {
-        sdProblem1().deserialize(res);
-        sdProblem2().deserialize(res);
-        wasRestarted_ = true;
-    }
-
-    /*!
-     * \brief Returns the number of global degrees of freedoms (DOFs)
-     */
-    DUNE_DEPRECATED_MSG("numDofs() is deprecated.")
-    size_t numDofs() const
-    {
-        return sdModel1().numDofs()*numEq1 + sdModel2().numDofs()*numEq2;
-    }
-
-    //! \copydoc Dumux::ImplicitModel::resetJacobianAssembler()
-    void resetJacobianAssembler()
-    {
-        jacAsm_.template reset<JacobianAssembler>(0);
-        jacAsm_ = std::make_shared<JacobianAssembler>(asImp_(), problem());
-    }
-
-
-protected:
-    Implementation &asImp_()
-    { return *static_cast<Implementation*>(this); }
-    const Implementation &asImp_() const
-    { return *static_cast<const Implementation*>(this); }
-
-    // the problem we want to solve. defines the constitutive
-    // relations, material laws, etc.
-    Problem *problem_;
-
-    // the jacobian assembler
-    std::shared_ptr<JacobianAssembler> jacAsm_;
-
-    // cur is the current solution, prev the solution of the previous
-    // time step
-    std::shared_ptr<SolutionVector> uCur_;
-    std::shared_ptr<SolutionVector> uPrev_;
-
-    bool wasRestarted_;
-};
-} // namespace Dumux
-
-#endif // DUMUX_MULTIDOMAIN_MODEL_HH
+#endif
diff --git a/dumux/multidomain/common/multidomainnewtoncontroller.hh b/dumux/multidomain/common/multidomainnewtoncontroller.hh
index 6725ea442c..88ccdc0bdd 100644
--- a/dumux/multidomain/common/multidomainnewtoncontroller.hh
+++ b/dumux/multidomain/common/multidomainnewtoncontroller.hh
@@ -1,312 +1,8 @@
-// -*- 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 Newton controller for multidomain problems
- */
-#ifndef DUMUX_MULTIDOMAIN_NEWTON_CONTROLLER_HH
-#define DUMUX_MULTIDOMAIN_NEWTON_CONTROLLER_HH
+#ifndef DUMUX_MULTIDOMAIN_NEWTON_CONTROLLER_HH_OLD
+#define DUMUX_MULTIDOMAIN_NEWTON_CONTROLLER_HH_OLD
 
-#include <dumux/nonlinear/newtoncontroller.hh>
-#include "multidomainconvergencewriter.hh"
+#warning this header is deprecated, use dumux/multidomain/common/newtoncontroller.hh instead
 
-namespace Dumux
-{
-template <class TypeTag>
-class MultiDomainNewtonController;
+#include <dumux/multidomain/common/newtoncontroller.hh>
 
-template <class TypeTag>
-struct MultiDomainConvergenceWriter;
-
-namespace Properties
-{
-NEW_PROP_TAG(NewtonWriteConvergence);
-
-// set default values for Newton for multidomain problems
-// they can be overwritten in the parameter file
-SET_INT_PROP(MultiDomain, NewtonTargetSteps, 8);
-SET_INT_PROP(MultiDomain, NewtonMaxSteps, 15);
-SET_SCALAR_PROP(MultiDomain, NewtonMaxRelativeShift, 1e-5);
-SET_BOOL_PROP(MultiDomain, NewtonWriteConvergence, false);
-}
-
-
-/*!
- * \ingroup Newton
- * \ingroup MultidomainModel
- * \brief Reference implementation of a newton controller for coupled problems.
- *
- * If you want to specialize only some methods but are happy with
- * the defaults of the reference controller, derive your
- * controller from this class and simply overload the required
- * methods.
- */
-template <class TypeTag>
-class MultiDomainNewtonController : public NewtonController<TypeTag>
-{
-    typedef NewtonController<TypeTag> ParentType;
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) Implementation;
-
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
-    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
-    typedef typename GET_PROP_TYPE(TypeTag, SplitAndMerge) SplitAndMerge;
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
-    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, GridView) GridView1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, GridView) GridView2;
-
-    typedef MultiDomainConvergenceWriter<TypeTag>  ConvergenceWriter;
-    typedef typename GET_PROP_TYPE(TypeTag, LinearSolver) LinearSolver;
-
-public:
-    /*!
-     * \brief Constructor
-     *
-     * \param problem The problem
-     */
-    MultiDomainNewtonController(const Problem &problem)
-        : ParentType(problem)
-        , endIterMsgStream_(std::ostringstream::out)
-        , linearSolver_(problem)
-        , convergenceWriter_(asImp_())
-    {
-        std::cout << "NewtonMaxRelativeShift= "
-                  << PROP_DIAGNOSTIC(TypeTag, NewtonMaxRelativeShift)
-                  << ", "
-                  << GET_PROP_VALUE(TypeTag, NewtonMaxRelativeShift)
-                  << std::endl;
-    }
-
-    //! \copydoc ParentType::newtonUpdateShift()
-    void newtonUpdateShift(const SolutionVector &uLastIter,
-                           const SolutionVector &deltaU)
-    {
-        // calculate the relative error as the maximum relative
-        // deflection in any degree of freedom.
-        this->shift_ = 0;
-
-        SolutionVector uNewI = uLastIter;
-        uNewI -= deltaU;
-
-        for (unsigned int i = 0; i < uLastIter.base().size(); ++i) {
-            for (unsigned int j = 0; j < uLastIter.base()[i].size(); ++j) {
-                Scalar vertexError = std::abs(deltaU.base()[i][j]);
-                vertexError /= std::max<Scalar>(1.0, std::abs(uLastIter.base()[i][j] + uNewI.base()[i][j])/2);
-
-                this->shift_ = std::max(this->shift_, vertexError);
-            }
-        }
-    }
-
-    /*!
-     * \brief Solve the linear system of equations
-     *        \f$ \mathbf{A} x - b = 0\f$.
-     *
-     * \param A Coefficient matrix A
-     * \param x Vector of unknowns
-     * \param b Right hand side
-     *
-     * Throws Dumux::NumericalProblem if the linear solver didn't
-     * converge.
-     */
-    template <class Matrix, class Vector>
-    void newtonSolveLinear(Matrix &A,
-                           Vector &x,
-                           Vector &b)
-    {
-        // if the deflection of the newton method is large, we do not
-        // need to solve the linear approximation accurately. Assuming
-        // that the initial value for the delta vector u is quite
-        // close to the final value, a reduction of 6 orders of
-        // magnitude in the defect should be sufficient...
-        try {
-            int converged = linearSolver_.solve(A.base(), x.base(), b.base());
-
-#if HAVE_MPI
-            // make sure all processes converged
-            int convergedSend = 1;
-            MPI_Allreduce(/*sendBuf=*/&convergedSend,
-                          /*recvBuf=*/&converged,
-                          /*count=*/1,
-                          MPI_INT,
-                          MPI_MIN,
-                          MPI_COMM_WORLD);
-#endif
-            if (!converged) {
-                DUNE_THROW(NumericalProblem,
-                           "Linear solver did not converge");
-            }
-        }
-        catch (const Dune::MatrixBlockError &e) {
-#if HAVE_MPI
-            // make sure all processes converged
-            int convergedSend = 0;
-            int converged;
-
-            MPI_Allreduce(/*sendBuf=*/&convergedSend,
-                          /*recvBuf=*/&converged,
-                          /*count=*/1,
-                          MPI_INT,
-                          MPI_MIN,
-                          MPI_COMM_WORLD);
-#endif
-
-            Dumux::NumericalProblem p;
-            std::string msg;
-            std::ostringstream ms(msg);
-            ms << e.what() << "M=" << A.base()[e.r][e.c];
-            p.message(ms.str());
-            throw p;
-        }
-        catch (const Dune::Exception &e) {
-#if HAVE_MPI
-            // make sure all processes converged
-            int convergedSend = 0;
-            int converged;
-
-            MPI_Allreduce(/*sendBuf=*/&convergedSend,
-                          /*recvBuf=*/&converged,
-                          /*count=*/1,
-                          MPI_INT,
-                          MPI_MIN,
-                          MPI_COMM_WORLD);
 #endif
-
-            Dumux::NumericalProblem p;
-            p.message(e.what());
-            throw p;
-        }
-    }
-
-    /*!
-    * \brief Update the current solution function with a delta vector.
-    *
-    * The error estimates required for the newtonConverged() and
-    * newtonProceed() methods should be updated here.
-    *
-    * Different update strategies, such as line search and chopped
-    * updates can be implemented. The default behaviour is just to
-    * subtract deltaU from uLastIter.
-    *
-    * \param uCurrentIter The solution of the current iteration
-    * \param uLastIter The solution of the last iteration
-    * \param deltaU The delta as calculated from solving the linear
-    *               system of equations. This parameter also stores
-    *               the updated solution.
-    *
-    */
-    void newtonUpdate(SolutionVector &uCurrentIter,
-                      const SolutionVector &uLastIter,
-                      const SolutionVector &deltaU)
-    {
-        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, WriteConvergence)) {
-            writeConvergence_(uLastIter, deltaU);
-        }
-
-        newtonUpdateShift(uLastIter, deltaU);
-
-        uCurrentIter = uLastIter;
-        uCurrentIter -= deltaU;
-    }
-
-    /*!
-    * \brief Indicates that one newton iteration was finished.
-    *
-    * \param uCurrentIter The solution of the current iteration
-    * \param uLastIter The solution of the last iteration
-    *
-    */
-    void newtonEndStep(SolutionVector &uCurrentIter, SolutionVector &uLastIter)
-    {
-        SplitAndMerge::splitSolVector(this->model_().curSol(),
-                                      this->model_().sdModel1().curSol(),
-                                      this->model_().sdModel2().curSol());
-
-        ParentType::newtonEndStep(uCurrentIter, uLastIter);
-    }
-
-    /*!
-    * \brief Called when the newton method was sucessful.
-    *
-    * This method is called _after_ newtonEnd()
-    */
-    void newtonSucceed()
-    {
-    }
-
-    /*!
-    * \brief the convergence writer produces the output
-    *
-    * \param uLastIter The solution of the last iteration
-    * \param deltaU The delta as calculated from solving the linear
-    *               system of equations. This parameter also stores
-    *               the updated solution.
-    *
-    */
-    void writeConvergence_(const SolutionVector &uLastIter,
-                           const SolutionVector &deltaU)
-    {
-        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, WriteConvergence)) {
-            convergenceWriter_.beginIteration(sdGridView1_(), sdGridView2_());
-            convergenceWriter_.writeFields(uLastIter, deltaU);
-            convergenceWriter_.endIteration();
-        }
-    }
-
-    /*!
-     * \brief the subdomain gridviews
-     */
-    const GridView1 sdGridView1_() const
-    { return this->problem_().sdGridView1(); }
-    const GridView2 sdGridView2_() const
-    { return this->problem_().sdGridView2(); }
-
-
-private:
-    Implementation &asImp_()
-    { return *static_cast<Implementation*>(this); }
-    const Implementation &asImp_() const
-    { return *static_cast<const Implementation*>(this); }
-
-    bool verbose_;
-
-    std::ostringstream endIterMsgStream_;
-    NewtonMethod *method_;
-
-    // optimal number of iterations we want to achieve
-    int targetSteps_;
-    // maximum number of iterations we do before giving up
-    int maxSteps_;
-    // actual number of steps done so far
-    int numSteps_;
-
-    // the linear solver
-    LinearSolver linearSolver_;
-
-    ConvergenceWriter convergenceWriter_;
-};
-
-} // namespace Dumux
-
-#endif // DUMUX_MULTIDOMAIN_NEWTON_CONTROLLER_HH
diff --git a/dumux/multidomain/common/multidomainproblem.hh b/dumux/multidomain/common/multidomainproblem.hh
index d78f96ec41..c95ccb2e01 100644
--- a/dumux/multidomain/common/multidomainproblem.hh
+++ b/dumux/multidomain/common/multidomainproblem.hh
@@ -1,449 +1,8 @@
-// -*- 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 Base class for problems which involve two sub problems
- */
+#ifndef DUMUX_MULTIDOMAIN_PROBLEM_HH_OLD
+#define DUMUX_MULTIDOMAIN_PROBLEM_HH_OLD
 
-#ifndef DUMUX_MULTIDOMAIN_PROBLEM_HH
-#define DUMUX_MULTIDOMAIN_PROBLEM_HH
+#warning this header is deprecated, use dumux/multidomain/common/problem.hh instead
 
-#include "multidomainmodel.hh"
-#include "multidomainnewtoncontroller.hh"
-#include "multidomainpropertydefaults.hh"
-#include "subdomainpropertydefaults.hh"
-#include "multidomainassembler.hh"
+#include <dumux/multidomain/common/problem.hh>
 
-#include <dumux/io/restart.hh>
-
-
-namespace Dumux
-{
-
-/*!
- * \ingroup ImplicitBaseProblems
- * \ingroup MultidomainModel
- * \brief Base class for problems which involve two sub problems (multidomain problems)s
- */
-template<class TypeTag>
-class MultiDomainProblem
-{
-
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
-
-    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
-    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
-
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
-    typedef typename GET_PROP_TYPE(TypeTag, GridCreator) GridCreator;
-
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, LocalResidual) LocalResidual1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, LocalResidual) LocalResidual2;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, Problem) SubDomainProblem1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, Problem) SubDomainProblem2;
-
-    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, GridView) SubDomainGridView1;
-    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, GridView) SubDomainGridView2;
-
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MultiDomainGrid;
-    typedef typename MultiDomainGrid::LeafGridView MultiDomainGridView;
-    typedef typename MultiDomainGrid::Traits::template Codim<0>::Entity MultiDomainElement;
-    typedef typename MultiDomainGrid::SubDomainGrid SubDomainGrid;
-    typedef typename SubDomainGrid::template Codim<0>::EntityPointer SubDomainElementPointer;
-
-    typedef Dune::MultiDomainMCMGMapper<MultiDomainGridView, Dune::MCMGVertexLayout> VertexMapper;
-
-    // copying a problem is not a good idea
-    MultiDomainProblem(const MultiDomainProblem &);
-
-public:
-    /*!
-     * \brief The problem for the coupling of Stokes and Darcy flow
-     *
-     * \param timeManager The time manager
-     * \param gridView The grid view
-     */
-    template<class GridView>
-    MultiDomainProblem(TimeManager &timeManager,
-                       GridView gridView)
-        : timeManager_(timeManager)
-        , newtonMethod_(asImp_())
-        , newtonCtl_(asImp_())
-    {
-        mdGrid_ = std::make_shared<MultiDomainGrid> (GridCreator::grid());
-        mdGridView_ = std::make_shared<MultiDomainGridView> (mdGrid_->leafGridView());
-        mdVertexMapper_ = std::make_shared<VertexMapper> (mdGrid_->leafGridView());
-        sdProblem1_ = std::make_shared<SubDomainProblem1> (timeManager, mdGrid_->subDomain(sdID1()).leafGridView());
-        sdProblem2_ = std::make_shared<SubDomainProblem2> (timeManager, mdGrid_->subDomain(sdID2()).leafGridView());
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::init()
-    void init()
-    {
-        // initialize the sub-problems
-        sdProblem1().init();
-        sdProblem2().init();
-
-        // set the initial condition of the model
-        model().init(asImp_());
-
-        // initialize Lagrange multipliers
-        asImp_().initMortarElements();
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::serialize()
-    template <class Restarter>
-    void serialize(Restarter &res)
-    {
-        this->model().serialize(res);
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::serialize()
-    void serialize()
-    {
-        typedef Dumux::Restart Restarter;
-        Restarter res;
-        res.serializeBegin(this->asImp_());
-        std::cout << "Serialize to file '" << res.fileName() << "'\n";
-        this->timeManager().serialize(res);
-        this->asImp_().serialize(res);
-        res.serializeEnd();
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::restart()
-    void restart(Scalar tRestart)
-    {
-        typedef Dumux::Restart Restarter;
-        Restarter res;
-        res.deserializeBegin(this->asImp_(), tRestart);
-        std::cout << "Deserialize from file '" << res.fileName() << "'\n";
-        this->timeManager().deserialize(res);
-        this->asImp_().deserialize(res);
-        res.deserializeEnd();
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::deserialize()
-    template <class Restarter>
-    void deserialize(Restarter &res)
-    {
-        this->model().deserialize(res);
-    }
-
-    /*!
-     * \name Simulation control
-     */
-    // \{
-
-    /*!
-     * \brief Called by the time manager before the time integration. Calls preTimeStep()
-     *        of the subproblems.
-     */
-    void preTimeStep()
-    {
-        asImp_().sdProblem1().preTimeStep();
-        asImp_().sdProblem2().preTimeStep();
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::timeIntegration()
-    void timeIntegration()
-    {
-        const int maxFails =
-                GET_PARAM_FROM_GROUP(TypeTag, int, Newton, MaxTimeStepDivisions);
-        for (int i = 0; i < maxFails; ++i)
-        {
-            if (model_.update(newtonMethod_, newtonCtl_))
-                return;
-
-            // update failed
-            Scalar dt = timeManager().timeStepSize();
-            Scalar nextDt = dt / 2;
-            timeManager().setTimeStepSize(nextDt);
-
-            std::cout << "Newton solver did not converge. Retrying with time step of "
-                      << timeManager().timeStepSize() << "sec\n";
-        }
-
-        DUNE_THROW(Dune::MathError,
-                   "Newton solver didn't converge after "
-                   << maxFails
-                   << " timestep divisions. dt="
-                   << timeManager().timeStepSize());
-    }
-
-    /*!
-     * \brief Called by the time manager after the time integration to
-     *        do some post processing on the solution. Calls postTimeStep()
-     *        of the subproblems.
-     */
-    void postTimeStep()
-    {
-        asImp_().sdProblem1().postTimeStep();
-        asImp_().sdProblem2().postTimeStep();
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::nextTimeStepSize()
-    Scalar nextTimeStepSize(const Scalar dt)
-    {
-        return newtonCtl_.suggestTimeStepSize(dt);
-    }
-
-    /*!
-     * \brief This method is called by the model if the update to the
-     *        next time step failed completely.
-     */
-    void updateSuccessful()
-    {
-        model_.updateSuccessful();
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::shouldWriteOutput()
-    bool shouldWriteOutput() const
-    { return true; }
-
-    //! \copydoc Dumux::ImplicitProblem::shouldWriteRestartFile()
-    bool shouldWriteRestartFile() const
-    { return false; }
-
-    //! \copydoc Dumux::ImplicitProblem::episodeEnd()
-    void episodeEnd()
-    {
-        std::cerr << "The end of an episode is reached, but the problem "
-                  << "does not override the episodeEnd() method. "
-                  << "Doing nothing!\n";
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::advanceTimeLevel()
-    void advanceTimeLevel()
-    {
-        asImp_().sdProblem1().advanceTimeLevel();
-        asImp_().sdProblem2().advanceTimeLevel();
-
-        model_.advanceTimeLevel();
-    }
-
-    //! \copydoc Dumux::ImplicitProblem::writeOutput()
-    void writeOutput()
-    {
-        // write the current result to disk
-        if (asImp_().shouldWriteOutput()) {
-            asImp_().sdProblem1().writeOutput();
-            asImp_().sdProblem2().writeOutput();
-        }
-    }
-
-
-    // \}
-
-    //! \copydoc Dumux::ImplicitProblem::name()
-    const char *name() const
-    { return simname_.c_str(); }
-
-    //! \copydoc Dumux::ImplicitProblem::setName()
-    static void setName(const char *newName)
-    { simname_ = newName; }
-
-    //! \copydoc Dumux::ImplicitProblem::timeManager()
-    TimeManager &timeManager()
-    { return timeManager_; }
-
-    //! \copydoc Dumux::ImplicitProblem::timeManager()
-    const TimeManager &timeManager() const
-    { return timeManager_; }
-
-    //! \copydoc Dumux::ImplicitProblem::newtonController()
-    NewtonController &newtonController()
-    { return newtonCtl_; }
-
-    //! \copydoc Dumux::ImplicitProblem::newtonController()
-    const NewtonController &newtonController() const
-    { return newtonCtl_; }
-
-    //! \copydoc Dumux::ImplicitProblem::model()
-    Model &model()
-    { return model_; }
-
-    //! \copydoc Dumux::ImplicitProblem::model()
-    const Model &model() const
-    { return model_; }
-    // \}
-
-    /*!
-     * \brief Returns the ID of the first domain
-     */
-    const typename MultiDomainGrid::SubDomainIndex sdID1() const
-    { return typename MultiDomainGrid::SubDomainIndex(0); }
-
-    /*!
-     * \brief Returns the ID of the second domain
-     */
-    const typename MultiDomainGrid::SubDomainIndex sdID2() const
-    { return typename MultiDomainGrid::SubDomainIndex(1); }
-
-    /*!
-     * \brief Returns a reference to subproblem1
-     */
-    SubDomainProblem1& sdProblem1()
-    { return *sdProblem1_; }
-
-    /*!
-     * \brief Returns a const reference to subproblem1
-     */
-    const SubDomainProblem1& sdProblem1() const
-    { return *sdProblem1_; }
-
-    /*!
-     * \brief Returns a reference to subproblem2
-     */
-    SubDomainProblem2& sdProblem2()
-    { return *sdProblem2_; }
-
-    /*!
-     * \brief Returns a const reference to subproblem2
-     */
-    const SubDomainProblem2& sdProblem2() const
-    { return *sdProblem2_; }
-
-    /*!
-     * \brief Returns a reference to the localresidual1
-     */
-    LocalResidual1& localResidual1()
-    { return sdProblem1().model().localResidual(); }
-
-    /*!
-     * \brief Returns a reference to the localresidual2
-     */
-    LocalResidual2& localResidual2()
-    { return sdProblem2().model().localResidual(); }
-
-    /*!
-     * \brief Returns a reference to the multidomain grid
-     */
-    MultiDomainGrid& mdGrid()
-    { return *mdGrid_; }
-
-    /*!
-     * \brief Returns a const reference to the multidomain grid
-     */
-    const MultiDomainGrid& mdGrid() const
-    { return *mdGrid_; }
-
-    /*!
-     * \brief Returns the multidomain gridview
-     */
-    const MultiDomainGridView& mdGridView() const
-    { return *mdGridView_; }
-
-    /*!
-     * \brief Returns the multidomain gridview
-     */
-    const MultiDomainGridView& gridView() const
-    { return *mdGridView_; }
-
-    /*!
-     * \brief Provides a vertex mapper for the multidomain
-     */
-    VertexMapper& mdVertexMapper()
-    { return *mdVertexMapper_; }
-
-    /*!
-     * \brief Returns a const reference to the subdomain1 grid
-     */
-    const SubDomainGrid& sdGrid1() const
-    { return mdGrid_->subDomain(sdID1()); }
-
-    /*!
-     * \brief Returns a const reference to the subdomain2 grid
-     */
-    const SubDomainGrid& sdGrid2() const
-    { return mdGrid_->subDomain(sdID2()); }
-
-    /*!
-     * \brief Returns the gridview of subdomain1
-     */
-    const SubDomainGridView1 sdGridView1() const
-    { return sdGrid1().leafGridView(); }
-
-    /*!
-     * \brief Returns the gridview of subdomain2
-     */
-    const SubDomainGridView2 sdGridView2() const
-    { return sdGrid2().leafGridView(); }
-
-    /*!
-     * \brief Returns a pointer to the subdomain1 element
-     *
-     * \param mdElement1 The multi domain element1
-     */
-    SubDomainElementPointer sdElementPointer1(const MultiDomainElement& mdElement1)
-    { return sdGrid1().subDomainEntityPointer(mdElement1); }
-
-    /*!
-     * \brief Returns a pointer to the subdomain2 element
-     *
-     * \param mdElement2 The multi domain element2
-     */
-    SubDomainElementPointer sdElementPointer2(const MultiDomainElement& mdElement2)
-    { return sdGrid2().subDomainEntityPointer(mdElement2); }
-
-
-protected:
-    void initMortarElements()
-    {}
-
-    Implementation &asImp_()
-    { return *static_cast<Implementation *>(this); }
-
-    //! \copydoc asImp_()
-    const Implementation &asImp_() const
-    { return *static_cast<const Implementation *>(this); }
-
-private:
-    // a string for the name of the current simulation, which could be
-    // set by means of an program argument, for example.
-    static std::string simname_;
-
-    TimeManager &timeManager_;
-    NewtonMethod newtonMethod_;
-    NewtonController newtonCtl_;
-
-    Model model_;
-
-    std::shared_ptr<MultiDomainGrid> mdGrid_;
-    std::shared_ptr<MultiDomainGridView> mdGridView_;
-    std::shared_ptr<VertexMapper> mdVertexMapper_;
-
-    std::shared_ptr<SubDomainProblem1> sdProblem1_;
-    std::shared_ptr<SubDomainProblem2> sdProblem2_;
-};
-
-// definition of the static class member simname_,
-// which is necessary because it is of type string.
-template <class TypeTag>
-std::string MultiDomainProblem<TypeTag>::simname_ = "simCoupled";
-
-} // namespace Dumux
-
-#endif // DUMUX_MULTIDOMAIN_PROBLEM_HH
+#endif
diff --git a/dumux/multidomain/common/multidomainproperties.hh b/dumux/multidomain/common/multidomainproperties.hh
index 06c04b5740..22c05bf084 100644
--- a/dumux/multidomain/common/multidomainproperties.hh
+++ b/dumux/multidomain/common/multidomainproperties.hh
@@ -1,113 +1,8 @@
-// -*- 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 Properties
- * \ingroup ImplicitProperties
- * \ingroup MultidomainModel
- * \brief Specify properties required for the coupled model
- */
-#ifndef DUMUX_MULTIDOMAIN_PROPERTIES_HH
-#define DUMUX_MULTIDOMAIN_PROPERTIES_HH
+#ifndef DUMUX_MULTIDOMAIN_PROPERTIES_HH_OLD
+#define DUMUX_MULTIDOMAIN_PROPERTIES_HH_OLD
 
-#include <dumux/implicit/properties.hh>
+#warning this header is deprecated, use dumux/multidomain/common/properties.hh instead
 
-namespace Dumux
-{
+#include <dumux/multidomain/common/properties.hh>
 
-namespace Properties
-{
-// \{
-
-//////////////////////////////////////////////////////////////////
-// Type tags tags
-//////////////////////////////////////////////////////////////////
-
-//! The type tag for problems which utilize the coupling approach
-NEW_TYPE_TAG(MultiDomain, INHERITS_FROM(ImplicitBase));
-
-//////////////////////////////////////////////////////////////////
-// Property tags
-//////////////////////////////////////////////////////////////////
-
-//! Specifies the model
-NEW_PROP_TAG(Model);
-
-//! Specifies the type tag of the first sub-problem
-NEW_PROP_TAG(SubDomain1TypeTag);
-
-//! Specifies the type tag of the second sub-problem
-NEW_PROP_TAG(SubDomain2TypeTag);
-
-//! Specifies the type tag of the other sub-problem
-NEW_PROP_TAG(OtherSubDomainTypeTag);
-
-//! Specifies the type tag of coupled problem
-NEW_PROP_TAG(MultiDomainTypeTag);
-
-//! Specifies the host grid
-NEW_PROP_TAG(Grid);
-
-//! Specifies the multidomain grid
-NEW_PROP_TAG(MultiDomainGrid);
-
-//! Specifies the number of equations in submodel 1
-NEW_PROP_TAG(NumEq1);
-
-//! Specifies the number of equations in submodel 2
-NEW_PROP_TAG(NumEq2);
-
-//! Specifies the fluidsystem that is used in the subdomains
-NEW_PROP_TAG(FluidSystem);
-
-//! the maximum allowed number of timestep divisions for the
-//! Newton solver
-NEW_PROP_TAG(NewtonMaxTimeStepDivisions);
-
-//! Specifies the multidomain grid function space
-NEW_PROP_TAG(MultiDomainGridFunctionSpace);
-
-//! Specifies the multidomain grid operator
-NEW_PROP_TAG(MultiDomainGridOperator);
-
-//! Specifies the equality conditions
-NEW_PROP_TAG(MultiDomainCondition);
-
-//! Specifies the multidomain type based subproblem for subdomain 1
-NEW_PROP_TAG(MultiDomainSubProblem1);
-
-//! Specifies the multidomain type based subproblem for subdomain 2
-NEW_PROP_TAG(MultiDomainSubProblem2);
-
-//! the local coupling operator for use with dune-multidomain
-NEW_PROP_TAG(MultiDomainCouplingLocalOperator);
-
-//! Specifies the multidomain coupling
-NEW_PROP_TAG(MultiDomainCoupling);
-
-//! Property tag for the multidomain constraints transformation
-NEW_PROP_TAG(MultiDomainConstraintsTrafo);
-
-//! the routines that are used to split and merge solution vectors
-NEW_PROP_TAG(SplitAndMerge);
-
-} // namespace Properties
-} // namespace Dumux
-
-#endif // DUMUX_MULTIDOMAIN_PROPERTIES_HH
+#endif
diff --git a/dumux/multidomain/common/multidomainpropertydefaults.hh b/dumux/multidomain/common/multidomainpropertydefaults.hh
index 599d59108f..e234dbcd74 100644
--- a/dumux/multidomain/common/multidomainpropertydefaults.hh
+++ b/dumux/multidomain/common/multidomainpropertydefaults.hh
@@ -1,256 +1,8 @@
-// -*- 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 Properties
- * \ingroup ImplicitProperties
- * \ingroup MultidomainModel
- * \brief Sets default values for the MultiDomain properties
- */
+#ifndef DUMUX_MULTIDOMAIN_PROPERTY_DEFAULTS_HH_OLD
+#define DUMUX_MULTIDOMAIN_PROPERTY_DEFAULTS_HH_OLD
 
-#ifndef DUMUX_MULTIDOMAIN_PROPERTY_DEFAULTS_HH
-#define DUMUX_MULTIDOMAIN_PROPERTY_DEFAULTS_HH
+#warning this header is deprecated, use dumux/multidomain/common/propertydefaults.hh instead
 
-#include <dune/istl/bvector.hh>
-#include <dune/istl/bcrsmatrix.hh>
-
-#include <dune/pdelab/backend/istlvectorbackend.hh>
-#include <dune/pdelab/backend/istlmatrixbackend.hh>
-#include <dune/pdelab/multidomain/multidomaingridfunctionspace.hh>
-#include <dune/pdelab/multidomain/subproblemlocalfunctionspace.hh>
-#include <dune/pdelab/multidomain/subproblem.hh>
-#include <dune/pdelab/multidomain/subdomainset.hh>
-#include <dune/pdelab/multidomain/coupling.hh>
-#include <dune/pdelab/multidomain/gridoperator.hh>
-
-#include <dune/pdelab/gridoperator/gridoperator.hh>
-
-#include "subdomainpropertydefaults.hh"
-#include "multidomainmodel.hh"
-#include "multidomainproperties.hh"
-#include "multidomainnewtoncontroller.hh"
-#include "splitandmerge.hh"
-
-#include <dumux/common/timemanager.hh>
-#include <dumux/nonlinear/newtonmethod.hh>
-
-namespace Dumux
-{
-template <class TypeTag> class MultiDomainModel;
-template <class TypeTag> class MultiDomainAssembler;
-template <class TypeTag> class MultiDomainNewtonController;
-
-namespace Properties
-{
-
-SET_PROP(MultiDomain, MultiDomainGrid)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, Grid) HostGrid;
-    typedef typename Dune::mdgrid::FewSubDomainsTraits<HostGrid::dimension,4> MDGridTraits;
-public:
-    typedef typename Dune::MultiDomainGrid<HostGrid, MDGridTraits> type;
-};
-
-SET_PROP(MultiDomain, MultiDomainGridFunctionSpace)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
-    typedef typename Dune::PDELab::LexicographicOrderingTag OrderingTag;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubTypeTag1;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubTypeTag2;
-    typedef typename GET_PROP_TYPE(SubTypeTag1, GridFunctionSpace) GridFunctionSpace1;
-    typedef typename GET_PROP_TYPE(SubTypeTag2, GridFunctionSpace) GridFunctionSpace2;
-public:
-    typedef Dune::PDELab::MultiDomain::MultiDomainGridFunctionSpace<MDGrid,
-                                                                    Dune::PDELab::ISTLVectorBackend<>,
-                                                                    OrderingTag,
-                                                                    GridFunctionSpace1,
-                                                                    GridFunctionSpace2> type;
-};
-
-// set the subdomain equality condition by default
-SET_PROP(MultiDomain, MultiDomainCondition)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
-public:
-    typedef Dune::PDELab::MultiDomain::SubDomainEqualityCondition<MDGrid> type;
-};
-
-SET_PROP(MultiDomain, MultiDomainSubProblem1)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MDGridFunctionSpace;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubTypeTag1;
-    typedef typename GET_PROP_TYPE(SubTypeTag1, Constraints) Constraints1;
-    typedef typename GET_PROP_TYPE(SubTypeTag1, LocalOperator) LocalOperator1;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCondition) MDCondition;
-    typedef typename GET_PROP_TYPE(SubTypeTag1, GridFunctionSpace) GridFunctionSpace1;
-public:
-    typedef Dune::PDELab::MultiDomain::SubProblem<MDGridFunctionSpace,
-                                                  MDGridFunctionSpace,
-                                                  LocalOperator1, MDCondition,
-                                                  0> type;
-};
-
-SET_PROP(MultiDomain, MultiDomainSubProblem2)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MDGridFunctionSpace;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubTypeTag2;
-    typedef typename GET_PROP_TYPE(SubTypeTag2, Constraints) Constraints2;
-    typedef typename GET_PROP_TYPE(SubTypeTag2, LocalOperator) LocalOperator2;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCondition) MDCondition;
-    typedef typename GET_PROP_TYPE(SubTypeTag2, GridFunctionSpace) GridFunctionSpace2;
-public:
-    typedef Dune::PDELab::MultiDomain::SubProblem<MDGridFunctionSpace,
-                                                  MDGridFunctionSpace,
-                                                  LocalOperator2, MDCondition,
-                                                  1> type;
-};
-
-SET_PROP(MultiDomain, MultiDomainCoupling)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem1) MDSubProblem1;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem2) MDSubProblem2;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCouplingLocalOperator) MDCouplingLocalOperator;
-public:
-    typedef Dune::PDELab::MultiDomain::Coupling<MDSubProblem1,
-                                                MDSubProblem2,
-                                                MDCouplingLocalOperator> type;
-};
-
-// set trivial constraints transformation by default
-SET_PROP(MultiDomain, MultiDomainConstraintsTrafo)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MDGridFunctionSpace;
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-public:
-    typedef typename MDGridFunctionSpace::template ConstraintsContainer<Scalar>::Type type;
-};
-
-SET_PROP(MultiDomain, MultiDomainGridOperator)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MDGridFunctionSpace;
-    typedef Dune::PDELab::ISTLMatrixBackend MBE;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem1) MDSubProblem1;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem2) MDSubProblem2;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCoupling) MDCoupling;
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainConstraintsTrafo) MDConstraintsTrafo;
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-public:
-    typedef Dune::PDELab::MultiDomain::GridOperator<
-                    MDGridFunctionSpace, MDGridFunctionSpace,
-                    MBE, Scalar, Scalar, Scalar,
-                    MDConstraintsTrafo, MDConstraintsTrafo,
-                    MDSubProblem1, MDSubProblem2, MDCoupling> type;
-};
-
-SET_PROP(MultiDomain, JacobianMatrix)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridOperator) MDGridOperator;
-public:
-    typedef typename MDGridOperator::Traits::Jacobian type;
-};
-
-SET_INT_PROP(MultiDomain, LinearSolverBlockSize, GET_PROP_VALUE(TypeTag, NumEq));
-
-
-// Set property values for the coupled model
-SET_TYPE_PROP(MultiDomain, Model, MultiDomainModel<TypeTag>);
-
-SET_PROP(MultiDomain, SolutionVector)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
-    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
-public:
-    typedef Dune::BlockVector<Dune::FieldVector<Scalar, numEq> > type;
-};
-
-// Specify the type of the multidomain assembler
-SET_TYPE_PROP(MultiDomain, JacobianAssembler, MultiDomainAssembler<TypeTag>);
-
-// use the plain newton method for the coupled problems by default
-SET_TYPE_PROP(MultiDomain, NewtonMethod, NewtonMethod<TypeTag>);
-
-// use the plain newton controller for coupled problems by default
-SET_TYPE_PROP(MultiDomain, NewtonController, MultiDomainNewtonController<TypeTag>);
-
-// Set the default type of the time manager for coupled models
-SET_TYPE_PROP(MultiDomain, TimeManager, TimeManager<TypeTag>);
-
-// needed to define size of ImplicitBase's PrimaryVariables
-SET_PROP(MultiDomain, NumEq)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) TypeTag1;
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TypeTag2;
-
-    enum {
-        numEq1 = GET_PROP_VALUE(TypeTag1, NumEq),
-        numEq2 = GET_PROP_VALUE(TypeTag2, NumEq)
-    };
-public:
-    static const int value = numEq1;
-};
-
-SET_PROP(MultiDomain, NumEq1)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) TypeTag1;
-    enum {numEq = GET_PROP_VALUE(TypeTag1, NumEq)};
-public:
-    static const int value = numEq;
-};
-
-SET_PROP(MultiDomain, NumEq2)
-{
-private:
-    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TypeTag2;
-    enum {numEq = GET_PROP_VALUE(TypeTag2, NumEq)};
-public:
-    static const int value = numEq;
-};
-
-// set the type of the linear solver
-SET_TYPE_PROP(MultiDomain, LinearSolver, ILU0BiCGSTABBackend<TypeTag>);
-
-// set the minimum residual reduction of the linear solver
-SET_SCALAR_PROP(MultiDomain, LinearSolverResidualReduction, 1e-6);
-
-// set the default number of maximum iterations for the linear solver
-SET_INT_PROP(MultiDomain, LinearSolverMaxIterations, 250);
-
-// set the maximum time step divisions
-SET_INT_PROP(MultiDomain, NewtonMaxTimeStepDivisions, 10);
-
-// set the routines for splitting and merging solution vectors
-SET_TYPE_PROP(MultiDomain, SplitAndMerge, SplitAndMerge<TypeTag>);
-
-} // namespace Properties
-} // namespace Dumux
-
-#endif // DUMUX_MULTIDOMAIN_PROPERTY_DEFAULTS_HH
+#include <dumux/multidomain/common/propertydefaults.hh>
 
+#endif
diff --git a/dumux/multidomain/common/newtoncontroller.hh b/dumux/multidomain/common/newtoncontroller.hh
new file mode 100644
index 0000000000..5a36bfc45e
--- /dev/null
+++ b/dumux/multidomain/common/newtoncontroller.hh
@@ -0,0 +1,312 @@
+// -*- 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 Newton controller for multidomain problems
+ */
+#ifndef DUMUX_MULTIDOMAIN_NEWTON_CONTROLLER_HH
+#define DUMUX_MULTIDOMAIN_NEWTON_CONTROLLER_HH
+
+#include <dumux/nonlinear/newtoncontroller.hh>
+#include "convergencewriter.hh"
+
+namespace Dumux
+{
+template <class TypeTag>
+class MultiDomainNewtonController;
+
+template <class TypeTag>
+struct MultiDomainConvergenceWriter;
+
+namespace Properties
+{
+NEW_PROP_TAG(NewtonWriteConvergence);
+
+// set default values for Newton for multidomain problems
+// they can be overwritten in the parameter file
+SET_INT_PROP(MultiDomain, NewtonTargetSteps, 8);
+SET_INT_PROP(MultiDomain, NewtonMaxSteps, 15);
+SET_SCALAR_PROP(MultiDomain, NewtonMaxRelativeShift, 1e-5);
+SET_BOOL_PROP(MultiDomain, NewtonWriteConvergence, false);
+}
+
+
+/*!
+ * \ingroup Newton
+ * \ingroup MultidomainModel
+ * \brief Reference implementation of a newton controller for coupled problems.
+ *
+ * If you want to specialize only some methods but are happy with
+ * the defaults of the reference controller, derive your
+ * controller from this class and simply overload the required
+ * methods.
+ */
+template <class TypeTag>
+class MultiDomainNewtonController : public NewtonController<TypeTag>
+{
+    typedef NewtonController<TypeTag> ParentType;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, SolutionVector) SolutionVector;
+    typedef typename GET_PROP_TYPE(TypeTag, SplitAndMerge) SplitAndMerge;
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
+    typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, GridView) GridView1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, GridView) GridView2;
+
+    typedef MultiDomainConvergenceWriter<TypeTag>  ConvergenceWriter;
+    typedef typename GET_PROP_TYPE(TypeTag, LinearSolver) LinearSolver;
+
+public:
+    /*!
+     * \brief Constructor
+     *
+     * \param problem The problem
+     */
+    MultiDomainNewtonController(const Problem &problem)
+        : ParentType(problem)
+        , endIterMsgStream_(std::ostringstream::out)
+        , linearSolver_(problem)
+        , convergenceWriter_(asImp_())
+    {
+        std::cout << "NewtonMaxRelativeShift= "
+                  << PROP_DIAGNOSTIC(TypeTag, NewtonMaxRelativeShift)
+                  << ", "
+                  << GET_PROP_VALUE(TypeTag, NewtonMaxRelativeShift)
+                  << std::endl;
+    }
+
+    //! \copydoc ParentType::newtonUpdateShift()
+    void newtonUpdateShift(const SolutionVector &uLastIter,
+                           const SolutionVector &deltaU)
+    {
+        // calculate the relative error as the maximum relative
+        // deflection in any degree of freedom.
+        this->shift_ = 0;
+
+        SolutionVector uNewI = uLastIter;
+        uNewI -= deltaU;
+
+        for (unsigned int i = 0; i < uLastIter.base().size(); ++i) {
+            for (unsigned int j = 0; j < uLastIter.base()[i].size(); ++j) {
+                Scalar vertexError = std::abs(deltaU.base()[i][j]);
+                vertexError /= std::max<Scalar>(1.0, std::abs(uLastIter.base()[i][j] + uNewI.base()[i][j])/2);
+
+                this->shift_ = std::max(this->shift_, vertexError);
+            }
+        }
+    }
+
+    /*!
+     * \brief Solve the linear system of equations
+     *        \f$ \mathbf{A} x - b = 0\f$.
+     *
+     * \param A Coefficient matrix A
+     * \param x Vector of unknowns
+     * \param b Right hand side
+     *
+     * Throws Dumux::NumericalProblem if the linear solver didn't
+     * converge.
+     */
+    template <class Matrix, class Vector>
+    void newtonSolveLinear(Matrix &A,
+                           Vector &x,
+                           Vector &b)
+    {
+        // if the deflection of the newton method is large, we do not
+        // need to solve the linear approximation accurately. Assuming
+        // that the initial value for the delta vector u is quite
+        // close to the final value, a reduction of 6 orders of
+        // magnitude in the defect should be sufficient...
+        try {
+            int converged = linearSolver_.solve(A.base(), x.base(), b.base());
+
+#if HAVE_MPI
+            // make sure all processes converged
+            int convergedSend = 1;
+            MPI_Allreduce(/*sendBuf=*/&convergedSend,
+                          /*recvBuf=*/&converged,
+                          /*count=*/1,
+                          MPI_INT,
+                          MPI_MIN,
+                          MPI_COMM_WORLD);
+#endif
+            if (!converged) {
+                DUNE_THROW(NumericalProblem,
+                           "Linear solver did not converge");
+            }
+        }
+        catch (const Dune::MatrixBlockError &e) {
+#if HAVE_MPI
+            // make sure all processes converged
+            int convergedSend = 0;
+            int converged;
+
+            MPI_Allreduce(/*sendBuf=*/&convergedSend,
+                          /*recvBuf=*/&converged,
+                          /*count=*/1,
+                          MPI_INT,
+                          MPI_MIN,
+                          MPI_COMM_WORLD);
+#endif
+
+            Dumux::NumericalProblem p;
+            std::string msg;
+            std::ostringstream ms(msg);
+            ms << e.what() << "M=" << A.base()[e.r][e.c];
+            p.message(ms.str());
+            throw p;
+        }
+        catch (const Dune::Exception &e) {
+#if HAVE_MPI
+            // make sure all processes converged
+            int convergedSend = 0;
+            int converged;
+
+            MPI_Allreduce(/*sendBuf=*/&convergedSend,
+                          /*recvBuf=*/&converged,
+                          /*count=*/1,
+                          MPI_INT,
+                          MPI_MIN,
+                          MPI_COMM_WORLD);
+#endif
+
+            Dumux::NumericalProblem p;
+            p.message(e.what());
+            throw p;
+        }
+    }
+
+    /*!
+    * \brief Update the current solution function with a delta vector.
+    *
+    * The error estimates required for the newtonConverged() and
+    * newtonProceed() methods should be updated here.
+    *
+    * Different update strategies, such as line search and chopped
+    * updates can be implemented. The default behaviour is just to
+    * subtract deltaU from uLastIter.
+    *
+    * \param uCurrentIter The solution of the current iteration
+    * \param uLastIter The solution of the last iteration
+    * \param deltaU The delta as calculated from solving the linear
+    *               system of equations. This parameter also stores
+    *               the updated solution.
+    *
+    */
+    void newtonUpdate(SolutionVector &uCurrentIter,
+                      const SolutionVector &uLastIter,
+                      const SolutionVector &deltaU)
+    {
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, WriteConvergence)) {
+            writeConvergence_(uLastIter, deltaU);
+        }
+
+        newtonUpdateShift(uLastIter, deltaU);
+
+        uCurrentIter = uLastIter;
+        uCurrentIter -= deltaU;
+    }
+
+    /*!
+    * \brief Indicates that one newton iteration was finished.
+    *
+    * \param uCurrentIter The solution of the current iteration
+    * \param uLastIter The solution of the last iteration
+    *
+    */
+    void newtonEndStep(SolutionVector &uCurrentIter, SolutionVector &uLastIter)
+    {
+        SplitAndMerge::splitSolVector(this->model_().curSol(),
+                                      this->model_().sdModel1().curSol(),
+                                      this->model_().sdModel2().curSol());
+
+        ParentType::newtonEndStep(uCurrentIter, uLastIter);
+    }
+
+    /*!
+    * \brief Called when the newton method was sucessful.
+    *
+    * This method is called _after_ newtonEnd()
+    */
+    void newtonSucceed()
+    {
+    }
+
+    /*!
+    * \brief the convergence writer produces the output
+    *
+    * \param uLastIter The solution of the last iteration
+    * \param deltaU The delta as calculated from solving the linear
+    *               system of equations. This parameter also stores
+    *               the updated solution.
+    *
+    */
+    void writeConvergence_(const SolutionVector &uLastIter,
+                           const SolutionVector &deltaU)
+    {
+        if (GET_PARAM_FROM_GROUP(TypeTag, bool, Newton, WriteConvergence)) {
+            convergenceWriter_.beginIteration(sdGridView1_(), sdGridView2_());
+            convergenceWriter_.writeFields(uLastIter, deltaU);
+            convergenceWriter_.endIteration();
+        }
+    }
+
+    /*!
+     * \brief the subdomain gridviews
+     */
+    const GridView1 sdGridView1_() const
+    { return this->problem_().sdGridView1(); }
+    const GridView2 sdGridView2_() const
+    { return this->problem_().sdGridView2(); }
+
+
+private:
+    Implementation &asImp_()
+    { return *static_cast<Implementation*>(this); }
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation*>(this); }
+
+    bool verbose_;
+
+    std::ostringstream endIterMsgStream_;
+    NewtonMethod *method_;
+
+    // optimal number of iterations we want to achieve
+    int targetSteps_;
+    // maximum number of iterations we do before giving up
+    int maxSteps_;
+    // actual number of steps done so far
+    int numSteps_;
+
+    // the linear solver
+    LinearSolver linearSolver_;
+
+    ConvergenceWriter convergenceWriter_;
+};
+
+} // namespace Dumux
+
+#endif // DUMUX_MULTIDOMAIN_NEWTON_CONTROLLER_HH
diff --git a/dumux/multidomain/common/problem.hh b/dumux/multidomain/common/problem.hh
new file mode 100644
index 0000000000..52fd9b77a8
--- /dev/null
+++ b/dumux/multidomain/common/problem.hh
@@ -0,0 +1,449 @@
+// -*- 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 Base class for problems which involve two sub problems
+ */
+
+#ifndef DUMUX_MULTIDOMAIN_PROBLEM_HH
+#define DUMUX_MULTIDOMAIN_PROBLEM_HH
+
+#include "model.hh"
+#include "newtoncontroller.hh"
+#include "propertydefaults.hh"
+#include "subdomainpropertydefaults.hh"
+#include "assembler.hh"
+
+#include <dumux/io/restart.hh>
+
+
+namespace Dumux
+{
+
+/*!
+ * \ingroup ImplicitBaseProblems
+ * \ingroup MultidomainModel
+ * \brief Base class for problems which involve two sub problems (multidomain problems)s
+ */
+template<class TypeTag>
+class MultiDomainProblem
+{
+
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Problem) Implementation;
+
+    typedef typename GET_PROP_TYPE(TypeTag, TimeManager) TimeManager;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonMethod) NewtonMethod;
+    typedef typename GET_PROP_TYPE(TypeTag, NewtonController) NewtonController;
+
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
+    typedef typename GET_PROP_TYPE(TypeTag, GridCreator) GridCreator;
+
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubDomain1TypeTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubDomain2TypeTag;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, LocalResidual) LocalResidual1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, LocalResidual) LocalResidual2;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, Problem) SubDomainProblem1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, Problem) SubDomainProblem2;
+
+    typedef typename GET_PROP_TYPE(SubDomain1TypeTag, GridView) SubDomainGridView1;
+    typedef typename GET_PROP_TYPE(SubDomain2TypeTag, GridView) SubDomainGridView2;
+
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MultiDomainGrid;
+    typedef typename MultiDomainGrid::LeafGridView MultiDomainGridView;
+    typedef typename MultiDomainGrid::Traits::template Codim<0>::Entity MultiDomainElement;
+    typedef typename MultiDomainGrid::SubDomainGrid SubDomainGrid;
+    typedef typename SubDomainGrid::template Codim<0>::EntityPointer SubDomainElementPointer;
+
+    typedef Dune::MultiDomainMCMGMapper<MultiDomainGridView, Dune::MCMGVertexLayout> VertexMapper;
+
+    // copying a problem is not a good idea
+    MultiDomainProblem(const MultiDomainProblem &);
+
+public:
+    /*!
+     * \brief The problem for the coupling of Stokes and Darcy flow
+     *
+     * \param timeManager The time manager
+     * \param gridView The grid view
+     */
+    template<class GridView>
+    MultiDomainProblem(TimeManager &timeManager,
+                       GridView gridView)
+        : timeManager_(timeManager)
+        , newtonMethod_(asImp_())
+        , newtonCtl_(asImp_())
+    {
+        mdGrid_ = std::make_shared<MultiDomainGrid> (GridCreator::grid());
+        mdGridView_ = std::make_shared<MultiDomainGridView> (mdGrid_->leafGridView());
+        mdVertexMapper_ = std::make_shared<VertexMapper> (mdGrid_->leafGridView());
+        sdProblem1_ = std::make_shared<SubDomainProblem1> (timeManager, mdGrid_->subDomain(sdID1()).leafGridView());
+        sdProblem2_ = std::make_shared<SubDomainProblem2> (timeManager, mdGrid_->subDomain(sdID2()).leafGridView());
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::init()
+    void init()
+    {
+        // initialize the sub-problems
+        sdProblem1().init();
+        sdProblem2().init();
+
+        // set the initial condition of the model
+        model().init(asImp_());
+
+        // initialize Lagrange multipliers
+        asImp_().initMortarElements();
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::serialize()
+    template <class Restarter>
+    void serialize(Restarter &res)
+    {
+        this->model().serialize(res);
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::serialize()
+    void serialize()
+    {
+        typedef Dumux::Restart Restarter;
+        Restarter res;
+        res.serializeBegin(this->asImp_());
+        std::cout << "Serialize to file '" << res.fileName() << "'\n";
+        this->timeManager().serialize(res);
+        this->asImp_().serialize(res);
+        res.serializeEnd();
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::restart()
+    void restart(Scalar tRestart)
+    {
+        typedef Dumux::Restart Restarter;
+        Restarter res;
+        res.deserializeBegin(this->asImp_(), tRestart);
+        std::cout << "Deserialize from file '" << res.fileName() << "'\n";
+        this->timeManager().deserialize(res);
+        this->asImp_().deserialize(res);
+        res.deserializeEnd();
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::deserialize()
+    template <class Restarter>
+    void deserialize(Restarter &res)
+    {
+        this->model().deserialize(res);
+    }
+
+    /*!
+     * \name Simulation control
+     */
+    // \{
+
+    /*!
+     * \brief Called by the time manager before the time integration. Calls preTimeStep()
+     *        of the subproblems.
+     */
+    void preTimeStep()
+    {
+        asImp_().sdProblem1().preTimeStep();
+        asImp_().sdProblem2().preTimeStep();
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::timeIntegration()
+    void timeIntegration()
+    {
+        const int maxFails =
+                GET_PARAM_FROM_GROUP(TypeTag, int, Newton, MaxTimeStepDivisions);
+        for (int i = 0; i < maxFails; ++i)
+        {
+            if (model_.update(newtonMethod_, newtonCtl_))
+                return;
+
+            // update failed
+            Scalar dt = timeManager().timeStepSize();
+            Scalar nextDt = dt / 2;
+            timeManager().setTimeStepSize(nextDt);
+
+            std::cout << "Newton solver did not converge. Retrying with time step of "
+                      << timeManager().timeStepSize() << "sec\n";
+        }
+
+        DUNE_THROW(Dune::MathError,
+                   "Newton solver didn't converge after "
+                   << maxFails
+                   << " timestep divisions. dt="
+                   << timeManager().timeStepSize());
+    }
+
+    /*!
+     * \brief Called by the time manager after the time integration to
+     *        do some post processing on the solution. Calls postTimeStep()
+     *        of the subproblems.
+     */
+    void postTimeStep()
+    {
+        asImp_().sdProblem1().postTimeStep();
+        asImp_().sdProblem2().postTimeStep();
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::nextTimeStepSize()
+    Scalar nextTimeStepSize(const Scalar dt)
+    {
+        return newtonCtl_.suggestTimeStepSize(dt);
+    }
+
+    /*!
+     * \brief This method is called by the model if the update to the
+     *        next time step failed completely.
+     */
+    void updateSuccessful()
+    {
+        model_.updateSuccessful();
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::shouldWriteOutput()
+    bool shouldWriteOutput() const
+    { return true; }
+
+    //! \copydoc Dumux::ImplicitProblem::shouldWriteRestartFile()
+    bool shouldWriteRestartFile() const
+    { return false; }
+
+    //! \copydoc Dumux::ImplicitProblem::episodeEnd()
+    void episodeEnd()
+    {
+        std::cerr << "The end of an episode is reached, but the problem "
+                  << "does not override the episodeEnd() method. "
+                  << "Doing nothing!\n";
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::advanceTimeLevel()
+    void advanceTimeLevel()
+    {
+        asImp_().sdProblem1().advanceTimeLevel();
+        asImp_().sdProblem2().advanceTimeLevel();
+
+        model_.advanceTimeLevel();
+    }
+
+    //! \copydoc Dumux::ImplicitProblem::writeOutput()
+    void writeOutput()
+    {
+        // write the current result to disk
+        if (asImp_().shouldWriteOutput()) {
+            asImp_().sdProblem1().writeOutput();
+            asImp_().sdProblem2().writeOutput();
+        }
+    }
+
+
+    // \}
+
+    //! \copydoc Dumux::ImplicitProblem::name()
+    const char *name() const
+    { return simname_.c_str(); }
+
+    //! \copydoc Dumux::ImplicitProblem::setName()
+    static void setName(const char *newName)
+    { simname_ = newName; }
+
+    //! \copydoc Dumux::ImplicitProblem::timeManager()
+    TimeManager &timeManager()
+    { return timeManager_; }
+
+    //! \copydoc Dumux::ImplicitProblem::timeManager()
+    const TimeManager &timeManager() const
+    { return timeManager_; }
+
+    //! \copydoc Dumux::ImplicitProblem::newtonController()
+    NewtonController &newtonController()
+    { return newtonCtl_; }
+
+    //! \copydoc Dumux::ImplicitProblem::newtonController()
+    const NewtonController &newtonController() const
+    { return newtonCtl_; }
+
+    //! \copydoc Dumux::ImplicitProblem::model()
+    Model &model()
+    { return model_; }
+
+    //! \copydoc Dumux::ImplicitProblem::model()
+    const Model &model() const
+    { return model_; }
+    // \}
+
+    /*!
+     * \brief Returns the ID of the first domain
+     */
+    const typename MultiDomainGrid::SubDomainIndex sdID1() const
+    { return typename MultiDomainGrid::SubDomainIndex(0); }
+
+    /*!
+     * \brief Returns the ID of the second domain
+     */
+    const typename MultiDomainGrid::SubDomainIndex sdID2() const
+    { return typename MultiDomainGrid::SubDomainIndex(1); }
+
+    /*!
+     * \brief Returns a reference to subproblem1
+     */
+    SubDomainProblem1& sdProblem1()
+    { return *sdProblem1_; }
+
+    /*!
+     * \brief Returns a const reference to subproblem1
+     */
+    const SubDomainProblem1& sdProblem1() const
+    { return *sdProblem1_; }
+
+    /*!
+     * \brief Returns a reference to subproblem2
+     */
+    SubDomainProblem2& sdProblem2()
+    { return *sdProblem2_; }
+
+    /*!
+     * \brief Returns a const reference to subproblem2
+     */
+    const SubDomainProblem2& sdProblem2() const
+    { return *sdProblem2_; }
+
+    /*!
+     * \brief Returns a reference to the localresidual1
+     */
+    LocalResidual1& localResidual1()
+    { return sdProblem1().model().localResidual(); }
+
+    /*!
+     * \brief Returns a reference to the localresidual2
+     */
+    LocalResidual2& localResidual2()
+    { return sdProblem2().model().localResidual(); }
+
+    /*!
+     * \brief Returns a reference to the multidomain grid
+     */
+    MultiDomainGrid& mdGrid()
+    { return *mdGrid_; }
+
+    /*!
+     * \brief Returns a const reference to the multidomain grid
+     */
+    const MultiDomainGrid& mdGrid() const
+    { return *mdGrid_; }
+
+    /*!
+     * \brief Returns the multidomain gridview
+     */
+    const MultiDomainGridView& mdGridView() const
+    { return *mdGridView_; }
+
+    /*!
+     * \brief Returns the multidomain gridview
+     */
+    const MultiDomainGridView& gridView() const
+    { return *mdGridView_; }
+
+    /*!
+     * \brief Provides a vertex mapper for the multidomain
+     */
+    VertexMapper& mdVertexMapper()
+    { return *mdVertexMapper_; }
+
+    /*!
+     * \brief Returns a const reference to the subdomain1 grid
+     */
+    const SubDomainGrid& sdGrid1() const
+    { return mdGrid_->subDomain(sdID1()); }
+
+    /*!
+     * \brief Returns a const reference to the subdomain2 grid
+     */
+    const SubDomainGrid& sdGrid2() const
+    { return mdGrid_->subDomain(sdID2()); }
+
+    /*!
+     * \brief Returns the gridview of subdomain1
+     */
+    const SubDomainGridView1 sdGridView1() const
+    { return sdGrid1().leafGridView(); }
+
+    /*!
+     * \brief Returns the gridview of subdomain2
+     */
+    const SubDomainGridView2 sdGridView2() const
+    { return sdGrid2().leafGridView(); }
+
+    /*!
+     * \brief Returns a pointer to the subdomain1 element
+     *
+     * \param mdElement1 The multi domain element1
+     */
+    SubDomainElementPointer sdElementPointer1(const MultiDomainElement& mdElement1)
+    { return sdGrid1().subDomainEntityPointer(mdElement1); }
+
+    /*!
+     * \brief Returns a pointer to the subdomain2 element
+     *
+     * \param mdElement2 The multi domain element2
+     */
+    SubDomainElementPointer sdElementPointer2(const MultiDomainElement& mdElement2)
+    { return sdGrid2().subDomainEntityPointer(mdElement2); }
+
+
+protected:
+    void initMortarElements()
+    {}
+
+    Implementation &asImp_()
+    { return *static_cast<Implementation *>(this); }
+
+    //! \copydoc asImp_()
+    const Implementation &asImp_() const
+    { return *static_cast<const Implementation *>(this); }
+
+private:
+    // a string for the name of the current simulation, which could be
+    // set by means of an program argument, for example.
+    static std::string simname_;
+
+    TimeManager &timeManager_;
+    NewtonMethod newtonMethod_;
+    NewtonController newtonCtl_;
+
+    Model model_;
+
+    std::shared_ptr<MultiDomainGrid> mdGrid_;
+    std::shared_ptr<MultiDomainGridView> mdGridView_;
+    std::shared_ptr<VertexMapper> mdVertexMapper_;
+
+    std::shared_ptr<SubDomainProblem1> sdProblem1_;
+    std::shared_ptr<SubDomainProblem2> sdProblem2_;
+};
+
+// definition of the static class member simname_,
+// which is necessary because it is of type string.
+template <class TypeTag>
+std::string MultiDomainProblem<TypeTag>::simname_ = "simCoupled";
+
+} // namespace Dumux
+
+#endif // DUMUX_MULTIDOMAIN_PROBLEM_HH
diff --git a/dumux/multidomain/common/properties.hh b/dumux/multidomain/common/properties.hh
new file mode 100644
index 0000000000..06c04b5740
--- /dev/null
+++ b/dumux/multidomain/common/properties.hh
@@ -0,0 +1,113 @@
+// -*- 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 Properties
+ * \ingroup ImplicitProperties
+ * \ingroup MultidomainModel
+ * \brief Specify properties required for the coupled model
+ */
+#ifndef DUMUX_MULTIDOMAIN_PROPERTIES_HH
+#define DUMUX_MULTIDOMAIN_PROPERTIES_HH
+
+#include <dumux/implicit/properties.hh>
+
+namespace Dumux
+{
+
+namespace Properties
+{
+// \{
+
+//////////////////////////////////////////////////////////////////
+// Type tags tags
+//////////////////////////////////////////////////////////////////
+
+//! The type tag for problems which utilize the coupling approach
+NEW_TYPE_TAG(MultiDomain, INHERITS_FROM(ImplicitBase));
+
+//////////////////////////////////////////////////////////////////
+// Property tags
+//////////////////////////////////////////////////////////////////
+
+//! Specifies the model
+NEW_PROP_TAG(Model);
+
+//! Specifies the type tag of the first sub-problem
+NEW_PROP_TAG(SubDomain1TypeTag);
+
+//! Specifies the type tag of the second sub-problem
+NEW_PROP_TAG(SubDomain2TypeTag);
+
+//! Specifies the type tag of the other sub-problem
+NEW_PROP_TAG(OtherSubDomainTypeTag);
+
+//! Specifies the type tag of coupled problem
+NEW_PROP_TAG(MultiDomainTypeTag);
+
+//! Specifies the host grid
+NEW_PROP_TAG(Grid);
+
+//! Specifies the multidomain grid
+NEW_PROP_TAG(MultiDomainGrid);
+
+//! Specifies the number of equations in submodel 1
+NEW_PROP_TAG(NumEq1);
+
+//! Specifies the number of equations in submodel 2
+NEW_PROP_TAG(NumEq2);
+
+//! Specifies the fluidsystem that is used in the subdomains
+NEW_PROP_TAG(FluidSystem);
+
+//! the maximum allowed number of timestep divisions for the
+//! Newton solver
+NEW_PROP_TAG(NewtonMaxTimeStepDivisions);
+
+//! Specifies the multidomain grid function space
+NEW_PROP_TAG(MultiDomainGridFunctionSpace);
+
+//! Specifies the multidomain grid operator
+NEW_PROP_TAG(MultiDomainGridOperator);
+
+//! Specifies the equality conditions
+NEW_PROP_TAG(MultiDomainCondition);
+
+//! Specifies the multidomain type based subproblem for subdomain 1
+NEW_PROP_TAG(MultiDomainSubProblem1);
+
+//! Specifies the multidomain type based subproblem for subdomain 2
+NEW_PROP_TAG(MultiDomainSubProblem2);
+
+//! the local coupling operator for use with dune-multidomain
+NEW_PROP_TAG(MultiDomainCouplingLocalOperator);
+
+//! Specifies the multidomain coupling
+NEW_PROP_TAG(MultiDomainCoupling);
+
+//! Property tag for the multidomain constraints transformation
+NEW_PROP_TAG(MultiDomainConstraintsTrafo);
+
+//! the routines that are used to split and merge solution vectors
+NEW_PROP_TAG(SplitAndMerge);
+
+} // namespace Properties
+} // namespace Dumux
+
+#endif // DUMUX_MULTIDOMAIN_PROPERTIES_HH
diff --git a/dumux/multidomain/common/propertydefaults.hh b/dumux/multidomain/common/propertydefaults.hh
new file mode 100644
index 0000000000..db6a538524
--- /dev/null
+++ b/dumux/multidomain/common/propertydefaults.hh
@@ -0,0 +1,255 @@
+// -*- 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 Properties
+ * \ingroup ImplicitProperties
+ * \ingroup MultidomainModel
+ * \brief Sets default values for the MultiDomain properties
+ */
+
+#ifndef DUMUX_MULTIDOMAIN_PROPERTY_DEFAULTS_HH
+#define DUMUX_MULTIDOMAIN_PROPERTY_DEFAULTS_HH
+
+#include <dune/istl/bvector.hh>
+#include <dune/istl/bcrsmatrix.hh>
+
+#include <dune/pdelab/backend/istlvectorbackend.hh>
+#include <dune/pdelab/backend/istlmatrixbackend.hh>
+#include <dune/pdelab/multidomain/multidomaingridfunctionspace.hh>
+#include <dune/pdelab/multidomain/subproblemlocalfunctionspace.hh>
+#include <dune/pdelab/multidomain/subproblem.hh>
+#include <dune/pdelab/multidomain/subdomainset.hh>
+#include <dune/pdelab/multidomain/coupling.hh>
+#include <dune/pdelab/multidomain/gridoperator.hh>
+
+#include <dune/pdelab/gridoperator/gridoperator.hh>
+
+#include "subdomainpropertydefaults.hh"
+#include "model.hh"
+#include "properties.hh"
+#include "newtoncontroller.hh"
+#include "splitandmerge.hh"
+
+#include <dumux/common/timemanager.hh>
+#include <dumux/nonlinear/newtonmethod.hh>
+
+namespace Dumux
+{
+template <class TypeTag> class MultiDomainModel;
+template <class TypeTag> class MultiDomainAssembler;
+template <class TypeTag> class MultiDomainNewtonController;
+
+namespace Properties
+{
+
+SET_PROP(MultiDomain, MultiDomainGrid)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Grid) HostGrid;
+    typedef typename Dune::mdgrid::FewSubDomainsTraits<HostGrid::dimension,4> MDGridTraits;
+public:
+    typedef typename Dune::MultiDomainGrid<HostGrid, MDGridTraits> type;
+};
+
+SET_PROP(MultiDomain, MultiDomainGridFunctionSpace)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
+    typedef typename Dune::PDELab::LexicographicOrderingTag OrderingTag;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubTypeTag1;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubTypeTag2;
+    typedef typename GET_PROP_TYPE(SubTypeTag1, GridFunctionSpace) GridFunctionSpace1;
+    typedef typename GET_PROP_TYPE(SubTypeTag2, GridFunctionSpace) GridFunctionSpace2;
+public:
+    typedef Dune::PDELab::MultiDomain::MultiDomainGridFunctionSpace<MDGrid,
+                                                                    Dune::PDELab::ISTLVectorBackend<>,
+                                                                    OrderingTag,
+                                                                    GridFunctionSpace1,
+                                                                    GridFunctionSpace2> type;
+};
+
+// set the subdomain equality condition by default
+SET_PROP(MultiDomain, MultiDomainCondition)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGrid) MDGrid;
+public:
+    typedef Dune::PDELab::MultiDomain::SubDomainEqualityCondition<MDGrid> type;
+};
+
+SET_PROP(MultiDomain, MultiDomainSubProblem1)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MDGridFunctionSpace;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) SubTypeTag1;
+    typedef typename GET_PROP_TYPE(SubTypeTag1, Constraints) Constraints1;
+    typedef typename GET_PROP_TYPE(SubTypeTag1, LocalOperator) LocalOperator1;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCondition) MDCondition;
+    typedef typename GET_PROP_TYPE(SubTypeTag1, GridFunctionSpace) GridFunctionSpace1;
+public:
+    typedef Dune::PDELab::MultiDomain::SubProblem<MDGridFunctionSpace,
+                                                  MDGridFunctionSpace,
+                                                  LocalOperator1, MDCondition,
+                                                  0> type;
+};
+
+SET_PROP(MultiDomain, MultiDomainSubProblem2)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MDGridFunctionSpace;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) SubTypeTag2;
+    typedef typename GET_PROP_TYPE(SubTypeTag2, Constraints) Constraints2;
+    typedef typename GET_PROP_TYPE(SubTypeTag2, LocalOperator) LocalOperator2;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCondition) MDCondition;
+    typedef typename GET_PROP_TYPE(SubTypeTag2, GridFunctionSpace) GridFunctionSpace2;
+public:
+    typedef Dune::PDELab::MultiDomain::SubProblem<MDGridFunctionSpace,
+                                                  MDGridFunctionSpace,
+                                                  LocalOperator2, MDCondition,
+                                                  1> type;
+};
+
+SET_PROP(MultiDomain, MultiDomainCoupling)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem1) MDSubProblem1;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem2) MDSubProblem2;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCouplingLocalOperator) MDCouplingLocalOperator;
+public:
+    typedef Dune::PDELab::MultiDomain::Coupling<MDSubProblem1,
+                                                MDSubProblem2,
+                                                MDCouplingLocalOperator> type;
+};
+
+// set trivial constraints transformation by default
+SET_PROP(MultiDomain, MultiDomainConstraintsTrafo)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MDGridFunctionSpace;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef typename MDGridFunctionSpace::template ConstraintsContainer<Scalar>::Type type;
+};
+
+SET_PROP(MultiDomain, MultiDomainGridOperator)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridFunctionSpace) MDGridFunctionSpace;
+    typedef Dune::PDELab::ISTLMatrixBackend MBE;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem1) MDSubProblem1;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainSubProblem2) MDSubProblem2;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainCoupling) MDCoupling;
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainConstraintsTrafo) MDConstraintsTrafo;
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+public:
+    typedef Dune::PDELab::MultiDomain::GridOperator<
+                    MDGridFunctionSpace, MDGridFunctionSpace,
+                    MBE, Scalar, Scalar, Scalar,
+                    MDConstraintsTrafo, MDConstraintsTrafo,
+                    MDSubProblem1, MDSubProblem2, MDCoupling> type;
+};
+
+SET_PROP(MultiDomain, JacobianMatrix)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, MultiDomainGridOperator) MDGridOperator;
+public:
+    typedef typename MDGridOperator::Traits::Jacobian type;
+};
+
+SET_INT_PROP(MultiDomain, LinearSolverBlockSize, GET_PROP_VALUE(TypeTag, NumEq));
+
+
+// Set property values for the coupled model
+SET_TYPE_PROP(MultiDomain, Model, MultiDomainModel<TypeTag>);
+
+SET_PROP(MultiDomain, SolutionVector)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
+    enum { numEq = GET_PROP_VALUE(TypeTag, NumEq) };
+public:
+    typedef Dune::BlockVector<Dune::FieldVector<Scalar, numEq> > type;
+};
+
+// Specify the type of the multidomain assembler
+SET_TYPE_PROP(MultiDomain, JacobianAssembler, MultiDomainAssembler<TypeTag>);
+
+// use the plain newton method for the coupled problems by default
+SET_TYPE_PROP(MultiDomain, NewtonMethod, NewtonMethod<TypeTag>);
+
+// use the plain newton controller for coupled problems by default
+SET_TYPE_PROP(MultiDomain, NewtonController, MultiDomainNewtonController<TypeTag>);
+
+// Set the default type of the time manager for coupled models
+SET_TYPE_PROP(MultiDomain, TimeManager, TimeManager<TypeTag>);
+
+// needed to define size of ImplicitBase's PrimaryVariables
+SET_PROP(MultiDomain, NumEq)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) TypeTag1;
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TypeTag2;
+
+    enum {
+        numEq1 = GET_PROP_VALUE(TypeTag1, NumEq),
+        numEq2 = GET_PROP_VALUE(TypeTag2, NumEq)
+    };
+public:
+    static const int value = numEq1;
+};
+
+SET_PROP(MultiDomain, NumEq1)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain1TypeTag) TypeTag1;
+    enum {numEq = GET_PROP_VALUE(TypeTag1, NumEq)};
+public:
+    static const int value = numEq;
+};
+
+SET_PROP(MultiDomain, NumEq2)
+{
+private:
+    typedef typename GET_PROP_TYPE(TypeTag, SubDomain2TypeTag) TypeTag2;
+    enum {numEq = GET_PROP_VALUE(TypeTag2, NumEq)};
+public:
+    static const int value = numEq;
+};
+
+// set the type of the linear solver
+SET_TYPE_PROP(MultiDomain, LinearSolver, ILU0BiCGSTABBackend<TypeTag>);
+
+// set the minimum residual reduction of the linear solver
+SET_SCALAR_PROP(MultiDomain, LinearSolverResidualReduction, 1e-6);
+
+// set the default number of maximum iterations for the linear solver
+SET_INT_PROP(MultiDomain, LinearSolverMaxIterations, 250);
+
+// set the maximum time step divisions
+SET_INT_PROP(MultiDomain, NewtonMaxTimeStepDivisions, 10);
+
+// set the routines for splitting and merging solution vectors
+SET_TYPE_PROP(MultiDomain, SplitAndMerge, SplitAndMerge<TypeTag>);
+
+} // namespace Properties
+} // namespace Dumux
+
+#endif // DUMUX_MULTIDOMAIN_PROPERTY_DEFAULTS_HH
diff --git a/dumux/multidomain/common/splitandmerge.hh b/dumux/multidomain/common/splitandmerge.hh
index 7282b0de86..297971ff9c 100644
--- a/dumux/multidomain/common/splitandmerge.hh
+++ b/dumux/multidomain/common/splitandmerge.hh
@@ -23,7 +23,7 @@
 #ifndef DUMUX_SPLIT_AND_MERGE_HH
 #define DUMUX_SPLIT_AND_MERGE_HH
 
-#include "multidomainproperties.hh"
+#include "properties.hh"
 #include <dumux/common/valgrind.hh>
 
 namespace Dumux
diff --git a/dumux/multidomain/common/subdomainpropertydefaults.hh b/dumux/multidomain/common/subdomainpropertydefaults.hh
index 6d8b6f0dcb..e122717863 100644
--- a/dumux/multidomain/common/subdomainpropertydefaults.hh
+++ b/dumux/multidomain/common/subdomainpropertydefaults.hh
@@ -33,8 +33,8 @@
 #include <dune/pdelab/constraints/conforming.hh>
 
 #include "subdomainproperties.hh"
-#include "multidomainproperties.hh"
-#include "multidomainlocaloperator.hh"
+#include "properties.hh"
+#include "localoperator.hh"
 #include "boxcouplinglocalresidual.hh"
 
 namespace Dumux
diff --git a/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproblem.hh b/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproblem.hh
index 076610f943..359bd79aa9 100644
--- a/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproblem.hh
+++ b/test/multidomain/2cnistokes2p2cni/2cnistokes2p2cniproblem.hh
@@ -38,9 +38,9 @@
 #include <dune/grid/io/file/dgfparser.hh>
 
 #include <dumux/material/fluidsystems/h2oairfluidsystem.hh>
-#include <dumux/multidomain/common/multidomainproblem.hh>
-#include <dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh>
-#include <dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnipropertydefaults.hh>
+#include <dumux/multidomain/common/problem.hh>
+#include <dumux/multidomain/2cnistokes2p2cni/localoperator.hh>
+#include <dumux/multidomain/2cnistokes2p2cni/propertydefaults.hh>
 
 #include <dumux/linear/seqsolverbackend.hh>
 #ifdef HAVE_PARDISO
diff --git a/test/multidomain/2cnistokes2p2cni/2p2cnisubproblem.hh b/test/multidomain/2cnistokes2p2cni/2p2cnisubproblem.hh
index 20688c0c7b..73c664b49b 100644
--- a/test/multidomain/2cnistokes2p2cni/2p2cnisubproblem.hh
+++ b/test/multidomain/2cnistokes2p2cni/2p2cnisubproblem.hh
@@ -31,7 +31,7 @@
 #include <dumux/io/gnuplotinterface.hh>
 #include <dumux/multidomain/2cnistokes2p2cni/2p2cnicouplinglocalresidual.hh>
 #include <dumux/multidomain/common/subdomainpropertydefaults.hh>
-#include <dumux/multidomain/common/multidomainlocaloperator.hh>
+#include <dumux/multidomain/common/localoperator.hh>
 #include <dumux/material/fluidmatrixinteractions/2p/thermalconductivitysomerton.hh>
 
 #include "2cnistokes2p2cnispatialparams.hh"
diff --git a/test/multidomain/2cnizeroeq2p2cni/2cnizeroeq2p2cniproblem.hh b/test/multidomain/2cnizeroeq2p2cni/2cnizeroeq2p2cniproblem.hh
index 8809f24796..97bac6ba3a 100644
--- a/test/multidomain/2cnizeroeq2p2cni/2cnizeroeq2p2cniproblem.hh
+++ b/test/multidomain/2cnizeroeq2p2cni/2cnizeroeq2p2cniproblem.hh
@@ -29,9 +29,9 @@
 #include <dune/grid/io/file/dgfparser.hh>
 
 #include <dumux/material/fluidsystems/h2oairfluidsystem.hh>
-#include <dumux/multidomain/common/multidomainproblem.hh>
-#include <dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnilocaloperator.hh>
-#include <dumux/multidomain/2cnistokes2p2cni/2cnistokes2p2cnipropertydefaults.hh>
+#include <dumux/multidomain/common/problem.hh>
+#include <dumux/multidomain/2cnistokes2p2cni/localoperator.hh>
+#include <dumux/multidomain/2cnistokes2p2cni/propertydefaults.hh>
 
 #include "2cnizeroeq2p2cnispatialparameters.hh"
 #include "zeroeq2cnisubproblem.hh"
diff --git a/test/multidomain/2cnizeroeq2p2cni/2p2cnisubproblem.hh b/test/multidomain/2cnizeroeq2p2cni/2p2cnisubproblem.hh
index 45504fe96b..c1d002ca16 100644
--- a/test/multidomain/2cnizeroeq2p2cni/2p2cnisubproblem.hh
+++ b/test/multidomain/2cnizeroeq2p2cni/2p2cnisubproblem.hh
@@ -29,7 +29,7 @@
 #include <dumux/material/fluidmatrixinteractions/2p/thermalconductivityjohansen.hh>
 #include <dumux/material/fluidmatrixinteractions/2p/thermalconductivitysomerton.hh>
 #include <dumux/multidomain/common/subdomainpropertydefaults.hh>
-#include <dumux/multidomain/common/multidomainlocaloperator.hh>
+#include <dumux/multidomain/common/localoperator.hh>
 #include <dumux/multidomain/2cnistokes2p2cni/2p2cnicouplinglocalresidual.hh>
 
 #include "2cnizeroeq2p2cnispatialparameters.hh"
diff --git a/test/multidomain/2cstokes2p2c/2cstokes2p2cproblem.hh b/test/multidomain/2cstokes2p2c/2cstokes2p2cproblem.hh
index 2988f3bc49..5355e6319d 100644
--- a/test/multidomain/2cstokes2p2c/2cstokes2p2cproblem.hh
+++ b/test/multidomain/2cstokes2p2c/2cstokes2p2cproblem.hh
@@ -38,9 +38,9 @@
 #include <dune/grid/io/file/dgfparser.hh>
 
 #include <dumux/material/fluidsystems/h2oairfluidsystem.hh>
-#include <dumux/multidomain/common/multidomainproblem.hh>
-#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh>
-#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh>
+#include <dumux/multidomain/common/problem.hh>
+#include <dumux/multidomain/2cstokes2p2c/localoperator.hh>
+#include <dumux/multidomain/2cstokes2p2c/propertydefaults.hh>
 
 #ifdef HAVE_PARDISO
 #include <dumux/linear/pardisobackend.hh>
diff --git a/test/multidomain/2cstokes2p2c/2p2csubproblem.hh b/test/multidomain/2cstokes2p2c/2p2csubproblem.hh
index edfb76caf2..9e73ad3a82 100644
--- a/test/multidomain/2cstokes2p2c/2p2csubproblem.hh
+++ b/test/multidomain/2cstokes2p2c/2p2csubproblem.hh
@@ -30,7 +30,7 @@
 #include <dumux/porousmediumflow/implicit/problem.hh>
 #include <dumux/multidomain/2cstokes2p2c/2p2ccouplinglocalresidual.hh>
 #include <dumux/multidomain/common/subdomainpropertydefaults.hh>
-#include <dumux/multidomain/common/multidomainlocaloperator.hh>
+#include <dumux/multidomain/common/localoperator.hh>
 
 #include "2cstokes2p2cspatialparams.hh"
 
diff --git a/test/multidomain/2czeroeq2p2c/2czeroeq2p2cproblem.hh b/test/multidomain/2czeroeq2p2c/2czeroeq2p2cproblem.hh
index 8254b1fffc..a03d43dc1f 100644
--- a/test/multidomain/2czeroeq2p2c/2czeroeq2p2cproblem.hh
+++ b/test/multidomain/2czeroeq2p2c/2czeroeq2p2cproblem.hh
@@ -29,9 +29,9 @@
 #include <dune/grid/io/file/dgfparser.hh>
 
 #include <dumux/material/fluidsystems/h2oairfluidsystem.hh>
-#include <dumux/multidomain/common/multidomainproblem.hh>
-#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2clocaloperator.hh>
-#include <dumux/multidomain/2cstokes2p2c/2cstokes2p2cpropertydefaults.hh>
+#include <dumux/multidomain/common/problem.hh>
+#include <dumux/multidomain/2cstokes2p2c/localoperator.hh>
+#include <dumux/multidomain/2cstokes2p2c/propertydefaults.hh>
 
 #include "2czeroeq2p2cspatialparameters.hh"
 #include "zeroeq2csubproblem.hh"
diff --git a/test/multidomain/2czeroeq2p2c/2p2csubproblem.hh b/test/multidomain/2czeroeq2p2c/2p2csubproblem.hh
index f7a26669f0..1ab0ca40a3 100644
--- a/test/multidomain/2czeroeq2p2c/2p2csubproblem.hh
+++ b/test/multidomain/2czeroeq2p2c/2p2csubproblem.hh
@@ -28,7 +28,7 @@
 #include <dumux/porousmediumflow/2p2c/implicit/indices.hh>
 #include <dumux/porousmediumflow/implicit/problem.hh>
 #include <dumux/multidomain/common/subdomainpropertydefaults.hh>
-#include <dumux/multidomain/common/multidomainlocaloperator.hh>
+#include <dumux/multidomain/common/localoperator.hh>
 #include <dumux/multidomain/2cstokes2p2c/2p2ccouplinglocalresidual.hh>
 
 #include "2czeroeq2p2cspatialparameters.hh"
-- 
GitLab