diff --git a/src/utils/checkpointing/Resume.cpp b/src/utils/checkpointing/Resume.cpp
index 184011049c31febd92f53439bf1389b49fbbd6f2..9d58e1d9dec4050f218d3efad71e5194ccaa5111 100644
--- a/src/utils/checkpointing/Resume.cpp
+++ b/src/utils/checkpointing/Resume.cpp
@@ -233,15 +233,19 @@ resume()
             }
             break;
           }
+            // LCOV_EXCL_START
           default: {
             throw NotImplementedError(symbol_name + " of type " + dataTypeName(attribute.dataType().contentType()));
           }
+            // LCOV_EXCL_STOP
           }
           break;
         }
+          // LCOV_EXCL_START
         default: {
           throw NotImplementedError(symbol_name + " of type " + dataTypeName(attribute.dataType()));
         }
+          // LCOV_EXCL_STOP
         }
       }
 
@@ -286,9 +290,11 @@ resume()
 
     checkpointing::ResumingData::destroy();
   }
+  // LCOV_EXCL_START
   catch (HighFive::Exception& e) {
     throw NormalError(e.what());
   }
+  // LCOV_EXCL_STOP
 }
 
 #else   // PUGS_HAS_HDF5
diff --git a/src/utils/checkpointing/ResumingData.cpp b/src/utils/checkpointing/ResumingData.cpp
index 2fc7996cc09f1d99d2ec827d5ea66ef2abe8b39a..2301f199496df36343dbe301feb5df11d3fcd9f2 100644
--- a/src/utils/checkpointing/ResumingData.cpp
+++ b/src/utils/checkpointing/ResumingData.cpp
@@ -368,33 +368,41 @@ ResumingData::_getFunctionIds(const HighFive::Group& checkpoint, std::shared_ptr
       for (auto symbol : p_symbol_table->symbolList()) {
         if (symbol.attributes().dataType() == ASTNodeDataType::function_t) {
           if (not function_group.exist(symbol.name())) {
+            // LCOV_EXCL_START
             std::ostringstream error_msg;
             error_msg << "cannot find function " << rang::fgB::yellow << symbol.name() << rang::fg::reset << " in "
                       << rang::fgB::cyan << checkpoint.getFile().getName() << rang::fg::reset;
-            throw NormalError(error_msg.str());
-          } else {
+            throw UnexpectedError(error_msg.str());
+            // LCOV_EXCL_STOP
+          } else {   // LCOV_EXCL_LINE
             const HighFive::Group function  = function_group.getGroup(symbol.name());
             const size_t stored_function_id = function.getAttribute("id").read<size_t>();
             const size_t function_id        = std::get<size_t>(symbol.attributes().value());
             if (symbol_table_id != function.getAttribute("symbol_table_id").read<size_t>()) {
+              // LCOV_EXCL_START
               std::ostringstream error_msg;
               error_msg << "symbol table of function " << rang::fgB::yellow << symbol.name() << rang::fg::reset
                         << " does not match the one stored in " << rang::fgB::cyan << checkpoint.getFile().getName()
                         << rang::fg::reset;
-              throw NormalError(error_msg.str());
+              throw UnexpectedError(error_msg.str());
+              // LCOV_EXCL_STOP
             } else if (function_id != stored_function_id) {
+              // LCOV_EXCL_START
               std::ostringstream error_msg;
               error_msg << "id (" << function_id << ") of function " << rang::fgB::yellow << symbol.name()
                         << rang::fg::reset << " does not match the one stored in " << rang::fgB::cyan
                         << checkpoint.getFile().getName() << rang::fg::reset << "(" << stored_function_id << ")";
-              throw NormalError(error_msg.str());
-            } else {
+              throw UnexpectedError(error_msg.str());
+              // LCOV_EXCL_STOP
+            } else {   // LCOV_EXCL_LINE
               if (m_id_to_function_symbol_id_map.contains(function_id)) {
+                // LCOV_EXCL_START
                 std::ostringstream error_msg;
                 error_msg << "id (" << function_id << ") of function " << rang::fgB::yellow << symbol.name()
                           << rang::fg::reset << " is duplicated";
                 throw UnexpectedError(error_msg.str());
-              }
+                // LCOV_EXCL_STOP
+              }   // LCOV_EXCL_LINE
               m_id_to_function_symbol_id_map[function_id] =
                 std::make_shared<FunctionSymbolId>(function_id, p_symbol_table);
             }
@@ -420,7 +428,9 @@ ResumingData::iConnectivity(const size_t connectivity_id) const
 {
   auto i_id_to_connectivity = m_id_to_iconnectivity_map.find(connectivity_id);
   if (i_id_to_connectivity == m_id_to_iconnectivity_map.end()) {
+    // LCOV_EXCL_START
     throw UnexpectedError("cannot find connectivity of id " + std::to_string(connectivity_id));
+    // LCOV_EXCL_STOP
   } else {
     return i_id_to_connectivity->second;
   }
@@ -431,7 +441,9 @@ ResumingData::meshVariant(const size_t mesh_id) const
 {
   auto i_id_to_mesh = m_id_to_mesh_variant_map.find(mesh_id);
   if (i_id_to_mesh == m_id_to_mesh_variant_map.end()) {
+    // LCOV_EXCL_START
     throw UnexpectedError("cannot find mesh of id " + std::to_string(mesh_id));
+    // LCOV_EXCL_STOP
   } else {
     return i_id_to_mesh->second;
   }
@@ -442,7 +454,9 @@ ResumingData::functionSymbolId(const size_t function_symbol_id) const
 {
   auto i_id_to_function_symbol_id = m_id_to_function_symbol_id_map.find(function_symbol_id);
   if (i_id_to_function_symbol_id == m_id_to_function_symbol_id_map.end()) {
+    // LCOV_EXCL_START
     throw UnexpectedError("cannot find function_symbol_id of id " + std::to_string(function_symbol_id));
+    // LCOV_EXCL_STOP
   } else {
     return i_id_to_function_symbol_id->second;
   }
diff --git a/src/utils/checkpointing/SetResumeFrom.cpp b/src/utils/checkpointing/SetResumeFrom.cpp
index 81502da2f74e9d0e71d812d8692d7318b3135e71..7f040e7caaaf7c4eb8a27017f608127507b59cf0 100644
--- a/src/utils/checkpointing/SetResumeFrom.cpp
+++ b/src/utils/checkpointing/SetResumeFrom.cpp
@@ -9,13 +9,19 @@
 
 #include <utils/Exceptions.hpp>
 #include <utils/HighFivePugsUtils.hpp>
+#include <utils/Messenger.hpp>
 
 void
 setResumeFrom(const std::string& filename, const uint64_t& checkpoint_number, std::ostream& os)
 {
   try {
     HighFive::SilenceHDF5 m_silence_hdf5{true};
-    HighFive::File file(filename, HighFive::File::ReadWrite);
+
+    HighFive::FileAccessProps fapl;
+    fapl.add(HighFive::MPIOFileAccess{parallel::Messenger::getInstance().comm(), MPI_INFO_NULL});
+    fapl.add(HighFive::MPIOCollectiveMetadata{});
+
+    HighFive::File file(filename, HighFive::File::ReadWrite, fapl);
     const std::string checkpoint_name = "checkpoint_" + std::to_string(checkpoint_number);
 
     if (not file.exist(checkpoint_name)) {
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 6a7c235ffd1c118f88b60e39e8f81d13290add53..c3a25aec9b243afb7e5bd9b951286f322606099b 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -7,8 +7,7 @@ include_directories(${PUGS_SOURCE_DIR}/tests)
 set(checkpointing_sequential_TESTS
   # this one should enventually integrate parallel tests
   test_checkpointing_Checkpoint_sequential.cpp
-
-  test_checkpointing_SetResumeFrom.cpp
+  test_checkpointing_Resume_sequential.cpp
 )
 
 add_executable (unit_tests
@@ -171,6 +170,7 @@ add_executable (unit_tests
     test_checkpointing_PrintScriptFrom.cpp
     test_checkpointing_ResumingManager.cpp
     test_checkpointing_ResumingUtils.cpp
+    test_checkpointing_SetResumeFrom.cpp
   )
 
 if(PUGS_HAS_HDF5)
diff --git a/tests/test_checkpointing_Checkpoint.cpp b/tests/test_checkpointing_Checkpoint.cpp
index cfcf67188c2f43261f21e4d9ece28bdc50c9c060..317683b26dfca317b4b6f0059b6a8e55c8d5e4f0 100644
--- a/tests/test_checkpointing_Checkpoint.cpp
+++ b/tests/test_checkpointing_Checkpoint.cpp
@@ -75,6 +75,9 @@ TEST_CASE("checkpointing_Checkpoint", "[utils/checkpointing]")
 {
 #ifdef PUGS_HAS_HDF5
 
+  ResumingManager::destroy();
+  ResumingManager::create();
+
   std::string tmp_dirname;
   {
     {
diff --git a/tests/test_checkpointing_Checkpoint_sequential.cpp b/tests/test_checkpointing_Checkpoint_sequential.cpp
index 23ddd807415ddf2111a6f8e010c60431010f47f9..160404f8835a7fcf6a0c94700ae79d023391b2ca 100644
--- a/tests/test_checkpointing_Checkpoint_sequential.cpp
+++ b/tests/test_checkpointing_Checkpoint_sequential.cpp
@@ -77,6 +77,9 @@ TEST_CASE("checkpointing_Checkpoint_sequential", "[utils/checkpointing]")
 {
 #ifdef PUGS_HAS_HDF5
 
+  ResumingManager::destroy();
+  ResumingManager::create();
+
   std::string tmp_dirname;
   {
     {
diff --git a/tests/test_checkpointing_Resume_sequential.cpp b/tests/test_checkpointing_Resume_sequential.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e8a3aa1038a3089c5188bfb2dc19f4dc6a4abdbc
--- /dev/null
+++ b/tests/test_checkpointing_Resume_sequential.cpp
@@ -0,0 +1,729 @@
+#include <catch2/catch_approx.hpp>
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_predicate.hpp>
+
+#include <utils/checkpointing/Resume.hpp>
+#include <utils/pugs_config.hpp>
+
+#ifdef PUGS_HAS_HDF5
+
+#include <MeshDataBaseForTests.hpp>
+#include <dev/ParallelChecker.hpp>
+#include <language/ast/ASTBuilder.hpp>
+#include <language/ast/ASTExecutionStack.hpp>
+#include <language/ast/ASTModulesImporter.hpp>
+#include <language/ast/ASTNodeDataTypeBuilder.hpp>
+#include <language/ast/ASTNodeDeclarationToAffectationConverter.hpp>
+#include <language/ast/ASTNodeExpressionBuilder.hpp>
+#include <language/ast/ASTNodeTypeCleaner.hpp>
+#include <language/ast/ASTSymbolTableBuilder.hpp>
+#include <language/modules/MathModule.hpp>
+#include <language/utils/ASTCheckpointsInfo.hpp>
+#include <language/utils/CheckpointResumeRepository.hpp>
+#include <mesh/DualMeshType.hpp>
+#include <utils/ExecutionStatManager.hpp>
+#include <utils/checkpointing/DualMeshTypeHFType.hpp>
+#include <utils/checkpointing/SetResumeFrom.hpp>
+
+class ASTCheckpointsInfoTester
+{
+ private:
+  ASTCheckpointsInfo m_ast_checkpoint_info;
+
+ public:
+  ASTCheckpointsInfoTester(const ASTNode& root_node) : m_ast_checkpoint_info(root_node) {}
+  ~ASTCheckpointsInfoTester() = default;
+};
+
+#define RUN_AST(data)                                          \
+  {                                                            \
+    ExecutionStatManager::create();                            \
+    ParallelChecker::create();                                 \
+    CheckpointResumeRepository::create();                      \
+                                                               \
+    TAO_PEGTL_NAMESPACE::string_input input{data, "test.pgs"}; \
+    auto ast = ASTBuilder::build(input);                       \
+                                                               \
+    ASTModulesImporter{*ast};                                  \
+    ASTNodeTypeCleaner<language::import_instruction>{*ast};    \
+                                                               \
+    ASTSymbolTableBuilder{*ast};                               \
+    ASTNodeDataTypeBuilder{*ast};                              \
+                                                               \
+    ASTNodeDeclarationToAffectationConverter{*ast};            \
+    ASTNodeTypeCleaner<language::var_declaration>{*ast};       \
+    ASTNodeTypeCleaner<language::fct_declaration>{*ast};       \
+                                                               \
+    ASTNodeExpressionBuilder{*ast};                            \
+    ExecutionPolicy exec_policy;                               \
+    ASTExecutionStack::create();                               \
+    ASTCheckpointsInfoTester ast_cp_info_tester{*ast};         \
+    ast->execute(exec_policy);                                 \
+    ASTExecutionStack::destroy();                              \
+    ast->m_symbol_table->clearValues();                        \
+                                                               \
+    CheckpointResumeRepository::destroy();                     \
+    ParallelChecker::destroy();                                \
+    ExecutionStatManager::destroy();                           \
+    ast->m_symbol_table->clearValues();                        \
+  }
+
+#endif   // PUGS_HAS_HDF5
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("checkpointing_Resume_sequential", "[utils/checkpointing]")
+{
+#ifdef PUGS_HAS_HDF5
+
+  auto frobeniusNorm = [](const auto& A) {
+    using A_T = std::decay_t<decltype(A)>;
+    static_assert(is_tiny_matrix_v<A_T>);
+    return std::sqrt(trace(transpose(A) * A));
+  };
+
+  using R1 = TinyVector<1>;
+  using R2 = TinyVector<2>;
+  using R3 = TinyVector<3>;
+
+  using R11 = TinyMatrix<1>;
+  using R22 = TinyMatrix<2>;
+  using R33 = TinyMatrix<3>;
+
+  MeshDataBaseForTests::destroy();
+  GlobalVariableManager::instance().setMeshId(0);
+  GlobalVariableManager::instance().setConnectivityId(0);
+
+  ResumingManager::destroy();
+  ResumingManager::create();
+
+  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";
+
+    ResumingManager::getInstance().setFilename(filename);
+  }
+
+  const std::string filename = ResumingManager::getInstance().filename();
+
+  std::string data = R"(
+import math;
+import mesh;
+import scheme;
+
+let f:R*R^3 -> R^3, (a, v) -> a * v;
+
+let alpha:R, alpha = 3.2;
+let u1:R^1, u1 = [0.3];
+let u2:R^2, u2 = [0.3, 1.2];
+let u3:R^3, u3 = [1, 2, 3];
+
+let A1:R^1x1, A1 = [[0.7]];
+let A2:R^2x2, A2 = [[1.4, 2.1], [0.6, 3]];
+let A3:R^3x3, A3 = [[1.1, 2.2, 3.3], [0.1, 0.2, 0.3], [1.6, 1.2, 1.4]];
+
+let m2d:mesh, m2d = cartesianMesh(0, [1,1], (10,10));
+
+let b_tuple:(B), b_tuple = (true, false, true);
+let n_tuple:(N), n_tuple = (1, 2, 3, 4);
+let z_tuple:(Z), z_tuple = (1, -2, 3, -4);
+let r_tuple:(R), r_tuple = (1.2, -2.4, 3.1, -4.3);
+let s_tuple:(string), s_tuple = ("foo", "bar");
+
+let r1_tuple:(R^1), r1_tuple = ([1], [2]);
+let r2_tuple:(R^2), r2_tuple = ([1.2, 3], [2.3, 4], [3.2, 1.4]);
+let r3_tuple:(R^3), r3_tuple = ([1.2, 0.2, 3], [2.3, -1, 4], [3.2, 2.1, 1.4]);
+
+let r11_tuple:(R^1x1), r11_tuple = ([[1.3]], [[2.4]]);
+let r22_tuple:(R^2x2), r22_tuple = ([[1.2, 3], [2.3, 4]], [[3.2, 1.4], [1.3, 5.2]]);
+let r33_tuple:(R^3x3), r33_tuple = ([[1.2, 0.2, 3], [2.3, -1, 4], [3.2, 2.1, 1.4]]);
+
+let duals_2d:(mesh), duals_2d = (diamondDual(m2d), medianDual(m2d));
+
+let m1d:mesh, m1d = cartesianMesh([0], [1], 10);
+let dual_1d:mesh, dual_1d = diamondDual(m1d);
+
+let m3d:mesh, m3d = cartesianMesh(0, [1,1,1], (6,6,6));
+let dual_3d:mesh, dual_3d = diamondDual(m3d);
+
+let b:B, b = false;
+let z:Z, z = -2;
+let s:string, s = "foobar";
+
+for(let i:N, i=0; i<3; ++i) {
+  checkpoint();
+
+  s = "foobar_"+i;
+  z += 1;
+  b = not b;
+
+  let g:R -> R^3, x -> [x, 1.2*x, 3];
+  u3 = f(alpha,u3);
+
+  checkpoint();
+}
+)";
+
+  const size_t initial_mesh_id         = GlobalVariableManager::instance().getMeshId();
+  const size_t initial_connectivity_id = GlobalVariableManager::instance().getConnectivityId();
+
+  RUN_AST(data);
+
+  GlobalVariableManager::instance().setMeshId(initial_mesh_id);
+  GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id);
+
+  {   // Check checkpoint file
+
+    HighFive::File file(ResumingManager::getInstance().filename(), HighFive::File::ReadOnly);
+
+    HighFive::Group checkpoint = file.getGroup("/resuming_checkpoint");
+
+    REQUIRE(checkpoint.getAttribute("id").read<uint64_t>() == 1);
+    REQUIRE(checkpoint.getAttribute("checkpoint_number").read<uint64_t>() == 5);
+    REQUIRE(checkpoint.getAttribute("name").read<std::string>() == "checkpoint_5");
+
+    HighFive::Group symbol_table0 = checkpoint.getGroup("symbol table");
+    REQUIRE(symbol_table0.getAttribute("i").read<uint64_t>() == 2);
+
+    HighFive::Group symbol_table1 = symbol_table0.getGroup("symbol table");
+    REQUIRE(symbol_table1.getAttribute("alpha").read<double>() == 3.2);
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u1").read<R1>() - R1{0.3}) == Catch::Approx(0).margin(1E-12));
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u2").read<R2>() - R2{0.3, 1.2}) == Catch::Approx(0).margin(1E-12));
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u3").read<R3>() - R3{32.768, 65.536, 98.304}) ==
+            Catch::Approx(0).margin(1E-12));
+    REQUIRE(symbol_table1.getAttribute("b").read<bool>() == true);
+    REQUIRE(symbol_table1.getAttribute("z").read<int64_t>() == 1);
+    REQUIRE(symbol_table1.getAttribute("s").read<std::string>() == "foobar_2");
+    REQUIRE(symbol_table1.getAttribute("A1").read<R11>()(0, 0) == Catch::Approx(0.7).margin(1E-12));
+    REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A2").read<R22>() - R22{1.4, 2.1, 0.6, 3}) ==
+            Catch::Approx(0).margin(1E-12));
+    REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A3").read<R33>() -
+                          R33{1.1, 2.2, 3.3, 0.1, 0.2, 0.3, 1.6, 1.2, 1.4}) == Catch::Approx(0).margin(1E-12));
+    REQUIRE(symbol_table1.getAttribute("b_tuple").read<std::vector<bool>>() == std::vector<bool>{true, false, true});
+    REQUIRE(symbol_table1.getAttribute("n_tuple").read<std::vector<uint64_t>>() == std::vector<uint64_t>{1, 2, 3, 4});
+    REQUIRE(symbol_table1.getAttribute("z_tuple").read<std::vector<int64_t>>() == std::vector<int64_t>{1, -2, 3, -4});
+    REQUIRE(symbol_table1.getAttribute("r_tuple").read<std::vector<double>>() ==
+            std::vector<double>{1.2, -2.4, 3.1, -4.3});
+    REQUIRE(symbol_table1.getAttribute("s_tuple").read<std::vector<std::string>>() ==
+            std::vector<std::string>{"foo", "bar"});
+
+    REQUIRE(symbol_table1.getAttribute("r1_tuple").read<std::vector<R1>>() == std::vector{R1{1}, R1{2}});
+    REQUIRE(symbol_table1.getAttribute("r2_tuple").read<std::vector<R2>>() ==
+            std::vector{R2{1.2, 3}, R2{2.3, 4}, R2{3.2, 1.4}});
+    REQUIRE(symbol_table1.getAttribute("r3_tuple").read<std::vector<R3>>() ==
+            std::vector{R3{1.2, 0.2, 3}, R3{2.3, -1, 4}, R3{3.2, 2.1, 1.4}});
+
+    REQUIRE(symbol_table1.getAttribute("r11_tuple").read<std::vector<R11>>() == std::vector{R11{1.3}, R11{2.4}});
+    REQUIRE(symbol_table1.getAttribute("r22_tuple").read<std::vector<R22>>() ==
+            std::vector{R22{1.2, 3, 2.3, 4}, R22{3.2, 1.4, 1.3, 5.2}});
+    REQUIRE(symbol_table1.getAttribute("r33_tuple").read<std::vector<R33>>() ==
+            std::vector{R33{1.2, 0.2, 3, 2.3, -1, 4, 3.2, 2.1, 1.4}});
+
+    HighFive::Group embedded1 = symbol_table1.getGroup("embedded");
+
+    HighFive::Group m1d = embedded1.getGroup("m1d");
+    REQUIRE(m1d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(m1d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 3);
+
+    HighFive::Group dual_1d = embedded1.getGroup("dual_1d");
+    REQUIRE(dual_1d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(dual_1d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 4);
+
+    HighFive::Group m2d = embedded1.getGroup("m2d");
+    REQUIRE(m2d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(m2d.getAttribute("id").read<uint64_t>() == initial_mesh_id);
+
+    HighFive::Group duals_2d = embedded1.getGroup("duals_2d");
+    REQUIRE(duals_2d.getAttribute("type").read<std::string>() == "(mesh)");
+    HighFive::Group duals_2d_0 = duals_2d.getGroup("0");
+    REQUIRE(duals_2d_0.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(duals_2d_0.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1);
+    HighFive::Group duals_2d_1 = duals_2d.getGroup("1");
+    REQUIRE(duals_2d_1.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(duals_2d_1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2);
+
+    HighFive::Group m3d = embedded1.getGroup("m3d");
+    REQUIRE(m3d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(m3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5);
+
+    HighFive::Group dual_3d = embedded1.getGroup("dual_3d");
+    REQUIRE(dual_3d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(dual_3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6);
+
+    HighFive::Group singleton        = checkpoint.getGroup("singleton");
+    HighFive::Group global_variables = singleton.getGroup("global_variables");
+    REQUIRE(global_variables.getAttribute("connectivity_id").read<uint64_t>() == initial_connectivity_id + 7);
+    REQUIRE(global_variables.getAttribute("mesh_id").read<uint64_t>() == initial_mesh_id + 7);
+    HighFive::Group execution_info = singleton.getGroup("execution_info");
+    REQUIRE(execution_info.getAttribute("run_number").read<uint64_t>() == 1);
+
+    HighFive::Group connectivity  = checkpoint.getGroup("connectivity");
+    HighFive::Group connectivity0 = connectivity.getGroup(std::to_string(initial_connectivity_id));
+    REQUIRE(connectivity0.getAttribute("dimension").read<uint64_t>() == 2);
+    REQUIRE(connectivity0.getAttribute("id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity0.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity1 = connectivity.getGroup(std::to_string(initial_connectivity_id + 1));
+    REQUIRE(connectivity1.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 1);
+    REQUIRE(connectivity1.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity1.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group connectivity2 = connectivity.getGroup(std::to_string(initial_connectivity_id + 2));
+    REQUIRE(connectivity2.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 2);
+    REQUIRE(connectivity2.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity2.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median);
+
+    HighFive::Group connectivity3 = connectivity.getGroup(std::to_string(initial_connectivity_id + 3));
+    REQUIRE(connectivity3.getAttribute("dimension").read<uint64_t>() == 1);
+    REQUIRE(connectivity3.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(connectivity3.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity4 = connectivity.getGroup(std::to_string(initial_connectivity_id + 4));
+    REQUIRE(connectivity4.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 4);
+    REQUIRE(connectivity4.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(connectivity4.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D);
+
+    HighFive::Group connectivity5 = connectivity.getGroup(std::to_string(initial_connectivity_id + 5));
+    REQUIRE(connectivity5.getAttribute("dimension").read<uint64_t>() == 3);
+    REQUIRE(connectivity5.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(connectivity5.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity6 = connectivity.getGroup(std::to_string(initial_connectivity_id + 6));
+    REQUIRE(connectivity6.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 6);
+    REQUIRE(connectivity6.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(connectivity6.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group mesh  = checkpoint.getGroup("mesh");
+    HighFive::Group mesh0 = mesh.getGroup(std::to_string(initial_mesh_id));
+    REQUIRE(mesh0.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(mesh0.getAttribute("dimension").read<uint64_t>() == 2);
+    REQUIRE(mesh0.getAttribute("id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh0.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh1 = mesh.getGroup(std::to_string(initial_mesh_id + 1));
+    REQUIRE(mesh1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1);
+    REQUIRE(mesh1.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh1.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group mesh2 = mesh.getGroup(std::to_string(initial_mesh_id + 2));
+    REQUIRE(mesh2.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2);
+    REQUIRE(mesh2.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh2.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median);
+
+    HighFive::Group mesh3 = mesh.getGroup(std::to_string(initial_mesh_id + 3));
+    REQUIRE(mesh3.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(mesh3.getAttribute("dimension").read<uint64_t>() == 1);
+    REQUIRE(mesh3.getAttribute("id").read<uint64_t>() == initial_mesh_id + 3);
+    REQUIRE(mesh3.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh4 = mesh.getGroup(std::to_string(initial_mesh_id + 4));
+    REQUIRE(mesh4.getAttribute("id").read<uint64_t>() == initial_mesh_id + 4);
+    REQUIRE(mesh4.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 3);
+    REQUIRE(mesh4.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D);
+
+    HighFive::Group mesh5 = mesh.getGroup(std::to_string(initial_mesh_id + 5));
+    REQUIRE(mesh5.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(mesh5.getAttribute("dimension").read<uint64_t>() == 3);
+    REQUIRE(mesh5.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5);
+    REQUIRE(mesh5.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh6 = mesh.getGroup(std::to_string(initial_mesh_id + 6));
+    REQUIRE(mesh6.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6);
+    REQUIRE(mesh6.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 5);
+    REQUIRE(mesh6.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group functions = checkpoint.getGroup("functions");
+    HighFive::Group f         = functions.getGroup("f");
+    REQUIRE(f.getAttribute("id").read<uint64_t>() == 0);
+    REQUIRE(f.getAttribute("symbol_table_id").read<uint64_t>() == 1);
+    HighFive::Group g = functions.getGroup("g");
+    REQUIRE(g.getAttribute("id").read<uint64_t>() == 1);
+    REQUIRE(g.getAttribute("symbol_table_id").read<uint64_t>() == 0);
+  }
+
+  parallel::barrier();
+
+  setResumeFrom(filename, 3);
+
+  parallel::barrier();
+
+  {   // Check checkpoint file
+
+    HighFive::File file(ResumingManager::getInstance().filename(), HighFive::File::ReadOnly);
+
+    HighFive::Group checkpoint = file.getGroup("/resuming_checkpoint");
+
+    REQUIRE(checkpoint.getAttribute("id").read<uint64_t>() == 1);
+    REQUIRE(checkpoint.getAttribute("checkpoint_number").read<uint64_t>() == 3);
+    REQUIRE(checkpoint.getAttribute("name").read<std::string>() == "checkpoint_3");
+
+    HighFive::Group symbol_table0 = checkpoint.getGroup("symbol table");
+    REQUIRE(symbol_table0.getAttribute("i").read<uint64_t>() == 1);
+
+    HighFive::Group symbol_table1 = symbol_table0.getGroup("symbol table");
+    REQUIRE(symbol_table1.getAttribute("alpha").read<double>() == 3.2);
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u1").read<R1>() - R1{0.3}) == Catch::Approx(0).margin(1E-12));
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u2").read<R2>() - R2{0.3, 1.2}) == Catch::Approx(0).margin(1E-12));
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u3").read<R3>() - R3{10.24, 20.48, 30.72}) ==
+            Catch::Approx(0).margin(1E-12));
+    REQUIRE(symbol_table1.getAttribute("b").read<bool>() == false);
+    REQUIRE(symbol_table1.getAttribute("z").read<int64_t>() == 0);
+    REQUIRE(symbol_table1.getAttribute("s").read<std::string>() == "foobar_1");
+    REQUIRE(symbol_table1.getAttribute("A1").read<R11>()(0, 0) == Catch::Approx(0.7).margin(1E-12));
+    REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A2").read<R22>() - R22{1.4, 2.1, 0.6, 3}) ==
+            Catch::Approx(0).margin(1E-12));
+    REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A3").read<R33>() -
+                          R33{1.1, 2.2, 3.3, 0.1, 0.2, 0.3, 1.6, 1.2, 1.4}) == Catch::Approx(0).margin(1E-12));
+
+    REQUIRE(symbol_table1.getAttribute("b_tuple").read<std::vector<bool>>() == std::vector<bool>{true, false, true});
+    REQUIRE(symbol_table1.getAttribute("n_tuple").read<std::vector<uint64_t>>() == std::vector<uint64_t>{1, 2, 3, 4});
+    REQUIRE(symbol_table1.getAttribute("z_tuple").read<std::vector<int64_t>>() == std::vector<int64_t>{1, -2, 3, -4});
+    REQUIRE(symbol_table1.getAttribute("r_tuple").read<std::vector<double>>() ==
+            std::vector<double>{1.2, -2.4, 3.1, -4.3});
+    REQUIRE(symbol_table1.getAttribute("s_tuple").read<std::vector<std::string>>() ==
+            std::vector<std::string>{"foo", "bar"});
+
+    REQUIRE(symbol_table1.getAttribute("r1_tuple").read<std::vector<R1>>() == std::vector{R1{1}, R1{2}});
+    REQUIRE(symbol_table1.getAttribute("r2_tuple").read<std::vector<R2>>() ==
+            std::vector{R2{1.2, 3}, R2{2.3, 4}, R2{3.2, 1.4}});
+    REQUIRE(symbol_table1.getAttribute("r3_tuple").read<std::vector<R3>>() ==
+            std::vector{R3{1.2, 0.2, 3}, R3{2.3, -1, 4}, R3{3.2, 2.1, 1.4}});
+
+    REQUIRE(symbol_table1.getAttribute("r11_tuple").read<std::vector<R11>>() == std::vector{R11{1.3}, R11{2.4}});
+    REQUIRE(symbol_table1.getAttribute("r22_tuple").read<std::vector<R22>>() ==
+            std::vector{R22{1.2, 3, 2.3, 4}, R22{3.2, 1.4, 1.3, 5.2}});
+    REQUIRE(symbol_table1.getAttribute("r33_tuple").read<std::vector<R33>>() ==
+            std::vector{R33{1.2, 0.2, 3, 2.3, -1, 4, 3.2, 2.1, 1.4}});
+
+    HighFive::Group embedded1 = symbol_table1.getGroup("embedded");
+
+    HighFive::Group m2d = embedded1.getGroup("m2d");
+    REQUIRE(m2d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(m2d.getAttribute("id").read<uint64_t>() == initial_mesh_id);
+
+    HighFive::Group duals_2d = embedded1.getGroup("duals_2d");
+    REQUIRE(duals_2d.getAttribute("type").read<std::string>() == "(mesh)");
+    HighFive::Group duals_2d_0 = duals_2d.getGroup("0");
+    REQUIRE(duals_2d_0.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(duals_2d_0.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1);
+    HighFive::Group duals_2d_1 = duals_2d.getGroup("1");
+    REQUIRE(duals_2d_1.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(duals_2d_1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2);
+
+    HighFive::Group m3d = embedded1.getGroup("m3d");
+    REQUIRE(m3d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(m3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5);
+
+    HighFive::Group dual_3d = embedded1.getGroup("dual_3d");
+    REQUIRE(dual_3d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(dual_3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6);
+
+    HighFive::Group singleton        = checkpoint.getGroup("singleton");
+    HighFive::Group global_variables = singleton.getGroup("global_variables");
+    REQUIRE(global_variables.getAttribute("connectivity_id").read<uint64_t>() == initial_connectivity_id + 7);
+    REQUIRE(global_variables.getAttribute("mesh_id").read<uint64_t>() == initial_mesh_id + 7);
+    HighFive::Group execution_info = singleton.getGroup("execution_info");
+    REQUIRE(execution_info.getAttribute("run_number").read<uint64_t>() == 1);
+
+    HighFive::Group connectivity  = checkpoint.getGroup("connectivity");
+    HighFive::Group connectivity0 = connectivity.getGroup(std::to_string(initial_connectivity_id));
+    REQUIRE(connectivity0.getAttribute("dimension").read<uint64_t>() == 2);
+    REQUIRE(connectivity0.getAttribute("id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity0.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity1 = connectivity.getGroup(std::to_string(initial_connectivity_id + 1));
+    REQUIRE(connectivity1.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 1);
+    REQUIRE(connectivity1.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity1.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group connectivity2 = connectivity.getGroup(std::to_string(initial_connectivity_id + 2));
+    REQUIRE(connectivity2.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 2);
+    REQUIRE(connectivity2.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity2.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median);
+
+    HighFive::Group connectivity3 = connectivity.getGroup(std::to_string(initial_connectivity_id + 3));
+    REQUIRE(connectivity3.getAttribute("dimension").read<uint64_t>() == 1);
+    REQUIRE(connectivity3.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(connectivity3.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity4 = connectivity.getGroup(std::to_string(initial_connectivity_id + 4));
+    REQUIRE(connectivity4.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 4);
+    REQUIRE(connectivity4.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(connectivity4.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D);
+
+    HighFive::Group connectivity5 = connectivity.getGroup(std::to_string(initial_connectivity_id + 5));
+    REQUIRE(connectivity5.getAttribute("dimension").read<uint64_t>() == 3);
+    REQUIRE(connectivity5.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(connectivity5.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity6 = connectivity.getGroup(std::to_string(initial_connectivity_id + 6));
+    REQUIRE(connectivity6.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 6);
+    REQUIRE(connectivity6.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(connectivity6.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group mesh  = checkpoint.getGroup("mesh");
+    HighFive::Group mesh0 = mesh.getGroup(std::to_string(initial_mesh_id));
+    REQUIRE(mesh0.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(mesh0.getAttribute("dimension").read<uint64_t>() == 2);
+    REQUIRE(mesh0.getAttribute("id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh0.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh1 = mesh.getGroup(std::to_string(initial_mesh_id + 1));
+    REQUIRE(mesh1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1);
+    REQUIRE(mesh1.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh1.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group mesh2 = mesh.getGroup(std::to_string(initial_mesh_id + 2));
+    REQUIRE(mesh2.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2);
+    REQUIRE(mesh2.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh2.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median);
+
+    HighFive::Group mesh3 = mesh.getGroup(std::to_string(initial_mesh_id + 3));
+    REQUIRE(mesh3.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(mesh3.getAttribute("dimension").read<uint64_t>() == 1);
+    REQUIRE(mesh3.getAttribute("id").read<uint64_t>() == initial_mesh_id + 3);
+    REQUIRE(mesh3.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh4 = mesh.getGroup(std::to_string(initial_mesh_id + 4));
+    REQUIRE(mesh4.getAttribute("id").read<uint64_t>() == initial_mesh_id + 4);
+    REQUIRE(mesh4.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 3);
+    REQUIRE(mesh4.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D);
+
+    HighFive::Group mesh5 = mesh.getGroup(std::to_string(initial_mesh_id + 5));
+    REQUIRE(mesh5.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(mesh5.getAttribute("dimension").read<uint64_t>() == 3);
+    REQUIRE(mesh5.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5);
+    REQUIRE(mesh5.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh6 = mesh.getGroup(std::to_string(initial_mesh_id + 6));
+    REQUIRE(mesh6.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6);
+    REQUIRE(mesh6.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 5);
+    REQUIRE(mesh6.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group functions = checkpoint.getGroup("functions");
+    HighFive::Group f         = functions.getGroup("f");
+    REQUIRE(f.getAttribute("id").read<uint64_t>() == 0);
+    REQUIRE(f.getAttribute("symbol_table_id").read<uint64_t>() == 1);
+    HighFive::Group g = functions.getGroup("g");
+    REQUIRE(g.getAttribute("id").read<uint64_t>() == 1);
+    REQUIRE(g.getAttribute("symbol_table_id").read<uint64_t>() == 0);
+  }
+
+  ResumingManager::destroy();
+  ResumingManager::create();
+  ResumingManager::getInstance().setFilename(filename);
+  ResumingManager::getInstance().setIsResuming(true);
+  GlobalVariableManager::instance().setMeshId(initial_mesh_id);
+  GlobalVariableManager::instance().setConnectivityId(initial_connectivity_id);
+
+  RUN_AST(data);
+
+  {   // Check checkpoint file
+
+    HighFive::File file(ResumingManager::getInstance().filename(), HighFive::File::ReadOnly);
+
+    HighFive::Group checkpoint = file.getGroup("/resuming_checkpoint");
+
+    REQUIRE(checkpoint.getAttribute("id").read<uint64_t>() == 1);
+    REQUIRE(checkpoint.getAttribute("checkpoint_number").read<uint64_t>() == 5);
+    REQUIRE(checkpoint.getAttribute("name").read<std::string>() == "checkpoint_5");
+
+    HighFive::Group symbol_table0 = checkpoint.getGroup("symbol table");
+    REQUIRE(symbol_table0.getAttribute("i").read<uint64_t>() == 2);
+
+    HighFive::Group symbol_table1 = symbol_table0.getGroup("symbol table");
+    REQUIRE(symbol_table1.getAttribute("alpha").read<double>() == 3.2);
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u1").read<R1>() - R1{0.3}) == Catch::Approx(0).margin(1E-12));
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u2").read<R2>() - R2{0.3, 1.2}) == Catch::Approx(0).margin(1E-12));
+    REQUIRE(l2Norm(symbol_table1.getAttribute("u3").read<R3>() - R3{32.768, 65.536, 98.304}) ==
+            Catch::Approx(0).margin(1E-12));
+    REQUIRE(symbol_table1.getAttribute("b").read<bool>() == true);
+    REQUIRE(symbol_table1.getAttribute("z").read<int64_t>() == 1);
+    REQUIRE(symbol_table1.getAttribute("s").read<std::string>() == "foobar_2");
+    REQUIRE(symbol_table1.getAttribute("A1").read<R11>()(0, 0) == Catch::Approx(0.7).margin(1E-12));
+    REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A2").read<R22>() - R22{1.4, 2.1, 0.6, 3}) ==
+            Catch::Approx(0).margin(1E-12));
+    REQUIRE(frobeniusNorm(symbol_table1.getAttribute("A3").read<R33>() -
+                          R33{1.1, 2.2, 3.3, 0.1, 0.2, 0.3, 1.6, 1.2, 1.4}) == Catch::Approx(0).margin(1E-12));
+
+    REQUIRE(symbol_table1.getAttribute("b_tuple").read<std::vector<bool>>() == std::vector<bool>{true, false, true});
+    REQUIRE(symbol_table1.getAttribute("n_tuple").read<std::vector<uint64_t>>() == std::vector<uint64_t>{1, 2, 3, 4});
+    REQUIRE(symbol_table1.getAttribute("z_tuple").read<std::vector<int64_t>>() == std::vector<int64_t>{1, -2, 3, -4});
+    REQUIRE(symbol_table1.getAttribute("r_tuple").read<std::vector<double>>() ==
+            std::vector<double>{1.2, -2.4, 3.1, -4.3});
+    REQUIRE(symbol_table1.getAttribute("s_tuple").read<std::vector<std::string>>() ==
+            std::vector<std::string>{"foo", "bar"});
+
+    REQUIRE(symbol_table1.getAttribute("r1_tuple").read<std::vector<R1>>() == std::vector{R1{1}, R1{2}});
+    REQUIRE(symbol_table1.getAttribute("r2_tuple").read<std::vector<R2>>() ==
+            std::vector{R2{1.2, 3}, R2{2.3, 4}, R2{3.2, 1.4}});
+    REQUIRE(symbol_table1.getAttribute("r3_tuple").read<std::vector<R3>>() ==
+            std::vector{R3{1.2, 0.2, 3}, R3{2.3, -1, 4}, R3{3.2, 2.1, 1.4}});
+
+    REQUIRE(symbol_table1.getAttribute("r11_tuple").read<std::vector<R11>>() == std::vector{R11{1.3}, R11{2.4}});
+    REQUIRE(symbol_table1.getAttribute("r22_tuple").read<std::vector<R22>>() ==
+            std::vector{R22{1.2, 3, 2.3, 4}, R22{3.2, 1.4, 1.3, 5.2}});
+    REQUIRE(symbol_table1.getAttribute("r33_tuple").read<std::vector<R33>>() ==
+            std::vector{R33{1.2, 0.2, 3, 2.3, -1, 4, 3.2, 2.1, 1.4}});
+
+    HighFive::Group embedded1 = symbol_table1.getGroup("embedded");
+
+    HighFive::Group m2d = embedded1.getGroup("m2d");
+    REQUIRE(m2d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(m2d.getAttribute("id").read<uint64_t>() == initial_mesh_id);
+
+    HighFive::Group duals_2d = embedded1.getGroup("duals_2d");
+    REQUIRE(duals_2d.getAttribute("type").read<std::string>() == "(mesh)");
+    HighFive::Group duals_2d_0 = duals_2d.getGroup("0");
+    REQUIRE(duals_2d_0.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(duals_2d_0.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1);
+    HighFive::Group duals_2d_1 = duals_2d.getGroup("1");
+    REQUIRE(duals_2d_1.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(duals_2d_1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2);
+
+    HighFive::Group m3d = embedded1.getGroup("m3d");
+    REQUIRE(m3d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(m3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5);
+
+    HighFive::Group dual_3d = embedded1.getGroup("dual_3d");
+    REQUIRE(dual_3d.getAttribute("type").read<std::string>() == "mesh");
+    REQUIRE(dual_3d.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6);
+
+    HighFive::Group singleton        = checkpoint.getGroup("singleton");
+    HighFive::Group global_variables = singleton.getGroup("global_variables");
+    REQUIRE(global_variables.getAttribute("connectivity_id").read<uint64_t>() == initial_connectivity_id + 7);
+    REQUIRE(global_variables.getAttribute("mesh_id").read<uint64_t>() == initial_mesh_id + 7);
+    HighFive::Group execution_info = singleton.getGroup("execution_info");
+    REQUIRE(execution_info.getAttribute("run_number").read<uint64_t>() == 2);
+
+    HighFive::Group connectivity  = checkpoint.getGroup("connectivity");
+    HighFive::Group connectivity0 = connectivity.getGroup(std::to_string(initial_connectivity_id));
+    REQUIRE(connectivity0.getAttribute("dimension").read<uint64_t>() == 2);
+    REQUIRE(connectivity0.getAttribute("id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity0.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity1 = connectivity.getGroup(std::to_string(initial_connectivity_id + 1));
+    REQUIRE(connectivity1.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 1);
+    REQUIRE(connectivity1.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity1.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group connectivity2 = connectivity.getGroup(std::to_string(initial_connectivity_id + 2));
+    REQUIRE(connectivity2.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 2);
+    REQUIRE(connectivity2.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(connectivity2.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median);
+
+    HighFive::Group connectivity3 = connectivity.getGroup(std::to_string(initial_connectivity_id + 3));
+    REQUIRE(connectivity3.getAttribute("dimension").read<uint64_t>() == 1);
+    REQUIRE(connectivity3.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(connectivity3.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity4 = connectivity.getGroup(std::to_string(initial_connectivity_id + 4));
+    REQUIRE(connectivity4.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 4);
+    REQUIRE(connectivity4.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(connectivity4.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D);
+
+    HighFive::Group connectivity5 = connectivity.getGroup(std::to_string(initial_connectivity_id + 5));
+    REQUIRE(connectivity5.getAttribute("dimension").read<uint64_t>() == 3);
+    REQUIRE(connectivity5.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(connectivity5.getAttribute("type").read<std::string>() == "unstructured");
+
+    HighFive::Group connectivity6 = connectivity.getGroup(std::to_string(initial_connectivity_id + 6));
+    REQUIRE(connectivity6.getAttribute("id").read<uint64_t>() == initial_connectivity_id + 6);
+    REQUIRE(connectivity6.getAttribute("primal_connectivity_id").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(connectivity6.getAttribute("type").read<std::string>() == "dual_connectivity");
+    REQUIRE(connectivity6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group mesh  = checkpoint.getGroup("mesh");
+    HighFive::Group mesh0 = mesh.getGroup(std::to_string(initial_mesh_id));
+    REQUIRE(mesh0.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id);
+    REQUIRE(mesh0.getAttribute("dimension").read<uint64_t>() == 2);
+    REQUIRE(mesh0.getAttribute("id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh0.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh1 = mesh.getGroup(std::to_string(initial_mesh_id + 1));
+    REQUIRE(mesh1.getAttribute("id").read<uint64_t>() == initial_mesh_id + 1);
+    REQUIRE(mesh1.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh1.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh1.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group mesh2 = mesh.getGroup(std::to_string(initial_mesh_id + 2));
+    REQUIRE(mesh2.getAttribute("id").read<uint64_t>() == initial_mesh_id + 2);
+    REQUIRE(mesh2.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id);
+    REQUIRE(mesh2.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh2.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Median);
+
+    HighFive::Group mesh3 = mesh.getGroup(std::to_string(initial_mesh_id + 3));
+    REQUIRE(mesh3.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 3);
+    REQUIRE(mesh3.getAttribute("dimension").read<uint64_t>() == 1);
+    REQUIRE(mesh3.getAttribute("id").read<uint64_t>() == initial_mesh_id + 3);
+    REQUIRE(mesh3.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh4 = mesh.getGroup(std::to_string(initial_mesh_id + 4));
+    REQUIRE(mesh4.getAttribute("id").read<uint64_t>() == initial_mesh_id + 4);
+    REQUIRE(mesh4.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 3);
+    REQUIRE(mesh4.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh4.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Dual1D);
+
+    HighFive::Group mesh5 = mesh.getGroup(std::to_string(initial_mesh_id + 5));
+    REQUIRE(mesh5.getAttribute("connectivity").read<uint64_t>() == initial_connectivity_id + 5);
+    REQUIRE(mesh5.getAttribute("dimension").read<uint64_t>() == 3);
+    REQUIRE(mesh5.getAttribute("id").read<uint64_t>() == initial_mesh_id + 5);
+    REQUIRE(mesh5.getAttribute("type").read<std::string>() == "polygonal");
+
+    HighFive::Group mesh6 = mesh.getGroup(std::to_string(initial_mesh_id + 6));
+    REQUIRE(mesh6.getAttribute("id").read<uint64_t>() == initial_mesh_id + 6);
+    REQUIRE(mesh6.getAttribute("primal_mesh_id").read<uint64_t>() == initial_mesh_id + 5);
+    REQUIRE(mesh6.getAttribute("type").read<std::string>() == "dual_mesh");
+    REQUIRE(mesh6.getAttribute("type_of_dual").read<DualMeshType>() == DualMeshType::Diamond);
+
+    HighFive::Group functions = checkpoint.getGroup("functions");
+    HighFive::Group f         = functions.getGroup("f");
+    REQUIRE(f.getAttribute("id").read<uint64_t>() == 0);
+    REQUIRE(f.getAttribute("symbol_table_id").read<uint64_t>() == 1);
+    HighFive::Group g = functions.getGroup("g");
+    REQUIRE(g.getAttribute("id").read<uint64_t>() == 1);
+    REQUIRE(g.getAttribute("symbol_table_id").read<uint64_t>() == 0);
+  }
+
+  parallel::barrier();
+  if (parallel::rank() == 0) {
+    std::filesystem::remove_all(std::filesystem::path{tmp_dirname});
+  }
+
+  // Revert to default value
+  ResumingManager::getInstance().setFilename("checkpoint.h5");
+  MeshDataBaseForTests::create();
+
+#else    // PUGS_HAS_HDF5
+  REQUIRE_THROWS_WITH(resume(), "error: checkpoint/resume mechanism requires HDF5");
+#endif   // PUGS_HAS_HDF5
+}