From 316d875b3c58cb4fe03e15924645cd6a82461e44 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Del=20Pino?= <stephane.delpino44@gmail.com>
Date: Fri, 25 Oct 2024 19:20:09 +0200
Subject: [PATCH] [ci-skip] WIP: Rework stencil construction

---
 src/mesh/StencilBuilder.cpp | 150 +++++++++++++++++++++++++++++++++++-
 src/mesh/StencilBuilder.hpp |   3 +
 2 files changed, 149 insertions(+), 4 deletions(-)

diff --git a/src/mesh/StencilBuilder.cpp b/src/mesh/StencilBuilder.cpp
index 1fa54e702..31db762a1 100644
--- a/src/mesh/StencilBuilder.cpp
+++ b/src/mesh/StencilBuilder.cpp
@@ -7,6 +7,104 @@
 
 #include <set>
 
+template <ItemType item_type>
+class StencilBuilder::Layer
+{
+  using ItemId = ItemIdT<item_type>;
+  std::vector<ItemId> m_item_id_vector;
+  std::vector<int> m_item_number_vector;
+
+ public:
+  size_t
+  size() const
+  {
+    Assert(m_item_id_vector.size() == m_item_number_vector.size());
+    return m_item_id_vector.size();
+  }
+
+  bool
+  hasItemNumber(const int item_number) const
+  {
+    ssize_t begin = 0;
+    ssize_t end   = m_item_number_vector.size();
+
+    while (begin < end) {
+      const ssize_t mid      = (begin + end) / 2;
+      const auto& mid_number = m_item_number_vector[mid];
+      if (mid_number == item_number) {
+        return true;   // We found the value
+      } else if (mid_number < item_number) {
+        if (begin == mid) {
+          break;
+        }
+        begin = mid - 1;
+      } else {
+        if (end == mid) {
+          break;
+        }
+        end = mid + 1;
+      }
+    }
+    return false;
+  }
+
+  const std::vector<ItemId>&
+  itemIdList() const
+  {
+    return m_item_id_vector;
+  }
+
+  void
+  add(const ItemId item_id, const int item_number)
+  {
+    ssize_t begin = 0;
+    ssize_t end   = m_item_number_vector.size();
+
+    while (begin < end) {
+      const ssize_t mid      = (begin + end) / 2;
+      const auto& mid_number = m_item_number_vector[mid];
+
+      if (mid_number == item_number) {
+        return;   // We found the value
+      } else if (mid_number < item_number) {
+        if (begin == mid) {
+          break;
+        }
+        begin = mid;
+      } else {
+        if (end == mid) {
+          break;
+        }
+        end = mid;
+      }
+    }
+
+    m_item_id_vector.push_back(item_id);
+    m_item_number_vector.push_back(item_number);
+
+    const auto& begin_number = m_item_number_vector[begin];
+
+    if (begin_number > item_number) {
+      for (ssize_t i = m_item_number_vector.size() - 2; i >= begin; --i) {
+        std::swap(m_item_number_vector[i], m_item_number_vector[i + 1]);
+        std::swap(m_item_id_vector[i], m_item_id_vector[i + 1]);
+      }
+    } else if (begin_number < item_number) {
+      for (ssize_t i = m_item_number_vector.size() - 2; i > begin; --i) {
+        std::swap(m_item_number_vector[i], m_item_number_vector[i + 1]);
+        std::swap(m_item_id_vector[i], m_item_id_vector[i + 1]);
+      }
+    }
+  }
+
+  Layer() = default;
+
+  Layer(const Layer&) = default;
+  Layer(Layer&&)      = default;
+
+  ~Layer() = default;
+};
+
 template <ItemType connecting_item_type, typename ConnectivityType>
 auto
 StencilBuilder::_buildSymmetryConnectingItemList(const ConnectivityType& connectivity,
@@ -203,16 +301,60 @@ StencilBuilder::_build_for_same_source_and_target(const ConnectivityType& connec
   auto item_to_connecting_item_matrix = connectivity.template getItemToItemMatrix<item_type, connecting_item_type>();
   auto connecting_item_to_item_matrix = connectivity.template getItemToItemMatrix<connecting_item_type, item_type>();
 
-  auto item_is_owned = connectivity.template isOwned<item_type>();
-  auto item_number   = connectivity.template number<item_type>();
+  auto item_is_owned          = connectivity.template isOwned<item_type>();
+  auto item_number            = connectivity.template number<item_type>();
+  auto connecting_item_number = connectivity.template number<connecting_item_type>();
 
   using ItemId           = ItemIdT<item_type>;
   using ConnectingItemId = ItemIdT<connecting_item_type>;
 
   if (symmetry_boundary_descriptor_list.size() == 0) {
     if (number_of_layers == 1) {
-      Array<const uint32_t> row_map        = this->_getRowMap(connectivity);
-      Array<const uint32_t> column_indices = this->_getColumnIndices(connectivity, row_map);
+      Array<uint32_t> row_map{connectivity.template numberOf<item_type>() + 1};
+      row_map[0] = 0;
+
+      std::vector<ItemId> column_indices_vector;
+
+      for (ItemId item_id = 0; item_id < connectivity.template numberOf<item_type>(); ++item_id) {
+        // First layer is a special case
+
+        Layer<item_type> item_layer;
+        Layer<connecting_item_type> connecting_layer;
+
+        if (item_is_owned[item_id]) {
+          for (size_t i_connecting_item_1 = 0; i_connecting_item_1 < item_to_connecting_item_matrix[item_id].size();
+               ++i_connecting_item_1) {
+            const ConnectingItemId layer_1_connecting_item_id =
+              item_to_connecting_item_matrix[item_id][i_connecting_item_1];
+            connecting_layer.add(layer_1_connecting_item_id, connecting_item_number[layer_1_connecting_item_id]);
+          }
+
+          for (auto connecting_item_id : connecting_layer.itemIdList()) {
+            for (size_t i_item_1 = 0; i_item_1 < connecting_item_to_item_matrix[connecting_item_id].size();
+                 ++i_item_1) {
+              const ItemId layer_1_item_id = connecting_item_to_item_matrix[connecting_item_id][i_item_1];
+              if (layer_1_item_id != item_id) {
+                item_layer.add(layer_1_item_id, item_number[layer_1_item_id]);
+              }
+            }
+          }
+        }
+
+        for (auto layer_item_id : item_layer.itemIdList()) {
+          column_indices_vector.push_back(layer_item_id);
+        }
+        row_map[item_id + 1] = row_map[item_id] + item_layer.itemIdList().size();
+      }
+
+      if (row_map[row_map.size() - 1] != column_indices_vector.size()) {
+        throw UnexpectedError("incorrect stencil size");
+      }
+      Array<uint32_t> column_indices(row_map[row_map.size() - 1]);
+      column_indices.fill(std::numeric_limits<uint32_t>::max());
+
+      for (size_t i = 0; i < column_indices.size(); ++i) {
+        column_indices[i] = column_indices_vector[i];
+      }
 
       return {ConnectivityMatrix{row_map, column_indices}, {}};
     } else {
diff --git a/src/mesh/StencilBuilder.hpp b/src/mesh/StencilBuilder.hpp
index 5bfd821ca..4f7ead00b 100644
--- a/src/mesh/StencilBuilder.hpp
+++ b/src/mesh/StencilBuilder.hpp
@@ -16,6 +16,9 @@ class StencilBuilder
   using BoundaryDescriptorList = std::vector<std::shared_ptr<const IBoundaryDescriptor>>;
 
  private:
+  template <ItemType item_type>
+  class Layer;
+
   template <typename ConnectivityType>
   Array<const uint32_t> _getRowMap(const ConnectivityType& connectivity) const;
 
-- 
GitLab