From 440692db6a2eae4834428ccd007c72b25284c18f Mon Sep 17 00:00:00 2001
From: Kilian Weishaupt <kilian.weishaupt@iws.uni-stuttgart.de>
Date: Thu, 6 Dec 2018 10:56:16 +0100
Subject: [PATCH] [ff-pnm] Update first exercise

---
 .../1pspatialparams.hh                        | 12 ++--
 .../2pspatialparams.hh                        | 12 ++--
 exercises/exercise-coupling-ff-pm/README.md   | 10 +++-
 .../interface/ex_interface_coupling_ff-pm.cc  | 53 +++++++++--------
 .../ex_interface_coupling_ff-pm.input         |  1 +
 .../interface/ex_interface_ffproblem.hh       | 58 +++++++++++--------
 .../interface/ex_interface_pmproblem.hh       | 43 ++++++++------
 .../1pspatialparams.hh                        | 12 ++--
 .../2pspatialparams.hh                        | 12 ++--
 .../interface/ex_interface_coupling_ff-pm.cc  | 23 ++++----
 .../ex_interface_coupling_ff-pm.input         |  1 +
 .../interface/ex_interface_ffproblem.hh       | 19 +++---
 .../interface/ex_interface_pmproblem.hh       |  2 +-
 13 files changed, 138 insertions(+), 120 deletions(-)

diff --git a/exercises/exercise-coupling-ff-pm/1pspatialparams.hh b/exercises/exercise-coupling-ff-pm/1pspatialparams.hh
index 64887e33..e95c2491 100644
--- a/exercises/exercise-coupling-ff-pm/1pspatialparams.hh
+++ b/exercises/exercise-coupling-ff-pm/1pspatialparams.hh
@@ -38,14 +38,14 @@ namespace Dumux
  */
 template<class TypeTag>
 class OnePSpatialParams
-: public FVSpatialParamsOneP<typename GET_PROP_TYPE(TypeTag, FVGridGeometry),
-                             typename GET_PROP_TYPE(TypeTag, Scalar),
+: public FVSpatialParamsOneP<GetPropType<TypeTag, Properties::FVGridGeometry>,
+                             GetPropType<TypeTag, Properties::Scalar>,
                              OnePSpatialParams<TypeTag>>
 {
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using Problem = GetPropType<TypeTag, Properties::Problem>;
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
     using ParentType = FVSpatialParamsOneP<FVGridGeometry, Scalar, OnePSpatialParams<TypeTag>>;
 
     using Element = typename GridView::template Codim<0>::Entity;
diff --git a/exercises/exercise-coupling-ff-pm/2pspatialparams.hh b/exercises/exercise-coupling-ff-pm/2pspatialparams.hh
index 1830f3cb..948b7a7b 100644
--- a/exercises/exercise-coupling-ff-pm/2pspatialparams.hh
+++ b/exercises/exercise-coupling-ff-pm/2pspatialparams.hh
@@ -40,15 +40,15 @@ namespace Dumux
  */
 template<class TypeTag>
 class TwoPSpatialParams
-: public FVSpatialParams<typename GET_PROP_TYPE(TypeTag, FVGridGeometry),
-                         typename GET_PROP_TYPE(TypeTag, Scalar),
+: public FVSpatialParams<GetPropType<TypeTag, Properties::FVGridGeometry>,
+                         GetPropType<TypeTag, Properties::Scalar>,
                          TwoPSpatialParams<TypeTag>>
 {
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using Problem = GetPropType<TypeTag, Properties::Problem>;
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
     using Element = typename GridView::template Codim<0>::Entity;
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
     using FVElementGeometry = typename FVGridGeometry::LocalView;
     using SubControlVolume = typename FVElementGeometry::SubControlVolume;
     using ParentType = FVSpatialParams<FVGridGeometry, Scalar, TwoPSpatialParams<TypeTag>>;
diff --git a/exercises/exercise-coupling-ff-pm/README.md b/exercises/exercise-coupling-ff-pm/README.md
index 58b75459..ec4e22aa 100644
--- a/exercises/exercise-coupling-ff-pm/README.md
+++ b/exercises/exercise-coupling-ff-pm/README.md
@@ -83,6 +83,7 @@ if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf))
 {
     values.setCouplingNeumann(Indices::conti0EqIdx);
     values.setCouplingNeumann(Indices::momentumYBalanceIdx);
+    values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface
 }
 ```
 
@@ -123,7 +124,11 @@ $`\frac{\partial v_x}{\partial y} = \frac{\alpha}{\sqrt K} (v_x - q_{pm})\quad`$
 
 with  $`\quad q_{pm}=0`$.
 
-To include this, just set a Beavers-Joseph-Saffman (BJS) boundary condition for the respective momentum balance:
+To include this, just replace the no-slip condition at the interface
+``` cpp
+values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface
+```
+with a Beavers-Joseph-Saffman (BJS) boundary condition for the respective momentum balance:
 ``` cpp
 values.setBJS(Indices::momentumXBalanceIdx);
 ```
@@ -223,7 +228,8 @@ liquid saturation as primary variables (p_g-S_l -> `p1s0`) or vice versa.
 * Set the property
 
 ```
-SET_PROP(DarcyTypeTag, Formulation)
+template<class TypeTag>
+struct Formulation<TypeTag, TTag::DarcyTypeTag>
 { static constexpr auto value = TwoPFormulation::p1s0; };
 ```
   in the Properties section in the problem file.
diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc
index 85226b99..62673d5a 100644
--- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc
+++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc
@@ -31,10 +31,11 @@
 #include <dumux/common/properties.hh>
 #include <dumux/common/parameters.hh>
 #include <dumux/common/dumuxmessage.hh>
+#include <dumux/common/partial.hh>
 #include <dumux/linear/seqsolverbackend.hh>
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
-#include <dumux/discretization/methods.hh>
+#include <dumux/discretization/method.hh>
 #include <dumux/io/vtkoutputmodule.hh>
 #include <dumux/io/staggeredvtkoutputmodule.hh>
 #include <dumux/io/grid/gridmanager.hh>
@@ -51,15 +52,17 @@
 namespace Dumux {
 namespace Properties {
 
-SET_PROP(StokesOnePTypeTag, CouplingManager)
+template<class TypeTag>
+struct CouplingManager<TypeTag, TTag::StokesOnePTypeTag>
 {
-    using Traits = StaggeredMultiDomainTraits<TypeTag, TypeTag, TTAG(DarcyOnePTypeTag)>;
+    using Traits = StaggeredMultiDomainTraits<TypeTag, TypeTag, Properties::TTag::DarcyOnePTypeTag>;
     using type = Dumux::StokesDarcyCouplingManager<Traits>;
 };
 
-SET_PROP(DarcyOnePTypeTag, CouplingManager)
+template<class TypeTag>
+struct CouplingManager<TypeTag, TTag::DarcyOnePTypeTag>
 {
-    using Traits = StaggeredMultiDomainTraits<TTAG(StokesOnePTypeTag), TTAG(StokesOnePTypeTag), TypeTag>;
+    using Traits = StaggeredMultiDomainTraits<Properties::TTag::StokesOnePTypeTag, Properties::TTag::StokesOnePTypeTag, TypeTag>;
     using type = Dumux::StokesDarcyCouplingManager<Traits>;
 };
 
@@ -81,8 +84,8 @@ int main(int argc, char** argv) try
     Parameters::init(argc, argv);
 
     // Define the sub problem type tags
-    using StokesTypeTag = TTAG(StokesOnePTypeTag);
-    using DarcyTypeTag = TTAG(DarcyOnePTypeTag);
+    using StokesTypeTag = Properties::TTag::StokesOnePTypeTag;
+    using DarcyTypeTag = Properties::TTag::DarcyOnePTypeTag;
 
 
 
@@ -90,11 +93,11 @@ int main(int argc, char** argv) try
 
     // create two individual grids (from the given grid file or the input file)
     // for both sub-domains
-    using DarcyGridManager = Dumux::GridManager<typename GET_PROP_TYPE(DarcyTypeTag, Grid)>;
+    using DarcyGridManager = Dumux::GridManager<GetPropType<DarcyTypeTag, Properties::Grid>>;
     DarcyGridManager darcyGridManager;
     darcyGridManager.init("Darcy"); // pass parameter group
 
-    using StokesGridManager = Dumux::GridManager<typename GET_PROP_TYPE(StokesTypeTag, Grid)>;
+    using StokesGridManager = Dumux::GridManager<GetPropType<StokesTypeTag, Properties::Grid>>;
     StokesGridManager stokesGridManager;
     stokesGridManager.init("Stokes"); // pass parameter group
 
@@ -149,10 +152,10 @@ int main(int argc, char** argv) try
 
 
     // create the finite volume grid geometry
-    using StokesFVGridGeometry = typename GET_PROP_TYPE(StokesTypeTag, FVGridGeometry);
+    using StokesFVGridGeometry = GetPropType<StokesTypeTag, Properties::FVGridGeometry>;
     auto stokesFvGridGeometry = std::make_shared<StokesFVGridGeometry>(stokesGridView);
     stokesFvGridGeometry->update();
-    using DarcyFVGridGeometry = typename GET_PROP_TYPE(DarcyTypeTag, FVGridGeometry);
+    using DarcyFVGridGeometry = GetPropType<DarcyTypeTag, Properties::FVGridGeometry>;
     auto darcyFvGridGeometry = std::make_shared<DarcyFVGridGeometry>(darcyGridView);
     darcyFvGridGeometry->update();
 
@@ -168,9 +171,9 @@ int main(int argc, char** argv) try
     constexpr auto darcyIdx = CouplingManager::darcyIdx;
 
     // the problem (initial and boundary conditions)
-    using StokesProblem = typename GET_PROP_TYPE(StokesTypeTag, Problem);
+    using StokesProblem = GetPropType<StokesTypeTag, Properties::Problem>;
     auto stokesProblem = std::make_shared<StokesProblem>(stokesFvGridGeometry, couplingManager);
-    using DarcyProblem = typename GET_PROP_TYPE(DarcyTypeTag, Problem);
+    using DarcyProblem = GetPropType<DarcyTypeTag, Properties::Problem>;
     auto darcyProblem = std::make_shared<DarcyProblem>(darcyFvGridGeometry, couplingManager);
 
     // the solution vector
@@ -179,24 +182,18 @@ int main(int argc, char** argv) try
     sol[stokesFaceIdx].resize(stokesFvGridGeometry->numFaceDofs());
     sol[darcyIdx].resize(darcyFvGridGeometry->numDofs());
 
-    const auto& cellCenterSol = sol[stokesCellCenterIdx];
-    const auto& faceSol = sol[stokesFaceIdx];
+    auto stokesSol = partial(sol, stokesCellCenterIdx, stokesFaceIdx);
 
-    // apply initial solution for instationary problems
-    typename GET_PROP_TYPE(StokesTypeTag, SolutionVector) stokesSol;
-    std::get<0>(stokesSol) = cellCenterSol;
-    std::get<1>(stokesSol) = faceSol;
     stokesProblem->applyInitialSolution(stokesSol);
-    sol[stokesCellCenterIdx] = stokesSol[stokesCellCenterIdx];
-    sol[stokesFaceIdx] = stokesSol[stokesFaceIdx];
+    darcyProblem->applyInitialSolution(sol[darcyIdx]);
 
     couplingManager->init(stokesProblem, darcyProblem, sol);
 
     // the grid variables
-    using StokesGridVariables = typename GET_PROP_TYPE(StokesTypeTag, GridVariables);
+    using StokesGridVariables = GetPropType<StokesTypeTag, Properties::GridVariables>;
     auto stokesGridVariables = std::make_shared<StokesGridVariables>(stokesProblem, stokesFvGridGeometry);
     stokesGridVariables->init(stokesSol);
-    using DarcyGridVariables = typename GET_PROP_TYPE(DarcyTypeTag, GridVariables);
+    using DarcyGridVariables = GetPropType<DarcyTypeTag, Properties::GridVariables>;
     auto darcyGridVariables = std::make_shared<DarcyGridVariables>(darcyProblem, darcyFvGridGeometry);
     darcyGridVariables->init(sol[darcyIdx]);
 
@@ -204,16 +201,18 @@ int main(int argc, char** argv) try
     const auto stokesName = getParam<std::string>("Problem.Name") + "_" + stokesProblem->name();
     const auto darcyName = getParam<std::string>("Problem.Name") + "_" + darcyProblem->name();
 
-    StaggeredVtkOutputModule<StokesTypeTag> stokesVtkWriter(*stokesProblem, *stokesFvGridGeometry, *stokesGridVariables, stokesSol, stokesName);
-    GET_PROP_TYPE(StokesTypeTag, VtkOutputFields)::init(stokesVtkWriter);
+    StaggeredVtkOutputModule<StokesGridVariables, decltype(stokesSol)> stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName);
+    GetPropType<StokesTypeTag, Properties::VtkOutputFields>::initOutputModule(stokesVtkWriter);
 
     //****** uncomment the add analytical solution of v_x *****//
     // stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x");
 
     stokesVtkWriter.write(0.0);
 
-    VtkOutputModule<DarcyTypeTag> darcyVtkWriter(*darcyProblem, *darcyFvGridGeometry, *darcyGridVariables, sol[darcyIdx], darcyName);
-    GET_PROP_TYPE(DarcyTypeTag, VtkOutputFields)::init(darcyVtkWriter);
+    VtkOutputModule<DarcyGridVariables, GetPropType<DarcyTypeTag, Properties::SolutionVector>> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName);
+    using DarcyVelocityOutput = GetPropType<DarcyTypeTag, Properties::VelocityOutput>;
+    darcyVtkWriter.addVelocityOutput(std::make_shared<DarcyVelocityOutput>(*darcyGridVariables));
+    GetPropType<DarcyTypeTag, Properties::IOFields>::initOutputModule(darcyVtkWriter);
     darcyVtkWriter.write(0.0);
 
     // the assembler for a stationary problem
diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input
index e3813950..4117b7f1 100644
--- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input
+++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input
@@ -28,6 +28,7 @@ Grading1 = 1
 [Stokes.Problem]
 Name = stokes
 PressureDifference = 1e-9
+EnableInertiaTerms = false
 
 [Darcy.Problem]
 Name = darcy
diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh b/exercises/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh
index 48d29d66..c5649a77 100644
--- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh
+++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh
@@ -42,20 +42,25 @@ class StokesSubProblem;
 
 namespace Properties
 {
-NEW_TYPE_TAG(StokesOnePTypeTag, INHERITS_FROM(StaggeredFreeFlowModel, NavierStokes));
+// Create new type tags
+namespace TTag {
+struct StokesOnePTypeTag { using InheritsFrom = std::tuple<NavierStokes, StaggeredFreeFlowModel>; };
+} // end namespace TTag
 
 // the fluid system
-SET_PROP(StokesOnePTypeTag, FluidSystem)
+template<class TypeTag>
+struct FluidSystem<TypeTag, TTag::StokesOnePTypeTag>
 {
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
     using type = FluidSystems::OnePLiquid<Scalar, Dumux::Components::SimpleH2O<Scalar> > ;
 };
 
 // Set the grid type
-SET_PROP(StokesOnePTypeTag, Grid)
+template<class TypeTag>
+struct Grid<TypeTag, TTag::StokesOnePTypeTag>
 {
     static constexpr auto dim = 2;
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
     using TensorGrid = Dune::YaspGrid<2, Dune::TensorProductCoordinates<Scalar, dim> >;
 
 //****** comment out for the last exercise *****//
@@ -67,13 +72,15 @@ SET_PROP(StokesOnePTypeTag, Grid)
 };
 
 // Set the problem property
-SET_TYPE_PROP(StokesOnePTypeTag, Problem, Dumux::StokesSubProblem<TypeTag> );
-
-SET_BOOL_PROP(StokesOnePTypeTag, EnableFVGridGeometryCache, true);
-SET_BOOL_PROP(StokesOnePTypeTag, EnableGridFluxVariablesCache, true);
-SET_BOOL_PROP(StokesOnePTypeTag, EnableGridVolumeVariablesCache, true);
-
-SET_BOOL_PROP(StokesOnePTypeTag, EnableInertiaTerms, false);
+template<class TypeTag>
+struct Problem<TypeTag, TTag::StokesOnePTypeTag> { using type = Dumux::StokesSubProblem<TypeTag> ; };
+
+template<class TypeTag>
+struct EnableFVGridGeometryCache<TypeTag, TTag::StokesOnePTypeTag> { static constexpr bool value = true; };
+template<class TypeTag>
+struct EnableGridFluxVariablesCache<TypeTag, TTag::StokesOnePTypeTag> { static constexpr bool value = true; };
+template<class TypeTag>
+struct EnableGridVolumeVariablesCache<TypeTag, TTag::StokesOnePTypeTag> { static constexpr bool value = true; };
 }
 
 /*!
@@ -84,25 +91,25 @@ class StokesSubProblem : public NavierStokesProblem<TypeTag>
 {
     using ParentType = NavierStokesProblem<TypeTag>;
 
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
 
-    using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
+    using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
 
-    using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
+    using BoundaryTypes = GetPropType<TypeTag, Properties::BoundaryTypes>;
 
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
     using FVElementGeometry = typename FVGridGeometry::LocalView;
     using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
     using Element = typename GridView::template Codim<0>::Entity;
 
     using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
 
-    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
-    using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
+    using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+    using NumEqVector = GetPropType<TypeTag, Properties::NumEqVector>;
+    using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
 
-    using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager);
+    using CouplingManager = GetPropType<TypeTag, Properties::CouplingManager>;
 
 public:
     StokesSubProblem(std::shared_ptr<const FVGridGeometry> fvGridGeometry, std::shared_ptr<CouplingManager> couplingManager)
@@ -170,6 +177,7 @@ public:
         {
             values.setCouplingNeumann(Indices::conti0EqIdx);
             values.setCouplingNeumann(Indices::momentumYBalanceIdx);
+            values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface
         }
 
         return values;
@@ -208,8 +216,8 @@ public:
 
         if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf))
         {
-            values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf);
-            values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf);
+            values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf);
+            values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf);
         }
 
         return values;
@@ -246,9 +254,9 @@ public:
     /*!
      * \brief Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition
      */
-    Scalar permeability(const SubControlVolumeFace& scvf) const
+    Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const
     {
-        return couplingManager().couplingData().darcyPermeability(scvf);
+        return couplingManager().couplingData().darcyPermeability(element, scvf);
     }
 
     /*!
diff --git a/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh b/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh
index 8b9f7495..e447100c 100644
--- a/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh
+++ b/exercises/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh
@@ -46,23 +46,29 @@ class DarcySubProblem;
 
 namespace Properties
 {
-NEW_TYPE_TAG(DarcyOnePTypeTag, INHERITS_FROM(CCTpfaModel, OneP));
+// Create new type tags
+namespace TTag {
+struct DarcyOnePTypeTag { using InheritsFrom = std::tuple<OneP, CCTpfaModel>; };
+} // end namespace TTag
 
 // Set the problem property
-SET_TYPE_PROP(DarcyOnePTypeTag, Problem, Dumux::DarcySubProblem<TypeTag>);
+template<class TypeTag>
+struct Problem<TypeTag, TTag::DarcyOnePTypeTag> { using type = Dumux::DarcySubProblem<TypeTag>; };
 
 // the fluid system
-SET_PROP(DarcyOnePTypeTag, FluidSystem)
+template<class TypeTag>
+struct FluidSystem<TypeTag, TTag::DarcyOnePTypeTag>
 {
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
     using type = FluidSystems::OnePLiquid<Scalar, Dumux::Components::SimpleH2O<Scalar> > ;
 };
 
 // Set the grid type
-SET_PROP(DarcyOnePTypeTag, Grid)
+template<class TypeTag>
+struct Grid<TypeTag, TTag::DarcyOnePTypeTag>
 {
     static constexpr auto dim = 2;
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
     using TensorGrid = Dune::YaspGrid<2, Dune::TensorProductCoordinates<Scalar, dim> >;
 
 //****** comment out for the last exercise *****//
@@ -73,7 +79,8 @@ SET_PROP(DarcyOnePTypeTag, Grid)
     // using type = Dune::SubGrid<dim, HostGrid>;
 };
 
-SET_TYPE_PROP(DarcyOnePTypeTag, SpatialParams, OnePSpatialParams<TypeTag>);
+template<class TypeTag>
+struct SpatialParams<TypeTag, TTag::DarcyOnePTypeTag> { using type = OnePSpatialParams<TypeTag>; };
 }
 
 /*!
@@ -83,23 +90,23 @@ template <class TypeTag>
 class DarcySubProblem : public PorousMediumFlowProblem<TypeTag>
 {
     using ParentType = PorousMediumFlowProblem<TypeTag>;
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
-    using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
-    using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
-    using VolumeVariables = typename GET_PROP_TYPE(TypeTag, VolumeVariables);
-    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView;
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+    using NumEqVector = GetPropType<TypeTag, Properties::NumEqVector>;
+    using BoundaryTypes = GetPropType<TypeTag, Properties::BoundaryTypes>;
+    using VolumeVariables = GetPropType<TypeTag, Properties::VolumeVariables>;
+    using FVElementGeometry = typename GetPropType<TypeTag, Properties::FVGridGeometry>::LocalView;
     using SubControlVolume = typename FVElementGeometry::SubControlVolume;
     using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace;
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
 
-    using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
+    using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
 
     using Element = typename GridView::template Codim<0>::Entity;
     using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
 
-    using CouplingManager = typename GET_PROP_TYPE(TypeTag, CouplingManager);
+    using CouplingManager = GetPropType<TypeTag, Properties::CouplingManager>;
 
 public:
     DarcySubProblem(std::shared_ptr<const FVGridGeometry> fvGridGeometry,
@@ -188,7 +195,7 @@ public:
 
         // ... except at the coupling interface
         if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf))
-            values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf);
+            values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf);
 
         return values;
     }
diff --git a/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh b/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh
index 64887e33..e95c2491 100644
--- a/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh
+++ b/exercises/solution/exercise-coupling-ff-pm/1pspatialparams.hh
@@ -38,14 +38,14 @@ namespace Dumux
  */
 template<class TypeTag>
 class OnePSpatialParams
-: public FVSpatialParamsOneP<typename GET_PROP_TYPE(TypeTag, FVGridGeometry),
-                             typename GET_PROP_TYPE(TypeTag, Scalar),
+: public FVSpatialParamsOneP<GetPropType<TypeTag, Properties::FVGridGeometry>,
+                             GetPropType<TypeTag, Properties::Scalar>,
                              OnePSpatialParams<TypeTag>>
 {
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using Problem = GetPropType<TypeTag, Properties::Problem>;
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
     using ParentType = FVSpatialParamsOneP<FVGridGeometry, Scalar, OnePSpatialParams<TypeTag>>;
 
     using Element = typename GridView::template Codim<0>::Entity;
diff --git a/exercises/solution/exercise-coupling-ff-pm/2pspatialparams.hh b/exercises/solution/exercise-coupling-ff-pm/2pspatialparams.hh
index 1830f3cb..948b7a7b 100644
--- a/exercises/solution/exercise-coupling-ff-pm/2pspatialparams.hh
+++ b/exercises/solution/exercise-coupling-ff-pm/2pspatialparams.hh
@@ -40,15 +40,15 @@ namespace Dumux
  */
 template<class TypeTag>
 class TwoPSpatialParams
-: public FVSpatialParams<typename GET_PROP_TYPE(TypeTag, FVGridGeometry),
-                         typename GET_PROP_TYPE(TypeTag, Scalar),
+: public FVSpatialParams<GetPropType<TypeTag, Properties::FVGridGeometry>,
+                         GetPropType<TypeTag, Properties::Scalar>,
                          TwoPSpatialParams<TypeTag>>
 {
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using Problem = GetPropType<TypeTag, Properties::Problem>;
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
     using Element = typename GridView::template Codim<0>::Entity;
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
     using FVElementGeometry = typename FVGridGeometry::LocalView;
     using SubControlVolume = typename FVElementGeometry::SubControlVolume;
     using ParentType = FVSpatialParams<FVGridGeometry, Scalar, TwoPSpatialParams<TypeTag>>;
diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc
index 116ed7e2..84434750 100644
--- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc
+++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.cc
@@ -31,10 +31,11 @@
 #include <dumux/common/properties.hh>
 #include <dumux/common/parameters.hh>
 #include <dumux/common/dumuxmessage.hh>
+#include <dumux/common/partial.hh>
 #include <dumux/linear/seqsolverbackend.hh>
 #include <dumux/assembly/fvassembler.hh>
 #include <dumux/assembly/diffmethod.hh>
-#include <dumux/discretization/methods.hh>
+#include <dumux/discretization/method.hh>
 #include <dumux/io/vtkoutputmodule.hh>
 #include <dumux/io/staggeredvtkoutputmodule.hh>
 #include <dumux/io/grid/gridmanager.hh>
@@ -171,16 +172,10 @@ int main(int argc, char** argv) try
     sol[stokesFaceIdx].resize(stokesFvGridGeometry->numFaceDofs());
     sol[darcyIdx].resize(darcyFvGridGeometry->numDofs());
 
-    const auto& cellCenterSol = sol[stokesCellCenterIdx];
-    const auto& faceSol = sol[stokesFaceIdx];
+    auto stokesSol = partial(sol, stokesCellCenterIdx, stokesFaceIdx);
 
-    // apply initial solution for instationary problems
-    typename GET_PROP_TYPE(StokesTypeTag, SolutionVector) stokesSol;
-    std::get<0>(stokesSol) = cellCenterSol;
-    std::get<1>(stokesSol) = faceSol;
     stokesProblem->applyInitialSolution(stokesSol);
-    sol[stokesCellCenterIdx] = stokesSol[stokesCellCenterIdx];
-    sol[stokesFaceIdx] = stokesSol[stokesFaceIdx];
+    darcyProblem->applyInitialSolution(sol[darcyIdx]);
 
     couplingManager->init(stokesProblem, darcyProblem, sol);
 
@@ -196,8 +191,8 @@ int main(int argc, char** argv) try
     const auto stokesName = getParam<std::string>("Problem.Name") + "_" + stokesProblem->name();
     const auto darcyName = getParam<std::string>("Problem.Name") + "_" + darcyProblem->name();
 
-    StaggeredVtkOutputModule<StokesTypeTag> stokesVtkWriter(*stokesProblem, *stokesFvGridGeometry, *stokesGridVariables, stokesSol, stokesName);
-    GET_PROP_TYPE(StokesTypeTag, VtkOutputFields)::init(stokesVtkWriter);
+    StaggeredVtkOutputModule<StokesGridVariables, decltype(stokesSol)> stokesVtkWriter(*stokesGridVariables, stokesSol, stokesName);
+    GetPropType<StokesTypeTag, Properties::VtkOutputFields>::initOutputModule(stokesVtkWriter);
 
 #if EXNUMBER >= 2
     stokesVtkWriter.addField(stokesProblem->getAnalyticalVelocityX(), "analyticalV_x");
@@ -205,8 +200,10 @@ int main(int argc, char** argv) try
 
     stokesVtkWriter.write(0.0);
 
-    VtkOutputModule<DarcyTypeTag> darcyVtkWriter(*darcyProblem, *darcyFvGridGeometry, *darcyGridVariables, sol[darcyIdx], darcyName);
-    GET_PROP_TYPE(DarcyTypeTag, VtkOutputFields)::init(darcyVtkWriter);
+    VtkOutputModule<DarcyGridVariables, GetPropType<DarcyTypeTag, Properties::SolutionVector>> darcyVtkWriter(*darcyGridVariables, sol[darcyIdx], darcyName);
+    using DarcyVelocityOutput = GetPropType<DarcyTypeTag, Properties::VelocityOutput>;
+    darcyVtkWriter.addVelocityOutput(std::make_shared<DarcyVelocityOutput>(*darcyGridVariables));
+    GetPropType<DarcyTypeTag, Properties::IOFields>::initOutputModule(darcyVtkWriter);
     darcyVtkWriter.write(0.0);
 
     // the assembler for a stationary problem
diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input
index e3813950..4117b7f1 100644
--- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input
+++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_coupling_ff-pm.input
@@ -28,6 +28,7 @@ Grading1 = 1
 [Stokes.Problem]
 Name = stokes
 PressureDifference = 1e-9
+EnableInertiaTerms = false
 
 [Darcy.Problem]
 Name = darcy
diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh
index 369a7bd2..c0dc4557 100644
--- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh
+++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_ffproblem.hh
@@ -74,7 +74,6 @@ SET_BOOL_PROP(StokesOnePTypeTag, EnableFVGridGeometryCache, true);
 SET_BOOL_PROP(StokesOnePTypeTag, EnableGridFluxVariablesCache, true);
 SET_BOOL_PROP(StokesOnePTypeTag, EnableGridVolumeVariablesCache, true);
 
-SET_BOOL_PROP(StokesOnePTypeTag, EnableInertiaTerms, false);
 }
 
 /*!
@@ -185,12 +184,12 @@ public:
             values.setCouplingNeumann(scvf.directionIndex());
 #endif
 
-#if EXNUMBER == 2
+#if EXNUMBER < 2
+            values.setDirichlet(Indices::velocityXIdx); // assume no slip on interface
+#elif EXNUMBER == 2
             // set the Beaver-Joseph-Saffman slip condition for the tangential momentum balance equation
             values.setBJS(Indices::momentumXBalanceIdx);
-#endif
-
-#if EXNUMBER == 3
+#else
             // set the Beaver-Joseph-Saffman slip condition for the tangential momentum balance equation,
             // consider orientation of face automatically
             values.setBJS(1 - scvf.directionIndex());
@@ -233,11 +232,11 @@ public:
 
         if(couplingManager().isCoupledEntity(CouplingManager::stokesIdx, scvf))
         {
-            values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf);
+            values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf);
 #if EXNUMBER < 3
-            values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf);
+            values[Indices::momentumYBalanceIdx] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf);
 #else
-            values[scvf.directionIndex()] = couplingManager().couplingData().momentumCouplingCondition(fvGeometry, elemVolVars, elemFaceVars, scvf);
+            values[scvf.directionIndex()] = couplingManager().couplingData().momentumCouplingCondition(element, fvGeometry, elemVolVars, elemFaceVars, scvf);
 #endif
 
         }
@@ -283,9 +282,9 @@ public:
     /*!
      * \brief Returns the intrinsic permeability of required as input parameter for the Beavers-Joseph-Saffman boundary condition
      */
-    Scalar permeability(const SubControlVolumeFace& scvf) const
+    Scalar permeability(const Element& element, const SubControlVolumeFace& scvf) const
     {
-        return couplingManager().couplingData().darcyPermeability(scvf);
+        return couplingManager().couplingData().darcyPermeability(element, scvf);
     }
 
     /*!
diff --git a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh
index d78c76f0..3549ff03 100644
--- a/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh
+++ b/exercises/solution/exercise-coupling-ff-pm/interface/ex_interface_pmproblem.hh
@@ -184,7 +184,7 @@ public:
         NumEqVector values(0.0);
 
         if (couplingManager().isCoupledEntity(CouplingManager::darcyIdx, scvf))
-            values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(fvGeometry, elemVolVars, scvf);
+            values[Indices::conti0EqIdx] = couplingManager().couplingData().massCouplingCondition(element, fvGeometry, elemVolVars, scvf);
 
         return values;
     }
-- 
GitLab