diff --git a/src/utils/checkpointing/CMakeLists.txt b/src/utils/checkpointing/CMakeLists.txt
index 39429c9548a2844e447dff97201b22406afa8c1f..cc46732096e78f577f9567258ead2861e5174379 100644
--- a/src/utils/checkpointing/CMakeLists.txt
+++ b/src/utils/checkpointing/CMakeLists.txt
@@ -13,6 +13,12 @@ list(APPEND checkpointing_SOURCES
 if(PUGS_HAS_HDF5)
   list(APPEND checkpointing_SOURCES
     CheckpointUtils.cpp
+    ReadIBoundaryConditionDescriptor.cpp
+    ReadIBoundaryDescriptor.cpp
+    ReadItemArrayVariant.cpp
+    ReadItemValueVariant.cpp
+    ReadSubItemArrayPerItemVariant.cpp
+    ReadSubItemValuePerItemVariant.cpp
     ResumeUtils.cpp
     ResumingData.cpp
   )
diff --git a/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp b/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..96f62113afd1b51b5ced78d4536a626f4d1d5eb3
--- /dev/null
+++ b/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.cpp
@@ -0,0 +1,108 @@
+#include <utils/checkpointing/ReadIBoundaryConditionDescriptor.hpp>
+
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <scheme/AxisBoundaryConditionDescriptor.hpp>
+#include <scheme/DirichletBoundaryConditionDescriptor.hpp>
+#include <scheme/ExternalBoundaryConditionDescriptor.hpp>
+#include <scheme/FixedBoundaryConditionDescriptor.hpp>
+#include <scheme/FourierBoundaryConditionDescriptor.hpp>
+#include <scheme/FreeBoundaryConditionDescriptor.hpp>
+#include <scheme/InflowBoundaryConditionDescriptor.hpp>
+#include <scheme/NeumannBoundaryConditionDescriptor.hpp>
+#include <scheme/OutflowBoundaryConditionDescriptor.hpp>
+#include <scheme/SymmetryBoundaryConditionDescriptor.hpp>
+#include <utils/Exceptions.hpp>
+#include <utils/checkpointing/IBoundaryConditionDescriptorHFType.hpp>
+#include <utils/checkpointing/ReadIBoundaryDescriptor.hpp>
+#include <utils/checkpointing/ResumingData.hpp>
+
+std::shared_ptr<const IBoundaryConditionDescriptor>
+readIBoundaryConditionDescriptor(const HighFive::Group& iboundaryconditiondecriptor_group)
+{
+  const IBoundaryConditionDescriptor::Type iboundary_condition_descriptor_type =
+    iboundaryconditiondecriptor_group.getAttribute("iboundary_condition_descriptor_type")
+      .read<IBoundaryConditionDescriptor::Type>();
+
+  HighFive::Group boundary_group = iboundaryconditiondecriptor_group.getGroup("boundary");
+  auto i_boundary_descriptor     = readIBoundaryDescriptor(boundary_group);
+
+  std::shared_ptr<const IBoundaryConditionDescriptor> bc_descriptor;
+
+  switch (iboundary_condition_descriptor_type) {
+  case IBoundaryConditionDescriptor::Type::axis: {
+    bc_descriptor = std::make_shared<const AxisBoundaryConditionDescriptor>(i_boundary_descriptor);
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::dirichlet: {
+    const std::string name = iboundaryconditiondecriptor_group.getAttribute("name").read<std::string>();
+    const size_t rhs_id    = iboundaryconditiondecriptor_group.getAttribute("rhs_function_id").read<size_t>();
+
+    bc_descriptor =
+      std::make_shared<const DirichletBoundaryConditionDescriptor>(name, i_boundary_descriptor,
+                                                                   *ResumingData::instance().functionSymbolId(rhs_id));
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::external: {
+    throw NotImplementedError("checkpoint/resume with sockets");
+
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::fourier: {
+    const std::string name = iboundaryconditiondecriptor_group.getAttribute("name").read<std::string>();
+    const size_t rhs_id    = iboundaryconditiondecriptor_group.getAttribute("rhs_function_id").read<size_t>();
+    const size_t mass_id   = iboundaryconditiondecriptor_group.getAttribute("mass_function_id").read<size_t>();
+
+    bc_descriptor =
+      std::make_shared<const FourierBoundaryConditionDescriptor>(name, i_boundary_descriptor,
+                                                                 *ResumingData::instance().functionSymbolId(mass_id),
+                                                                 *ResumingData::instance().functionSymbolId(rhs_id));
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::fixed: {
+    bc_descriptor = std::make_shared<const FixedBoundaryConditionDescriptor>(i_boundary_descriptor);
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::free: {
+    bc_descriptor = std::make_shared<const FreeBoundaryConditionDescriptor>(i_boundary_descriptor);
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::inflow: {
+    const size_t function_id = iboundaryconditiondecriptor_group.getAttribute("function_id").read<size_t>();
+
+    bc_descriptor =
+      std::make_shared<const InflowBoundaryConditionDescriptor>(i_boundary_descriptor,
+                                                                *ResumingData::instance().functionSymbolId(
+                                                                  function_id));
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::neumann: {
+    const std::string name = iboundaryconditiondecriptor_group.getAttribute("name").read<std::string>();
+    const size_t rhs_id    = iboundaryconditiondecriptor_group.getAttribute("rhs_function_id").read<size_t>();
+
+    bc_descriptor =
+      std::make_shared<const NeumannBoundaryConditionDescriptor>(name, i_boundary_descriptor,
+                                                                 *ResumingData::instance().functionSymbolId(rhs_id));
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::outflow: {
+    bc_descriptor = std::make_shared<const OutflowBoundaryConditionDescriptor>(i_boundary_descriptor);
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::symmetry: {
+    bc_descriptor = std::make_shared<const SymmetryBoundaryConditionDescriptor>(i_boundary_descriptor);
+    break;
+  }
+  }
+
+  return bc_descriptor;
+}
+
+EmbeddedData
+readIBoundaryConditionDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
+{
+  std::shared_ptr<const IBoundaryConditionDescriptor> bc_descriptor =
+    readIBoundaryConditionDescriptor(symbol_table_group.getGroup("embedded/" + symbol_name));
+  return {std::make_shared<DataHandler<const IBoundaryConditionDescriptor>>(bc_descriptor)};
+}
diff --git a/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.hpp b/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1187efdc0f8e13bfbfa0c920ecca5ae1df3159e9
--- /dev/null
+++ b/src/utils/checkpointing/ReadIBoundaryConditionDescriptor.hpp
@@ -0,0 +1,15 @@
+#ifndef READ_IBOUNDARY_CONDITION_DESCRIPTOR_HPP
+#define READ_IBOUNDARY_CONDITION_DESCRIPTOR_HPP
+
+#include <utils/HighFivePugsUtils.hpp>
+
+class IBoundaryConditionDescriptor;
+class EmbeddedData;
+
+std::shared_ptr<const IBoundaryConditionDescriptor> readIBoundaryConditionDescriptor(
+  const HighFive::Group& iboundaryconditiondecriptor_group);
+
+EmbeddedData readIBoundaryConditionDescriptor(const std::string& symbol_name,
+                                              const HighFive::Group& symbol_table_group);
+
+#endif   // READ_IBOUNDARY_CONDITION_DESCRIPTOR_HPP
diff --git a/src/utils/checkpointing/ReadIBoundaryDescriptor.cpp b/src/utils/checkpointing/ReadIBoundaryDescriptor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ed9cdd65419c24fbc0ecb65c197ebceea540c023
--- /dev/null
+++ b/src/utils/checkpointing/ReadIBoundaryDescriptor.cpp
@@ -0,0 +1,41 @@
+#include <utils/checkpointing/ReadIBoundaryDescriptor.hpp>
+
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <mesh/IBoundaryDescriptor.hpp>
+#include <mesh/NamedBoundaryDescriptor.hpp>
+#include <mesh/NumberedBoundaryDescriptor.hpp>
+#include <utils/checkpointing/IBoundaryDescriptorHFType.hpp>
+
+std::shared_ptr<const IBoundaryDescriptor>
+readIBoundaryDescriptor(const HighFive::Group& iboundarydescriptor_group)
+{
+  const IBoundaryDescriptor::Type iboundary_descriptor_type =
+    iboundarydescriptor_group.getAttribute("iboundary_descriptor_type").read<IBoundaryDescriptor::Type>();
+
+  std::shared_ptr<const IBoundaryDescriptor> i_boundary_descriptor;
+
+  switch (iboundary_descriptor_type) {
+  case IBoundaryDescriptor::Type::named: {
+    const std::string name = iboundarydescriptor_group.getAttribute("name").read<std::string>();
+    i_boundary_descriptor  = std::make_shared<const NamedBoundaryDescriptor>(name);
+    break;
+  }
+  case IBoundaryDescriptor::Type::numbered: {
+    const unsigned int number = iboundarydescriptor_group.getAttribute("number").read<unsigned int>();
+    i_boundary_descriptor     = std::make_shared<const NumberedBoundaryDescriptor>(number);
+    break;
+  }
+  }
+
+  return i_boundary_descriptor;
+}
+
+EmbeddedData
+readIBoundaryDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
+{
+  const HighFive::Group iboundarydescriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+
+  return {std::make_shared<DataHandler<const IBoundaryDescriptor>>(readIBoundaryDescriptor(iboundarydescriptor_group))};
+}
diff --git a/src/utils/checkpointing/ReadIBoundaryDescriptor.hpp b/src/utils/checkpointing/ReadIBoundaryDescriptor.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..86883f873a5628c3ed383725f9c5efaee3e3905e
--- /dev/null
+++ b/src/utils/checkpointing/ReadIBoundaryDescriptor.hpp
@@ -0,0 +1,14 @@
+#ifndef READ_IBOUNDARY_DESCRIPTOR_HPP
+#define READ_IBOUNDARY_DESCRIPTOR_HPP
+
+#include <utils/HighFivePugsUtils.hpp>
+
+class IBoundaryDescriptor;
+class EmbeddedData;
+
+std::shared_ptr<const IBoundaryDescriptor> readIBoundaryDescriptor(const HighFive::Group& iboundarydescriptor_group);
+
+EmbeddedData readIBoundaryConditionDescriptor(const std::string& symbol_name,
+                                              const HighFive::Group& symbol_table_group);
+
+#endif   // READ_IBOUNDARY_DESCRIPTOR_HPP
diff --git a/src/utils/checkpointing/ReadItemArray.hpp b/src/utils/checkpointing/ReadItemArray.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..bddd9799ca85274d2d8e74ed3390f39758ca0c35
--- /dev/null
+++ b/src/utils/checkpointing/ReadItemArray.hpp
@@ -0,0 +1,16 @@
+#ifndef READ_ITEM_ARRAY_HPP
+#define READ_ITEM_ARRAY_HPP
+
+#include <mesh/ItemArray.hpp>
+#include <utils/HighFivePugsUtils.hpp>
+
+#include <utils/checkpointing/ResumeUtils.hpp>
+
+template <typename T, ItemType item_type>
+ItemArray<T, item_type>
+readItemArray(const HighFive::Group& group, const std::string& name, const IConnectivity& connectivity)
+{
+  return {connectivity, readTable<T>(group, name)};
+}
+
+#endif   // READ_ITEM_ARRAY_HPP
diff --git a/src/utils/checkpointing/ReadItemArrayVariant.cpp b/src/utils/checkpointing/ReadItemArrayVariant.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f684e03d027ae369b4068428ce3c9ddef8d1addf
--- /dev/null
+++ b/src/utils/checkpointing/ReadItemArrayVariant.cpp
@@ -0,0 +1,93 @@
+#include <utils/checkpointing/ReadItemArrayVariant.hpp>
+
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <mesh/Connectivity.hpp>
+#include <mesh/ItemArrayVariant.hpp>
+#include <utils/checkpointing/ItemTypeHFType.hpp>
+#include <utils/checkpointing/ReadItemArray.hpp>
+#include <utils/checkpointing/ResumingData.hpp>
+
+template <ItemType item_type>
+std::shared_ptr<ItemArrayVariant>
+readItemArrayVariant(const HighFive::Group& item_array_variant_group)
+{
+  const std::string data_type  = item_array_variant_group.getAttribute("data_type").read<std::string>();
+  const size_t connectivity_id = item_array_variant_group.getAttribute("connectivity_id").read<size_t>();
+
+  const IConnectivity& connectivity = *ResumingData::instance().iConnectivity(connectivity_id);
+
+  std::shared_ptr<ItemArrayVariant> p_item_array;
+
+  if (data_type == dataTypeName(ast_node_data_type_from<bool>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<bool, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<long int>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<long int, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<unsigned long int>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<unsigned long int, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<double>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<double, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<1>>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<TinyVector<1>, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<2>>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<TinyVector<2>, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<3>>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<TinyVector<3>, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<1>>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<TinyMatrix<1>, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<2>>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<TinyMatrix<2>, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<3>>)) {
+    p_item_array = std::make_shared<ItemArrayVariant>(
+      readItemArray<TinyMatrix<3>, item_type>(item_array_variant_group, "arrays", connectivity));
+  } else {
+    throw UnexpectedError("unexpected discrete function data type: " + data_type);
+  }
+  return p_item_array;
+}
+
+std::shared_ptr<ItemArrayVariant>
+readItemArrayVariant(const HighFive::Group& item_array_variant_group)
+{
+  const ItemType item_type = item_array_variant_group.getAttribute("item_type").read<ItemType>();
+
+  std::shared_ptr<ItemArrayVariant> p_item_array;
+
+  switch (item_type) {
+  case ItemType::cell: {
+    p_item_array = readItemArrayVariant<ItemType::cell>(item_array_variant_group);
+    break;
+  }
+  case ItemType::face: {
+    p_item_array = readItemArrayVariant<ItemType::face>(item_array_variant_group);
+    break;
+  }
+  case ItemType::edge: {
+    p_item_array = readItemArrayVariant<ItemType::edge>(item_array_variant_group);
+    break;
+  }
+  case ItemType::node: {
+    p_item_array = readItemArrayVariant<ItemType::node>(item_array_variant_group);
+    break;
+  }
+  }
+
+  return p_item_array;
+}
+
+EmbeddedData
+readItemArrayVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
+{
+  const HighFive::Group item_array_variant_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+  return {std::make_shared<DataHandler<const ItemArrayVariant>>(readItemArrayVariant(item_array_variant_group))};
+}
diff --git a/src/utils/checkpointing/ReadItemArrayVariant.hpp b/src/utils/checkpointing/ReadItemArrayVariant.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..721571eeafdcbbb5c6c4523f8012a19770fb0570
--- /dev/null
+++ b/src/utils/checkpointing/ReadItemArrayVariant.hpp
@@ -0,0 +1,13 @@
+#ifndef READ_ITEM_ARRAY_VARIANT_HPP
+#define READ_ITEM_ARRAY_VARIANT_HPP
+
+#include <mesh/ItemArrayVariant.hpp>
+#include <utils/HighFivePugsUtils.hpp>
+
+class EmbeddedData;
+
+std::shared_ptr<ItemArrayVariant> readItemArrayVariant(const HighFive::Group& item_array_variant_group);
+
+EmbeddedData readItemArrayVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group);
+
+#endif   // READ_ITEM_ARRAY_VARIANT_HPP
diff --git a/src/utils/checkpointing/ReadItemValue.hpp b/src/utils/checkpointing/ReadItemValue.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d3d9013c4a87fc53521299fbc4b3147ac39e10b
--- /dev/null
+++ b/src/utils/checkpointing/ReadItemValue.hpp
@@ -0,0 +1,16 @@
+#ifndef READ_ITEM_VALUE_HPP
+#define READ_ITEM_VALUE_HPP
+
+#include <mesh/ItemValue.hpp>
+#include <utils/HighFivePugsUtils.hpp>
+
+#include <utils/checkpointing/ResumeUtils.hpp>
+
+template <typename T, ItemType item_type>
+ItemValue<T, item_type>
+readItemValue(const HighFive::Group& group, const std::string& name, const IConnectivity& connectivity)
+{
+  return {connectivity, readArray<T>(group, name)};
+}
+
+#endif   // READ_ITEM_VALUE_HPP
diff --git a/src/utils/checkpointing/ReadItemValueVariant.cpp b/src/utils/checkpointing/ReadItemValueVariant.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2ec70594c98a56bdaa64b24e06d50b9a5338ce0c
--- /dev/null
+++ b/src/utils/checkpointing/ReadItemValueVariant.cpp
@@ -0,0 +1,93 @@
+#include <utils/checkpointing/ReadItemValueVariant.hpp>
+
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <mesh/Connectivity.hpp>
+#include <mesh/ItemValueVariant.hpp>
+#include <utils/checkpointing/ItemTypeHFType.hpp>
+#include <utils/checkpointing/ReadItemValue.hpp>
+#include <utils/checkpointing/ResumingData.hpp>
+
+template <ItemType item_type>
+std::shared_ptr<ItemValueVariant>
+readItemValueVariant(const HighFive::Group& item_value_variant_group)
+{
+  const std::string data_type  = item_value_variant_group.getAttribute("data_type").read<std::string>();
+  const size_t connectivity_id = item_value_variant_group.getAttribute("connectivity_id").read<size_t>();
+
+  const IConnectivity& connectivity = *ResumingData::instance().iConnectivity(connectivity_id);
+
+  std::shared_ptr<ItemValueVariant> p_item_value;
+
+  if (data_type == dataTypeName(ast_node_data_type_from<bool>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<bool, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<long int>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<long int, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<unsigned long int>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<unsigned long int, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<double>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<double, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<1>>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<TinyVector<1>, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<2>>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<TinyVector<2>, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<3>>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<TinyVector<3>, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<1>>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<TinyMatrix<1>, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<2>>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<TinyMatrix<2>, item_type>(item_value_variant_group, "values", connectivity));
+  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<3>>)) {
+    p_item_value = std::make_shared<ItemValueVariant>(
+      readItemValue<TinyMatrix<3>, item_type>(item_value_variant_group, "values", connectivity));
+  } else {
+    throw UnexpectedError("unexpected discrete function data type: " + data_type);
+  }
+  return p_item_value;
+}
+
+std::shared_ptr<ItemValueVariant>
+readItemValueVariant(const HighFive::Group& item_value_variant_group)
+{
+  const ItemType item_type = item_value_variant_group.getAttribute("item_type").read<ItemType>();
+
+  std::shared_ptr<ItemValueVariant> p_item_value;
+
+  switch (item_type) {
+  case ItemType::cell: {
+    p_item_value = readItemValueVariant<ItemType::cell>(item_value_variant_group);
+    break;
+  }
+  case ItemType::face: {
+    p_item_value = readItemValueVariant<ItemType::face>(item_value_variant_group);
+    break;
+  }
+  case ItemType::edge: {
+    p_item_value = readItemValueVariant<ItemType::edge>(item_value_variant_group);
+    break;
+  }
+  case ItemType::node: {
+    p_item_value = readItemValueVariant<ItemType::node>(item_value_variant_group);
+    break;
+  }
+  }
+
+  return p_item_value;
+}
+
+EmbeddedData
+readItemValueVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
+{
+  const HighFive::Group item_value_variant_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+  return {std::make_shared<DataHandler<const ItemValueVariant>>(readItemValueVariant(item_value_variant_group))};
+}
diff --git a/src/utils/checkpointing/ReadItemValueVariant.hpp b/src/utils/checkpointing/ReadItemValueVariant.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..521cac48692b55dbbde641f982f440c38b5b29ad
--- /dev/null
+++ b/src/utils/checkpointing/ReadItemValueVariant.hpp
@@ -0,0 +1,13 @@
+#ifndef READ_ITEM_VALUE_VARIANT_HPP
+#define READ_ITEM_VALUE_VARIANT_HPP
+
+#include <mesh/ItemValueVariant.hpp>
+#include <utils/HighFivePugsUtils.hpp>
+
+class EmbeddedData;
+
+std::shared_ptr<ItemValueVariant> readItemValueVariant(const HighFive::Group& item_value_variant_group);
+
+EmbeddedData readItemValueVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group);
+
+#endif   // READ_ITEM_VALUE_VARIANT_HPP
diff --git a/src/utils/checkpointing/ReadSubItemArrayPerItemVariant.cpp b/src/utils/checkpointing/ReadSubItemArrayPerItemVariant.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a1c1d4e528c2cd27aabd295a7d4fff141dcef26
--- /dev/null
+++ b/src/utils/checkpointing/ReadSubItemArrayPerItemVariant.cpp
@@ -0,0 +1,153 @@
+#include <utils/checkpointing/ReadSubItemArrayPerItemVariant.hpp>
+
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <mesh/Connectivity.hpp>
+#include <mesh/SubItemArrayPerItemVariant.hpp>
+#include <utils/checkpointing/ItemTypeHFType.hpp>
+#include <utils/checkpointing/ResumeUtils.hpp>
+#include <utils/checkpointing/ResumingData.hpp>
+
+template <typename T, ItemType item_type, ItemType sub_item_type>
+SubItemArrayPerItem<T, ItemOfItemType<sub_item_type, item_type>>
+readSubItemArrayPerItem(const HighFive::Group& group, const std::string& name, const IConnectivity& connectivity)
+{
+  return {connectivity, readTable<T>(group, name)};
+}
+
+template <ItemType item_type, ItemType sub_item_type>
+std::shared_ptr<SubItemArrayPerItemVariant>
+readSubItemArrayPerItemVariant(const HighFive::Group& sub_item_array_per_item_variant_group)
+{
+  if constexpr (item_type != sub_item_type) {
+    const std::string data_type  = sub_item_array_per_item_variant_group.getAttribute("data_type").read<std::string>();
+    const size_t connectivity_id = sub_item_array_per_item_variant_group.getAttribute("connectivity_id").read<size_t>();
+
+    const IConnectivity& connectivity = *ResumingData::instance().iConnectivity(connectivity_id);
+
+    std::shared_ptr<SubItemArrayPerItemVariant> p_sub_item_array_per_item_variant;
+
+    if (data_type == dataTypeName(ast_node_data_type_from<bool>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<bool, item_type, sub_item_type>(sub_item_array_per_item_variant_group, "arrays",
+                                                                connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<long int>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<long int, item_type, sub_item_type>(sub_item_array_per_item_variant_group, "arrays",
+                                                                    connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<unsigned long int>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<unsigned long int, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
+                                                                             "arrays", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<double>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<double, item_type, sub_item_type>(sub_item_array_per_item_variant_group, "arrays",
+                                                                  connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<1>>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<TinyVector<1>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
+                                                                         "arrays", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<2>>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<TinyVector<2>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
+                                                                         "arrays", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<3>>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<TinyVector<3>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
+                                                                         "arrays", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<1>>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<TinyMatrix<1>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
+                                                                         "arrays", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<2>>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<TinyMatrix<2>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
+                                                                         "arrays", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<3>>)) {
+      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
+        readSubItemArrayPerItem<TinyMatrix<3>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
+                                                                         "arrays", connectivity));
+    } else {
+      throw UnexpectedError("unexpected discrete function data type: " + data_type);
+    }
+    return p_sub_item_array_per_item_variant;
+  } else {
+    throw UnexpectedError("item_type and sub_item_type must be different");
+  }
+}
+
+template <ItemType item_type>
+std::shared_ptr<SubItemArrayPerItemVariant>
+readSubItemArrayPerItemVariant(const HighFive::Group& sub_item_array_per_item_variant_group)
+{
+  const ItemType sub_item_type = sub_item_array_per_item_variant_group.getAttribute("sub_item_type").read<ItemType>();
+
+  std::shared_ptr<SubItemArrayPerItemVariant> p_sub_item_array_per_item_variant;
+
+  switch (sub_item_type) {
+  case ItemType::cell: {
+    p_sub_item_array_per_item_variant =
+      readSubItemArrayPerItemVariant<item_type, ItemType::cell>(sub_item_array_per_item_variant_group);
+    break;
+  }
+  case ItemType::face: {
+    p_sub_item_array_per_item_variant =
+      readSubItemArrayPerItemVariant<item_type, ItemType::face>(sub_item_array_per_item_variant_group);
+    break;
+  }
+  case ItemType::edge: {
+    p_sub_item_array_per_item_variant =
+      readSubItemArrayPerItemVariant<item_type, ItemType::edge>(sub_item_array_per_item_variant_group);
+    break;
+  }
+  case ItemType::node: {
+    p_sub_item_array_per_item_variant =
+      readSubItemArrayPerItemVariant<item_type, ItemType::node>(sub_item_array_per_item_variant_group);
+    break;
+  }
+  }
+
+  return p_sub_item_array_per_item_variant;
+}
+
+std::shared_ptr<SubItemArrayPerItemVariant>
+readSubItemArrayPerItemVariant(const HighFive::Group& sub_item_array_per_item_variant_group)
+{
+  const ItemType item_type = sub_item_array_per_item_variant_group.getAttribute("item_type").read<ItemType>();
+
+  std::shared_ptr<SubItemArrayPerItemVariant> p_sub_item_array_per_item_variant;
+
+  switch (item_type) {
+  case ItemType::cell: {
+    p_sub_item_array_per_item_variant =
+      readSubItemArrayPerItemVariant<ItemType::cell>(sub_item_array_per_item_variant_group);
+    break;
+  }
+  case ItemType::face: {
+    p_sub_item_array_per_item_variant =
+      readSubItemArrayPerItemVariant<ItemType::face>(sub_item_array_per_item_variant_group);
+    break;
+  }
+  case ItemType::edge: {
+    p_sub_item_array_per_item_variant =
+      readSubItemArrayPerItemVariant<ItemType::edge>(sub_item_array_per_item_variant_group);
+    break;
+  }
+  case ItemType::node: {
+    p_sub_item_array_per_item_variant =
+      readSubItemArrayPerItemVariant<ItemType::node>(sub_item_array_per_item_variant_group);
+    break;
+  }
+  }
+
+  return p_sub_item_array_per_item_variant;
+}
+
+EmbeddedData
+readSubItemArrayPerItemVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
+{
+  const HighFive::Group sub_item_array_per_item_variant_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+  return {std::make_shared<DataHandler<const SubItemArrayPerItemVariant>>(
+    readSubItemArrayPerItemVariant(sub_item_array_per_item_variant_group))};
+}
diff --git a/src/utils/checkpointing/ReadSubItemArrayPerItemVariant.hpp b/src/utils/checkpointing/ReadSubItemArrayPerItemVariant.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..27b04ce94f1607d2556a9e1e8bc7b3b6e5e2d74c
--- /dev/null
+++ b/src/utils/checkpointing/ReadSubItemArrayPerItemVariant.hpp
@@ -0,0 +1,10 @@
+#ifndef READ_SUB_ITEM_ARRAY_PER_ITEM_VARIANT_HPP
+#define READ_SUB_ITEM_ARRAY_PER_ITEM_VARIANT_HPP
+
+#include <utils/HighFivePugsUtils.hpp>
+
+class EmbeddedData;
+
+EmbeddedData readSubItemArrayPerItemVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group);
+
+#endif   // READ_SUB_ITEM_ARRAY_PER_ITEM_VARIANT_HPP
diff --git a/src/utils/checkpointing/ReadSubItemValuePerItemVariant.cpp b/src/utils/checkpointing/ReadSubItemValuePerItemVariant.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6c690f9bfdc91c83aaaacb9b6f73a3b8a50a6c8a
--- /dev/null
+++ b/src/utils/checkpointing/ReadSubItemValuePerItemVariant.cpp
@@ -0,0 +1,153 @@
+#include <utils/checkpointing/ReadSubItemValuePerItemVariant.hpp>
+
+#include <language/utils/ASTNodeDataTypeTraits.hpp>
+#include <language/utils/DataHandler.hpp>
+#include <language/utils/EmbeddedData.hpp>
+#include <mesh/Connectivity.hpp>
+#include <mesh/SubItemValuePerItemVariant.hpp>
+#include <utils/checkpointing/ItemTypeHFType.hpp>
+#include <utils/checkpointing/ResumeUtils.hpp>
+#include <utils/checkpointing/ResumingData.hpp>
+
+template <typename T, ItemType item_type, ItemType sub_item_type>
+SubItemValuePerItem<T, ItemOfItemType<sub_item_type, item_type>>
+readSubItemValuePerItem(const HighFive::Group& group, const std::string& name, const IConnectivity& connectivity)
+{
+  return {connectivity, readArray<T>(group, name)};
+}
+
+template <ItemType item_type, ItemType sub_item_type>
+std::shared_ptr<SubItemValuePerItemVariant>
+readSubItemValuePerItemVariant(const HighFive::Group& sub_item_value_per_item_variant_group)
+{
+  if constexpr (item_type != sub_item_type) {
+    const std::string data_type  = sub_item_value_per_item_variant_group.getAttribute("data_type").read<std::string>();
+    const size_t connectivity_id = sub_item_value_per_item_variant_group.getAttribute("connectivity_id").read<size_t>();
+
+    const IConnectivity& connectivity = *ResumingData::instance().iConnectivity(connectivity_id);
+
+    std::shared_ptr<SubItemValuePerItemVariant> p_sub_item_value_per_item_variant;
+
+    if (data_type == dataTypeName(ast_node_data_type_from<bool>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<bool, item_type, sub_item_type>(sub_item_value_per_item_variant_group, "values",
+                                                                connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<long int>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<long int, item_type, sub_item_type>(sub_item_value_per_item_variant_group, "values",
+                                                                    connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<unsigned long int>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<unsigned long int, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
+                                                                             "values", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<double>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<double, item_type, sub_item_type>(sub_item_value_per_item_variant_group, "values",
+                                                                  connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<1>>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<TinyVector<1>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
+                                                                         "values", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<2>>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<TinyVector<2>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
+                                                                         "values", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<3>>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<TinyVector<3>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
+                                                                         "values", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<1>>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<TinyMatrix<1>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
+                                                                         "values", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<2>>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<TinyMatrix<2>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
+                                                                         "values", connectivity));
+    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<3>>)) {
+      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
+        readSubItemValuePerItem<TinyMatrix<3>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
+                                                                         "values", connectivity));
+    } else {
+      throw UnexpectedError("unexpected discrete function data type: " + data_type);
+    }
+    return p_sub_item_value_per_item_variant;
+  } else {
+    throw UnexpectedError("item_type and sub_item_type must be different");
+  }
+}
+
+template <ItemType item_type>
+std::shared_ptr<SubItemValuePerItemVariant>
+readSubItemValuePerItemVariant(const HighFive::Group& sub_item_value_per_item_variant_group)
+{
+  const ItemType sub_item_type = sub_item_value_per_item_variant_group.getAttribute("sub_item_type").read<ItemType>();
+
+  std::shared_ptr<SubItemValuePerItemVariant> p_sub_item_value_per_item_variant;
+
+  switch (sub_item_type) {
+  case ItemType::cell: {
+    p_sub_item_value_per_item_variant =
+      readSubItemValuePerItemVariant<item_type, ItemType::cell>(sub_item_value_per_item_variant_group);
+    break;
+  }
+  case ItemType::face: {
+    p_sub_item_value_per_item_variant =
+      readSubItemValuePerItemVariant<item_type, ItemType::face>(sub_item_value_per_item_variant_group);
+    break;
+  }
+  case ItemType::edge: {
+    p_sub_item_value_per_item_variant =
+      readSubItemValuePerItemVariant<item_type, ItemType::edge>(sub_item_value_per_item_variant_group);
+    break;
+  }
+  case ItemType::node: {
+    p_sub_item_value_per_item_variant =
+      readSubItemValuePerItemVariant<item_type, ItemType::node>(sub_item_value_per_item_variant_group);
+    break;
+  }
+  }
+
+  return p_sub_item_value_per_item_variant;
+}
+
+std::shared_ptr<SubItemValuePerItemVariant>
+readSubItemValuePerItemVariant(const HighFive::Group& sub_item_value_per_item_variant_group)
+{
+  const ItemType item_type = sub_item_value_per_item_variant_group.getAttribute("item_type").read<ItemType>();
+
+  std::shared_ptr<SubItemValuePerItemVariant> p_sub_item_value_per_item_variant;
+
+  switch (item_type) {
+  case ItemType::cell: {
+    p_sub_item_value_per_item_variant =
+      readSubItemValuePerItemVariant<ItemType::cell>(sub_item_value_per_item_variant_group);
+    break;
+  }
+  case ItemType::face: {
+    p_sub_item_value_per_item_variant =
+      readSubItemValuePerItemVariant<ItemType::face>(sub_item_value_per_item_variant_group);
+    break;
+  }
+  case ItemType::edge: {
+    p_sub_item_value_per_item_variant =
+      readSubItemValuePerItemVariant<ItemType::edge>(sub_item_value_per_item_variant_group);
+    break;
+  }
+  case ItemType::node: {
+    p_sub_item_value_per_item_variant =
+      readSubItemValuePerItemVariant<ItemType::node>(sub_item_value_per_item_variant_group);
+    break;
+  }
+  }
+
+  return p_sub_item_value_per_item_variant;
+}
+
+EmbeddedData
+readSubItemValuePerItemVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
+{
+  const HighFive::Group sub_item_value_per_item_variant_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+  return {std::make_shared<DataHandler<const SubItemValuePerItemVariant>>(
+    readSubItemValuePerItemVariant(sub_item_value_per_item_variant_group))};
+}
diff --git a/src/utils/checkpointing/ReadSubItemValuePerItemVariant.hpp b/src/utils/checkpointing/ReadSubItemValuePerItemVariant.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..dc69e55438aa0ab862ce0520e556304bdbf54fdc
--- /dev/null
+++ b/src/utils/checkpointing/ReadSubItemValuePerItemVariant.hpp
@@ -0,0 +1,10 @@
+#ifndef READ_SUB_ITEM_VALUE_PER_ITEM_VARIANT_HPP
+#define READ_SUB_ITEM_VALUE_PER_ITEM_VARIANT_HPP
+
+#include <utils/HighFivePugsUtils.hpp>
+
+class EmbeddedData;
+
+EmbeddedData readSubItemValuePerItemVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group);
+
+#endif   // READ_SUB_ITEM_VALUE_PER_ITEM_VARIANT_HPP
diff --git a/src/utils/checkpointing/ResumeUtils.cpp b/src/utils/checkpointing/ResumeUtils.cpp
index 7d1e3eea29e5ee650a4041d7a15aea0def82385c..9f057a35dd396e0e971fa0c824e2aa8ad36761bc 100644
--- a/src/utils/checkpointing/ResumeUtils.cpp
+++ b/src/utils/checkpointing/ResumeUtils.cpp
@@ -8,10 +8,8 @@
 #include <language/utils/SymbolTable.hpp>
 #include <mesh/ItemArrayVariant.hpp>
 #include <mesh/ItemValueVariant.hpp>
-#include <mesh/NamedBoundaryDescriptor.hpp>
 #include <mesh/NamedInterfaceDescriptor.hpp>
 #include <mesh/NamedZoneDescriptor.hpp>
-#include <mesh/NumberedBoundaryDescriptor.hpp>
 #include <mesh/NumberedInterfaceDescriptor.hpp>
 #include <mesh/NumberedZoneDescriptor.hpp>
 #include <mesh/SubItemArrayPerItemVariant.hpp>
@@ -22,21 +20,10 @@
 #include <output/NamedItemArrayVariant.hpp>
 #include <output/NamedItemValueVariant.hpp>
 #include <output/VTKWriter.hpp>
-#include <scheme/AxisBoundaryConditionDescriptor.hpp>
-#include <scheme/DirichletBoundaryConditionDescriptor.hpp>
 #include <scheme/DiscreteFunctionDescriptorP0.hpp>
 #include <scheme/DiscreteFunctionDescriptorP0Vector.hpp>
 #include <scheme/DiscreteFunctionP0.hpp>
 #include <scheme/DiscreteFunctionVariant.hpp>
-#include <scheme/ExternalBoundaryConditionDescriptor.hpp>
-#include <scheme/FixedBoundaryConditionDescriptor.hpp>
-#include <scheme/FourierBoundaryConditionDescriptor.hpp>
-#include <scheme/FreeBoundaryConditionDescriptor.hpp>
-#include <scheme/IBoundaryConditionDescriptor.hpp>
-#include <scheme/InflowBoundaryConditionDescriptor.hpp>
-#include <scheme/NeumannBoundaryConditionDescriptor.hpp>
-#include <scheme/OutflowBoundaryConditionDescriptor.hpp>
-#include <scheme/SymmetryBoundaryConditionDescriptor.hpp>
 #include <scheme/VariableBCDescriptor.hpp>
 #include <utils/checkpointing/DiscreteFunctionTypeHFType.hpp>
 #include <utils/checkpointing/IBoundaryConditionDescriptorHFType.hpp>
@@ -48,160 +35,13 @@
 #include <utils/checkpointing/ItemTypeHFType.hpp>
 #include <utils/checkpointing/OStreamTypeHFType.hpp>
 #include <utils/checkpointing/QuadratureTypeHFType.hpp>
+#include <utils/checkpointing/ReadItemArray.hpp>
+#include <utils/checkpointing/ReadItemArrayVariant.hpp>
+#include <utils/checkpointing/ReadItemValue.hpp>
+#include <utils/checkpointing/ReadItemValueVariant.hpp>
 #include <utils/checkpointing/ResumingData.hpp>
 
-std::shared_ptr<DiscreteFunctionVariant> readDiscreteFunctionVariant(const HighFive::Group& discrete_function_group);
-std::shared_ptr<ItemArrayVariant> readItemArrayVariant(const HighFive::Group& item_array_variant_group);
-std::shared_ptr<ItemValueVariant> readItemValueVariant(const HighFive::Group& item_value_variant_group);
-
-template <typename T, ItemType item_type>
-ItemArray<T, item_type>
-readItemArray(const HighFive::Group& group, const std::string& name, const IConnectivity& connectivity)
-{
-  return {connectivity, readTable<T>(group, name)};
-}
-
-template <typename T, ItemType item_type>
-ItemValue<T, item_type>
-readItemValue(const HighFive::Group& group, const std::string& name, const IConnectivity& connectivity)
-{
-  return {connectivity, readArray<T>(group, name)};
-}
-
-template <typename T, ItemType item_type, ItemType sub_item_type>
-SubItemArrayPerItem<T, ItemOfItemType<sub_item_type, item_type>>
-readSubItemArrayPerItem(const HighFive::Group& group, const std::string& name, const IConnectivity& connectivity)
-{
-  return {connectivity, readTable<T>(group, name)};
-}
-
-template <typename T, ItemType item_type, ItemType sub_item_type>
-SubItemValuePerItem<T, ItemOfItemType<sub_item_type, item_type>>
-readSubItemValuePerItem(const HighFive::Group& group, const std::string& name, const IConnectivity& connectivity)
-{
-  return {connectivity, readArray<T>(group, name)};
-}
-
-std::shared_ptr<const IBoundaryDescriptor>
-readIBoundaryDescriptor(const HighFive::Group& iboundarydescriptor_group)
-{
-  const IBoundaryDescriptor::Type iboundary_descriptor_type =
-    iboundarydescriptor_group.getAttribute("iboundary_descriptor_type").read<IBoundaryDescriptor::Type>();
-
-  std::shared_ptr<const IBoundaryDescriptor> i_boundary_descriptor;
-
-  switch (iboundary_descriptor_type) {
-  case IBoundaryDescriptor::Type::named: {
-    const std::string name = iboundarydescriptor_group.getAttribute("name").read<std::string>();
-    i_boundary_descriptor  = std::make_shared<const NamedBoundaryDescriptor>(name);
-    break;
-  }
-  case IBoundaryDescriptor::Type::numbered: {
-    const unsigned int number = iboundarydescriptor_group.getAttribute("number").read<unsigned int>();
-    i_boundary_descriptor     = std::make_shared<const NumberedBoundaryDescriptor>(number);
-    break;
-  }
-  }
-
-  return i_boundary_descriptor;
-}
-
-std::shared_ptr<const IBoundaryConditionDescriptor>
-readIBoundaryConditionDescriptor(const HighFive::Group& iboundaryconditiondecriptor_group)
-{
-  const IBoundaryConditionDescriptor::Type iboundary_condition_descriptor_type =
-    iboundaryconditiondecriptor_group.getAttribute("iboundary_condition_descriptor_type")
-      .read<IBoundaryConditionDescriptor::Type>();
-
-  HighFive::Group boundary_group = iboundaryconditiondecriptor_group.getGroup("boundary");
-  auto i_boundary_descriptor     = readIBoundaryDescriptor(boundary_group);
-
-  std::shared_ptr<const IBoundaryConditionDescriptor> bc_descriptor;
-
-  switch (iboundary_condition_descriptor_type) {
-  case IBoundaryConditionDescriptor::Type::axis: {
-    bc_descriptor = std::make_shared<const AxisBoundaryConditionDescriptor>(i_boundary_descriptor);
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::dirichlet: {
-    const std::string name = iboundaryconditiondecriptor_group.getAttribute("name").read<std::string>();
-    const size_t rhs_id    = iboundaryconditiondecriptor_group.getAttribute("rhs_function_id").read<size_t>();
-
-    bc_descriptor =
-      std::make_shared<const DirichletBoundaryConditionDescriptor>(name, i_boundary_descriptor,
-                                                                   *ResumingData::instance().functionSymbolId(rhs_id));
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::external: {
-    throw NotImplementedError("checkpoint/resume with sockets");
-
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::fourier: {
-    const std::string name = iboundaryconditiondecriptor_group.getAttribute("name").read<std::string>();
-    const size_t rhs_id    = iboundaryconditiondecriptor_group.getAttribute("rhs_function_id").read<size_t>();
-    const size_t mass_id   = iboundaryconditiondecriptor_group.getAttribute("mass_function_id").read<size_t>();
-
-    bc_descriptor =
-      std::make_shared<const FourierBoundaryConditionDescriptor>(name, i_boundary_descriptor,
-                                                                 *ResumingData::instance().functionSymbolId(mass_id),
-                                                                 *ResumingData::instance().functionSymbolId(rhs_id));
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::fixed: {
-    bc_descriptor = std::make_shared<const FixedBoundaryConditionDescriptor>(i_boundary_descriptor);
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::free: {
-    bc_descriptor = std::make_shared<const FreeBoundaryConditionDescriptor>(i_boundary_descriptor);
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::inflow: {
-    const size_t function_id = iboundaryconditiondecriptor_group.getAttribute("function_id").read<size_t>();
-
-    bc_descriptor =
-      std::make_shared<const InflowBoundaryConditionDescriptor>(i_boundary_descriptor,
-                                                                *ResumingData::instance().functionSymbolId(
-                                                                  function_id));
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::neumann: {
-    const std::string name = iboundaryconditiondecriptor_group.getAttribute("name").read<std::string>();
-    const size_t rhs_id    = iboundaryconditiondecriptor_group.getAttribute("rhs_function_id").read<size_t>();
-
-    bc_descriptor =
-      std::make_shared<const NeumannBoundaryConditionDescriptor>(name, i_boundary_descriptor,
-                                                                 *ResumingData::instance().functionSymbolId(rhs_id));
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::outflow: {
-    bc_descriptor = std::make_shared<const OutflowBoundaryConditionDescriptor>(i_boundary_descriptor);
-    break;
-  }
-  case IBoundaryConditionDescriptor::Type::symmetry: {
-    bc_descriptor = std::make_shared<const SymmetryBoundaryConditionDescriptor>(i_boundary_descriptor);
-    break;
-  }
-  }
-
-  return bc_descriptor;
-}
-
-EmbeddedData
-readIBoundaryConditionDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
-{
-  std::shared_ptr<const IBoundaryConditionDescriptor> bc_descriptor =
-    readIBoundaryConditionDescriptor(symbol_table_group.getGroup("embedded/" + symbol_name));
-  return {std::make_shared<DataHandler<const IBoundaryConditionDescriptor>>(bc_descriptor)};
-}
-
-EmbeddedData
-readIBoundaryDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
-{
-  const HighFive::Group iboundarydescriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
-
-  return {std::make_shared<DataHandler<const IBoundaryDescriptor>>(readIBoundaryDescriptor(iboundarydescriptor_group))};
-}
+#include <utils/checkpointing/ReadIBoundaryConditionDescriptor.hpp>
 
 EmbeddedData
 readIDiscreteFunctionDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
@@ -250,6 +90,8 @@ readIInterfaceDescriptor(const std::string& symbol_name, const HighFive::Group&
   return {std::make_shared<DataHandler<const IInterfaceDescriptor>>(iinterface_descriptor)};
 }
 
+std::shared_ptr<DiscreteFunctionVariant> readDiscreteFunctionVariant(const HighFive::Group& discrete_function_group);
+
 EmbeddedData
 readINamedDiscreteData(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
 {
@@ -312,88 +154,7 @@ readIQuadratureDescriptor(const std::string& symbol_name, const HighFive::Group&
   return {std::make_shared<DataHandler<const IQuadratureDescriptor>>(iquadrature_descrptor)};
 }
 
-template <ItemType item_type>
-std::shared_ptr<ItemArrayVariant>
-readItemArrayVariant(const HighFive::Group& item_array_variant_group)
-{
-  const std::string data_type  = item_array_variant_group.getAttribute("data_type").read<std::string>();
-  const size_t connectivity_id = item_array_variant_group.getAttribute("connectivity_id").read<size_t>();
-
-  const IConnectivity& connectivity = *ResumingData::instance().iConnectivity(connectivity_id);
-
-  std::shared_ptr<ItemArrayVariant> p_item_array;
-
-  if (data_type == dataTypeName(ast_node_data_type_from<bool>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<bool, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<long int>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<long int, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<unsigned long int>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<unsigned long int, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<double>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<double, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<1>>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<TinyVector<1>, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<2>>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<TinyVector<2>, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<3>>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<TinyVector<3>, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<1>>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<TinyMatrix<1>, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<2>>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<TinyMatrix<2>, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<3>>)) {
-    p_item_array = std::make_shared<ItemArrayVariant>(
-      readItemArray<TinyMatrix<3>, item_type>(item_array_variant_group, "arrays", connectivity));
-  } else {
-    throw UnexpectedError("unexpected discrete function data type: " + data_type);
-  }
-  return p_item_array;
-}
-
-std::shared_ptr<ItemArrayVariant>
-readItemArrayVariant(const HighFive::Group& item_array_variant_group)
-{
-  const ItemType item_type = item_array_variant_group.getAttribute("item_type").read<ItemType>();
-
-  std::shared_ptr<ItemArrayVariant> p_item_array;
-
-  switch (item_type) {
-  case ItemType::cell: {
-    p_item_array = readItemArrayVariant<ItemType::cell>(item_array_variant_group);
-    break;
-  }
-  case ItemType::face: {
-    p_item_array = readItemArrayVariant<ItemType::face>(item_array_variant_group);
-    break;
-  }
-  case ItemType::edge: {
-    p_item_array = readItemArrayVariant<ItemType::edge>(item_array_variant_group);
-    break;
-  }
-  case ItemType::node: {
-    p_item_array = readItemArrayVariant<ItemType::node>(item_array_variant_group);
-    break;
-  }
-  }
-
-  return p_item_array;
-}
-
-EmbeddedData
-readItemArrayVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
-{
-  const HighFive::Group item_array_variant_group = symbol_table_group.getGroup("embedded/" + symbol_name);
-  return {std::make_shared<DataHandler<const ItemArrayVariant>>(readItemArrayVariant(item_array_variant_group))};
-}
+std::shared_ptr<ItemArrayVariant> readItemArrayVariant(const HighFive::Group& item_array_variant_group);
 
 EmbeddedData
 readItemType(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
@@ -404,361 +165,6 @@ readItemType(const std::string& symbol_name, const HighFive::Group& symbol_table
   return {std::make_shared<DataHandler<const ItemType>>(std::make_shared<const ItemType>(item_type))};
 }
 
-template <ItemType item_type>
-std::shared_ptr<ItemValueVariant>
-readItemValueVariant(const HighFive::Group& item_value_variant_group)
-{
-  const std::string data_type  = item_value_variant_group.getAttribute("data_type").read<std::string>();
-  const size_t connectivity_id = item_value_variant_group.getAttribute("connectivity_id").read<size_t>();
-
-  const IConnectivity& connectivity = *ResumingData::instance().iConnectivity(connectivity_id);
-
-  std::shared_ptr<ItemValueVariant> p_item_value;
-
-  if (data_type == dataTypeName(ast_node_data_type_from<bool>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<bool, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<long int>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<long int, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<unsigned long int>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<unsigned long int, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<double>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<double, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<1>>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<TinyVector<1>, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<2>>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<TinyVector<2>, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<3>>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<TinyVector<3>, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<1>>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<TinyMatrix<1>, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<2>>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<TinyMatrix<2>, item_type>(item_value_variant_group, "values", connectivity));
-  } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<3>>)) {
-    p_item_value = std::make_shared<ItemValueVariant>(
-      readItemValue<TinyMatrix<3>, item_type>(item_value_variant_group, "values", connectivity));
-  } else {
-    throw UnexpectedError("unexpected discrete function data type: " + data_type);
-  }
-  return p_item_value;
-}
-
-std::shared_ptr<ItemValueVariant>
-readItemValueVariant(const HighFive::Group& item_value_variant_group)
-{
-  const ItemType item_type = item_value_variant_group.getAttribute("item_type").read<ItemType>();
-
-  std::shared_ptr<ItemValueVariant> p_item_value;
-
-  switch (item_type) {
-  case ItemType::cell: {
-    p_item_value = readItemValueVariant<ItemType::cell>(item_value_variant_group);
-    break;
-  }
-  case ItemType::face: {
-    p_item_value = readItemValueVariant<ItemType::face>(item_value_variant_group);
-    break;
-  }
-  case ItemType::edge: {
-    p_item_value = readItemValueVariant<ItemType::edge>(item_value_variant_group);
-    break;
-  }
-  case ItemType::node: {
-    p_item_value = readItemValueVariant<ItemType::node>(item_value_variant_group);
-    break;
-  }
-  }
-
-  return p_item_value;
-}
-
-EmbeddedData
-readItemValueVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
-{
-  const HighFive::Group item_value_variant_group = symbol_table_group.getGroup("embedded/" + symbol_name);
-  return {std::make_shared<DataHandler<const ItemValueVariant>>(readItemValueVariant(item_value_variant_group))};
-}
-
-template <ItemType item_type, ItemType sub_item_type>
-std::shared_ptr<SubItemArrayPerItemVariant>
-readSubItemArrayPerItemVariant(const HighFive::Group& sub_item_array_per_item_variant_group)
-{
-  if constexpr (item_type != sub_item_type) {
-    const std::string data_type  = sub_item_array_per_item_variant_group.getAttribute("data_type").read<std::string>();
-    const size_t connectivity_id = sub_item_array_per_item_variant_group.getAttribute("connectivity_id").read<size_t>();
-
-    const IConnectivity& connectivity = *ResumingData::instance().iConnectivity(connectivity_id);
-
-    std::shared_ptr<SubItemArrayPerItemVariant> p_sub_item_array_per_item_variant;
-
-    if (data_type == dataTypeName(ast_node_data_type_from<bool>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<bool, item_type, sub_item_type>(sub_item_array_per_item_variant_group, "arrays",
-                                                                connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<long int>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<long int, item_type, sub_item_type>(sub_item_array_per_item_variant_group, "arrays",
-                                                                    connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<unsigned long int>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<unsigned long int, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
-                                                                             "arrays", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<double>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<double, item_type, sub_item_type>(sub_item_array_per_item_variant_group, "arrays",
-                                                                  connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<1>>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<TinyVector<1>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
-                                                                         "arrays", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<2>>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<TinyVector<2>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
-                                                                         "arrays", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<3>>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<TinyVector<3>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
-                                                                         "arrays", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<1>>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<TinyMatrix<1>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
-                                                                         "arrays", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<2>>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<TinyMatrix<2>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
-                                                                         "arrays", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<3>>)) {
-      p_sub_item_array_per_item_variant = std::make_shared<SubItemArrayPerItemVariant>(
-        readSubItemArrayPerItem<TinyMatrix<3>, item_type, sub_item_type>(sub_item_array_per_item_variant_group,
-                                                                         "arrays", connectivity));
-    } else {
-      throw UnexpectedError("unexpected discrete function data type: " + data_type);
-    }
-    return p_sub_item_array_per_item_variant;
-  } else {
-    throw UnexpectedError("item_type and sub_item_type must be different");
-  }
-}
-
-template <ItemType item_type>
-std::shared_ptr<SubItemArrayPerItemVariant>
-readSubItemArrayPerItemVariant(const HighFive::Group& sub_item_array_per_item_variant_group)
-{
-  const ItemType sub_item_type = sub_item_array_per_item_variant_group.getAttribute("sub_item_type").read<ItemType>();
-
-  std::shared_ptr<SubItemArrayPerItemVariant> p_sub_item_array_per_item_variant;
-
-  switch (sub_item_type) {
-  case ItemType::cell: {
-    p_sub_item_array_per_item_variant =
-      readSubItemArrayPerItemVariant<item_type, ItemType::cell>(sub_item_array_per_item_variant_group);
-    break;
-  }
-  case ItemType::face: {
-    p_sub_item_array_per_item_variant =
-      readSubItemArrayPerItemVariant<item_type, ItemType::face>(sub_item_array_per_item_variant_group);
-    break;
-  }
-  case ItemType::edge: {
-    p_sub_item_array_per_item_variant =
-      readSubItemArrayPerItemVariant<item_type, ItemType::edge>(sub_item_array_per_item_variant_group);
-    break;
-  }
-  case ItemType::node: {
-    p_sub_item_array_per_item_variant =
-      readSubItemArrayPerItemVariant<item_type, ItemType::node>(sub_item_array_per_item_variant_group);
-    break;
-  }
-  }
-
-  return p_sub_item_array_per_item_variant;
-}
-
-std::shared_ptr<SubItemArrayPerItemVariant>
-readSubItemArrayPerItemVariant(const HighFive::Group& sub_item_array_per_item_variant_group)
-{
-  const ItemType item_type = sub_item_array_per_item_variant_group.getAttribute("item_type").read<ItemType>();
-
-  std::shared_ptr<SubItemArrayPerItemVariant> p_sub_item_array_per_item_variant;
-
-  switch (item_type) {
-  case ItemType::cell: {
-    p_sub_item_array_per_item_variant =
-      readSubItemArrayPerItemVariant<ItemType::cell>(sub_item_array_per_item_variant_group);
-    break;
-  }
-  case ItemType::face: {
-    p_sub_item_array_per_item_variant =
-      readSubItemArrayPerItemVariant<ItemType::face>(sub_item_array_per_item_variant_group);
-    break;
-  }
-  case ItemType::edge: {
-    p_sub_item_array_per_item_variant =
-      readSubItemArrayPerItemVariant<ItemType::edge>(sub_item_array_per_item_variant_group);
-    break;
-  }
-  case ItemType::node: {
-    p_sub_item_array_per_item_variant =
-      readSubItemArrayPerItemVariant<ItemType::node>(sub_item_array_per_item_variant_group);
-    break;
-  }
-  }
-
-  return p_sub_item_array_per_item_variant;
-}
-
-EmbeddedData
-readSubItemArrayPerItemVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
-{
-  const HighFive::Group sub_item_array_per_item_variant_group = symbol_table_group.getGroup("embedded/" + symbol_name);
-  return {std::make_shared<DataHandler<const SubItemArrayPerItemVariant>>(
-    readSubItemArrayPerItemVariant(sub_item_array_per_item_variant_group))};
-}
-
-template <ItemType item_type, ItemType sub_item_type>
-std::shared_ptr<SubItemValuePerItemVariant>
-readSubItemValuePerItemVariant(const HighFive::Group& sub_item_value_per_item_variant_group)
-{
-  if constexpr (item_type != sub_item_type) {
-    const std::string data_type  = sub_item_value_per_item_variant_group.getAttribute("data_type").read<std::string>();
-    const size_t connectivity_id = sub_item_value_per_item_variant_group.getAttribute("connectivity_id").read<size_t>();
-
-    const IConnectivity& connectivity = *ResumingData::instance().iConnectivity(connectivity_id);
-
-    std::shared_ptr<SubItemValuePerItemVariant> p_sub_item_value_per_item_variant;
-
-    if (data_type == dataTypeName(ast_node_data_type_from<bool>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<bool, item_type, sub_item_type>(sub_item_value_per_item_variant_group, "values",
-                                                                connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<long int>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<long int, item_type, sub_item_type>(sub_item_value_per_item_variant_group, "values",
-                                                                    connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<unsigned long int>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<unsigned long int, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
-                                                                             "values", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<double>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<double, item_type, sub_item_type>(sub_item_value_per_item_variant_group, "values",
-                                                                  connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<1>>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<TinyVector<1>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
-                                                                         "values", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<2>>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<TinyVector<2>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
-                                                                         "values", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyVector<3>>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<TinyVector<3>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
-                                                                         "values", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<1>>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<TinyMatrix<1>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
-                                                                         "values", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<2>>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<TinyMatrix<2>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
-                                                                         "values", connectivity));
-    } else if (data_type == dataTypeName(ast_node_data_type_from<TinyMatrix<3>>)) {
-      p_sub_item_value_per_item_variant = std::make_shared<SubItemValuePerItemVariant>(
-        readSubItemValuePerItem<TinyMatrix<3>, item_type, sub_item_type>(sub_item_value_per_item_variant_group,
-                                                                         "values", connectivity));
-    } else {
-      throw UnexpectedError("unexpected discrete function data type: " + data_type);
-    }
-    return p_sub_item_value_per_item_variant;
-  } else {
-    throw UnexpectedError("item_type and sub_item_type must be different");
-  }
-}
-
-template <ItemType item_type>
-std::shared_ptr<SubItemValuePerItemVariant>
-readSubItemValuePerItemVariant(const HighFive::Group& sub_item_value_per_item_variant_group)
-{
-  const ItemType sub_item_type = sub_item_value_per_item_variant_group.getAttribute("sub_item_type").read<ItemType>();
-
-  std::shared_ptr<SubItemValuePerItemVariant> p_sub_item_value_per_item_variant;
-
-  switch (sub_item_type) {
-  case ItemType::cell: {
-    p_sub_item_value_per_item_variant =
-      readSubItemValuePerItemVariant<item_type, ItemType::cell>(sub_item_value_per_item_variant_group);
-    break;
-  }
-  case ItemType::face: {
-    p_sub_item_value_per_item_variant =
-      readSubItemValuePerItemVariant<item_type, ItemType::face>(sub_item_value_per_item_variant_group);
-    break;
-  }
-  case ItemType::edge: {
-    p_sub_item_value_per_item_variant =
-      readSubItemValuePerItemVariant<item_type, ItemType::edge>(sub_item_value_per_item_variant_group);
-    break;
-  }
-  case ItemType::node: {
-    p_sub_item_value_per_item_variant =
-      readSubItemValuePerItemVariant<item_type, ItemType::node>(sub_item_value_per_item_variant_group);
-    break;
-  }
-  }
-
-  return p_sub_item_value_per_item_variant;
-}
-
-std::shared_ptr<SubItemValuePerItemVariant>
-readSubItemValuePerItemVariant(const HighFive::Group& sub_item_value_per_item_variant_group)
-{
-  const ItemType item_type = sub_item_value_per_item_variant_group.getAttribute("item_type").read<ItemType>();
-
-  std::shared_ptr<SubItemValuePerItemVariant> p_sub_item_value_per_item_variant;
-
-  switch (item_type) {
-  case ItemType::cell: {
-    p_sub_item_value_per_item_variant =
-      readSubItemValuePerItemVariant<ItemType::cell>(sub_item_value_per_item_variant_group);
-    break;
-  }
-  case ItemType::face: {
-    p_sub_item_value_per_item_variant =
-      readSubItemValuePerItemVariant<ItemType::face>(sub_item_value_per_item_variant_group);
-    break;
-  }
-  case ItemType::edge: {
-    p_sub_item_value_per_item_variant =
-      readSubItemValuePerItemVariant<ItemType::edge>(sub_item_value_per_item_variant_group);
-    break;
-  }
-  case ItemType::node: {
-    p_sub_item_value_per_item_variant =
-      readSubItemValuePerItemVariant<ItemType::node>(sub_item_value_per_item_variant_group);
-    break;
-  }
-  }
-
-  return p_sub_item_value_per_item_variant;
-}
-
-EmbeddedData
-readSubItemValuePerItemVariant(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
-{
-  const HighFive::Group sub_item_value_per_item_variant_group = symbol_table_group.getGroup("embedded/" + symbol_name);
-  return {std::make_shared<DataHandler<const SubItemValuePerItemVariant>>(
-    readSubItemValuePerItemVariant(sub_item_value_per_item_variant_group))};
-}
-
 EmbeddedData
 readIWriter(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
 {