diff -ruN exercises/exercise-basic/2p2cmain.cc exercises/solution/exercise-basic/2p2cmain.cc
--- exercises/exercise-basic/2p2cmain.cc	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/2p2cmain.cc	1970-01-01 01:00:00.000000000 +0100
@@ -1,154 +0,0 @@
-// -*- 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 3 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 main file for the 2p2c porousmediumflow problem in exercise-basic
- */
-#include <config.h>
-
-#include <iostream>
-
-#include <dumux/common/initialize.hh>
-#include <dumux/common/properties.hh>
-#include <dumux/common/parameters.hh>
-
-#include <dumux/linear/istlsolvers.hh>
-#include <dumux/linear/linearsolvertraits.hh>
-#include <dumux/linear/linearalgebratraits.hh>
-#include <dumux/nonlinear/newtonsolver.hh>
-
-#include <dumux/assembly/fvassembler.hh>
-#include <dumux/assembly/diffmethod.hh>
-
-#include <dumux/io/vtkoutputmodule.hh>
-#include <dumux/io/grid/gridmanager_yasp.hh>
-
-// The properties file, where the compile time options are defined
-#include "properties2p2c.hh"
-
-////////////////////////
-// the main function
-////////////////////////
-int main(int argc, char** argv)
-{
-    using namespace Dumux;
-
-    // define the type tag for this problem
-    using TypeTag = Properties::TTag::Injection2p2cCC;
-
-    // initialize MPI+X, finalize is done automatically on exit
-    Dumux::initialize(argc, argv);
-
-    // parse command line arguments and input file
-    Parameters::init(argc, argv);
-
-    // try to create a grid (from the given grid file or the input file)
-    GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
-    gridManager.init();
-
-    ////////////////////////////////////////////////////////////
-    // run instationary non-linear problem on this grid
-    ////////////////////////////////////////////////////////////
-
-    // we compute on the leaf grid view
-    const auto& leafGridView = gridManager.grid().leafGridView();
-
-    // create the finite volume grid geometry
-    using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
-    auto gridGeometry = std::make_shared<GridGeometry>(leafGridView);
-
-    // the problem (initial and boundary conditions)
-    using Problem = GetPropType<TypeTag, Properties::Problem>;
-    auto problem = std::make_shared<Problem>(gridGeometry);
-
-    // the solution vector
-    using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
-    SolutionVector x;
-    problem->applyInitialSolution(x);
-    auto xOld = x;
-
-    // the grid variables
-    using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
-    auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
-    gridVariables->init(x);
-
-    // initialize the vtk output module
-    using IOFields = GetPropType<TypeTag, Properties::IOFields>;
-    VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, x, problem->name());
-    using VelocityOutput = GetPropType<TypeTag, Properties::VelocityOutput>;
-    vtkWriter.addVelocityOutput(std::make_shared<VelocityOutput>(*gridVariables));
-    IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields
-    vtkWriter.write(0.0);
-
-    // instantiate time loop
-    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
-    const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
-    const auto dt = getParam<Scalar>("TimeLoop.DtInitial");
-    auto timeLoop = std::make_shared<TimeLoop<Scalar>>(0.0, dt, tEnd);
-    timeLoop->setMaxTimeStepSize(maxDt);
-
-    // the assembler with time loop for instationary problem
-    using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
-    auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables, timeLoop, xOld);
-
-    // the linear solver
-    using LinearSolver = AMGBiCGSTABIstlSolver<LinearSolverTraits<GridGeometry>, LinearAlgebraTraitsFromAssembler<Assembler>>;
-    auto linearSolver = std::make_shared<LinearSolver>(gridGeometry->gridView(), gridGeometry->dofMapper());
-
-    // the non-linear solver
-//     using PrimaryVariableSwitch = GetPropType<TypeTag, Properties::PrimaryVariableSwitch>;
-    using NewtonSolver = NewtonSolver<Assembler, LinearSolver>;
-    NewtonSolver nonLinearSolver(assembler, linearSolver);
-
-    // time loop
-    timeLoop->start();
-    while (!timeLoop->finished())
-    {
-        //set time in problem (is used in time-dependent Neumann boundary condition)
-        problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
-
-        // solve the non-linear system with time step control
-        nonLinearSolver.solve(x, *timeLoop);
-
-        // make the new solution the old solution
-        xOld = x;
-        gridVariables->advanceTimeStep();
-
-        // advance to the time loop to the next step
-        timeLoop->advanceTimeStep();
-
-        // report statistics of this time step
-        timeLoop->reportTimeStep();
-
-        // set new dt as suggested by the newton solver
-        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
-
-        // output to vtk
-        vtkWriter.write(timeLoop->time());
-    }
-
-    timeLoop->finalize(leafGridView.comm());
-
-    // print parameter report
-    if (leafGridView.comm().rank() == 0)
-        Parameters::print();
-
-    return 0;
-} // end main
diff -ruN exercises/exercise-basic/2pmain.cc exercises/solution/exercise-basic/2pmain.cc
--- exercises/exercise-basic/2pmain.cc	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/2pmain.cc	1970-01-01 01:00:00.000000000 +0100
@@ -1,157 +0,0 @@
-// -*- 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 3 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 main file for the two-phase porousmediumflow problem of exercise-basic
- */
-#include <config.h>
-
-#include <iostream>
-
-#include <dumux/common/initialize.hh>
-#include <dumux/common/properties.hh>
-#include <dumux/common/parameters.hh>
-
-#include <dumux/linear/istlsolvers.hh>
-#include <dumux/linear/linearsolvertraits.hh>
-#include <dumux/linear/linearalgebratraits.hh>
-#include <dumux/nonlinear/newtonsolver.hh>
-
-#include <dumux/assembly/fvassembler.hh>
-#include <dumux/assembly/diffmethod.hh>
-
-#include <dumux/io/vtkoutputmodule.hh>
-#include <dumux/io/grid/gridmanager_yasp.hh>
-
-// The properties file, where the compile time options are defined
-#include "properties2p.hh"
-
-////////////////////////
-// the main function
-////////////////////////
-int main(int argc, char** argv)
-{
-    using namespace Dumux;
-
-    // define the type tag for this problem
-    using TypeTag = Properties::TTag::Injection2pCC;
-
-    /// initialize MPI+X, finalize is done automatically on exit
-    Dumux::initialize(argc, argv);
-
-    // parse command line arguments and input file
-    Parameters::init(argc, argv);
-
-    // try to create a grid (from the given grid file or the input file)
-    GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
-    gridManager.init();
-
-    ////////////////////////////////////////////////////////////
-    // run instationary non-linear problem on this grid
-    ////////////////////////////////////////////////////////////
-
-    // we compute on the leaf grid view
-    const auto& leafGridView = gridManager.grid().leafGridView();
-
-    // create the finite volume grid geometry
-    using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
-    auto gridGeometry = std::make_shared<GridGeometry>(leafGridView);
-
-    // the problem (initial and boundary conditions)
-    using Problem = GetPropType<TypeTag, Properties::Problem>;
-    auto problem = std::make_shared<Problem>(gridGeometry);
-
-    // the solution vector
-    using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
-    SolutionVector x;
-    problem->applyInitialSolution(x);
-    auto xOld = x;
-
-    // the grid variables
-    using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
-    auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
-    gridVariables->init(x);
-
-    // initialize the vtk output module
-    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(0.0);
-
-    // instantiate time loop
-    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
-    const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
-    const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
-    const auto dt = getParam<Scalar>("TimeLoop.DtInitial");
-    auto timeLoop = std::make_shared<TimeLoop<Scalar>>(0.0, dt, tEnd);
-    timeLoop->setMaxTimeStepSize(maxDt);
-
-    // the assembler with time loop for instationary problem
-    using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
-    auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables, timeLoop, xOld);
-
-    // the linear solver
-    using LinearSolver = AMGBiCGSTABIstlSolver<LinearSolverTraits<GridGeometry>, LinearAlgebraTraitsFromAssembler<Assembler>>;
-    auto linearSolver = std::make_shared<LinearSolver>(gridGeometry->gridView(), gridGeometry->dofMapper());
-
-    // the non-linear solver
-    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
-    NewtonSolver nonLinearSolver(assembler, linearSolver);
-
-    // time loop
-    timeLoop->start();
-    while (!timeLoop->finished())
-    {
-        //set time in problem (is used in time-dependent Neumann boundary condition)
-        problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
-
-        // solve the non-linear system with time step control
-        nonLinearSolver.solve(x, *timeLoop);
-
-        // make the new solution the old solution
-        xOld = x;
-        gridVariables->advanceTimeStep();
-
-        // advance to the time loop to the next step
-        timeLoop->advanceTimeStep();
-
-        // report statistics of this time step
-        timeLoop->reportTimeStep();
-
-        // set new dt as suggested by the newton solver
-        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
-
-        // output to vtk
-        vtkWriter.write(timeLoop->time());
-    }
-
-    timeLoop->finalize(leafGridView.comm());
-
-    // print parameter report
-    if (leafGridView.comm().rank() == 0)
-        Parameters::print();
-
-    return 0;
-} // end main
diff -ruN exercises/exercise-basic/2pnimain.cc exercises/solution/exercise-basic/2pnimain.cc
--- exercises/exercise-basic/2pnimain.cc	1970-01-01 01:00:00.000000000 +0100
+++ exercises/solution/exercise-basic/2pnimain.cc	2023-04-26 14:37:49.789150797 +0200
@@ -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 3 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 solution main file for the two-phase porousmediumflow problem of exercise-basic
+ */
+#include <config.h>
+
+#include <iostream>
+
+#include <dumux/common/initialize.hh>
+#include <dumux/common/properties.hh>
+#include <dumux/common/parameters.hh>
+
+#include <dumux/linear/istlsolvers.hh>
+#include <dumux/linear/linearsolvertraits.hh>
+#include <dumux/linear/linearalgebratraits.hh>
+#include <dumux/nonlinear/newtonsolver.hh>
+
+#include <dumux/assembly/fvassembler.hh>
+#include <dumux/assembly/diffmethod.hh>
+
+#include <dumux/io/vtkoutputmodule.hh>
+#include <dumux/io/grid/gridmanager_yasp.hh>
+
+// The properties file, where the compile time options are defined
+#include "properties2pni.hh"
+
+int main(int argc, char** argv)
+{
+    using namespace Dumux;
+
+    // define the type tag for this problem
+    using TypeTag = Properties::TTag::Injection2pNICC;
+
+    // initialize MPI+X, finalize is done automatically on exit
+    Dumux::initialize(argc, argv);
+
+    // parse command line arguments and input file
+    Parameters::init(argc, argv);
+
+    // try to create a grid (from the given grid file or the input file)
+    GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
+    gridManager.init();
+
+    ////////////////////////////////////////////////////////////
+    // run instationary non-linear problem on this grid
+    ////////////////////////////////////////////////////////////
+
+    // we compute on the leaf grid view
+    const auto& leafGridView = gridManager.grid().leafGridView();
+
+    // create the finite volume grid geometry
+    using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
+    auto gridGeometry = std::make_shared<GridGeometry>(leafGridView);
+
+    // the problem (initial and boundary conditions)
+    using Problem = GetPropType<TypeTag, Properties::Problem>;
+    auto problem = std::make_shared<Problem>(gridGeometry);
+
+    // the solution vector
+    using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
+    SolutionVector x;
+    problem->applyInitialSolution(x);
+    auto xOld = x;
+
+    // the grid variables
+    using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
+    auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
+    gridVariables->init(x);
+
+    // initialize the vtk output module
+    using IOFields = GetPropType<TypeTag, Properties::IOFields>;
+    VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, x, problem->name());
+    using VelocityOutput = GetPropType<TypeTag, Properties::VelocityOutput>;
+    vtkWriter.addVelocityOutput(std::make_shared<VelocityOutput>(*gridVariables));
+    IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields
+    vtkWriter.write(0.0);
+
+    // instantiate time loop
+    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+    const auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
+    const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
+    const auto dt = getParam<Scalar>("TimeLoop.DtInitial");
+    auto timeLoop = std::make_shared<TimeLoop<Scalar>>(0.0, dt, tEnd);
+    timeLoop->setMaxTimeStepSize(maxDt);
+
+    // the assembler with time loop for instationary problem
+    using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
+    auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables, timeLoop, xOld);
+
+    // the linear solver
+    using LinearSolver = AMGBiCGSTABIstlSolver<LinearSolverTraits<GridGeometry>, LinearAlgebraTraitsFromAssembler<Assembler>>;
+    auto linearSolver = std::make_shared<LinearSolver>(gridGeometry->gridView(), gridGeometry->dofMapper());
+
+    // the non-linear solver
+    using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+    NewtonSolver nonLinearSolver(assembler, linearSolver);
+
+    // time loop
+    timeLoop->start();
+    while (!timeLoop->finished())
+    {
+        //set time in problem (is used in time-dependent Neumann boundary condition)
+        problem->setTime(timeLoop->time()+timeLoop->timeStepSize());
+
+        // solve the non-linear system with time step control
+        nonLinearSolver.solve(x, *timeLoop);
+
+        // make the new solution the old solution
+        xOld = x;
+        gridVariables->advanceTimeStep();
+
+        // advance to the time loop to the next step
+        timeLoop->advanceTimeStep();
+
+        // report statistics of this time step
+        timeLoop->reportTimeStep();
+
+        // set new dt as suggested by the newton solver
+        timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
+
+        // output to vtk
+        vtkWriter.write(timeLoop->time());
+    }
+
+    timeLoop->finalize(leafGridView.comm());
+
+    // print parameter report
+    if (leafGridView.comm().rank() == 0)
+        Parameters::print();
+
+    return 0;
+} // end main
diff -ruN exercises/exercise-basic/CMakeLists.txt exercises/solution/exercise-basic/CMakeLists.txt
--- exercises/exercise-basic/CMakeLists.txt	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/CMakeLists.txt	2023-04-26 14:37:49.789150797 +0200
@@ -1,13 +1,6 @@
-# the immiscible two-phase simulation program
-dumux_add_test(NAME exercise_basic_2p
-               SOURCES 2pmain.cc)
-
-# the compositional two-phase two-component simulation program
-dumux_add_test(NAME exercise_basic_2p2c
-               SOURCES 2p2cmain.cc)
-
-# here, add the two-phase non-isothermal simulation program
-
+# the two-phase non-isothermal simulation program
+dumux_add_test(NAME exercise_basic_2pni_solution
+               SOURCES 2pnimain.cc)
 
 # add a symlink for each input file
 add_input_file_links()
diff -ruN exercises/exercise-basic/injection2p2cproblem.hh exercises/solution/exercise-basic/injection2p2cproblem.hh
--- exercises/exercise-basic/injection2p2cproblem.hh	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/injection2p2cproblem.hh	1970-01-01 01:00:00.000000000 +0100
@@ -1,229 +0,0 @@
-// -*- 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 3 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 two-phase porousmediumflow problem for exercise-basic
- */
-
-#ifndef DUMUX_EX_BASIC_PROBLEM_2P2C_HH
-#define DUMUX_EX_BASIC_PROBLEM_2P2C_HH
-
-#include <dumux/common/properties.hh>
-#include <dumux/common/boundarytypes.hh>
-#include <dumux/common/numeqvector.hh>
-#include <dumux/porousmediumflow/problem.hh>
-#include <dumux/material/binarycoefficients/h2o_n2.hh>
-
-namespace Dumux {
-
-/*!
- * \ingroup TwoPTwoCModel
- * \ingroup ImplicitTestProblems
- * \brief Gas injection problem where a gas (here  nitrogen) is injected into a fully
- *        water saturated medium. During buoyancy driven upward migration the gas
- *        passes a high temperature area.
- *
- * The domain is sized 60 m times 40 m.
- *
- * For the mass conservation equation Neumann boundary conditions are used on
- * the top, on the bottom and on the right of the domain, while Dirichlet conditions
- * apply on the left boundary.
- *
- * Gas is injected at the right boundary from 7 m to 15 m at a rate of
- * 0.001 kg/(s m), the remaining Neumann boundaries are no-flow
- * boundaries.
- *
- * At the Dirichlet boundaries a hydrostatic pressure and a gas saturation of zero a
- *
- * This problem uses the \ref TwoPModel model.
- */
-template<class TypeTag>
-class Injection2p2cProblem : public PorousMediumFlowProblem<TypeTag>
-{
-    using ParentType = PorousMediumFlowProblem<TypeTag>;
-    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
-    using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
-    using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
-    using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
-    using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
-    using FVElementGeometry = typename GridGeometry::LocalView;
-    using GridView = typename GridGeometry::GridView;
-    using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
-    using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
-
-    static constexpr int dimWorld = GridView::dimensionworld;
-    using Element = typename GridView::template Codim<0>::Entity;
-    using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
-
-public:
-    Injection2p2cProblem(std::shared_ptr<const GridGeometry> gridGeometry)
-    : ParentType(gridGeometry)
-    {
-        // initialize the tables of the fluid system
-        FluidSystem::init(/*tempMin=*/273.15,
-                /*tempMax=*/423.15,
-                /*numTemp=*/50,
-                /*pMin=*/0.0,
-                /*pMax=*/30e6,
-                /*numP=*/300);
-
-        // name of the problem and output file
-        // getParam<TYPE>("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME
-        // of type TYPE given in the group GROUPNAME from the input file
-        name_ = getParam<std::string>("Problem.Name");
-        // depth of the aquifer, units: m
-        aquiferDepth_ = getParam<Scalar>("Problem.AquiferDepth");
-        // the duration of the injection, units: second
-        injectionDuration_ = getParam<Scalar>("Problem.InjectionDuration");
-    }
-
-    /*!
-     * \brief Returns the problem name
-     *
-     * This is used as a prefix for files generated by the simulation.
-     */
-    std::string name() const
-    { return name_+"-2p2c"; }
-
-    /*!
-     * \brief Specifies which kind of boundary condition should be
-     *        used for which equation on a given boundary segment.
-     *
-     * \param globalPos The position for which the bc type should be evaluated
-     */
-    BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
-    {
-         BoundaryTypes bcTypes;
-        if (globalPos[0] < eps_)
-            bcTypes.setAllDirichlet();
-        else
-            bcTypes.setAllNeumann();
-
-        return bcTypes;
-    }
-
-    /*!
-     * \brief Evaluates the boundary conditions for a Dirichlet
-     *        boundary segment
-     *
-     * \param globalPos The global position
-     */
-    PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
-    {
-        return initialAtPos(globalPos);
-    }
-
-    /*!
-     * \brief Evaluate the boundary conditions for a Neumann
-     *        boundary segment.
-     *
-     * \param globalPos The position of the integration point of the boundary segment.
-     */
-    NumEqVector neumannAtPos(const GlobalPosition &globalPos) const
-    {
-        // initialize values to zero, i.e. no-flow Neumann boundary conditions
-        NumEqVector values(0.0);
-
-        // if we are inside the injection zone set inflow Neumann boundary conditions
-        if (injectionActive() && onInjectionBoundary(globalPos))
-        {
-            // TODO: dumux-course-task
-            //instead of setting -1e-4 here directly use totalAreaSpecificInflow_ in the computation
-
-            // inject nitrogen. negative values mean injection
-            // convert from units kg/(s*m^2) to mole/(s*m^2)
-            values[Indices::conti0EqIdx + FluidSystem::N2Idx] = -1e-4/FluidSystem::molarMass(FluidSystem::N2Idx);
-            values[Indices::conti0EqIdx + FluidSystem::H2OIdx] = 0.0;
-        }
-
-        return values;
-    }
-
-    /*!
-     * \brief Evaluate the source term for all phases within a given
-     *        sub-control-volume.
-     *
-     * \param globalPos The position for which the source term should be evaluated
-     */
-    NumEqVector sourceAtPos(const GlobalPosition &globalPos) const
-    {
-        return NumEqVector(0.0);
-    }
-
-    /*!
-     * \brief Evaluate the initial value for a control volume.
-     *
-     * \param globalPos The position for which the initial condition should be evaluated
-     */
-    PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
-    {
-        PrimaryVariables values(0.0);
-        values.setState(Indices::firstPhaseOnly);
-        // get the water density at atmospheric conditions
-        const Scalar densityW = FluidSystem::H2O::liquidDensity(this->spatialParams().temperatureAtPos(globalPos), 1.0e5);
-
-        // assume an initially hydrostatic liquid pressure profile
-        // note: we subtract rho_w*g*h because g is defined negative
-        const Scalar pw = 1.0e5 - densityW*this->spatialParams().gravity(globalPos)[dimWorld-1]*(aquiferDepth_ - globalPos[dimWorld-1]);
-
-        // initially we have some nitrogen dissolved
-        // saturation mole fraction would be
-        // moleFracLiquidN2 = (pw + pc + p_vap^sat)/henry;
-        const Scalar moleFracLiquidN2 = pw*0.95/BinaryCoeff::H2O_N2::henry(this->spatialParams().temperatureAtPos(globalPos));
-
-        // note that because we start with a single phase system the primary variables
-        // are pl and x^w_N2. This will switch as soon after we start injecting to a two
-        // phase system so the primary variables will be pl and Sn (nonwetting saturation).
-        values[Indices::pressureIdx] = pw;
-        values[Indices::switchIdx] = moleFracLiquidN2;
-
-        return values;
-    }
-
-    //! set the time for the time dependent boundary conditions (called from main)
-    void setTime(Scalar time)
-    { time_ = time; }
-
-    //! Return true if the injection is currently active
-    bool injectionActive() const
-    { return time_ < injectionDuration_; }
-
-    //! Return true if the given position is in the injection boundary region
-    bool onInjectionBoundary(const GlobalPosition& globalPos) const
-    {
-        return globalPos[1] < 15. + eps_
-            && globalPos[1] > 7. - eps_
-            && globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_;
-    }
-
-private:
-    static constexpr Scalar eps_ = 1e-6;
-    std::string name_; //! Problem name
-    Scalar aquiferDepth_; //! Depth of the aquifer in m
-    Scalar injectionDuration_; //! Duration of the injection in seconds
-    Scalar time_;
-    //TODO: dumux-course-task
-    //define the Scalar totalAreaSpecificInflow_ here
-
-};
-
-} //end namespace Dumux
-
-#endif
diff -ruN exercises/exercise-basic/injection2pniproblem.hh exercises/solution/exercise-basic/injection2pniproblem.hh
--- exercises/exercise-basic/injection2pniproblem.hh	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/injection2pniproblem.hh	2023-04-26 14:37:49.789150797 +0200
@@ -19,7 +19,7 @@
 /*!
  * \file
  *
- * \brief The two-phase nonisothermal porousmediumflow problem for exercise-basic
+ * \brief The solution of the two-phase nonisothermal porousmediumflow problem for exercise-basic
  */
 
 #ifndef DUMUX_EX_BASIC_PROBLEM_2PNI_HH
@@ -31,7 +31,6 @@
 #include <dumux/porousmediumflow/problem.hh>
 
 namespace Dumux {
-
 /*!
  * \ingroup TwoPModel
  * \ingroup ImplicitTestProblems
@@ -46,7 +45,7 @@
  * apply on the left boundary.
  *
  * Gas is injected at the right boundary from 7 m to 15 m at a rate of
- * 0.0001 kg/(s m), the remaining Neumann boundaries are no-flow
+ * 0.001 kg/(s m), the remaining Neumann boundaries are no-flow
  * boundaries.
  *
  * At the Dirichlet boundaries a hydrostatic pressure and a gas saturation of zero a
@@ -57,13 +56,13 @@
 class Injection2PNIProblem : public PorousMediumFlowProblem<TypeTag>
 {
     using ParentType = PorousMediumFlowProblem<TypeTag>;
+    using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
     using Scalar = GetPropType<TypeTag, Properties::Scalar>;
     using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
     using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
     using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
     using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
-    using FVElementGeometry = typename GridGeometry::LocalView;
-    using GridView = typename GridGeometry::GridView;
+    using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
     using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
     using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
 
@@ -115,14 +114,6 @@
         else
             bcTypes.setAllNeumann();
 
-         /*!
-          * TODO:dumux-course-task:
-          * dumux-course-task:
-          * set Dirichlet conditions for the energy equation on the left boundary
-          * and Neumann everywhere else
-          * think about: is there anything necessary to do here?
-          */
-
         return bcTypes;
     }
 
@@ -135,13 +126,6 @@
     PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
     {
         return initialAtPos(globalPos);
-
-         /*!
-          * TODO:dumux-course-task:
-          * dumux-course-task:
-          * set Dirichlet conditions for the energy equation on the left boundary
-          * think about: is there anything necessary to do here?
-          */
     }
 
     /*!
@@ -156,19 +140,14 @@
         NumEqVector values(0.0);
 
         // if we are inside the injection zone set inflow Neumann boundary conditions
-        if (injectionActive() && onInjectionBoundary(globalPos))
+         if (injectionActive() && onInjectionBoundary(globalPos))
         {
+        
             // inject nitrogen. negative values mean injection
             // units kg/(s*m^2)
             values[Indices::conti0EqIdx + FluidSystem::N2Idx] = -1e-4;
             values[Indices::conti0EqIdx + FluidSystem::H2OIdx] = 0.0;
-
-         /*!
-          * TODO:dumux-course-task:
-          * dumux-course-task:
-          * set Neumann noflow conditions for the energy equation everywhere else except the left boundary
-          * hint: use Indices::energyEqIdx) for that (if required)
-          */
+            values[Indices::energyEqIdx] = 0.0;
         }
 
         return values;
@@ -204,20 +183,17 @@
         values[Indices::pressureIdx] = pw;
         values[Indices::saturationIdx] = 0.0;
 
-        /*!
-        *  TODO:dumux-course-task:
-        * set a temperature gradient of 0.03 K per m beginning at 283 K here.
-        * Hint: you can use aquiferDepth_ and the globalPos similar to the pressure gradient
-        * use globalPos[0] and globalPos[1] to implement the high temperature lens with 380 K
-        * Hint : use Indices::temperatureIdx to address the initial values for temperature
-        */
+        values[Indices::temperatureIdx] = 283.0 + (aquiferDepth_ - globalPos[1])*0.03;
+        if (globalPos[0] > 20 - eps_ && globalPos[0] < 30 + eps_ && globalPos[1] > 5 - eps_ && globalPos[1] < 35 + eps_)
+            values[Indices::temperatureIdx] = 380;
+
         return values;
     }
 
     //! set the time for the time dependent boundary conditions (called from main)
     void setTime(Scalar time)
     { time_ = time; }
-
+    
     //! Return true if the injection is currently active
     bool injectionActive() const
     { return time_ < injectionDuration_; }
diff -ruN exercises/exercise-basic/injection2pproblem.hh exercises/solution/exercise-basic/injection2pproblem.hh
--- exercises/exercise-basic/injection2pproblem.hh	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/injection2pproblem.hh	1970-01-01 01:00:00.000000000 +0100
@@ -1,223 +0,0 @@
-// -*- 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 3 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 two-phase porousmediumflow problem for exercise-basic
- */
-
-#ifndef DUMUX_EX_BASIC_PROBLEM_2P_HH
-#define DUMUX_EX_BASIC_PROBLEM_2P_HH
-
-#include <dumux/common/properties.hh>
-#include <dumux/common/boundarytypes.hh>
-#include <dumux/common/numeqvector.hh>
-#include <dumux/porousmediumflow/problem.hh>
-
-namespace Dumux {
-
-/*!
- * \ingroup TwoPModel
- * \ingroup ImplicitTestProblems
- * \brief Gas injection problem where a gas (here  nitrogen) is injected into a fully
- *        water saturated medium. During buoyancy driven upward migration the gas
- *        passes a high temperature area.
- *
- * The domain is sized 60 m times 40 m.
- *
- * For the mass conservation equation neumann boundary conditions are used on
- * the top, on the bottom and on the right of the domain, while dirichlet conditions
- * apply on the left boundary.
- *
- * Gas is injected at the right boundary from 7 m to 15 m at a rate of
- * 0.001 kg/(s m), the remaining neumann boundaries are no-flow
- * boundaries.
- *
- * At the dirichlet boundaries a hydrostatic pressure and a gas saturation of zero a
- *
- * This problem uses the \ref TwoPModel model.
- */
-template<class TypeTag>
-class Injection2PProblem : public PorousMediumFlowProblem<TypeTag>
-{
-    using ParentType = PorousMediumFlowProblem<TypeTag>;
-    using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
-    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
-    using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
-    using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
-    using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
-    using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
-    using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;
-    using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
-    using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
-
-    static constexpr int dimWorld = GridView::dimensionworld;
-    using Element = typename GridView::template Codim<0>::Entity;
-    using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
-
-public:
-    Injection2PProblem(std::shared_ptr<const GridGeometry> gridGeometry)
-    : ParentType(gridGeometry)
-    {
-        // initialize the tables of the fluid system
-        FluidSystem::init(/*tempMin=*/273.15,
-                /*tempMax=*/423.15,
-                /*numTemp=*/50,
-                /*pMin=*/0.0,
-                /*pMax=*/30e6,
-                /*numP=*/300);
-
-        // name of the problem and output file
-        // getParam<TYPE>("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME
-        // of type TYPE given in the group GROUPNAME from the input file
-        name_ = getParam<std::string>("Problem.Name");
-        // depth of the aquifer, units: m
-        aquiferDepth_ = getParam<Scalar>("Problem.AquiferDepth");
-        // the duration of the injection, units: second
-        injectionDuration_ = getParam<Scalar>("Problem.InjectionDuration");
-    }
-
-
-    /*!
-     * \brief Returns the problem name
-     *
-     * This is used as a prefix for files generated by the simulation.
-     */
-    std::string name() const
-    { return name_+"-2p"; }
-
-
-    /*!
-     * \brief Specifies which kind of boundary condition should be
-     *        used for which equation on a given boundary segment.
-     *
-     * \param globalPos The position for which the bc type should be evaluated
-     */
-    BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
-    {
-        BoundaryTypes bcTypes;
-        // set the left of the domain (with the global position in "0 = x" direction as a Dirichlet boundary
-        if (globalPos[0] < eps_)
-            bcTypes.setAllDirichlet();
-        // set all other as Neumann boundaries
-        else
-            bcTypes.setAllNeumann();
-
-        return bcTypes;
-    }
-
-    /*!
-     * \brief Evaluates the boundary conditions for a Dirichlet
-     *        boundary segment
-     *
-     * \param globalPos The global position
-     */
-    PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
-    {
-        return initialAtPos(globalPos);
-    }
-
-    /*!
-     * \brief Evaluate the boundary conditions for a neumann
-     *        boundary segment.
-     *
-     * \param globalPos The position of the integration point of the boundary segment.
-     */
-    NumEqVector neumannAtPos(const GlobalPosition &globalPos) const
-    {
-        // initialize values to zero, i.e. no-flow Neumann boundary conditions
-        NumEqVector values(0.0);
-
-        // if we are inside the injection zone set inflow Neumann boundary conditions
-        // using < boundary + eps_ or > boundary - eps_ is safer for floating point comparisons
-        // than using <= or >= as it is robust with regard to imprecision introduced by rounding errors.
-        if (injectionActive() && onInjectionBoundary(globalPos))
-        {
-            // inject nitrogen. negative values mean injection
-            // units kg/(s*m^2)
-            values[Indices::conti0EqIdx + FluidSystem::N2Idx] = -1e-4;
-            values[Indices::conti0EqIdx + FluidSystem::H2OIdx] = 0.0;
-        }
-
-        return values;
-    }
-
-
-    /*!
-     * \brief Evaluate the source term for all phases within a given
-     *        sub-control-volume.
-     *
-     * \param globalPos The position for which the source term should be evaluated
-     */
-    NumEqVector sourceAtPos(const GlobalPosition &globalPos) const
-    {
-        return NumEqVector(0.0);
-    }
-
-    /*!
-     * \brief Evaluate the initial value for a control volume.
-     *
-     * \param globalPos The position for which the initial condition should be evaluated
-     */
-    PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
-    {
-        PrimaryVariables values(0.0);
-
-        // get the water density at atmospheric conditions
-        const Scalar densityW = FluidSystem::H2O::liquidDensity(this->spatialParams().temperatureAtPos(globalPos), 1.0e5);
-
-        // assume an initially hydrostatic liquid pressure profile
-        // note: we subtract rho_w*g*h because g is defined negative
-        const Scalar pw = 1.0e5 - densityW*this->spatialParams().gravity(globalPos)[dimWorld-1]*(aquiferDepth_ - globalPos[dimWorld-1]);
-
-        values[Indices::pressureIdx] = pw;
-        values[Indices::saturationIdx] = 0.0;
-
-        return values;
-    }
-
-    // \}
-
-    //! set the time for the time dependent boundary conditions (called from main)
-    void setTime(Scalar time)
-    { time_ = time; }
-
-    //! Return true if the injection is currently active
-    bool injectionActive() const
-    { return time_ < injectionDuration_; }
-
-    //! Return true if the given position is in the injection boundary region
-    bool onInjectionBoundary(const GlobalPosition& globalPos) const
-    {
-        return globalPos[1] < 15. + eps_
-            && globalPos[1] > 7. - eps_
-            && globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_;
-    }
-
-private:
-    static constexpr Scalar eps_ = 1e-6;
-    std::string name_; //! Problem name
-    Scalar aquiferDepth_; //! Depth of the aquifer in m
-    Scalar injectionDuration_; //! Duration of the injection in seconds
-    Scalar time_;
-};
-
-} //end namespace Dumux
-
-#endif
diff -ruN exercises/exercise-basic/params.input exercises/solution/exercise-basic/params.input
--- exercises/exercise-basic/params.input	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/params.input	2023-04-26 14:37:49.789150797 +0200
@@ -1,6 +1,6 @@
 [TimeLoop]
 DtInitial = 3600 # in seconds
-TEnd = 3.154e9 # in seconds, i.e one hundred years
+TEnd = 3.154e9 # in seconds, i.e ten years
 
 [Grid]
 UpperRight = 60 40
@@ -24,7 +24,7 @@
 Aquifer.Snr = 0.0
 
 # these parameters are only used in the nonisothermal model. Uncomment them for that
-#[Component]
-#SolidDensity = 2700 # solid density of granite
-#SolidThermalConductivity = 2.8 # solid thermal conducitivity of granite
-#SolidHeatCapacity = 790 # solid heat capacity of granite
+[Component]
+SolidDensity = 2700 # solid density of granite
+SolidThermalConductivity = 2.8 # solid thermal conducitivity of granite
+SolidHeatCapacity = 790 # solid heat capacity of granite
diff -ruN exercises/exercise-basic/properties2p2c.hh exercises/solution/exercise-basic/properties2p2c.hh
--- exercises/exercise-basic/properties2p2c.hh	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/properties2p2c.hh	1970-01-01 01:00:00.000000000 +0100
@@ -1,78 +0,0 @@
-// -*- 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 3 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 two-phase two-component porousmediumflow properties file for exercise-basic
- */
-
-#ifndef DUMUX_EX_BASIC_PROPERTIES_2P2C_HH
-#define DUMUX_EX_BASIC_PROPERTIES_2P2C_HH
-
-#include <dune/grid/yaspgrid.hh>
-
-#include <dumux/discretization/cctpfa.hh>
-#include <dumux/porousmediumflow/2p2c/model.hh>
-#include <dumux/material/fluidsystems/h2on2.hh>
-
-#include "injection2p2cproblem.hh"
-#include "injection2pspatialparams.hh"
-
-namespace Dumux::Properties {
-
-// Create new type tags
-namespace TTag {
-struct Injection2p2c { using InheritsFrom = std::tuple<TwoPTwoC>; };
-struct Injection2p2cCC { using InheritsFrom = std::tuple<Injection2p2c, CCTpfaModel>; };
-} // end namespace TTag
-
-// Set the grid type
-template<class TypeTag>
-struct Grid<TypeTag, TTag::Injection2p2c> { using type = Dune::YaspGrid<2>; };
-
-// Set the problem property
-template<class TypeTag>
-struct Problem<TypeTag, TTag::Injection2p2c> { using type = Injection2p2cProblem<TypeTag>; };
-
-// Set the spatial parameters
-template<class TypeTag>
-struct SpatialParams<TypeTag, TTag::Injection2p2c>
-{
-private:
-    using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
-    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
-public:
-    using type = InjectionSpatialParams<GridGeometry, Scalar>;
-};
-
-// Set fluid configuration
-template<class TypeTag>
-struct FluidSystem<TypeTag, TTag::Injection2p2c>
-{
-    using type = FluidSystems::H2ON2< GetPropType<TypeTag, Properties::Scalar>,
-                                      FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true> >;
-};
-
-// Define whether mole (true) or mass (false) fractions are used
-template<class TypeTag>
-struct UseMoles<TypeTag, TTag::Injection2p2c> { static constexpr bool value = true; };
-
-} // end namespace Dumux::Properties
-
-#endif
diff -ruN exercises/exercise-basic/properties2p.hh exercises/solution/exercise-basic/properties2p.hh
--- exercises/exercise-basic/properties2p.hh	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/properties2p.hh	1970-01-01 01:00:00.000000000 +0100
@@ -1,75 +0,0 @@
-// -*- 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 3 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 two-phase porousmediumflow properties file for exercise-basic
- */
-
-#ifndef DUMUX_EX_BASIC_PROPERTIES_2P_HH
-#define DUMUX_EX_BASIC_PROPERTIES_2P_HH
-
-#include <dune/grid/yaspgrid.hh>
-
-#include <dumux/discretization/cctpfa.hh>
-#include <dumux/porousmediumflow/2p/model.hh>
-#include <dumux/material/fluidsystems/h2on2.hh>
-
-#include "injection2pproblem.hh"
-#include "injection2pspatialparams.hh"
-
-namespace Dumux::Properties {
-
-// define the TypeTag for this problem with a cell-centered two-point flux approximation spatial discretization.
-// Create new type tags
-namespace TTag {
-struct Injection2p { using InheritsFrom = std::tuple<TwoP>; };
-struct Injection2pCC { using InheritsFrom = std::tuple<Injection2p, CCTpfaModel>; };
-} // end namespace TTag
-
-// Set the grid type
-template<class TypeTag>
-struct Grid<TypeTag, TTag::Injection2p> { using type = Dune::YaspGrid<2>; };
-
-// Set the problem property
-template<class TypeTag>
-struct Problem<TypeTag, TTag::Injection2p> { using type = Injection2PProblem<TypeTag>; };
-
-// Set the spatial parameters
-template<class TypeTag>
-struct SpatialParams<TypeTag, TTag::Injection2p>
-{
-private:
-    using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
-    using Scalar = GetPropType<TypeTag, Properties::Scalar>;
-public:
-    using type = InjectionSpatialParams<GridGeometry, Scalar>;
-};
-
-// Set fluid configuration
-template<class TypeTag>
-struct FluidSystem<TypeTag, TTag::Injection2p>
-{
-    using type = FluidSystems::H2ON2< GetPropType<TypeTag, Properties::Scalar>,
-                                      FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/ true> >;
-};
-
-} // end namespace Dumux::Properties
-
-#endif
diff -ruN exercises/exercise-basic/properties2pni.hh exercises/solution/exercise-basic/properties2pni.hh
--- exercises/exercise-basic/properties2pni.hh	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/properties2pni.hh	2023-04-26 14:37:49.789150797 +0200
@@ -31,18 +31,14 @@
 #include <dumux/porousmediumflow/2p/model.hh>
 #include <dumux/material/fluidsystems/h2on2.hh>
 
-#include "injection2pniproblem.hh"
 #include "injection2pspatialparams.hh"
+#include "injection2pniproblem.hh"
 
 namespace Dumux::Properties {
 
- /*!
-* TODO:dumux-course-task 4
-* Inherit from the TwoPNI model instead of TwoP here
-*/
 // Create new type tags
 namespace TTag {
-struct Injection2pNITypeTag { using InheritsFrom = std::tuple<TwoP>; };
+struct Injection2pNITypeTag { using InheritsFrom = std::tuple<TwoPNI>; };
 struct Injection2pNICC { using InheritsFrom = std::tuple<Injection2pNITypeTag, CCTpfaModel>; };
 } // end namespace TTag
 
@@ -69,8 +65,8 @@
 template<class TypeTag>
 struct FluidSystem<TypeTag, TTag::Injection2pNITypeTag>
 {
-    using type = FluidSystems::H2ON2< GetPropType<TypeTag, Properties::Scalar>,
-                                      FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/true> >;
+    using type = FluidSystems::H2ON2<GetPropType<TypeTag, Properties::Scalar>,
+                                     FluidSystems::H2ON2DefaultPolicy</*fastButSimplifiedRelations=*/true>>;
 };
 
 } // end namespace Dumux::Properties
diff -ruN exercises/exercise-basic/README.md exercises/solution/exercise-basic/README.md
--- exercises/exercise-basic/README.md	2023-06-01 14:31:33.149062999 +0200
+++ exercises/solution/exercise-basic/README.md	1970-01-01 01:00:00.000000000 +0100
@@ -1,106 +0,0 @@
-# Exercise Basics (DuMuX course)
-<br>
-
-## Problem set-up
-
-N$_2$ is injected in an aquifer previously saturated with water with an injection rate of 0.0001 kg/(s*m$^2$).
-The aquifer is situated 2700 m below sea level and the domain size is 60 m x 40 m. It consists of two layers, a moderately permeable one ($\Omega_1$) and a lower permeable one ($\Omega_2$).
-
-<img src="https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/raw/master/exercises/extradoc/exercise1_setup.png" width="1000">
-
-## Preparing the exercise
-
-* Navigate to the directory `dumux-course/exercises/exercise-basic`
-
-This exercise deals with two problems: a two-phase immiscible problem (__2p__) and a two-phase compositional problem (__2p2c__). They both set up the same scenario with the difference that the 2p2c assumes a miscible fluid state for the two fluids (water and gaseous N$_2$) and the 2p model assumes an immiscible fluid state.
-
-<br><br>
-### Task 1: Getting familiar with the code
-<hr>
-
-Locate all the files you will need for this exercise
-* The __main file__ for the __2p__ problem : `2pmain.cc`
-* The __main file__ for the __2p2c__ problem : `2p2cmain.cc`
-* The __problem file__ for the __2p__ problem: `injection2pproblem.hh`
-* The __problem file__ for the __2p2c__ problem: `injection2p2cproblem.hh`
-* The __properties file__ for the __2p__ problem: `properties2p.hh`
-* The __properties file__ for the __2p2c__ problem: `properties2p2c.hh`
-* The shared __spatial parameters file__: `injection2pspatialparams.hh`
-* The shared __input file__: `params.input`
-
-<br><br>
-### Task 2: Compiling and running an executable
-<hr>
-
-* Change to the build-directory
-
-```bash
-cd ../../build-cmake/exercises/exercise-basic
-```
-
-* Compile both executables `exercise_basic_2p` and `exercise_basic_2p2c`
-
-```bash
-make exercise_basic_2p exercise_basic_2p2c
-```
-
-* Execute the two problems and inspect the result
-
-```bash
-./exercise_basic_2p params.input
-./exercise_basic_2p2c params.input
-```
-
-* you can look at the results with paraview
-
-```bash
-paraview injection-2p2c.pvd
-```
-
-<br><br>
-### Task 3: Setting up a new executable (for a non-isothermal simulation)
-<hr>
-
-* Copy the main file `2pmain.cc` and rename it to `2pnimain.cc`
-* In  `2pnimain.cc`, include the header `properties2pni.hh` instead of `properties2p.hh`.
-* In  `2pnimain.cc`, change `Injection2pCC` to `Injection2pNICC` in the line `using TypeTag = Properties::TTag::Injection2pNICC;`
-* Add a new executable in `CMakeLists.txt` by adding the lines
-
-```cmake
-# the two-phase non-isothermal simulation program
-dumux_add_test(NAME exercise_basic_2pni
-              SOURCES 2pnimain.cc)
-```
-
-* Test that everything compiles without error
-
-```bash
-make # should rerun cmake
-make exercise_basic_2pni # builds new executable
-```
-
-<br><br>
-### Task 4: Setting up a non-isothermal __2pni__ test problem
-<hr>
-
-* Open the files `injection2pniproblem.hh` and `properties2pni.hh`.
-These are copies of the `injection2pproblem.hh` and `properties2p.hh` files, with some useful comments on how to implement a non-isothermal model.
-Look for comments containing
-
-```c++
-// TODO: dumux-course-task 4
-```
-
-* The following set-up should be realized:
-
-  __Boundary conditions:__ Dirichlet conditions at the left boundary. For the primary variable __temperature__ use a varying temperature of <br/>
-$`\displaystyle T(y) = 283~\text{K} + 0.03~\frac{\text{K}}{\text{m}} \cdot \left( d_\text{aquifer} - y \right)`$, <br/>
-with the aquifer depth
-$\displaystyle d_\text{aquifer}=2700~\text{m}$.
-Assign Neumann no-flow for the energy balance to the rest of the boundaries.
-
-  __Initial conditions:__ The same temperature gradient as in the boundary conditions with an exception in the subdomain (20 < x < 30, 5 < y < 35), where you assign a constant initial temperature of 380 K.
-
-<img src="https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/raw/master/exercises/extradoc/exercise1_nonisothermal.png" width="800">
-
-The non-isothermal model requires additional parameters like the thermal conductivity of the solid component. They are already implemented and set in `params.input`, you just need to _uncomment_ them.