From bb3fcfb538eeee92560d9fbcb9d217892ee66bca Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Sat, 20 Apr 2024 13:02:45 +0200
Subject: [PATCH] Add checkpoint/resume for boundary condition descriptor

---
 src/language/modules/SchemeModule.cpp         |  13 ++
 .../DirichletBoundaryConditionDescriptor.hpp  |   6 +-
 .../ExternalBoundaryConditionDescriptor.hpp   |   6 +-
 .../FixedBoundaryConditionDescriptor.hpp      |   2 -
 .../FourierBoundaryConditionDescriptor.hpp    |   6 +-
 .../NeumannBoundaryConditionDescriptor.hpp    |   6 +-
 src/utils/checkpointing/Checkpoint.cpp        |  10 +-
 src/utils/checkpointing/CheckpointUtils.cpp   | 137 +++++++++++--
 src/utils/checkpointing/CheckpointUtils.hpp   |   6 +
 .../IBoundaryConditionDescriptorHFType.hpp    |  23 +++
 src/utils/checkpointing/Resume.cpp            |   2 +-
 src/utils/checkpointing/ResumeUtils.cpp       | 192 +++++++++++++-----
 src/utils/checkpointing/ResumeUtils.hpp       |   2 +
 13 files changed, 327 insertions(+), 84 deletions(-)
 create mode 100644 src/utils/checkpointing/IBoundaryConditionDescriptorHFType.hpp

diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp
index b595e0d34..76581725b 100644
--- a/src/language/modules/SchemeModule.cpp
+++ b/src/language/modules/SchemeModule.cpp
@@ -689,6 +689,19 @@ SchemeModule::registerOperators() const
 void
 SchemeModule::registerCheckpointResume() const
 {
+  CheckpointResumeRepository::instance()
+    .addCheckpointResume(ast_node_data_type_from<std::shared_ptr<const IBoundaryConditionDescriptor>>,
+                         std::function([](const std::string& symbol_name, const EmbeddedData& embedded_data,
+                                          HighFive::File& file, HighFive::Group& checkpoint_group,
+                                          HighFive::Group& symbol_table_group) {
+                           writeIBoundaryConditionDescriptor(symbol_name, embedded_data, file, checkpoint_group,
+                                                             symbol_table_group);
+                         }),
+                         std::function([](const std::string& symbol_name,
+                                          const HighFive::Group& symbol_table_group) -> EmbeddedData {
+                           return readIBoundaryConditionDescriptor(symbol_name, symbol_table_group);
+                         }));
+
   CheckpointResumeRepository::instance()
     .addCheckpointResume(ast_node_data_type_from<std::shared_ptr<const IDiscreteFunctionDescriptor>>,
                          std::function([](const std::string& symbol_name, const EmbeddedData& embedded_data,
diff --git a/src/scheme/DirichletBoundaryConditionDescriptor.hpp b/src/scheme/DirichletBoundaryConditionDescriptor.hpp
index 36f95df0d..32e340810 100644
--- a/src/scheme/DirichletBoundaryConditionDescriptor.hpp
+++ b/src/scheme/DirichletBoundaryConditionDescriptor.hpp
@@ -17,13 +17,13 @@ class DirichletBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return os;
   }
 
-  const std::string_view m_name;
+  const std::string m_name;
 
   std::shared_ptr<const IBoundaryDescriptor> m_boundary_descriptor;
   const FunctionSymbolId m_rhs_symbol_id;
 
  public:
-  std::string_view
+  const std::string&
   name() const
   {
     return m_name;
@@ -47,7 +47,7 @@ class DirichletBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return Type::dirichlet;
   }
 
-  DirichletBoundaryConditionDescriptor(const std::string_view name,
+  DirichletBoundaryConditionDescriptor(const std::string& name,
                                        std::shared_ptr<const IBoundaryDescriptor> boundary_descriptor,
                                        const FunctionSymbolId& rhs_symbol_id)
     : m_name{name}, m_boundary_descriptor(boundary_descriptor), m_rhs_symbol_id{rhs_symbol_id}
diff --git a/src/scheme/ExternalBoundaryConditionDescriptor.hpp b/src/scheme/ExternalBoundaryConditionDescriptor.hpp
index 056592931..05fa10eb1 100644
--- a/src/scheme/ExternalBoundaryConditionDescriptor.hpp
+++ b/src/scheme/ExternalBoundaryConditionDescriptor.hpp
@@ -17,13 +17,13 @@ class ExternalBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return os;
   }
 
-  const std::string_view m_name;
+  const std::string m_name;
 
   std::shared_ptr<const IBoundaryDescriptor> m_boundary_descriptor;
   const std::shared_ptr<const Socket> m_socket;
 
  public:
-  std::string_view
+  const std::string&
   name() const
   {
     return m_name;
@@ -47,7 +47,7 @@ class ExternalBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return Type::external;
   }
 
-  ExternalBoundaryConditionDescriptor(const std::string_view name,
+  ExternalBoundaryConditionDescriptor(const std::string& name,
                                       std::shared_ptr<const IBoundaryDescriptor> boundary_descriptor,
                                       const std::shared_ptr<const Socket>& socket)
     : m_name{name}, m_boundary_descriptor(boundary_descriptor), m_socket{socket}
diff --git a/src/scheme/FixedBoundaryConditionDescriptor.hpp b/src/scheme/FixedBoundaryConditionDescriptor.hpp
index b69648e38..bc7ca9cca 100644
--- a/src/scheme/FixedBoundaryConditionDescriptor.hpp
+++ b/src/scheme/FixedBoundaryConditionDescriptor.hpp
@@ -17,8 +17,6 @@ class FixedBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return os;
   }
 
-  const std::string_view m_name;
-
   std::shared_ptr<const IBoundaryDescriptor> m_boundary_descriptor;
 
  public:
diff --git a/src/scheme/FourierBoundaryConditionDescriptor.hpp b/src/scheme/FourierBoundaryConditionDescriptor.hpp
index c9d75883d..9fdf9d493 100644
--- a/src/scheme/FourierBoundaryConditionDescriptor.hpp
+++ b/src/scheme/FourierBoundaryConditionDescriptor.hpp
@@ -17,14 +17,14 @@ class FourierBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return os;
   }
 
-  const std::string_view m_name;
+  const std::string& m_name;
 
   std::shared_ptr<const IBoundaryDescriptor> m_boundary_descriptor;
   const FunctionSymbolId m_mass_symbol_id;
   const FunctionSymbolId m_rhs_symbol_id;
 
  public:
-  std::string_view
+  const std::string&
   name() const
   {
     return m_name;
@@ -54,7 +54,7 @@ class FourierBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return Type::fourier;
   }
 
-  FourierBoundaryConditionDescriptor(const std::string_view name,
+  FourierBoundaryConditionDescriptor(const std::string& name,
                                      std::shared_ptr<const IBoundaryDescriptor> boundary_descriptor,
                                      const FunctionSymbolId& mass_symbol_id,
                                      const FunctionSymbolId& rhs_symbol_id)
diff --git a/src/scheme/NeumannBoundaryConditionDescriptor.hpp b/src/scheme/NeumannBoundaryConditionDescriptor.hpp
index 597ab95e7..d318d2842 100644
--- a/src/scheme/NeumannBoundaryConditionDescriptor.hpp
+++ b/src/scheme/NeumannBoundaryConditionDescriptor.hpp
@@ -17,13 +17,13 @@ class NeumannBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return os;
   }
 
-  const std::string_view m_name;
+  const std::string m_name;
 
   std::shared_ptr<const IBoundaryDescriptor> m_boundary_descriptor;
   const FunctionSymbolId m_rhs_symbol_id;
 
  public:
-  std::string_view
+  const std::string&
   name() const
   {
     return m_name;
@@ -47,7 +47,7 @@ class NeumannBoundaryConditionDescriptor : public IBoundaryConditionDescriptor
     return Type::neumann;
   }
 
-  NeumannBoundaryConditionDescriptor(const std::string_view name,
+  NeumannBoundaryConditionDescriptor(const std::string& name,
                                      std::shared_ptr<const IBoundaryDescriptor> boundary_descriptor,
                                      const FunctionSymbolId& rhs_symbol_id)
     : m_name{name}, m_boundary_descriptor(boundary_descriptor), m_rhs_symbol_id{rhs_symbol_id}
diff --git a/src/utils/checkpointing/Checkpoint.cpp b/src/utils/checkpointing/Checkpoint.cpp
index 2de99e48e..ea5ede9cb 100644
--- a/src/utils/checkpointing/Checkpoint.cpp
+++ b/src/utils/checkpointing/Checkpoint.cpp
@@ -75,6 +75,7 @@ checkpoint()
 
     std::shared_ptr<const SymbolTable> p_symbol_table = ASTExecutionStack::getInstance().currentNode().m_symbol_table;
     auto symbol_table_group                           = checkpoint;
+    size_t symbol_table_id                            = 0;
     while (p_symbol_table.use_count() > 0) {
       symbol_table_group = symbol_table_group.createGroup("symbol table");
 
@@ -85,13 +86,17 @@ checkpoint()
       for (auto& symbol : symbol_list) {
         switch (symbol.attributes().dataType()) {
         case ASTNodeDataType::builtin_function_t:
-        case ASTNodeDataType::function_t:
         case ASTNodeDataType::type_name_id_t: {
           break;
         }
+        case ASTNodeDataType::function_t: {
+          HighFive::Group function_group = checkpoint.createGroup("functions/" + symbol.name());
+          function_group.createAttribute("id", std::get<size_t>(symbol.attributes().value()));
+          function_group.createAttribute("symbol_table_id", symbol_table_id);
+          break;
+        }
         default: {
           if ((symbol_table.has(symbol.name(), ASTExecutionStack::getInstance().currentNode().begin())) and
-              (symbol.attributes().dataType() != ASTNodeDataType::builtin_function_t) and
               (not symbol.attributes().isModuleVariable())) {
             std::visit(
               [&](auto&& data) {
@@ -130,6 +135,7 @@ checkpoint()
       }
 
       p_symbol_table = symbol_table.parentTable();
+      ++symbol_table_id;
     }
 
     if (file.exist("last_checkpoint")) {
diff --git a/src/utils/checkpointing/CheckpointUtils.cpp b/src/utils/checkpointing/CheckpointUtils.cpp
index 6a45d332a..86aad96ae 100644
--- a/src/utils/checkpointing/CheckpointUtils.cpp
+++ b/src/utils/checkpointing/CheckpointUtils.cpp
@@ -16,7 +16,9 @@
 #include <mesh/NumberedZoneDescriptor.hpp>
 #include <scheme/DiscreteFunctionP0.hpp>
 #include <scheme/DiscreteFunctionP0Vector.hpp>
+#include <scheme/IBoundaryConditionDescriptor.hpp>
 #include <utils/checkpointing/DiscreteFunctionTypeHFType.hpp>
+#include <utils/checkpointing/IBoundaryConditionDescriptorHFType.hpp>
 #include <utils/checkpointing/IBoundaryDescriptorHFType.hpp>
 #include <utils/checkpointing/IInterfaceDescriptorHFType.hpp>
 #include <utils/checkpointing/IZoneDescriptorHFType.hpp>
@@ -24,6 +26,17 @@
 #include <utils/checkpointing/QuadratureTypeHFType.hpp>
 #include <utils/checkpointing/RefItemListHFType.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>
+
 template <ItemType item_type, size_t Dimension>
 void
 writeRefItemList(const Connectivity<Dimension>& connectivity, HighFive::Group& connectivity_group)
@@ -141,20 +154,8 @@ writeConnectivity(const Connectivity<Dimension>& connectivity, HighFive::File& f
 }
 
 void
-writeIBoundaryDescriptor(const std::string& symbol_name,
-                         const EmbeddedData& embedded_data,
-                         HighFive::File&,
-                         HighFive::Group&,
-                         HighFive::Group& symbol_table_group)
+writeIBoundaryDescriptor(HighFive::Group& variable_group, const IBoundaryDescriptor& iboundary_descriptor)
 {
-  HighFive::Group variable_group = symbol_table_group.createGroup("embedded/" + symbol_name);
-
-  std::shared_ptr<const IBoundaryDescriptor> iboundary_descriptor_p =
-    dynamic_cast<const DataHandler<const IBoundaryDescriptor>&>(embedded_data.get()).data_ptr();
-
-  const IBoundaryDescriptor& iboundary_descriptor = *iboundary_descriptor_p;
-
-  variable_group.createAttribute("type", dataTypeName(ast_node_data_type_from<decltype(iboundary_descriptor_p)>));
   variable_group.createAttribute("iboundary_descriptor_type", iboundary_descriptor.type());
 
   switch (iboundary_descriptor.type()) {
@@ -173,6 +174,116 @@ writeIBoundaryDescriptor(const std::string& symbol_name,
   }
 }
 
+void
+writeIBoundaryConditionDescriptor(const std::string& symbol_name,
+                                  const EmbeddedData& embedded_data,
+                                  HighFive::File&,
+                                  HighFive::Group&,
+                                  HighFive::Group& symbol_table_group)
+{
+  HighFive::Group variable_group = symbol_table_group.createGroup("embedded/" + symbol_name);
+
+  std::shared_ptr<const IBoundaryConditionDescriptor> iboundary_condition_descriptor_p =
+    dynamic_cast<const DataHandler<const IBoundaryConditionDescriptor>&>(embedded_data.get()).data_ptr();
+
+  const IBoundaryConditionDescriptor& iboundary_condition_descriptor = *iboundary_condition_descriptor_p;
+
+  variable_group.createAttribute("type",
+                                 dataTypeName(ast_node_data_type_from<decltype(iboundary_condition_descriptor_p)>));
+  variable_group.createAttribute("iboundary_condition_descriptor_type", iboundary_condition_descriptor.type());
+
+  HighFive::Group boundary_group = variable_group.createGroup("boundary");
+
+  switch (iboundary_condition_descriptor.type()) {
+  case IBoundaryConditionDescriptor::Type::axis: {
+    const AxisBoundaryConditionDescriptor& axis_bc_descriptor =
+      dynamic_cast<const AxisBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, axis_bc_descriptor.boundaryDescriptor());
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::dirichlet: {
+    const DirichletBoundaryConditionDescriptor& dirichlet_bc_descriptor =
+      dynamic_cast<const DirichletBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, dirichlet_bc_descriptor.boundaryDescriptor());
+    variable_group.createAttribute("name", dirichlet_bc_descriptor.name());
+    variable_group.createAttribute("rhs_function_id", dirichlet_bc_descriptor.rhsSymbolId().id());
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::external: {
+    throw NotImplementedError("checkpoint/resume with sockets");
+
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::fourier: {
+    const FourierBoundaryConditionDescriptor& fourier_bc_descriptor =
+      dynamic_cast<const FourierBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, fourier_bc_descriptor.boundaryDescriptor());
+    variable_group.createAttribute("name", fourier_bc_descriptor.name());
+    variable_group.createAttribute("rhs_function_id", fourier_bc_descriptor.rhsSymbolId().id());
+    variable_group.createAttribute("mass_function_id", fourier_bc_descriptor.massSymbolId().id());
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::fixed: {
+    const FixedBoundaryConditionDescriptor& fixed_bc_descriptor =
+      dynamic_cast<const FixedBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, fixed_bc_descriptor.boundaryDescriptor());
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::free: {
+    const FreeBoundaryConditionDescriptor& free_bc_descriptor =
+      dynamic_cast<const FreeBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, free_bc_descriptor.boundaryDescriptor());
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::inflow: {
+    const InflowBoundaryConditionDescriptor& inflow_bc_descriptor =
+      dynamic_cast<const InflowBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, inflow_bc_descriptor.boundaryDescriptor());
+    variable_group.createAttribute("function_id", inflow_bc_descriptor.functionSymbolId().id());
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::neumann: {
+    const NeumannBoundaryConditionDescriptor& neumann_bc_descriptor =
+      dynamic_cast<const NeumannBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, neumann_bc_descriptor.boundaryDescriptor());
+    variable_group.createAttribute("name", neumann_bc_descriptor.name());
+    variable_group.createAttribute("rhs_function_id", neumann_bc_descriptor.rhsSymbolId().id());
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::outflow: {
+    const OutflowBoundaryConditionDescriptor& outflow_bc_descriptor =
+      dynamic_cast<const OutflowBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, outflow_bc_descriptor.boundaryDescriptor());
+    break;
+  }
+  case IBoundaryConditionDescriptor::Type::symmetry: {
+    const SymmetryBoundaryConditionDescriptor& symmetric_bc_descriptor =
+      dynamic_cast<const SymmetryBoundaryConditionDescriptor&>(iboundary_condition_descriptor);
+    writeIBoundaryDescriptor(boundary_group, symmetric_bc_descriptor.boundaryDescriptor());
+    break;
+  }
+  }
+}
+
+void
+writeIBoundaryDescriptor(const std::string& symbol_name,
+                         const EmbeddedData& embedded_data,
+                         HighFive::File&,
+                         HighFive::Group&,
+                         HighFive::Group& symbol_table_group)
+{
+  HighFive::Group variable_group = symbol_table_group.createGroup("embedded/" + symbol_name);
+
+  std::shared_ptr<const IBoundaryDescriptor> iboundary_descriptor_p =
+    dynamic_cast<const DataHandler<const IBoundaryDescriptor>&>(embedded_data.get()).data_ptr();
+
+  const IBoundaryDescriptor& iboundary_descriptor = *iboundary_descriptor_p;
+
+  variable_group.createAttribute("type", dataTypeName(ast_node_data_type_from<decltype(iboundary_descriptor_p)>));
+
+  writeIBoundaryDescriptor(variable_group, iboundary_descriptor);
+}
+
 void
 writeIDiscreteFunctionDescriptor(const std::string& symbol_name,
                                  const EmbeddedData& embedded_data,
diff --git a/src/utils/checkpointing/CheckpointUtils.hpp b/src/utils/checkpointing/CheckpointUtils.hpp
index 9c9a03a19..77de3fc32 100644
--- a/src/utils/checkpointing/CheckpointUtils.hpp
+++ b/src/utils/checkpointing/CheckpointUtils.hpp
@@ -42,6 +42,12 @@ write(HighFive::Group& group,
   write(group, name, item_value.arrayView());
 }
 
+void writeIBoundaryConditionDescriptor(const std::string& symbol_name,
+                                       const EmbeddedData& embedded_data,
+                                       HighFive::File& file,
+                                       HighFive::Group& checkpoint_group,
+                                       HighFive::Group& symbol_table_group);
+
 void writeIBoundaryDescriptor(const std::string& symbol_name,
                               const EmbeddedData& embedded_data,
                               HighFive::File& file,
diff --git a/src/utils/checkpointing/IBoundaryConditionDescriptorHFType.hpp b/src/utils/checkpointing/IBoundaryConditionDescriptorHFType.hpp
new file mode 100644
index 000000000..f6854a5df
--- /dev/null
+++ b/src/utils/checkpointing/IBoundaryConditionDescriptorHFType.hpp
@@ -0,0 +1,23 @@
+#ifndef I_BOUNDARY_CONDITION_DESCRIPTOR_HF_TYPE_HPP
+#define I_BOUNDARY_CONDITION_DESCRIPTOR_HF_TYPE_HPP
+
+#include <scheme/IBoundaryConditionDescriptor.hpp>
+#include <utils/checkpointing/CheckpointUtils.hpp>
+
+HighFive::EnumType<IBoundaryConditionDescriptor::Type> PUGS_INLINE
+create_enum_i_boundary_condition_descriptor_type()
+{
+  return {{"axis", IBoundaryConditionDescriptor::Type::axis},
+          {"dirichlet", IBoundaryConditionDescriptor::Type::dirichlet},
+          {"external", IBoundaryConditionDescriptor::Type::external},
+          {"fixed", IBoundaryConditionDescriptor::Type::fixed},
+          {"fourier", IBoundaryConditionDescriptor::Type::fourier},
+          {"free", IBoundaryConditionDescriptor::Type::free},
+          {"inflow", IBoundaryConditionDescriptor::Type::inflow},
+          {"neumann", IBoundaryConditionDescriptor::Type::neumann},
+          {"outflow", IBoundaryConditionDescriptor::Type::outflow},
+          {"symmetry", IBoundaryConditionDescriptor::Type::symmetry}};
+}
+HIGHFIVE_REGISTER_TYPE(IBoundaryConditionDescriptor::Type, create_enum_i_boundary_condition_descriptor_type);
+
+#endif   // I_BOUNDARY_CONDITION_DESCRIPTOR_HF_TYPE_HPP
diff --git a/src/utils/checkpointing/Resume.cpp b/src/utils/checkpointing/Resume.cpp
index 0bddcac07..c71f79eb8 100644
--- a/src/utils/checkpointing/Resume.cpp
+++ b/src/utils/checkpointing/Resume.cpp
@@ -59,7 +59,7 @@ resume()
       std::cout << rang::fgB::magenta << "Resume DualMeshManager NIY" << rang::fg::reset << '\n';
     }
 
-    ResumingData::instance().readData(checkpoint);
+    ResumingData::instance().readData(checkpoint, p_symbol_table);
 
     bool finished = true;
     do {
diff --git a/src/utils/checkpointing/ResumeUtils.cpp b/src/utils/checkpointing/ResumeUtils.cpp
index a4a47125f..6f76e8cc0 100644
--- a/src/utils/checkpointing/ResumeUtils.cpp
+++ b/src/utils/checkpointing/ResumeUtils.cpp
@@ -13,7 +13,9 @@
 #include <mesh/NumberedZoneDescriptor.hpp>
 #include <scheme/DiscreteFunctionDescriptorP0.hpp>
 #include <scheme/DiscreteFunctionDescriptorP0Vector.hpp>
+#include <scheme/IBoundaryConditionDescriptor.hpp>
 #include <utils/checkpointing/DiscreteFunctionTypeHFType.hpp>
+#include <utils/checkpointing/IBoundaryConditionDescriptorHFType.hpp>
 #include <utils/checkpointing/IBoundaryDescriptorHFType.hpp>
 #include <utils/checkpointing/IInterfaceDescriptorHFType.hpp>
 #include <utils/checkpointing/IZoneDescriptorHFType.hpp>
@@ -21,87 +23,176 @@
 #include <utils/checkpointing/QuadratureTypeHFType.hpp>
 #include <utils/checkpointing/ResumingData.hpp>
 
-EmbeddedData
-readIBoundaryDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
+#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>
+
+std::shared_ptr<const IBoundaryDescriptor>
+readIBoundaryDescriptor(const HighFive::Group& iboundarydescriptor_group)
 {
-  const HighFive::Group iboundarydecriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
   const IBoundaryDescriptor::Type iboundary_descriptor_type =
-    iboundarydecriptor_group.getAttribute("iboundary_descriptor_type").read<IBoundaryDescriptor::Type>();
+    iboundarydescriptor_group.getAttribute("iboundary_descriptor_type").read<IBoundaryDescriptor::Type>();
 
-  EmbeddedData embedded_data;
+  std::shared_ptr<const IBoundaryDescriptor> i_boundary_descriptor;
 
   switch (iboundary_descriptor_type) {
   case IBoundaryDescriptor::Type::named: {
-    const std::string name = iboundarydecriptor_group.getAttribute("name").read<std::string>();
-
-    embedded_data = {
-      std::make_shared<DataHandler<const IBoundaryDescriptor>>(std::make_shared<const NamedBoundaryDescriptor>(name))};
+    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 = iboundarydecriptor_group.getAttribute("number").read<unsigned int>();
+    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
+readIBoundaryConditionDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
+{
+  const HighFive::Group iboundaryconditiondecriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+  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>();
 
-    embedded_data = {std::make_shared<DataHandler<const IBoundaryDescriptor>>(
-      std::make_shared<const NumberedBoundaryDescriptor>(number))};
+    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 embedded_data;
+  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))};
 }
 
 EmbeddedData
 readIDiscreteFunctionDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
 {
-  const HighFive::Group idiscrete_function_decriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+  const HighFive::Group idiscrete_function_descriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
   const DiscreteFunctionType discrete_function_type =
-    idiscrete_function_decriptor_group.getAttribute("discrete_function_type").read<DiscreteFunctionType>();
+    idiscrete_function_descriptor_group.getAttribute("discrete_function_type").read<DiscreteFunctionType>();
 
-  EmbeddedData embedded_data;
+  std::shared_ptr<const IDiscreteFunctionDescriptor> idiscrete_function_descriptor;
 
   switch (discrete_function_type) {
   case DiscreteFunctionType::P0: {
-    embedded_data = {std::make_shared<DataHandler<const IDiscreteFunctionDescriptor>>(
-      std::make_shared<const DiscreteFunctionDescriptorP0>())};
+    idiscrete_function_descriptor = std::make_shared<const DiscreteFunctionDescriptorP0>();
     break;
   }
   case DiscreteFunctionType::P0Vector: {
-    embedded_data = {std::make_shared<DataHandler<const IDiscreteFunctionDescriptor>>(
-      std::make_shared<const DiscreteFunctionDescriptorP0Vector>())};
+    idiscrete_function_descriptor = std::make_shared<const DiscreteFunctionDescriptorP0Vector>();
     break;
   }
   }
 
-  return embedded_data;
+  return {std::make_shared<DataHandler<const IDiscreteFunctionDescriptor>>(idiscrete_function_descriptor)};
 }
 
 EmbeddedData
 readIInterfaceDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
 {
-  const HighFive::Group iinterfacedecriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+  const HighFive::Group iinterfacedescriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
   const IInterfaceDescriptor::Type iinterface_descriptor_type =
-    iinterfacedecriptor_group.getAttribute("iinterface_descriptor_type").read<IInterfaceDescriptor::Type>();
+    iinterfacedescriptor_group.getAttribute("iinterface_descriptor_type").read<IInterfaceDescriptor::Type>();
 
-  EmbeddedData embedded_data;
+  std::shared_ptr<const IInterfaceDescriptor> iinterface_descriptor;
 
   switch (iinterface_descriptor_type) {
   case IInterfaceDescriptor::Type::named: {
-    const std::string name = iinterfacedecriptor_group.getAttribute("name").read<std::string>();
-
-    embedded_data = {std::make_shared<DataHandler<const IInterfaceDescriptor>>(
-      std::make_shared<const NamedInterfaceDescriptor>(name))};
+    const std::string name = iinterfacedescriptor_group.getAttribute("name").read<std::string>();
+    iinterface_descriptor  = std::make_shared<const NamedInterfaceDescriptor>(name);
     break;
   }
   case IInterfaceDescriptor::Type::numbered: {
-    const unsigned int number = iinterfacedecriptor_group.getAttribute("number").read<unsigned int>();
-
-    embedded_data = {std::make_shared<DataHandler<const IInterfaceDescriptor>>(
-      std::make_shared<const NumberedInterfaceDescriptor>(number))};
+    const unsigned int number = iinterfacedescriptor_group.getAttribute("number").read<unsigned int>();
+    iinterface_descriptor     = std::make_shared<const NumberedInterfaceDescriptor>(number);
     break;
   }
   }
-
-  return embedded_data;
+  return {std::make_shared<DataHandler<const IInterfaceDescriptor>>(iinterface_descriptor)};
 }
 
 EmbeddedData
@@ -112,27 +203,24 @@ readIQuadratureDescriptor(const std::string& symbol_name, const HighFive::Group&
     iquadraturedescriptor_group.getAttribute("quadrature_type").read<QuadratureType>();
   const size_t degree = iquadraturedescriptor_group.getAttribute("quadrature_degree").read<size_t>();
 
-  EmbeddedData embedded_data;
+  std::shared_ptr<const IQuadratureDescriptor> iquadrature_descrptor;
 
   switch (quadrature_type) {
   case QuadratureType::Gauss: {
-    embedded_data = {std::make_shared<DataHandler<const IQuadratureDescriptor>>(
-      std::make_shared<const GaussQuadratureDescriptor>(degree))};
+    iquadrature_descrptor = std::make_shared<const GaussQuadratureDescriptor>(degree);
     break;
   }
   case QuadratureType::GaussLegendre: {
-    embedded_data = {std::make_shared<DataHandler<const IQuadratureDescriptor>>(
-      std::make_shared<const GaussLegendreQuadratureDescriptor>(degree))};
+    iquadrature_descrptor = std::make_shared<const GaussLegendreQuadratureDescriptor>(degree);
     break;
   }
   case QuadratureType::GaussLobatto: {
-    embedded_data = {std::make_shared<DataHandler<const IQuadratureDescriptor>>(
-      std::make_shared<const GaussLobattoQuadratureDescriptor>(degree))};
+    iquadrature_descrptor = std::make_shared<const GaussLobattoQuadratureDescriptor>(degree);
     break;
   }
   }
 
-  return embedded_data;
+  return {std::make_shared<DataHandler<const IQuadratureDescriptor>>(iquadrature_descrptor)};
 }
 
 EmbeddedData
@@ -147,30 +235,26 @@ readItemType(const std::string& symbol_name, const HighFive::Group& symbol_table
 EmbeddedData
 readIZoneDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group)
 {
-  const HighFive::Group izonedecriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
+  const HighFive::Group izonedescriptor_group = symbol_table_group.getGroup("embedded/" + symbol_name);
   const IZoneDescriptor::Type izone_descriptor_type =
-    izonedecriptor_group.getAttribute("izone_descriptor_type").read<IZoneDescriptor::Type>();
+    izonedescriptor_group.getAttribute("izone_descriptor_type").read<IZoneDescriptor::Type>();
 
-  EmbeddedData embedded_data;
+  std::shared_ptr<const IZoneDescriptor> izone_descriptor;
 
   switch (izone_descriptor_type) {
   case IZoneDescriptor::Type::named: {
-    const std::string name = izonedecriptor_group.getAttribute("name").read<std::string>();
-
-    embedded_data = {
-      std::make_shared<DataHandler<const IZoneDescriptor>>(std::make_shared<const NamedZoneDescriptor>(name))};
+    const std::string name = izonedescriptor_group.getAttribute("name").read<std::string>();
+    izone_descriptor       = std::make_shared<const NamedZoneDescriptor>(name);
     break;
   }
   case IZoneDescriptor::Type::numbered: {
-    const unsigned int number = izonedecriptor_group.getAttribute("number").read<unsigned int>();
-
-    embedded_data = {
-      std::make_shared<DataHandler<const IZoneDescriptor>>(std::make_shared<const NumberedZoneDescriptor>(number))};
+    const unsigned int number = izonedescriptor_group.getAttribute("number").read<unsigned int>();
+    izone_descriptor          = std::make_shared<const NumberedZoneDescriptor>(number);
     break;
   }
   }
 
-  return embedded_data;
+  return {std::make_shared<DataHandler<const IZoneDescriptor>>(izone_descriptor)};
 }
 
 EmbeddedData
diff --git a/src/utils/checkpointing/ResumeUtils.hpp b/src/utils/checkpointing/ResumeUtils.hpp
index 777216896..2419cfb5b 100644
--- a/src/utils/checkpointing/ResumeUtils.hpp
+++ b/src/utils/checkpointing/ResumeUtils.hpp
@@ -28,6 +28,8 @@ read(const HighFive::Group& group, const std::string& name)
   return array;
 }
 
+EmbeddedData readIBoundaryConditionDescriptor(const std::string& symbol_name,
+                                              const HighFive::Group& symbol_table_group);
 EmbeddedData readIBoundaryDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group);
 EmbeddedData readIDiscreteFunctionDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group);
 EmbeddedData readIInterfaceDescriptor(const std::string& symbol_name, const HighFive::Group& symbol_table_group);
-- 
GitLab