Skip to content

Add support for JSON data bases for graph data structures. - #205

Open
YohannDudouit wants to merge 15 commits into
developfrom
yohann/json-db
Open

Add support for JSON data bases for graph data structures.#205
YohannDudouit wants to merge 15 commits into
developfrom
yohann/json-db

Conversation

@YohannDudouit

@YohannDudouit YohannDudouit commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

This PR introduces a JSON-indexed filesystem backend for persisting training data produced by AMS workflows. It is primarily intended to capture graph inputs and physics outputs when a surrogate is unavailable or rejected, without requiring HDF5 or RabbitMQ.

  • Add AMS_JSON as a configurable database type.
  • Store tensor data and homogeneous graphs as binary tensor files with shape, dtype, and path metadata in manifest.json.
  • Route graph execution through AMSWorkflow::evaluate, preserving the surrogate-first flow and recording data after physics fallback.
  • Add integration coverage for forced fallback, rejected surrogates, disabled storage, repeated executions, and operation without a configured database.
  • Fix a missing struct import in the diffusion MGN fixture generator.

The initial graph implementation focuses on homogeneous graphs and binary-backed JSON manifests; heterogeneous graph storage is not yet implemented.

@YohannDudouit
YohannDudouit requested a review from lpottier August 21, 2026 23:38

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cpp-linter Review

Used clang-format v18.1.8

Click here for the full clang-format patch
diff --git a/src/AMSlib/wf/basedb.cpp b/src/AMSlib/wf/basedb.cpp
index b5adaa1..ac1a9cc 100644
--- a/src/AMSlib/wf/basedb.cpp
+++ b/src/AMSlib/wf/basedb.cpp
@@ -1 +1,2 @@
-#include <string>
+#include "wf/basedb.hpp"
+
@@ -2,0 +4 @@
+#include <string>
@@ -5 +6,0 @@
-#include "wf/basedb.hpp"
diff --git a/src/AMSlib/wf/basedb.hpp b/src/AMSlib/wf/basedb.hpp
index d54980e..9bc64f5 100644
--- a/src/AMSlib/wf/basedb.hpp
+++ b/src/AMSlib/wf/basedb.hpp
@@ -159 +159,2 @@ public:
-          (this->type() + " database does not support heterogeneous graph storage")
+          (this->type() + " database does not support heterogeneous graph "
+                          "storage")
diff --git a/src/AMSlib/wf/jsondb.cpp b/src/AMSlib/wf/jsondb.cpp
index 52edd15..7117057 100644
--- a/src/AMSlib/wf/jsondb.cpp
+++ b/src/AMSlib/wf/jsondb.cpp
@@ -57 +57,2 @@ std::string base64Encode(const uint8_t* data, size_t len)
-      for (i = 0; i < 4; i++) ret += base64_chars[char_array_4[i]];
+      for (i = 0; i < 4; i++)
+        ret += base64_chars[char_array_4[i]];
@@ -63 +64,2 @@ std::string base64Encode(const uint8_t* data, size_t len)
-    for (int j = i; j < 3; j++) char_array_3[j] = '\0';
+    for (int j = i; j < 3; j++)
+      char_array_3[j] = '\0';
@@ -71 +73,2 @@ std::string base64Encode(const uint8_t* data, size_t len)
-    for (int j = 0; j < i + 1; j++) ret += base64_chars[char_array_4[j]];
+    for (int j = 0; j < i + 1; j++)
+      ret += base64_chars[char_array_4[j]];
@@ -73 +76,2 @@ std::string base64Encode(const uint8_t* data, size_t len)
-    while (i++ < 3) ret += '=';
+    while (i++ < 3)
+      ret += '=';
@@ -102,2 +106 @@ JSONDB::JSONDB(std::string path,
-          ("Invalid json_mode: " + json_mode_ +
-           ". Must be 'binary' or 'json'.")
+          ("Invalid json_mode: " + json_mode_ + ". Must be 'binary' or 'json'.")
@@ -107,4 +110 @@ JSONDB::JSONDB(std::string path,
-  AMS_DBG(JSONDB,
-          "Created JSONDB at '{}' with mode '{}'",
-          fp,
-          json_mode_);
+  AMS_DBG(JSONDB, "Created JSONDB at '{}' with mode '{}'", fp, json_mode_);
@@ -144,8 +144,4 @@ std::string JSONDB::torchDTypeToString(torch::Dtype dtype) const
-  if (dtype == torch::kFloat32 || dtype == torch::kFloat)
-    return "float32";
-  if (dtype == torch::kFloat64 || dtype == torch::kDouble)
-    return "float64";
-  if (dtype == torch::kInt32)
-    return "int32";
-  if (dtype == torch::kInt64 || dtype == torch::kLong)
-    return "int64";
+  if (dtype == torch::kFloat32 || dtype == torch::kFloat) return "float32";
+  if (dtype == torch::kFloat64 || dtype == torch::kDouble) return "float64";
+  if (dtype == torch::kInt32) return "int32";
+  if (dtype == torch::kInt64 || dtype == torch::kLong) return "int64";
@@ -172 +168 @@ size_t JSONDB::writeBinaryTensor(const AMSTensor& tensor,
-                                  const std::string& path)
+                                 const std::string& path)
@@ -182,6 +178,5 @@ size_t JSONDB::writeBinaryTensor(const AMSTensor& tensor,
-    AMS_WARNING(
-        JSONDB,
-        "GPU tensor detected. Copying to CPU for serialization (not yet "
-        "implemented - will fail).");
-    THROW(std::runtime_error,
-          "GPU tensor serialization not yet implemented");
+    AMS_WARNING(JSONDB,
+                "GPU tensor detected. Copying to CPU for serialization (not "
+                "yet "
+                "implemented - will fail).");
+    THROW(std::runtime_error, "GPU tensor serialization not yet implemented");
@@ -214,4 +209 @@ size_t JSONDB::writeBinaryTensor(const AMSTensor& tensor,
-  AMS_DBG(JSONDB,
-          "Wrote binary tensor to '{}' ({} bytes)",
-          path,
-          byte_size);
+  AMS_DBG(JSONDB, "Wrote binary tensor to '{}' ({} bytes)", path, byte_size);
@@ -223 +215 @@ size_t JSONDB::writeBinaryTensor(const torch::Tensor& tensor,
-                                  const std::string& path)
+                                 const std::string& path)
@@ -243,4 +235 @@ size_t JSONDB::writeBinaryTensor(const torch::Tensor& tensor,
-  AMS_DBG(JSONDB,
-          "Wrote PyTorch tensor to '{}' ({} bytes)",
-          path,
-          byte_size);
+  AMS_DBG(JSONDB, "Wrote PyTorch tensor to '{}' ({} bytes)", path, byte_size);
@@ -258,2 +247 @@ nlohmann::json JSONDB::encodeBase64Tensor(const AMSTensor& tensor)
-  if (tensor.location() != AMSResourceType::AMS_HOST ||
-      !tensor.contiguous()) {
+  if (tensor.location() != AMSResourceType::AMS_HOST || !tensor.contiguous()) {
@@ -292,2 +280 @@ void JSONDB::validateEdgeIndex(const AMSTensor& edge_index, int64_t num_nodes)
-    THROW(std::invalid_argument,
-          "edge_index must have dtype int64");
+    THROW(std::invalid_argument, "edge_index must have dtype int64");
@@ -313,2 +300,2 @@ void JSONDB::validateEdgeIndex(const AMSTensor& edge_index, int64_t num_nodes)
-      oss << "edge_index contains self-loop at edge " << i << ": "
-          << indices[i] << " -> " << indices[i + num_edges];
+      oss << "edge_index contains self-loop at edge " << i << ": " << indices[i]
+          << " -> " << indices[i + num_edges];
@@ -351,4 +338,5 @@ void JSONDB::store(ArrayRef<torch::Tensor> Inputs,
-      tensors_json[name] = nlohmann::json{{"path", rel_path},
-                                          {"dtype", torchDTypeToString(Inputs[i].scalar_type())},
-                                          {"shape", shape},
-                                          {"byte_size", byte_size}};
+      tensors_json[name] =
+          nlohmann::json{{"path", rel_path},
+                         {"dtype", torchDTypeToString(Inputs[i].scalar_type())},
+                         {"shape", shape},
+                         {"byte_size", byte_size}};
@@ -375,4 +363,6 @@ void JSONDB::store(ArrayRef<torch::Tensor> Inputs,
-      tensors_json[name] = nlohmann::json{{"path", rel_path},
-                                          {"dtype", torchDTypeToString(Outputs[i].scalar_type())},
-                                          {"shape", shape},
-                                          {"byte_size", byte_size}};
+      tensors_json[name] =
+          nlohmann::json{{"path", rel_path},
+                         {"dtype",
+                          torchDTypeToString(Outputs[i].scalar_type())},
+                         {"shape", shape},
+                         {"byte_size", byte_size}};
@@ -455,5 +445,4 @@ void JSONDB::store(const ams::AMSHomogeneousGraph& graph,
-    tensors_json["edge_index"] = {
-        {"path", rel_path},
-        {"dtype", "int64"},
-        {"shape", std::vector<int64_t>{2, num_edges}},
-        {"byte_size", byte_size}};
+    tensors_json["edge_index"] = {{"path", rel_path},
+                                  {"dtype", "int64"},
+                                  {"shape", std::vector<int64_t>{2, num_edges}},
+                                  {"byte_size", byte_size}};
diff --git a/src/AMSlib/wf/jsondb.hpp b/src/AMSlib/wf/jsondb.hpp
index b68322f..7505792 100644
--- a/src/AMSlib/wf/jsondb.hpp
+++ b/src/AMSlib/wf/jsondb.hpp
@@ -11,2 +10,0 @@
-#include <nlohmann/json.hpp>
-
@@ -14,0 +13 @@
+#include <nlohmann/json.hpp>
diff --git a/src/AMSlib/wf/workflow.hpp b/src/AMSlib/wf/workflow.hpp
index 34d448f..b5e5ae5 100644
--- a/src/AMSlib/wf/workflow.hpp
+++ b/src/AMSlib/wf/workflow.hpp
@@ -106 +106,2 @@ class AMSWorkflow
-      AMS_WARNING(Workflow, "Cannot store graph data: database not initialized");
+      AMS_WARNING(Workflow,
+                  "Cannot store graph data: database not initialized");
@@ -124 +125,2 @@ class AMSWorkflow
-      AMS_WARNING(Workflow, "Cannot store graph data: database not initialized");
+      AMS_WARNING(Workflow,
+                  "Cannot store graph data: database not initialized");
diff --git a/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp b/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
index b6b5589..9644528 100644
--- a/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
+++ b/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
@@ -9 +8,0 @@
-
@@ -76 +75 @@ CATCH_TEST_CASE(
-    ei[e] = e;              // source in first half
+    ei[e] = e;                // source in first half
@@ -103,11 +102,11 @@ CATCH_TEST_CASE(
-  HomogeneousGraphDomainFn physics =
-      [&](const AMSHomogeneousGraph& g, AMSHomogeneousGraphFields& o) {
-        callback_count++;
-
-        // Return float64 delta_u [N, 1] (MFEM precision)
-        const int64_t num_nodes = g.node_features.shape()[0];
-        auto delta = makeTensor<double>({num_nodes, 1});
-        double* data = delta.data<double>();
-        for (int64_t i = 0; i < num_nodes; i++) {
-          data[i] = static_cast<double>(i) * 0.123;
-        }
+  HomogeneousGraphDomainFn physics = [&](const AMSHomogeneousGraph& g,
+                                         AMSHomogeneousGraphFields& o) {
+    callback_count++;
+
+    // Return float64 delta_u [N, 1] (MFEM precision)
+    const int64_t num_nodes = g.node_features.shape()[0];
+    auto delta = makeTensor<double>({num_nodes, 1});
+    double* data = delta.data<double>();
+    for (int64_t i = 0; i < num_nodes; i++) {
+      data[i] = static_cast<double>(i) * 0.123;
+    }
@@ -115,2 +114,2 @@ CATCH_TEST_CASE(
-        o.node_fields.insert("delta_u", std::move(delta));
-      };
+    o.node_fields.insert("delta_u", std::move(delta));
+  };
@@ -175,2 +174,3 @@ CATCH_TEST_CASE(
-  CATCH_REQUIRE(case0["tensors"]["global_features"]["dtype"].get<std::string>() ==
-                "float32");
+  CATCH_REQUIRE(
+      case0["tensors"]["global_features"]["dtype"].get<std::string>() ==
+      "float32");
@@ -207,2 +207,3 @@ CATCH_TEST_CASE(
-CATCH_TEST_CASE("store_data=false returns physics output with zero recorded cases",
-                "[wf][graph][storage]")
+CATCH_TEST_CASE(
+    "store_data=false returns physics output with zero recorded cases",
+    "[wf][graph][storage]")
@@ -210,2 +211 @@ CATCH_TEST_CASE("store_data=false returns physics output with zero recorded case
-  fs::path test_dir =
-      fs::temp_directory_path() / "ams_graph_no_storage_test";
+  fs::path test_dir = fs::temp_directory_path() / "ams_graph_no_storage_test";
@@ -231 +231,2 @@ CATCH_TEST_CASE("store_data=false returns physics output with zero recorded case
-  for (int i = 0; i < 10; i++) nf[i] = static_cast<float>(i) + 100.0f;
+  for (int i = 0; i < 10; i++)
+    nf[i] = static_cast<float>(i) + 100.0f;
@@ -235,2 +236,8 @@ CATCH_TEST_CASE("store_data=false returns physics output with zero recorded case
-  ei[0] = 0; ei[1] = 1; ei[2] = 2; ei[3] = 3;  // sources
-  ei[4] = 1; ei[5] = 2; ei[6] = 3; ei[7] = 4;  // destinations
+  ei[0] = 0;
+  ei[1] = 1;
+  ei[2] = 2;
+  ei[3] = 3;  // sources
+  ei[4] = 1;
+  ei[5] = 2;
+  ei[6] = 3;
+  ei[7] = 4;  // destinations
@@ -240 +247,2 @@ CATCH_TEST_CASE("store_data=false returns physics output with zero recorded case
-  for (int i = 0; i < 4; i++) ef[i] = static_cast<float>(i) * 0.5f;
+  for (int i = 0; i < 4; i++)
+    ef[i] = static_cast<float>(i) * 0.5f;
@@ -255,9 +263,10 @@ CATCH_TEST_CASE("store_data=false returns physics output with zero recorded case
-  HomogeneousGraphDomainFn physics =
-      [&](const AMSHomogeneousGraph& g, AMSHomogeneousGraphFields& o) {
-        callback_count++;
-        const int64_t N = g.node_features.shape()[0];
-        auto delta = makeTensor<double>({N, 1});
-        double* data = delta.data<double>();
-        for (int64_t i = 0; i < N; i++) data[i] = static_cast<double>(i) + 200.0;
-        o.node_fields.insert("delta_u", std::move(delta));
-      };
+  HomogeneousGraphDomainFn physics = [&](const AMSHomogeneousGraph& g,
+                                         AMSHomogeneousGraphFields& o) {
+    callback_count++;
+    const int64_t N = g.node_features.shape()[0];
+    auto delta = makeTensor<double>({N, 1});
+    double* data = delta.data<double>();
+    for (int64_t i = 0; i < N; i++)
+      data[i] = static_cast<double>(i) + 200.0;
+    o.node_fields.insert("delta_u", std::move(delta));
+  };
@@ -293,2 +302 @@ CATCH_TEST_CASE("Multiple calls accumulate cases with distinguishable values",
-  fs::path test_dir =
-      fs::temp_directory_path() / "ams_graph_accumulation_test";
+  fs::path test_dir = fs::temp_directory_path() / "ams_graph_accumulation_test";
@@ -323,2 +331,6 @@ CATCH_TEST_CASE("Multiple calls accumulate cases with distinguishable values",
-    ei[0] = 0; ei[1] = 1; ei[2] = 2;  // sources
-    ei[3] = 1; ei[4] = 2; ei[5] = 3;  // destinations
+    ei[0] = 0;
+    ei[1] = 1;
+    ei[2] = 2;  // sources
+    ei[3] = 1;
+    ei[4] = 2;
+    ei[5] = 3;  // destinations
@@ -398,2 +410,2 @@ CATCH_TEST_CASE("Heterogeneous graph typed storage",
-  fs::path test_dir =
-      fs::temp_directory_path() / "ams_graph_heterogeneous_test";
+  fs::path test_dir = fs::temp_directory_path() / "ams_graph_heterogeneous_"
+                                                  "test";
@@ -417 +429,2 @@ CATCH_TEST_CASE("Heterogeneous graph typed storage",
-  for (int i = 0; i < 15; i++) ff[i] = static_cast<float>(i) * 0.1f;
+  for (int i = 0; i < 15; i++)
+    ff[i] = static_cast<float>(i) * 0.1f;
@@ -424 +437,2 @@ CATCH_TEST_CASE("Heterogeneous graph typed storage",
-  for (int i = 0; i < 6; i++) sf[i] = static_cast<float>(i) * 0.2f;
+  for (int i = 0; i < 6; i++)
+    sf[i] = static_cast<float>(i) * 0.2f;
@@ -432,2 +446,8 @@ CATCH_TEST_CASE("Heterogeneous graph typed storage",
-  ei[0] = 0; ei[1] = 1; ei[2] = 2; ei[3] = 3;  // fluid nodes (sources)
-  ei[4] = 0; ei[5] = 1; ei[6] = 1; ei[7] = 2;  // solid nodes (destinations)
+  ei[0] = 0;
+  ei[1] = 1;
+  ei[2] = 2;
+  ei[3] = 3;  // fluid nodes (sources)
+  ei[4] = 0;
+  ei[5] = 1;
+  ei[6] = 1;
+  ei[7] = 2;  // solid nodes (destinations)
@@ -446,18 +466,20 @@ CATCH_TEST_CASE("Heterogeneous graph typed storage",
-  HeterogeneousGraphDomainFn physics =
-      [&](const AMSHeterogeneousGraph& g, AMSHeterogeneousGraphFields& o) {
-        callback_count++;
-
-        // Output for fluid nodes
-        auto& fluid_out = o.getOrCreateNodeStore("fluid");
-        auto fluid_delta = makeTensor<double>({5, 1});
-        double* fd = fluid_delta.data<double>();
-        for (int i = 0; i < 5; i++) fd[i] = static_cast<double>(i) + 10.0;
-        fluid_out.insert("delta_u", std::move(fluid_delta));
-
-        // Output for solid nodes
-        auto& solid_out = o.getOrCreateNodeStore("solid");
-        auto solid_delta = makeTensor<double>({3, 1});
-        double* sd = solid_delta.data<double>();
-        for (int i = 0; i < 3; i++) sd[i] = static_cast<double>(i) + 20.0;
-        solid_out.insert("delta_u", std::move(solid_delta));
-      };
+  HeterogeneousGraphDomainFn physics = [&](const AMSHeterogeneousGraph& g,
+                                           AMSHeterogeneousGraphFields& o) {
+    callback_count++;
+
+    // Output for fluid nodes
+    auto& fluid_out = o.getOrCreateNodeStore("fluid");
+    auto fluid_delta = makeTensor<double>({5, 1});
+    double* fd = fluid_delta.data<double>();
+    for (int i = 0; i < 5; i++)
+      fd[i] = static_cast<double>(i) + 10.0;
+    fluid_out.insert("delta_u", std::move(fluid_delta));
+
+    // Output for solid nodes
+    auto& solid_out = o.getOrCreateNodeStore("solid");
+    auto solid_delta = makeTensor<double>({3, 1});
+    double* sd = solid_delta.data<double>();
+    for (int i = 0; i < 3; i++)
+      sd[i] = static_cast<double>(i) + 20.0;
+    solid_out.insert("delta_u", std::move(solid_delta));
+  };
@@ -493,2 +515,4 @@ CATCH_TEST_CASE("Heterogeneous graph typed storage",
-  CATCH_REQUIRE(case0["tensors"]["target_node_fluid__delta_u"]["dtype"] == "float64");
-  CATCH_REQUIRE(case0["tensors"]["target_node_solid__delta_u"]["dtype"] == "float64");
+  CATCH_REQUIRE(case0["tensors"]["target_node_fluid__delta_u"]["dtype"] ==
+                "float64");
+  CATCH_REQUIRE(case0["tensors"]["target_node_solid__delta_u"]["dtype"] ==
+                "float64");
@@ -535 +559,2 @@ CATCH_TEST_CASE("Surrogate success: zero callbacks and zero stored cases",
-  for (int i = 0; i < 6; i++) nf[i] = static_cast<float>(i);
+  for (int i = 0; i < 6; i++)
+    nf[i] = static_cast<float>(i);
@@ -538,2 +563,4 @@ CATCH_TEST_CASE("Surrogate success: zero callbacks and zero stored cases",
-  ei[0] = 0; ei[1] = 1;  // sources
-  ei[2] = 1; ei[3] = 2;  // destinations
+  ei[0] = 0;
+  ei[1] = 1;  // sources
+  ei[2] = 1;
+  ei[3] = 2;  // destinations
@@ -542 +569,2 @@ CATCH_TEST_CASE("Surrogate success: zero callbacks and zero stored cases",
-  ef[0] = 0.5f; ef[1] = 1.0f;
+  ef[0] = 0.5f;
+  ef[1] = 1.0f;
@@ -555,6 +583,6 @@ CATCH_TEST_CASE("Surrogate success: zero callbacks and zero stored cases",
-  HomogeneousGraphDomainFn physics =
-      [&](const AMSHomogeneousGraph& g, AMSHomogeneousGraphFields& o) {
-        callback_count++;
-        auto delta = makeTensor<double>({3, 1});
-        o.node_fields.insert("delta_u", std::move(delta));
-      };
+  HomogeneousGraphDomainFn physics = [&](const AMSHomogeneousGraph& g,
+                                         AMSHomogeneousGraphFields& o) {
+    callback_count++;
+    auto delta = makeTensor<double>({3, 1});
+    o.node_fields.insert("delta_u", std::move(delta));
+  };
@@ -599 +627,2 @@ CATCH_TEST_CASE("No database configured: physics output returned without crash",
-  for (int i = 0; i < 8; i++) nf[i] = static_cast<float>(i);
+  for (int i = 0; i < 8; i++)
+    nf[i] = static_cast<float>(i);
@@ -602,2 +631,6 @@ CATCH_TEST_CASE("No database configured: physics output returned without crash",
-  ei[0] = 0; ei[1] = 1; ei[2] = 2;  // sources
-  ei[3] = 1; ei[4] = 2; ei[5] = 3;  // destinations
+  ei[0] = 0;
+  ei[1] = 1;
+  ei[2] = 2;  // sources
+  ei[3] = 1;
+  ei[4] = 2;
+  ei[5] = 3;  // destinations
@@ -606 +639,2 @@ CATCH_TEST_CASE("No database configured: physics output returned without crash",
-  for (int i = 0; i < 3; i++) ef[i] = static_cast<float>(i) * 0.3f;
+  for (int i = 0; i < 3; i++)
+    ef[i] = static_cast<float>(i) * 0.3f;
@@ -619,9 +653,10 @@ CATCH_TEST_CASE("No database configured: physics output returned without crash",
-  HomogeneousGraphDomainFn physics =
-      [&](const AMSHomogeneousGraph& g, AMSHomogeneousGraphFields& o) {
-        callback_count++;
-        const int64_t N = g.node_features.shape()[0];
-        auto delta = makeTensor<double>({N, 1});
-        double* data = delta.data<double>();
-        for (int64_t i = 0; i < N; i++) data[i] = static_cast<double>(i) * 2.5;
-        o.node_fields.insert("delta_u", std::move(delta));
-      };
+  HomogeneousGraphDomainFn physics = [&](const AMSHomogeneousGraph& g,
+                                         AMSHomogeneousGraphFields& o) {
+    callback_count++;
+    const int64_t N = g.node_features.shape()[0];
+    auto delta = makeTensor<double>({N, 1});
+    double* data = delta.data<double>();
+    for (int64_t i = 0; i < N; i++)
+      data[i] = static_cast<double>(i) * 2.5;
+    o.node_fields.insert("delta_u", std::move(delta));
+  };
@@ -650 +685,2 @@ CATCH_TEST_CASE(
-    "Surrogate rejection: model runs but rejected, physics executes once, exact output stored",
+    "Surrogate rejection: model runs but rejected, physics executes once, "
+    "exact output stored",
@@ -681 +717,2 @@ CATCH_TEST_CASE(
-  for (int i = 0; i < 12; i++) nf[i] = static_cast<float>(i) * 1.5f;
+  for (int i = 0; i < 12; i++)
+    nf[i] = static_cast<float>(i) * 1.5f;
@@ -685,2 +722,10 @@ CATCH_TEST_CASE(
-  ei[0] = 0; ei[1] = 1; ei[2] = 2; ei[3] = 3; ei[4] = 4;  // sources
-  ei[5] = 1; ei[6] = 2; ei[7] = 3; ei[8] = 4; ei[9] = 5;  // destinations
+  ei[0] = 0;
+  ei[1] = 1;
+  ei[2] = 2;
+  ei[3] = 3;
+  ei[4] = 4;  // sources
+  ei[5] = 1;
+  ei[6] = 2;
+  ei[7] = 3;
+  ei[8] = 4;
+  ei[9] = 5;  // destinations
@@ -690 +735,2 @@ CATCH_TEST_CASE(
-  for (int i = 0; i < 5; i++) ef[i] = static_cast<float>(i) * 0.25f;
+  for (int i = 0; i < 5; i++)
+    ef[i] = static_cast<float>(i) * 0.25f;
@@ -704,9 +750,10 @@ CATCH_TEST_CASE(
-  HomogeneousGraphDomainFn physics =
-      [&](const AMSHomogeneousGraph& g, AMSHomogeneousGraphFields& o) {
-        callback_count++;
-        const int64_t N = g.node_features.shape()[0];
-        auto delta = makeTensor<double>({N, 1});
-        double* data = delta.data<double>();
-        for (int64_t i = 0; i < N; i++) data[i] = static_cast<double>(i) * 3.7;
-        o.node_fields.insert("delta_u", std::move(delta));
-      };
+  HomogeneousGraphDomainFn physics = [&](const AMSHomogeneousGraph& g,
+                                         AMSHomogeneousGraphFields& o) {
+    callback_count++;
+    const int64_t N = g.node_features.shape()[0];
+    auto delta = makeTensor<double>({N, 1});
+    double* data = delta.data<double>();
+    for (int64_t i = 0; i < N; i++)
+      data[i] = static_cast<double>(i) * 3.7;
+    o.node_fields.insert("delta_u", std::move(delta));
+  };

Have any feedback or feature suggestions? Share it here.

Comment thread src/AMSlib/wf/basedb.cpp Outdated
Comment thread src/AMSlib/wf/basedb.cpp
Comment thread src/AMSlib/wf/basedb.cpp Outdated
Comment thread src/AMSlib/wf/basedb.hpp Outdated
Comment thread src/AMSlib/wf/jsondb.cpp Outdated
Comment thread tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp Outdated
Comment thread tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp Outdated
Comment thread tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp Outdated
Comment thread tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp Outdated
Comment thread tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cpp-linter Review

Used clang-format v18.1.8

Click here for the full clang-format patch
diff --git a/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp b/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
index 9644528..45163fd 100644
--- a/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
+++ b/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
@@ -410,2 +410,3 @@ CATCH_TEST_CASE("Heterogeneous graph typed storage",
-  fs::path test_dir = fs::temp_directory_path() / "ams_graph_heterogeneous_"
-                                                  "test";
+  fs::path test_dir = fs::temp_directory_path() /
+                      "ams_graph_heterogeneous_"
+                      "test";

Have any feedback or feature suggestions? Share it here.

Comment thread tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cpp-linter Review

Used clang-format v18.1.8

Click here for the full clang-format patch
diff --git a/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp b/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
index 60a9fdf..5feb888 100644
--- a/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
+++ b/tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp
@@ -229,2 +229,3 @@ CATCH_TEST_CASE("Homogeneous graph without globals omits global storage",
-  fs::path test_dir = fs::temp_directory_path() / "ams_graph_empty_globals_"
-                                                  "test";
+  fs::path test_dir = fs::temp_directory_path() /
+                      "ams_graph_empty_globals_"
+                      "test";

Have any feedback or feature suggestions? Share it here.

Comment thread tests/AMSlib/ams_interface/test_graph_workflow_storage.cpp Outdated
Comment thread src/AMSlib/wf/workflow.hpp
Comment thread src/AMSlib/wf/jsondb.cpp
Comment thread src/AMSlib/wf/jsondb.cpp Outdated
Comment thread src/AMSlib/wf/jsondb.hpp Outdated
Comment thread src/AMSlib/wf/jsondb.cpp Outdated
Comment thread src/AMSlib/wf/workflow.hpp Outdated
Comment thread src/AMSlib/wf/interface.cpp
Comment thread src/AMSlib/wf/jsondb.cpp
Comment thread src/AMSlib/wf/jsondb.hpp
Comment thread src/AMSlib/wf/jsondb.cpp Outdated
Comment thread src/AMSlib/wf/jsondb.cpp Outdated
@lpottier
lpottier self-requested a review September 2, 2026 17:06
Comment thread src/AMSlib/wf/jsondb.cpp
// Build complete manifest
nlohmann::json manifest;
manifest["format_version"] = 1;
manifest["endianness"] = "little";

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use isLittleEndian() here?

Comment thread src/AMSlib/wf/jsondb.cpp
{
// Create case directory
std::ostringstream case_name;
case_name << "case_" << std::setw(6) << std::setfill('0') << case_counter_;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need rId to distinguish ranks here too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants