diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index d83622ee1297dad1b7093a831a93aedb47450284..9d2b66f1e41d8d73dfabceffe4e0b56fea2b5fb9 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -174,6 +174,7 @@ if(PUGS_HAS_HDF5)
     test_checkpointing_IQuadratureDescriptor.cpp
     test_checkpointing_IDiscreteFunctionDescriptor.cpp
     test_checkpointing_IInterfaceDescriptor.cpp
+    test_checkpointing_INamedDiscreteData.cpp
     test_checkpointing_ItemType.cpp
     test_checkpointing_IWriter.cpp
     test_checkpointing_IZoneDescriptor.cpp
diff --git a/tests/checkpointing_Connectivity_utilities.hpp b/tests/checkpointing_Connectivity_utilities.hpp
index a107ed78f54a8ee814b9e3085d286892df777aea..c71f4ed629f9e2e21a5d593d777609c05bce4e5a 100644
--- a/tests/checkpointing_Connectivity_utilities.hpp
+++ b/tests/checkpointing_Connectivity_utilities.hpp
@@ -187,6 +187,47 @@ isSameConnectivity(const Connectivity<Dimension>& connectivity, const Connectivi
   return same;
 }
 
+PUGS_INLINE bool
+isSameConnectivity(const IConnectivity& i_connectivity, const IConnectivity& read_i_connectivity)
+{
+  if (i_connectivity.dimension() != read_i_connectivity.dimension()) {
+    return false;
+  } else {
+    switch (i_connectivity.dimension()) {
+    case 1: {
+      constexpr size_t Dimension = 1;
+
+      const Connectivity<Dimension>& connectivity = dynamic_cast<const Connectivity<Dimension>&>(i_connectivity);
+      const Connectivity<Dimension>& read_connectivity =
+        dynamic_cast<const Connectivity<Dimension>&>(read_i_connectivity);
+
+      return isSameConnectivity(connectivity, read_connectivity);
+    }
+    case 2: {
+      constexpr size_t Dimension = 2;
+
+      const Connectivity<Dimension>& connectivity = dynamic_cast<const Connectivity<Dimension>&>(i_connectivity);
+      const Connectivity<Dimension>& read_connectivity =
+        dynamic_cast<const Connectivity<Dimension>&>(read_i_connectivity);
+
+      return isSameConnectivity(connectivity, read_connectivity);
+    }
+    case 3: {
+      constexpr size_t Dimension = 3;
+
+      const Connectivity<Dimension>& connectivity = dynamic_cast<const Connectivity<Dimension>&>(i_connectivity);
+      const Connectivity<Dimension>& read_connectivity =
+        dynamic_cast<const Connectivity<Dimension>&>(read_i_connectivity);
+
+      return isSameConnectivity(connectivity, read_connectivity);
+    }
+    default: {
+      return false;
+    }
+    }
+  }
+}
+
 }   // namespace test_only
 
 #endif   // CHECKPOINTING_CONNECTIVITY_UTILITIES_HPP
diff --git a/tests/test_checkpointing_INamedDiscreteData.cpp b/tests/test_checkpointing_INamedDiscreteData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d11e29dca2f4d475f8b8a14a8a2e6e3696d961ce
--- /dev/null
+++ b/tests/test_checkpointing_INamedDiscreteData.cpp
@@ -0,0 +1,555 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_all.hpp>
+
+#include <utils/Messenger.hpp>
+
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <mesh/ItemArrayVariant.hpp>
+#include <mesh/ItemValueVariant.hpp>
+#include <mesh/Mesh.hpp>
+#include <output/INamedDiscreteData.hpp>
+#include <output/NamedDiscreteFunction.hpp>
+#include <output/NamedItemArrayVariant.hpp>
+#include <output/NamedItemValueVariant.hpp>
+#include <scheme/DiscreteFunctionVariant.hpp>
+#include <utils/GlobalVariableManager.hpp>
+#include <utils/checkpointing/ReadINamedDiscreteData.hpp>
+#include <utils/checkpointing/ResumingData.hpp>
+#include <utils/checkpointing/WriteINamedDiscreteData.hpp>
+
+#include <MeshDataBaseForTests.hpp>
+#include <checkpointing_Connectivity_utilities.hpp>
+#include <checkpointing_Mesh_utilities.hpp>
+
+#include <filesystem>
+
+// clazy:excludeall=non-pod-global-static
+
+namespace test_only
+{
+
+PUGS_INLINE void
+INamedDiscreteData_check_is_same_type(const INamedDiscreteData::Type& type, const EmbeddedData& e_read_data)
+{
+  REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()));
+
+  std::shared_ptr<const INamedDiscreteData> p_new_data_v =
+    dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()).data_ptr();
+
+  REQUIRE(p_new_data_v->type() == type);
+}
+
+PUGS_INLINE void
+INamedDiscreteData_check_is_same_name(const std::string& name, const EmbeddedData& e_read_data)
+{
+  REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()));
+
+  std::shared_ptr<const INamedDiscreteData> p_new_data_v =
+    dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()).data_ptr();
+
+  REQUIRE(p_new_data_v->name() == name);
+}
+
+template <typename DataType>
+PUGS_INLINE void
+INamedDiscreteData_check_is_same_data(const DiscreteFunctionP0<DataType>& reference, const EmbeddedData& e_read_data)
+{
+  auto same_value = [](const auto& a, const auto& b) -> bool {
+    bool same = true;
+    for (size_t i = 0; i < a.size(); ++i) {
+      same &= (a[i] == b[i]);
+    }
+    return parallel::allReduceAnd(same);
+  };
+
+  REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()));
+
+  const INamedDiscreteData& i_named_discrete_data =
+    *dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()).data_ptr();
+
+  REQUIRE_NOTHROW(dynamic_cast<const NamedDiscreteFunction&>(i_named_discrete_data));
+
+  const NamedDiscreteFunction& named_discrete_function =
+    dynamic_cast<const NamedDiscreteFunction&>(i_named_discrete_data);
+
+  using DiscreteFunctionT = DiscreteFunctionP0<const DataType>;
+
+  DiscreteFunctionT read_data = named_discrete_function.discreteFunctionVariant()->get<DiscreteFunctionT>();
+
+  REQUIRE(test_only::isSameMesh(read_data.meshVariant(), reference.meshVariant()));
+
+  REQUIRE(same_value(reference.cellValues().arrayView(), read_data.cellValues().arrayView()));
+}
+
+template <typename DataType>
+PUGS_INLINE void
+INamedDiscreteData_check_is_same_data(const DiscreteFunctionP0Vector<DataType>& reference,
+                                      const EmbeddedData& e_read_data)
+{
+  auto same_value = [](const auto& a, const auto& b) -> bool {
+    bool same = true;
+    for (size_t i = 0; i < a.numberOfRows(); ++i) {
+      for (size_t j = 0; j < a.numberOfColumns(); ++j) {
+        same &= (a(i, j) == b(i, j));
+      }
+    }
+    return parallel::allReduceAnd(same);
+  };
+
+  REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()));
+
+  const INamedDiscreteData& i_named_discrete_data =
+    *dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()).data_ptr();
+
+  REQUIRE_NOTHROW(dynamic_cast<const NamedDiscreteFunction&>(i_named_discrete_data));
+
+  const NamedDiscreteFunction& named_discrete_function =
+    dynamic_cast<const NamedDiscreteFunction&>(i_named_discrete_data);
+
+  using DiscreteFunctionT = DiscreteFunctionP0Vector<const DataType>;
+
+  DiscreteFunctionT read_data = named_discrete_function.discreteFunctionVariant()->get<DiscreteFunctionT>();
+
+  REQUIRE(test_only::isSameMesh(read_data.meshVariant(), reference.meshVariant()));
+
+  REQUIRE(same_value(reference.cellArrays().tableView(), read_data.cellArrays().tableView()));
+}
+
+template <ItemType item_type, typename DataType>
+PUGS_INLINE void
+INamedDiscreteData_check_is_same_data(const ItemValue<DataType, item_type>& reference, const EmbeddedData& e_read_data)
+{
+  auto same_value = [](const auto& a, const auto& b) -> bool {
+    bool same = true;
+    for (size_t i = 0; i < a.size(); ++i) {
+      same &= (a[i] == b[i]);
+    }
+    return parallel::allReduceAnd(same);
+  };
+
+  REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()));
+
+  const INamedDiscreteData& i_named_discrete_data =
+    *dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()).data_ptr();
+
+  REQUIRE_NOTHROW(dynamic_cast<const NamedItemValueVariant&>(i_named_discrete_data));
+
+  const NamedItemValueVariant& named_item_value_variant =
+    dynamic_cast<const NamedItemValueVariant&>(i_named_discrete_data);
+
+  using ItemValueT = ItemValue<const DataType, item_type>;
+
+  ItemValueT read_data = named_item_value_variant.itemValueVariant()->get<ItemValueT>();
+
+  REQUIRE(test_only::isSameConnectivity(*read_data.connectivity_ptr(), *reference.connectivity_ptr()));
+
+  REQUIRE(same_value(reference.arrayView(), read_data.arrayView()));
+}
+
+template <ItemType item_type, typename DataType>
+PUGS_INLINE void
+INamedDiscreteData_check_is_same_data(const ItemArray<DataType, item_type>& reference, const EmbeddedData& e_read_data)
+{
+  auto same_value = [](const auto& a, const auto& b) -> bool {
+    bool same = true;
+    for (size_t i = 0; i < a.numberOfRows(); ++i) {
+      for (size_t j = 0; j < a.numberOfColumns(); ++j) {
+        same &= (a(i, j) == b(i, j));
+      }
+    }
+    return parallel::allReduceAnd(same);
+  };
+
+  REQUIRE_NOTHROW(dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()));
+
+  const INamedDiscreteData& i_named_discrete_data =
+    *dynamic_cast<const DataHandler<const INamedDiscreteData>&>(e_read_data.get()).data_ptr();
+
+  REQUIRE_NOTHROW(dynamic_cast<const NamedItemArrayVariant&>(i_named_discrete_data));
+
+  const NamedItemArrayVariant& named_item_array_variant =
+    dynamic_cast<const NamedItemArrayVariant&>(i_named_discrete_data);
+
+  using ItemArrayT = ItemArray<const DataType, item_type>;
+
+  ItemArrayT read_data = named_item_array_variant.itemArrayVariant()->get<ItemArrayT>();
+
+  REQUIRE(test_only::isSameConnectivity(*read_data.connectivity_ptr(), *reference.connectivity_ptr()));
+
+  REQUIRE(reference.sizeOfArrays() == read_data.sizeOfArrays());
+
+  REQUIRE(same_value(reference.tableView(), read_data.tableView()));
+}
+
+}   // namespace test_only
+
+TEST_CASE("checkpointing_INamedDiscreteData", "[utils/checkpointing]")
+{
+  std::string tmp_dirname;
+  {
+    {
+      if (parallel::rank() == 0) {
+        tmp_dirname = [&]() -> std::string {
+          std::string temp_filename = std::filesystem::temp_directory_path() / "pugs_checkpointing_XXXXXX";
+          return std::string{mkdtemp(&temp_filename[0])};
+        }();
+      }
+      parallel::broadcast(tmp_dirname, 0);
+    }
+    std::filesystem::path path = tmp_dirname;
+    const std::string filename = path / "checkpoint.h5";
+
+    HighFive::FileAccessProps fapl;
+    fapl.add(HighFive::MPIOFileAccess{MPI_COMM_WORLD, MPI_INFO_NULL});
+    fapl.add(HighFive::MPIOCollectiveMetadata{});
+    HighFive::File file = HighFive::File(filename, HighFive::File::Truncate, fapl);
+
+    const size_t initial_connectivity_id = GlobalVariableManager::instance().getConnectivityId();
+    const size_t initial_mesh_id         = GlobalVariableManager::instance().getMeshId();
+
+    SECTION("Mesh")
+    {
+      using R1   = TinyVector<1>;
+      using R2   = TinyVector<2>;
+      using R3   = TinyVector<3>;
+      using R1x1 = TinyMatrix<1>;
+      using R2x2 = TinyMatrix<2>;
+      using R3x3 = TinyMatrix<3>;
+
+      NamedDiscreteFunction ndf;
+
+      HighFive::Group checkpoint_group   = file.createGroup("checkpoint");
+      HighFive::Group symbol_table_group = checkpoint_group.createGroup("symbol_table");
+
+      auto mesh_1d = MeshDataBaseForTests::get().unordered1DMesh()->get<Mesh<1>>();
+
+      DiscreteFunctionP0<double> df_R_1d{mesh_1d};
+      for (CellId cell_id = 0; cell_id < mesh_1d->numberOfCells(); ++cell_id) {
+        df_R_1d[cell_id] = std::rand() / (1. * RAND_MAX / mesh_1d->numberOfCells());
+      }
+
+      DiscreteFunctionP0<R1> df_R1_1d{mesh_1d};
+      for (CellId cell_id = 0; cell_id < mesh_1d->numberOfCells(); ++cell_id) {
+        df_R1_1d[cell_id] = R1{std::rand() / (1. * RAND_MAX / mesh_1d->numberOfCells())};
+      }
+
+      DiscreteFunctionP0<R2> df_R2_1d{mesh_1d};
+      for (CellId cell_id = 0; cell_id < mesh_1d->numberOfCells(); ++cell_id) {
+        df_R2_1d[cell_id] = R2{std::rand() / (1. * RAND_MAX / mesh_1d->numberOfCells()),
+                               std::rand() / (1. * RAND_MAX / mesh_1d->numberOfCells())};
+      }
+
+      auto mesh_2d = MeshDataBaseForTests::get().hybrid2DMesh()->get<Mesh<2>>();
+
+      DiscreteFunctionP0<R3> df_R3_2d{mesh_2d};
+      for (CellId cell_id = 0; cell_id < mesh_2d->numberOfCells(); ++cell_id) {
+        df_R3_2d[cell_id] = R3{std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells()),
+                               std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells()),
+                               std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells())};
+      }
+
+      DiscreteFunctionP0<R2x2> df_R2x2_2d{mesh_2d};
+      for (CellId cell_id = 0; cell_id < mesh_2d->numberOfCells(); ++cell_id) {
+        df_R2x2_2d[cell_id] = R2x2{std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells())};
+      }
+
+      NodeValue<R2x2> iv_R2x2_2d{mesh_2d->connectivity()};
+      for (NodeId node_id = 0; node_id < mesh_2d->numberOfNodes(); ++node_id) {
+        iv_R2x2_2d[node_id] = R2x2{std::rand() / (1. * RAND_MAX / mesh_2d->numberOfNodes()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfNodes()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfNodes()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfNodes())};
+      }
+
+      FaceArray<R2x2> ia_R2x2_2d{mesh_2d->connectivity(), 3};
+      for (FaceId face_id = 0; face_id < mesh_2d->numberOfFaces(); ++face_id) {
+        for (size_t i = 0; i < ia_R2x2_2d.sizeOfArrays(); ++i) {
+          ia_R2x2_2d[face_id][i] = R2x2{std::rand() / (1. * RAND_MAX / mesh_2d->numberOfFaces()),
+                                        std::rand() / (1. * RAND_MAX / mesh_2d->numberOfFaces()),
+                                        std::rand() / (1. * RAND_MAX / mesh_2d->numberOfFaces()),
+                                        std::rand() / (1. * RAND_MAX / mesh_2d->numberOfFaces())};
+        }
+      }
+
+      DiscreteFunctionP0Vector<double> dfv_R_2d{mesh_2d, 3};
+      for (CellId cell_id = 0; cell_id < mesh_2d->numberOfCells(); ++cell_id) {
+        for (size_t i = 0; i < dfv_R_2d.size(); ++i) {
+          dfv_R_2d[cell_id][i] = std::rand() / (1. * RAND_MAX / mesh_2d->numberOfCells());
+        }
+      }
+
+      auto mesh_3d = MeshDataBaseForTests::get().hybrid3DMesh()->get<Mesh<3>>();
+
+      DiscreteFunctionP0<R3> df_R3_3d{mesh_3d};
+      for (CellId cell_id = 0; cell_id < mesh_3d->numberOfCells(); ++cell_id) {
+        df_R3_3d[cell_id] = R3{std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                               std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                               std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells())};
+      }
+
+      DiscreteFunctionP0<R1x1> df_R1x1_3d{mesh_3d};
+      for (CellId cell_id = 0; cell_id < mesh_3d->numberOfCells(); ++cell_id) {
+        df_R1x1_3d[cell_id] = R1x1{std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells())};
+      }
+
+      DiscreteFunctionP0<R3x3> df_R3x3_3d{mesh_3d};
+      for (CellId cell_id = 0; cell_id < mesh_3d->numberOfCells(); ++cell_id) {
+        df_R3x3_3d[cell_id] = R3x3{std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells()),
+                                   std::rand() / (1. * RAND_MAX / mesh_3d->numberOfCells())};
+      }
+
+      EdgeValue<R3x3> iv_R3x3_3d{mesh_3d->connectivity()};
+      for (EdgeId edge_id = 0; edge_id < mesh_3d->numberOfEdges(); ++edge_id) {
+        iv_R3x3_3d[edge_id] = R3x3{std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges()),
+                                   std::rand() / (1. * RAND_MAX / mesh_2d->numberOfEdges())};
+      }
+
+      {   // Write
+        using DataHandlerT = DataHandler<const INamedDiscreteData>;
+
+        auto new_mesh_1d_v              = test_only::duplicateMesh(std::make_shared<MeshVariant>(mesh_1d));
+        auto new_mesh_1d                = new_mesh_1d_v->get<const Mesh<1>>();
+        const auto& new_connectivity_1d = new_mesh_1d->connectivity();
+
+        DiscreteFunctionP0<const double> df_R_1d_new{new_mesh_1d_v,
+                                                     CellValue<const double>{new_connectivity_1d,
+                                                                             df_R_1d.cellValues().arrayView()}};
+        DiscreteFunctionP0<const R1> df_R1_1d_new{new_mesh_1d_v,
+                                                  CellValue<const R1>{new_connectivity_1d,
+                                                                      df_R1_1d.cellValues().arrayView()}};
+        DiscreteFunctionP0<const R2> df_R2_1d_new{new_mesh_1d_v,
+                                                  CellValue<const R2>{new_connectivity_1d,
+                                                                      df_R2_1d.cellValues().arrayView()}};
+        std::shared_ptr<const INamedDiscreteData> i_named_df_R_1d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(df_R_1d_new),
+                                                  "df_R_1d");
+
+        checkpointing::writeINamedDiscreteData("df_R_1d", EmbeddedData{std::make_shared<DataHandlerT>(i_named_df_R_1d)},
+                                               file, checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_df_R1_1d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(df_R1_1d_new),
+                                                  "df_R1_1d");
+
+        checkpointing::writeINamedDiscreteData("df_R1_1d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_df_R1_1d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_df_R2_1d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(df_R2_1d_new),
+                                                  "df_R2_1d");
+
+        checkpointing::writeINamedDiscreteData("df_R2_1d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_df_R2_1d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        auto new_mesh_2d_v              = test_only::duplicateMesh(std::make_shared<MeshVariant>(mesh_2d));
+        auto new_mesh_2d                = new_mesh_2d_v->get<const Mesh<2>>();
+        const auto& new_connectivity_2d = new_mesh_2d->connectivity();
+
+        DiscreteFunctionP0<const R3> df_R3_2d_new{new_mesh_2d_v,
+                                                  CellValue<const R3>{new_connectivity_2d,
+                                                                      df_R3_2d.cellValues().arrayView()}};
+        DiscreteFunctionP0<const R2x2> df_R2x2_2d_new{new_mesh_2d_v,
+                                                      CellValue<const R2x2>{new_connectivity_2d,
+                                                                            df_R2x2_2d.cellValues().arrayView()}};
+
+        NodeValue<const R2x2> iv_R2x2_2d_new{new_connectivity_2d, iv_R2x2_2d.arrayView()};
+
+        FaceArray<const R2x2> ia_R2x2_2d_new{new_connectivity_2d, ia_R2x2_2d.tableView()};
+
+        DiscreteFunctionP0Vector<const double> dfv_R_2d_new{new_mesh_2d_v,
+                                                            CellArray<const double>{new_connectivity_2d,
+                                                                                    dfv_R_2d.cellArrays().tableView()}};
+
+        std::shared_ptr<const INamedDiscreteData> i_named_df_R3_2d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(df_R3_2d_new),
+                                                  "df_R3_2d");
+
+        checkpointing::writeINamedDiscreteData("df_R3_2d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_df_R3_2d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_df_R2x2_2d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(df_R2x2_2d_new),
+                                                  "df_R2x2_2d");
+
+        checkpointing::writeINamedDiscreteData("df_R2x2_2d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_df_R2x2_2d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_iv_R2x2_2d =
+          std::make_shared<NamedItemValueVariant>(std::make_shared<const ItemValueVariant>(iv_R2x2_2d_new),
+                                                  "iv_R2x2_2d");
+
+        checkpointing::writeINamedDiscreteData("iv_R2x2_2d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_iv_R2x2_2d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_ia_R2x2_2d =
+          std::make_shared<NamedItemArrayVariant>(std::make_shared<const ItemArrayVariant>(ia_R2x2_2d_new),
+                                                  "ia_R2x2_2d");
+
+        checkpointing::writeINamedDiscreteData("ia_R2x2_2d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_ia_R2x2_2d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_dfv_R_2d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(dfv_R_2d_new),
+                                                  "dfv_R_2d");
+
+        checkpointing::writeINamedDiscreteData("dfv_R_2d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_dfv_R_2d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        auto new_mesh_3d_v              = test_only::duplicateMesh(std::make_shared<MeshVariant>(mesh_3d));
+        auto new_mesh_3d                = new_mesh_3d_v->get<const Mesh<3>>();
+        const auto& new_connectivity_3d = new_mesh_3d->connectivity();
+
+        DiscreteFunctionP0<const R3> df_R3_3d_new{new_mesh_3d, CellValue<const R3>{new_connectivity_3d,
+                                                                                   df_R3_3d.cellValues().arrayView()}};
+        DiscreteFunctionP0<const R1x1> df_R1x1_3d_new{new_mesh_3d,
+                                                      CellValue<const R1x1>{new_connectivity_3d,
+                                                                            df_R1x1_3d.cellValues().arrayView()}};
+        DiscreteFunctionP0<const R3x3> df_R3x3_3d_new{new_mesh_3d,
+                                                      CellValue<const R3x3>{new_connectivity_3d,
+                                                                            df_R3x3_3d.cellValues().arrayView()}};
+
+        EdgeValue<const R3x3> iv_R3x3_3d_new{new_connectivity_3d, iv_R3x3_3d.arrayView()};
+
+        std::shared_ptr<const INamedDiscreteData> i_named_df_R3_3d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(df_R3_3d_new),
+                                                  "df_R3_3d");
+
+        checkpointing::writeINamedDiscreteData("df_R3_3d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_df_R3_3d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_df_R1x1_3d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(df_R1x1_3d_new),
+                                                  "df_R1x1_3d");
+
+        checkpointing::writeINamedDiscreteData("df_R1x1_3d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_df_R1x1_3d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_df_R3x3_3d =
+          std::make_shared<NamedDiscreteFunction>(std::make_shared<const DiscreteFunctionVariant>(df_R3x3_3d_new),
+                                                  "df_R3x3_3d");
+
+        checkpointing::writeINamedDiscreteData("df_R3x3_3d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_df_R3x3_3d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        std::shared_ptr<const INamedDiscreteData> i_named_iv_R3x3_3d =
+          std::make_shared<NamedItemValueVariant>(std::make_shared<const ItemValueVariant>(iv_R3x3_3d_new),
+                                                  "iv_R3x3_3d");
+        checkpointing::writeINamedDiscreteData("iv_R3x3_3d",
+                                               EmbeddedData{std::make_shared<DataHandlerT>(i_named_iv_R3x3_3d)}, file,
+                                               checkpoint_group, symbol_table_group);
+
+        HighFive::Group global_variables_group = checkpoint_group.createGroup("singleton/global_variables");
+        global_variables_group.createAttribute("connectivity_id",
+                                               GlobalVariableManager::instance().getConnectivityId());
+        global_variables_group.createAttribute("mesh_id", GlobalVariableManager::instance().getMeshId());
+      }
+
+      // reset to reuse after resuming
+      GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id);
+      GlobalVariableManager::instance().setMeshId(initial_mesh_id);
+
+      file.flush();
+
+      checkpointing::ResumingData::create();
+      checkpointing::ResumingData::instance().readData(checkpoint_group, nullptr);
+
+      GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id);
+      GlobalVariableManager::instance().setMeshId(initial_mesh_id);
+      {   // Read
+        auto e_df_R_1d = checkpointing::readINamedDiscreteData("df_R_1d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_df_R_1d);
+        test_only::INamedDiscreteData_check_is_same_name("df_R_1d", e_df_R_1d);
+        test_only::INamedDiscreteData_check_is_same_data(df_R_1d, e_df_R_1d);
+
+        auto e_df_R1_1d = checkpointing::readINamedDiscreteData("df_R1_1d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_df_R1_1d);
+        test_only::INamedDiscreteData_check_is_same_name("df_R1_1d", e_df_R1_1d);
+        test_only::INamedDiscreteData_check_is_same_data(df_R1_1d, e_df_R1_1d);
+
+        auto e_df_R2_1d = checkpointing::readINamedDiscreteData("df_R2_1d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_df_R2_1d);
+        test_only::INamedDiscreteData_check_is_same_name("df_R2_1d", e_df_R2_1d);
+        test_only::INamedDiscreteData_check_is_same_data(df_R2_1d, e_df_R2_1d);
+
+        auto e_df_R3_2d = checkpointing::readINamedDiscreteData("df_R3_2d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_df_R3_2d);
+        test_only::INamedDiscreteData_check_is_same_name("df_R3_2d", e_df_R3_2d);
+        test_only::INamedDiscreteData_check_is_same_data(df_R3_2d, e_df_R3_2d);
+
+        auto e_df_R2x2_2d = checkpointing::readINamedDiscreteData("df_R2x2_2d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_df_R2x2_2d);
+        test_only::INamedDiscreteData_check_is_same_name("df_R2x2_2d", e_df_R2x2_2d);
+        test_only::INamedDiscreteData_check_is_same_data(df_R2x2_2d, e_df_R2x2_2d);
+
+        auto e_iv_R2x2_2d = checkpointing::readINamedDiscreteData("iv_R2x2_2d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::item_value, e_iv_R2x2_2d);
+        test_only::INamedDiscreteData_check_is_same_name("iv_R2x2_2d", e_iv_R2x2_2d);
+        test_only::INamedDiscreteData_check_is_same_data(iv_R2x2_2d, e_iv_R2x2_2d);
+
+        auto e_ia_R2x2_2d = checkpointing::readINamedDiscreteData("ia_R2x2_2d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::item_array, e_ia_R2x2_2d);
+        test_only::INamedDiscreteData_check_is_same_name("ia_R2x2_2d", e_ia_R2x2_2d);
+        test_only::INamedDiscreteData_check_is_same_data(ia_R2x2_2d, e_ia_R2x2_2d);
+
+        auto e_dfv_R_2d = checkpointing::readINamedDiscreteData("dfv_R_2d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_dfv_R_2d);
+        test_only::INamedDiscreteData_check_is_same_name("dfv_R_2d", e_dfv_R_2d);
+        test_only::INamedDiscreteData_check_is_same_data(dfv_R_2d, e_dfv_R_2d);
+
+        auto e_df_R3_3d = checkpointing::readINamedDiscreteData("df_R3_3d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_df_R3_3d);
+        test_only::INamedDiscreteData_check_is_same_name("df_R3_3d", e_df_R3_3d);
+        test_only::INamedDiscreteData_check_is_same_data(df_R3_3d, e_df_R3_3d);
+
+        auto e_iv_R3x3_3d = checkpointing::readINamedDiscreteData("iv_R3x3_3d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::item_value, e_iv_R3x3_3d);
+        test_only::INamedDiscreteData_check_is_same_name("iv_R3x3_3d", e_iv_R3x3_3d);
+        test_only::INamedDiscreteData_check_is_same_data(iv_R3x3_3d, e_iv_R3x3_3d);
+
+        auto e_df_R1x1_3d = checkpointing::readINamedDiscreteData("df_R1x1_3d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_df_R1x1_3d);
+        test_only::INamedDiscreteData_check_is_same_name("df_R1x1_3d", e_df_R1x1_3d);
+        test_only::INamedDiscreteData_check_is_same_data(df_R1x1_3d, e_df_R1x1_3d);
+
+        auto e_df_R3x3_3d = checkpointing::readINamedDiscreteData("df_R3x3_3d", symbol_table_group);
+        test_only::INamedDiscreteData_check_is_same_type(INamedDiscreteData::Type::discrete_function, e_df_R3x3_3d);
+        test_only::INamedDiscreteData_check_is_same_name("df_R3x3_3d", e_df_R3x3_3d);
+        test_only::INamedDiscreteData_check_is_same_data(df_R3x3_3d, e_df_R3x3_3d);
+      }
+      checkpointing::ResumingData::destroy();
+    }
+  }
+
+  parallel::barrier();
+  if (parallel::rank() == 0) {
+    std::filesystem::remove_all(std::filesystem::path{tmp_dirname});
+  }
+}