diff --git a/dumux/freeflow/navierstokes/model.hh b/dumux/freeflow/navierstokes/model.hh
index a4f6c02a9e64869d9fb1cf7bcbc4929917a17207..417604bddb29d945a44864ee461483b5e4fe9257 100644
--- a/dumux/freeflow/navierstokes/model.hh
+++ b/dumux/freeflow/navierstokes/model.hh
@@ -103,6 +103,12 @@ struct NavierStokesModelTraits
 
     //! the indices
     using Indices = NavierStokesIndices<dim()>;
+
+    //! return the name of the primary variables
+    static std::string primaryVariableName(int pvIdx, int state = 0)
+    {
+        return pvIdx == 0 ? "p" : "faceVelocity";
+    }
 };
 
 /*!
diff --git a/dumux/io/loadsolution.hh b/dumux/io/loadsolution.hh
index b5f07746100b515253dde5a25cee1cbf5e903d09..aa2cdd60c03e0cd256780b877ccfadb3a6a52219 100644
--- a/dumux/io/loadsolution.hh
+++ b/dumux/io/loadsolution.hh
@@ -30,9 +30,11 @@
 #include <unordered_set>
 
 #include <dune/common/exceptions.hh>
+#include <dune/common/indices.hh>
 
 #include <dumux/common/parameters.hh>
 #include <dumux/common/typetraits/isvalid.hh>
+#include <dumux/common/typetraits/vector.hh>
 #include <dumux/io/vtk/vtkreader.hh>
 
 namespace Dumux {
@@ -119,6 +121,65 @@ auto loadSolutionFromVtkFile(const std::string fileName,
     }
 }
 
+/*!
+ * \ingroup InputOutput
+ * \brief helper function to read from a file into a solution vector
+ */
+template <class SolutionVector, class PvNamesFunc>
+auto loadSolutionFromVtkFile(const std::string fileName,
+                             const VTKReader::DataType& dataType,
+                             PvNamesFunc&& pvNamesFunc,
+                             SolutionVector& sol)
+-> typename std::enable_if_t<decltype(isMultiTypeBlockVector<SolutionVector>())::value, void>
+{}
+
+/*!
+ * \ingroup InputOutput
+ * \brief helper function to read from two files into a staggered solution vector
+ */
+template <class SolutionVector, class PvNamesFunc>
+auto loadStaggeredSolutionFromVtkFiles(const std::string fileName,
+                                       PvNamesFunc&& pvNamesFunc,
+                                       SolutionVector& sol)
+-> typename std::enable_if_t<decltype(!isMultiTypeBlockVector<SolutionVector>())::value, void>
+{}
+
+/*!
+ * \ingroup InputOutput
+ * \brief helper function to read from two files into a staggered solution vector
+ */
+template <class SolutionVector, class PvNamesFunc>
+auto loadStaggeredSolutionFromVtkFiles(const std::string baseFileName,
+                                       PvNamesFunc&& pvNamesFunc,
+                                       SolutionVector& sol)
+-> typename std::enable_if_t<decltype(isMultiTypeBlockVector<SolutionVector>())::value, void>
+{
+
+    // assume that the first component contains the cell data
+    auto& cellSol = sol[Dune::index_constant<0>{}];
+    using CellPrimaryVariables = typename std::decay_t<decltype(cellSol)>::block_type;
+    using Scalar = typename CellPrimaryVariables::field_type;
+    VTKReader cellVtk(baseFileName + ".vtu");
+    for (size_t pvIdx = 0; pvIdx < CellPrimaryVariables::dimension; ++pvIdx)
+    {
+        const auto vec = cellVtk.readData<std::vector<Scalar>>(pvNamesFunc(pvIdx),
+                                                               VTKReader::DataType::cellData);
+        for (size_t i = 0; i < cellSol.size(); ++i)
+            cellSol[i][pvIdx] = vec[i];
+    }
+
+    // assume that the second component contains the face data
+    auto& faceSol = sol[Dune::index_constant<1>{}];
+    using FacePrimaryVariables = typename std::decay_t<decltype(faceSol)>::block_type;
+    auto nameSize = baseFileName.size();
+    // assume that baseFileName contains numbers like '-000123' in the end
+    VTKReader faceVtk(baseFileName.substr(0, nameSize - 6) + "-face" + baseFileName.substr(nameSize - 6) + ".vtp");
+    const auto vec = faceVtk.readData<std::vector<Scalar>>(pvNamesFunc(CellPrimaryVariables::dimension),
+                                                           VTKReader::DataType::pointData);
+    for (size_t i = 0; i < faceSol.size(); ++i)
+        faceSol[i][0] = std::accumulate(&vec[3*i], &vec[3*(i+1)], 0.0);
+}
+
 /*!
  * \ingroup InputOutput
  * \brief helper function to determine the primray variable names of a model with privar state
@@ -129,12 +190,12 @@ std::string primaryVariableName(int pvIdx, int state)
     static auto numStates = (1 << ModelTraits::numPhases()) - 1;
     const auto paramNameWithState = "LoadSolution.PriVarNamesState" + std::to_string(state);
 
-    if (haveParam("LoadSolution.PriVarNames") && !haveParam(paramNameWithState))
+    if (hasParam("LoadSolution.PriVarNames") && !hasParam(paramNameWithState))
     {
         DUNE_THROW(Dune::NotImplemented, "please provide LoadSolution.PriVarNamesState1..." << numStates
                    << " or remove LoadSolution.PriVarNames to use default names");
     }
-    else if (haveParam(paramNameWithState))
+    else if (hasParam(paramNameWithState))
     {
         const auto pvNames = getParam<std::vector<std::string>>(paramNameWithState);
         return pvNames[pvIdx];
@@ -150,7 +211,7 @@ std::string primaryVariableName(int pvIdx, int state)
 template<class ModelTraits>
 std::string primaryVariableName(int pvIdx)
 {
-    if (haveParam("LoadSolution.PriVarNames"))
+    if (hasParam("LoadSolution.PriVarNames"))
     {
         static auto pvNames = getParam<std::vector<std::string>>("LoadSolution.PriVarNames");
         return pvNames[pvIdx];
@@ -179,6 +240,8 @@ void loadSolution(const std::string& fileName,
                               ? VTKReader::DataType::pointData : VTKReader::DataType::cellData;
         loadSolutionFromVtkFile(fileName, dataType, pvNamesFunc, sol);
     }
+    else if (extension == fileName && discMethod == DiscretizationMethod::staggered)
+        loadStaggeredSolutionFromVtkFiles(fileName, pvNamesFunc, sol);
     else
         DUNE_THROW(Dune::NotImplemented, "loadSolution for extension " << extension);
 }
diff --git a/test/freeflow/navierstokes/CMakeLists.txt b/test/freeflow/navierstokes/CMakeLists.txt
index d74193f31913083ef9ac6272c0f6b4870c41e001..cdcf5b0a93347c16868bda28471c476ae417aad9 100644
--- a/test/freeflow/navierstokes/CMakeLists.txt
+++ b/test/freeflow/navierstokes/CMakeLists.txt
@@ -70,7 +70,20 @@ dune_add_test(NAME test_channel_navierstokes
               CMD_ARGS       --script fuzzy
                              --files ${CMAKE_SOURCE_DIR}/test/references/channel-navierstokes-reference.vtu
                                      ${CMAKE_CURRENT_BINARY_DIR}/test_channel_navierstokes-00002.vtu
-                             --command "${CMAKE_CURRENT_BINARY_DIR}/test_channel_navierstokes")
+                             --command "${CMAKE_CURRENT_BINARY_DIR}/test_channel_navierstokes -Vtk.WriteFaceData 1")
+
+dune_add_test(NAME test_channel_navierstokes_restart
+              SOURCES test_channel.cc
+              COMPILE_DEFINITIONS ENABLE_NAVIERSTOKES=1
+              CMAKE_GUARD HAVE_UMFPACK
+              COMMAND ${CMAKE_SOURCE_DIR}/bin/testing/runtest.py
+              CMD_ARGS       --script fuzzy
+                             --files ${CMAKE_SOURCE_DIR}/test/references/channel-navierstokes-reference.vtu
+                                     ${CMAKE_CURRENT_BINARY_DIR}/test_channel_navierstokes_restart-00001.vtu
+                             --command "${CMAKE_CURRENT_BINARY_DIR}/test_channel_navierstokes -Vtk.WriteFaceData 1 -TimeLoop.DtInitial 1 -Restart.Time 1 -Restart.File test_channel_navierstokes-00001 -Problem.Name test_channel_navierstokes_restart")
+
+# the restart test has to run after the test that produces the corresponding vtu file
+set_tests_properties(test_channel_navierstokes_restart PROPERTIES DEPENDS test_channel_navierstokes)
 
 dune_add_test(NAME test_stokes_donea_no_caching
               SOURCES test_donea.cc
diff --git a/test/freeflow/navierstokes/test_channel.cc b/test/freeflow/navierstokes/test_channel.cc
index bee7ed183fd72be3295274245c615602bc303e85..57d5345763ac9c51745d83b45aebe62ea1951220 100644
--- a/test/freeflow/navierstokes/test_channel.cc
+++ b/test/freeflow/navierstokes/test_channel.cc
@@ -50,6 +50,7 @@
 
 #include <dumux/io/staggeredvtkoutputmodule.hh>
 #include <dumux/io/grid/gridmanager.hh>
+#include <dumux/io/loadsolution.hh>
 
 #include <dumux/freeflow/navierstokes/staggered/fluxoversurface.hh>
 
@@ -129,14 +130,7 @@ int main(int argc, char** argv) try
     auto dt = getParam<Scalar>("TimeLoop.DtInitial");
 
     // check if we are about to restart a previously interrupted simulation
-    Scalar restartTime = 0;
-    if (Parameters::getTree().hasKey("Restart") || Parameters::getTree().hasKey("TimeLoop.Restart"))
-        restartTime = getParam<Scalar>("TimeLoop.Restart");
-
-    // instantiate time loop
-    auto timeLoop = std::make_shared<CheckPointTimeLoop<Scalar>>(restartTime, dt, tEnd);
-    timeLoop->setMaxTimeStepSize(maxDt);
-    problem->setTimeLoop(timeLoop);
+    Scalar restartTime = getParam<Scalar>("Restart.Time", 0);
 
     // the solution vector
     using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector);
@@ -145,9 +139,21 @@ int main(int argc, char** argv) try
     SolutionVector x;
     x[FVGridGeometry::cellCenterIdx()].resize(numDofsCellCenter);
     x[FVGridGeometry::faceIdx()].resize(numDofsFace);
-    problem->applyInitialSolution(x);
+    if (restartTime > 0)
+    {
+        using ModelTraits = typename GET_PROP_TYPE(TypeTag, ModelTraits);
+        auto fileName = getParam<std::string>("Restart.File");
+        loadSolution(fileName, FVGridGeometry::discMethod, primaryVariableName<ModelTraits>, x);
+    }
+    else
+        problem->applyInitialSolution(x);
     auto xOld = x;
 
+    // instantiate time loop
+    auto timeLoop = std::make_shared<CheckPointTimeLoop<Scalar>>(restartTime, dt, tEnd);
+    timeLoop->setMaxTimeStepSize(maxDt);
+    problem->setTimeLoop(timeLoop);
+
     // the grid variables
     using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables);
     auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry);
@@ -157,7 +163,7 @@ int main(int argc, char** argv) try
     using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields);
     StaggeredVtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, x, problem->name());
     VtkOutputFields::init(vtkWriter); //!< Add model specific output fields
-    vtkWriter.write(0.0);
+    vtkWriter.write(restartTime);
 
     // the assembler with time loop for instationary problem
     using Assembler = StaggeredFVAssembler<TypeTag, DiffMethod::numeric>;