diff --git a/exercises/exercise-basic/README.md b/exercises/exercise-basic/README.md
index 8aee3292b4f5fc7e87d5e474f241aa70c50fbbf9..cc81fd40918b369e1a2aeafce156083ae7189251 100644
--- a/exercises/exercise-basic/README.md
+++ b/exercises/exercise-basic/README.md
@@ -60,7 +60,7 @@ paraview injection-2p2c.pvd
 
 * Copy the main file `exercise_basic_2p.cc` and rename it to `exercise_basic_2pni.cc`
 * In  `exercise_basic_2pni.cc`, include the header `injection2pniproblem.hh` instead of `injection2pproblem.hh`.
-* In  `exercise_basic_2pni.cc`, change `Injection2pCCTypeTag` to `Injection2pNICCTypeTag` in the line `using TypeTag = TTAG(Injection2pCCTypeTag);`
+* In  `exercise_basic_2pni.cc`, change `Injection2pCCTypeTag` to `Injection2pNICCTypeTag` in the line `using TypeTag = Properties::TTag::Injection2pNICCTypeTag;`
 * Add a new executable in `CMakeLists.txt` by adding the lines
 
 ```cmake
diff --git a/exercises/exercise-basic/exercise_basic_2p.cc b/exercises/exercise-basic/exercise_basic_2p.cc
index 88f18f84da4bccded1a97b48ccf2bab040369909..babdd6785167f3d519fa9dc664aff95b0dc551bd 100644
--- a/exercises/exercise-basic/exercise_basic_2p.cc
+++ b/exercises/exercise-basic/exercise_basic_2p.cc
@@ -41,10 +41,11 @@
 #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/grid/gridmanager.hh>
+#include <dumux/io/loadsolution.hh>
 
 // The problem file, where setup-specific boundary and initial conditions are defined.
 #include "injection2pproblem.hh"
@@ -57,7 +58,7 @@ int main(int argc, char** argv) try
     using namespace Dumux;
 
     // define the type tag for this problem
-    using TypeTag = TTAG(Injection2pCCTypeTag);
+    using TypeTag = Properties::TTag::Injection2pCCTypeTag;
 
     // initialize MPI, finalize is done automatically on exit
     const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv);
@@ -70,7 +71,7 @@ int main(int argc, char** argv) try
     Parameters::init(argc, argv);
 
     // try to create a grid (from the given grid file or the input file)
-    GridManager<typename GET_PROP_TYPE(TypeTag, Grid)> gridManager;
+    GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
     gridManager.init();
 
     ////////////////////////////////////////////////////////////
@@ -81,35 +82,57 @@ int main(int argc, char** argv) try
     const auto& leafGridView = gridManager.grid().leafGridView();
 
     // create the finite volume grid geometry
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
     auto fvGridGeometry = std::make_shared<FVGridGeometry>(leafGridView);
     fvGridGeometry->update();
 
     // the problem (initial and boundary conditions)
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using Problem = GetPropType<TypeTag, Properties::Problem>;
     auto problem = std::make_shared<Problem>(fvGridGeometry);
 
+    // check if we are about to restart a previously interrupted simulation
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    Scalar restartTime = getParam<Scalar>("Restart.Time", 0);
+
     // the solution vector
-    using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
+    using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
     SolutionVector x(fvGridGeometry->numDofs());
-    problem->applyInitialSolution(x);
+    if (restartTime > 0)
+    {
+        using IOFields = GetPropType<TypeTag, Properties::IOFields>;
+        using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+        using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>;
+        using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
+        const auto fileName = getParam<std::string>("Restart.File");
+        const auto pvName = createPVNameFunction<IOFields, PrimaryVariables, ModelTraits, FluidSystem>();
+        loadSolution(x, fileName, pvName, *fvGridGeometry);
+    }
+    else
+        problem->applyInitialSolution(x);
     auto xOld = x;
 
     // the grid variables
-    using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables);
+    using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
     auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry);
-    gridVariables->init(x, xOld);
+    gridVariables->init(x);
 
     // get some time loop parameters
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
     // intialize the vtk output module
-    using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields);
-    VtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name());
-    VtkOutputFields::init(vtkWriter); //! Add model specific output fields
+    using IOFields = GetPropType<TypeTag, Properties::IOFields>;
+
+    // use non-conforming output for the test with interface solver
+    const auto ncOutput = getParam<bool>("Problem.UseNonConformingOutput", false);
+    VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, x, problem->name(), "",
+                                                             ncOutput ? Dune::VTK::nonconforming : Dune::VTK::conforming);
+    using VelocityOutput = GetPropType<TypeTag, Properties::VelocityOutput>;
+    vtkWriter.addVelocityOutput(std::make_shared<VelocityOutput>(*gridVariables));
+    IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields
+    vtkWriter.write(restartTime);
 
     // instantiate time loop
     auto timeLoop = std::make_shared<TimeLoop<Scalar>>(0.0, dt, tEnd);
diff --git a/exercises/exercise-basic/exercise_basic_2p2c.cc b/exercises/exercise-basic/exercise_basic_2p2c.cc
index b4359b9ea717c3b3a01ae3ba0601ecda031f64e5..68c91ea1cf64954a1185f76fcf2a5a0979ccc2bb 100644
--- a/exercises/exercise-basic/exercise_basic_2p2c.cc
+++ b/exercises/exercise-basic/exercise_basic_2p2c.cc
@@ -36,15 +36,16 @@
 #include <dumux/common/dumuxmessage.hh>
 
 #include <dumux/linear/amgbackend.hh>
-#include <dumux/nonlinear/privarswitchnewtonsolver.hh>
+#include <dumux/nonlinear/newtonsolver.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/grid/gridmanager.hh>
+#include <dumux/io/loadsolution.hh>
 
 // The problem file, where setup-specific boundary and initial conditions are defined.
 #include "injection2p2cproblem.hh"
@@ -57,7 +58,7 @@ int main(int argc, char** argv) try
     using namespace Dumux;
 
     // define the type tag for this problem
-    using TypeTag = TTAG(Injection2p2cCCTypeTag);
+    using TypeTag = Properties::TTag::Injection2p2cCCTypeTag;
 
     // initialize MPI, finalize is done automatically on exit
     const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv);
@@ -70,7 +71,7 @@ int main(int argc, char** argv) try
     Parameters::init(argc, argv);
 
     // try to create a grid (from the given grid file or the input file)
-    GridManager<typename GET_PROP_TYPE(TypeTag, Grid)> gridManager;
+    GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
     gridManager.init();
 
     ////////////////////////////////////////////////////////////
@@ -81,38 +82,62 @@ int main(int argc, char** argv) try
     const auto& leafGridView = gridManager.grid().leafGridView();
 
     // create the finite volume grid geometry
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
     auto fvGridGeometry = std::make_shared<FVGridGeometry>(leafGridView);
     fvGridGeometry->update();
 
     // the problem (initial and boundary conditions)
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using Problem = GetPropType<TypeTag, Properties::Problem>;
     auto problem = std::make_shared<Problem>(fvGridGeometry);
 
+    // check if we are about to restart a previously interrupted simulation
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    Scalar restartTime = getParam<Scalar>("Restart.Time", 0);
+
     // the solution vector
-    using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
+    using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
     SolutionVector x(fvGridGeometry->numDofs());
-    problem->applyInitialSolution(x);
+//     problem->applyInitialSolution(x);
+        if (restartTime > 0)
+    {
+        using IOFields = GetPropType<TypeTag, Properties::IOFields>;
+        using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+        using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>;
+        using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
+        const auto fileName = getParam<std::string>("Restart.File");
+        const auto pvName = createPVNameFunction<IOFields, PrimaryVariables, ModelTraits, FluidSystem>();
+        loadSolution(x, fileName, pvName, *fvGridGeometry);
+    }
+    else
+        problem->applyInitialSolution(x);
     auto xOld = x;
 
     // the grid variables
-    using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables);
+    using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
     auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry);
-    gridVariables->init(x, xOld);
+    gridVariables->init(x);
 
     // get some time loop parameters
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
     // intialize the vtk output module
-    using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields);
-    VtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name());
-    VtkOutputFields::init(vtkWriter); //! Add model specific output fields
+//     using VtkOutputFields = GetPropType<TypeTag, Properties::VtkOutputFields>;
+//     VtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name());
+//     VtkOutputFields::init(vtkWriter); //! Add model specific output fields
+
+    // intialize the vtk output module
+    using VtkOutputFields = GetPropType<TypeTag, Properties::VtkOutputFields>;
+    VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, x, problem->name());
+    using VelocityOutput = GetPropType<TypeTag, Properties::VelocityOutput>;
+    vtkWriter.addVelocityOutput(std::make_shared<VelocityOutput>(*gridVariables));
+    VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields
+    vtkWriter.write(restartTime);
 
     // instantiate time loop
-    auto timeLoop = std::make_shared<TimeLoop<Scalar>>(0.0, dt, tEnd);
+    auto timeLoop = std::make_shared<TimeLoop<Scalar>>(restartTime, dt, tEnd);
     timeLoop->setMaxTimeStepSize(maxDt);
 
     // the assembler with time loop for instationary problem
@@ -124,8 +149,8 @@ int main(int argc, char** argv) try
     auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper());
 
     // the non-linear solver
-    using PrimaryVariableSwitch = typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch);
-    using NewtonSolver = Dumux::PriVarSwitchNewtonSolver<Assembler, LinearSolver, PrimaryVariableSwitch>;
+//     using PrimaryVariableSwitch = GetPropType<TypeTag, Properties::PrimaryVariableSwitch>;
+    using NewtonSolver = NewtonSolver<Assembler, LinearSolver>;
     NewtonSolver nonLinearSolver(assembler, linearSolver);
 
     // time loop
diff --git a/exercises/exercise-basic/injection2p2cproblem.hh b/exercises/exercise-basic/injection2p2cproblem.hh
index 39b0ab57b0389f731defb65b161dbef572692a73..276f3ccbec81d8766c941e2e3dade5ece2684163 100644
--- a/exercises/exercise-basic/injection2p2cproblem.hh
+++ b/exercises/exercise-basic/injection2p2cproblem.hh
@@ -38,25 +38,32 @@ template <class TypeTag>
 class Injection2p2cProblem;
 
 namespace Properties {
-NEW_TYPE_TAG(Injection2p2cTypeTag, INHERITS_FROM(TwoPTwoC));
-NEW_TYPE_TAG(Injection2p2cCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2p2cTypeTag));
+// Create new type tags
+namespace TTag {
+struct Injection2p2cTypeTag { using InheritsFrom = std::tuple<TwoPTwoC>; };
+struct Injection2p2cCCTypeTag { using InheritsFrom = std::tuple<CCTpfaModel, Injection2p2cTypeTag>; };
+} // end namespace TTag
 
 // Set the grid type
-SET_TYPE_PROP(Injection2p2cTypeTag, Grid, Dune::YaspGrid<2>);
+template<class TypeTag>
+struct Grid<TypeTag, TTag::Injection2p2cTypeTag> { using type = Dune::YaspGrid<2>; };
 
 // Set the problem property
-SET_TYPE_PROP(Injection2p2cTypeTag, Problem, Injection2p2cProblem<TypeTag>);
+template<class TypeTag>
+struct Problem<TypeTag, TTag::Injection2p2cTypeTag> { using type = Injection2p2cProblem<TypeTag>; };
 
 // Set the spatial parameters
 SET_TYPE_PROP(Injection2p2cTypeTag, SpatialParams,
-              InjectionSpatialParams<typename GET_PROP_TYPE(TypeTag, FVGridGeometry),
-                                     typename GET_PROP_TYPE(TypeTag, Scalar)>);
+              InjectionSpatialParams<GetPropType<TypeTag, Properties::FVGridGeometry>,
+                                     GetPropType<TypeTag, Properties::Scalar>>);
 
 // Set fluid configuration
-SET_TYPE_PROP(Injection2p2cTypeTag, FluidSystem, FluidSystems::H2ON2<typename GET_PROP_TYPE(TypeTag, Scalar), FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true>>);
+template<class TypeTag>
+struct FluidSystem<TypeTag, TTag::Injection2p2cTypeTag> { using type = FluidSystems::H2ON2<GetPropType<TypeTag, Properties::Scalar>, FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true>>; };
 
 // Define whether mole(true) or mass (false) fractions are used
-SET_BOOL_PROP(Injection2p2cTypeTag, UseMoles, true);
+template<class TypeTag>
+struct UseMoles<TypeTag, TTag::Injection2p2cTypeTag> { static constexpr bool value = true; };
 } // end namespace Properties
 
 /*!
@@ -84,15 +91,15 @@ template<class TypeTag>
 class Injection2p2cProblem : public PorousMediumFlowProblem<TypeTag>
 {
     using ParentType = PorousMediumFlowProblem<TypeTag>;
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
-    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
-    using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
-    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView;
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
+    using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+    using BoundaryTypes = GetPropType<TypeTag, Properties::BoundaryTypes>;
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
+    using FVElementGeometry = typename GetPropType<TypeTag, Properties::FVGridGeometry>::LocalView;
+    using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
+    using NumEqVector = GetPropType<TypeTag, Properties::NumEqVector>;
 
     enum { dimWorld = GridView::dimensionworld };
     using Element = typename GridView::template Codim<0>::Entity;
diff --git a/exercises/exercise-basic/injection2pniproblem.hh b/exercises/exercise-basic/injection2pniproblem.hh
index 5d03855918653c1227ee2d31bc21cba1f6644df8..4a1e9603443dd1950446c99aa46f0fd4ecad2e48 100644
--- a/exercises/exercise-basic/injection2pniproblem.hh
+++ b/exercises/exercise-basic/injection2pniproblem.hh
@@ -44,22 +44,28 @@ namespace Properties
 * TODO:dumux-course-task:
 * inherit from the TwoPNI model instead of TwoP here
 */
-NEW_TYPE_TAG(Injection2pNITypeTag, INHERITS_FROM(TwoP));
-NEW_TYPE_TAG(Injection2pNICCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pNITypeTag));
+// Create new type tags
+namespace TTag {
+struct Injection2pNITypeTag { using InheritsFrom = std::tuple<TwoP>; };
+struct Injection2pNICCTypeTag { using InheritsFrom = std::tuple<Injection2pNITypeTag, CCTpfaModel>; };
+} // end namespace TTag
 
 // Set the grid type
-SET_TYPE_PROP(Injection2pNITypeTag, Grid, Dune::YaspGrid<2>);
+template<class TypeTag>
+struct Grid<TypeTag, TTag::Injection2pNITypeTag> { using type = Dune::YaspGrid<2>; };
 
 // Set the problem property
-SET_TYPE_PROP(Injection2pNITypeTag, Problem, InjectionProblem2PNI<TypeTag>);
+template<class TypeTag>
+struct Problem<TypeTag, TTag::Injection2pNITypeTag> { using type = InjectionProblem2PNI<TypeTag>; };
 
 // Set the spatial parameters
 SET_TYPE_PROP(Injection2pNITypeTag, SpatialParams,
-              InjectionSpatialParams<typename GET_PROP_TYPE(TypeTag, FVGridGeometry),
-                                     typename GET_PROP_TYPE(TypeTag, Scalar)>);
+              InjectionSpatialParams<GetPropType<TypeTag, Properties::FVGridGeometry>,
+                                     GetPropType<TypeTag, Properties::Scalar>>);
 
 // Set fluid configuration
-SET_TYPE_PROP(Injection2pNITypeTag, FluidSystem, FluidSystems::H2ON2<typename GET_PROP_TYPE(TypeTag, Scalar), FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true>>);
+template<class TypeTag>
+struct FluidSystem<TypeTag, TTag::Injection2pNITypeTag> { using type = FluidSystems::H2ON2<GetPropType<TypeTag, Properties::Scalar>, FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true>>; };
 } // end namespace Properties
 
 /*!
@@ -87,15 +93,15 @@ template<class TypeTag>
 class InjectionProblem2PNI : public PorousMediumFlowProblem<TypeTag>
 {
     using ParentType = PorousMediumFlowProblem<TypeTag>;
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
-    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
-    using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
-    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView;
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
+    using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+    using BoundaryTypes = GetPropType<TypeTag, Properties::BoundaryTypes>;
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
+    using FVElementGeometry = typename GetPropType<TypeTag, Properties::FVGridGeometry>::LocalView;
+    using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
+    using NumEqVector = GetPropType<TypeTag, Properties::NumEqVector>;
 
     enum { dimWorld = GridView::dimensionworld };
     using Element = typename GridView::template Codim<0>::Entity;
diff --git a/exercises/exercise-basic/injection2pproblem.hh b/exercises/exercise-basic/injection2pproblem.hh
index aae875173477bd98d8ac046ab2c7ba976132b5ed..0f05fafd223be512bf0476a31cdf3118b9a1e307 100644
--- a/exercises/exercise-basic/injection2pproblem.hh
+++ b/exercises/exercise-basic/injection2pproblem.hh
@@ -40,22 +40,28 @@ class InjectionProblem2P;
 
 namespace Properties {
 // define the TypeTag for this problem with a cell-centered two-point flux approximation spatial discretization.
-NEW_TYPE_TAG(Injection2pTypeTag, INHERITS_FROM(TwoP));
-NEW_TYPE_TAG(Injection2pCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pTypeTag));
+// Create new type tags
+namespace TTag {
+struct Injection2pTypeTag { using InheritsFrom = std::tuple<TwoP>; };
+struct Injection2pCCTypeTag { using InheritsFrom = std::tuple<Injection2pTypeTag, CCTpfaModel>; };
+} // end namespace TTag
 
 // Set the grid type
-SET_TYPE_PROP(Injection2pTypeTag, Grid, Dune::YaspGrid<2>);
+template<class TypeTag>
+struct Grid<TypeTag, TTag::Injection2pTypeTag> { using type = Dune::YaspGrid<2>; };
 
 // Set the problem property
-SET_TYPE_PROP(Injection2pTypeTag, Problem, InjectionProblem2P<TypeTag>);
+template<class TypeTag>
+struct Problem<TypeTag, TTag::Injection2pTypeTag> { using type = InjectionProblem2P<TypeTag>; };
 
 // Set the spatial parameters
 SET_TYPE_PROP(Injection2pTypeTag, SpatialParams,
-              InjectionSpatialParams<typename GET_PROP_TYPE(TypeTag, FVGridGeometry),
-                                     typename GET_PROP_TYPE(TypeTag, Scalar)>);
+              InjectionSpatialParams<GetPropType<TypeTag, Properties::FVGridGeometry>,
+                                     GetPropType<TypeTag, Properties::Scalar>>);
 
 // Set fluid configuration
-SET_TYPE_PROP(Injection2pTypeTag, FluidSystem, FluidSystems::H2ON2<typename GET_PROP_TYPE(TypeTag, Scalar), FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true>>);
+template<class TypeTag>
+struct FluidSystem<TypeTag, TTag::Injection2pTypeTag> { using type = FluidSystems::H2ON2<GetPropType<TypeTag, Properties::Scalar>, FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true>>; };
 } // end namespace Properties
 
 /*!
@@ -83,15 +89,15 @@ template<class TypeTag>
 class InjectionProblem2P : public PorousMediumFlowProblem<TypeTag>
 {
     using ParentType = PorousMediumFlowProblem<TypeTag>;
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
-    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
-    using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
-    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView;
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
+    using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+    using BoundaryTypes = GetPropType<TypeTag, Properties::BoundaryTypes>;
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
+    using FVElementGeometry = typename GetPropType<TypeTag, Properties::FVGridGeometry>::LocalView;
+    using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
+    using NumEqVector = GetPropType<TypeTag, Properties::NumEqVector>;
 
     enum { dimWorld = GridView::dimensionworld };
     using Element = typename GridView::template Codim<0>::Entity;
diff --git a/exercises/solution/exercise-basic/exercise_basic_2pni.cc b/exercises/solution/exercise-basic/exercise_basic_2pni.cc
index c772513cb855bb999ad5e85713ff964a383fcf63..3a9037d996109d266a39c12c8659e9511252a26b 100644
--- a/exercises/solution/exercise-basic/exercise_basic_2pni.cc
+++ b/exercises/solution/exercise-basic/exercise_basic_2pni.cc
@@ -41,10 +41,11 @@
 #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/grid/gridmanager.hh>
+#include <dumux/io/loadsolution.hh>
 
 // The problem file, where setup-specific boundary and initial conditions are defined.
 #include "injection2pniproblem.hh"
@@ -57,7 +58,7 @@ int main(int argc, char** argv) try
     using namespace Dumux;
 
     // define the type tag for this problem
-    using TypeTag = TTAG(Injection2pNICCTypeTag);
+    using TypeTag = Properties::TTag::Injection2pNICCTypeTag;
 
     // initialize MPI, finalize is done automatically on exit
     const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv);
@@ -70,7 +71,7 @@ int main(int argc, char** argv) try
     Parameters::init(argc, argv);
 
     // try to create a grid (from the given grid file or the input file)
-    GridManager<typename GET_PROP_TYPE(TypeTag, Grid)> gridManager;
+    GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
     gridManager.init();
 
     ////////////////////////////////////////////////////////////
@@ -81,35 +82,53 @@ int main(int argc, char** argv) try
     const auto& leafGridView = gridManager.grid().leafGridView();
 
     // create the finite volume grid geometry
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
     auto fvGridGeometry = std::make_shared<FVGridGeometry>(leafGridView);
     fvGridGeometry->update();
 
     // the problem (initial and boundary conditions)
-    using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
+    using Problem = GetPropType<TypeTag, Properties::Problem>;
     auto problem = std::make_shared<Problem>(fvGridGeometry);
 
+    // check if we are about to restart a previously interrupted simulation
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    Scalar restartTime = getParam<Scalar>("Restart.Time", 0);
+
     // the solution vector
-    using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
+    using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
     SolutionVector x(fvGridGeometry->numDofs());
-    problem->applyInitialSolution(x);
+    if (restartTime > 0)
+    {
+        using IOFields = GetPropType<TypeTag, Properties::IOFields>;
+        using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+        using ModelTraits = GetPropType<TypeTag, Properties::ModelTraits>;
+        using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
+        const auto fileName = getParam<std::string>("Restart.File");
+        const auto pvName = createPVNameFunction<IOFields, PrimaryVariables, ModelTraits, FluidSystem>();
+        loadSolution(x, fileName, pvName, *fvGridGeometry);
+    }
+    else
+        problem->applyInitialSolution(x);
     auto xOld = x;
 
     // the grid variables
-    using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables);
+    using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
     auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry);
-    gridVariables->init(x, xOld);
+    gridVariables->init(x);
 
     // get some time loop parameters
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
     const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
     const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
     // intialize the vtk output module
-    using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields);
-    VtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name());
-    VtkOutputFields::init(vtkWriter); //! Add model specific output fields
+    using VtkOutputFields = GetPropType<TypeTag, Properties::VtkOutputFields>;
+    VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, x, problem->name());
+    using VelocityOutput = GetPropType<TypeTag, Properties::VelocityOutput>;
+    vtkWriter.addVelocityOutput(std::make_shared<VelocityOutput>(*gridVariables));
+    VtkOutputFields::initOutputModule(vtkWriter); //!< Add model specific output fields
+    vtkWriter.write(restartTime);
 
     // instantiate time loop
     auto timeLoop = std::make_shared<TimeLoop<Scalar>>(0.0, dt, tEnd);
diff --git a/exercises/solution/exercise-basic/injection2pniproblem.hh b/exercises/solution/exercise-basic/injection2pniproblem.hh
index f8868632743897a52c318d4a6d00a1bcb0315bcd..6625627e419ed3a18ae38b44f9d2b492c57f0650 100644
--- a/exercises/solution/exercise-basic/injection2pniproblem.hh
+++ b/exercises/solution/exercise-basic/injection2pniproblem.hh
@@ -39,23 +39,28 @@ template <class TypeTag>
 class InjectionProblem2PNI;
 
 namespace Properties {
-NEW_TYPE_TAG(Injection2pNITypeTag, INHERITS_FROM(TwoPNI));
-NEW_TYPE_TAG(Injection2pNICCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2pNITypeTag));
+// Create new type tags
+namespace TTag {
+struct Injection2pNITypeTag { using InheritsFrom = std::tuple<TwoPNI>; };
+struct Injection2pNICCTypeTag { using InheritsFrom = std::tuple<Injection2pNITypeTag, CCTpfaModel>; };
+} // end namespace TTag
 
 // Set the grid type
-SET_TYPE_PROP(Injection2pNITypeTag, Grid, Dune::YaspGrid<2>);
+template<class TypeTag>
+struct Grid<TypeTag, TTag::Injection2pNITypeTag> { using type = Dune::YaspGrid<2>; };
 
 // Set the problem property
-SET_TYPE_PROP(Injection2pNITypeTag, Problem, InjectionProblem2PNI<TypeTag>);
+template<class TypeTag>
+struct Problem<TypeTag, TTag::Injection2pNITypeTag> { using type = InjectionProblem2PNI<TypeTag>; };
 
 // Set the spatial parameters
 SET_TYPE_PROP(Injection2pNITypeTag, SpatialParams,
-              InjectionSpatialParams<typename GET_PROP_TYPE(TypeTag, FVGridGeometry),
-                                     typename GET_PROP_TYPE(TypeTag, Scalar)>);
+              InjectionSpatialParams<GetPropType<TypeTag, Properties::FVGridGeometry>,
+                                     GetPropType<TypeTag, Properties::Scalar>>);
 
 // Set fluid configuration
 SET_TYPE_PROP(Injection2pNITypeTag, FluidSystem,
-    FluidSystems::H2ON2<typename GET_PROP_TYPE(TypeTag, Scalar), FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true>>);
+    FluidSystems::H2ON2<GetPropType<TypeTag, Properties::Scalar>, FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true>>);
 } // end namespace Properties
 
 /*!
@@ -83,15 +88,15 @@ template<class TypeTag>
 class InjectionProblem2PNI : public PorousMediumFlowProblem<TypeTag>
 {
     using ParentType = PorousMediumFlowProblem<TypeTag>;
-    using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
-    using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
-    using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
-    using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
-    using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
-    using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry);
-    using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView;
-    using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
-    using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector);
+    using GridView = GetPropType<TypeTag, Properties::GridView>;
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
+    using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
+    using BoundaryTypes = GetPropType<TypeTag, Properties::BoundaryTypes>;
+    using FVGridGeometry = GetPropType<TypeTag, Properties::FVGridGeometry>;
+    using FVElementGeometry = typename GetPropType<TypeTag, Properties::FVGridGeometry>::LocalView;
+    using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
+    using NumEqVector = GetPropType<TypeTag, Properties::NumEqVector>;
 
     enum { dimWorld = GridView::dimensionworld };
     using Element = typename GridView::template Codim<0>::Entity;