From 2569d3e72cf81ab46fcf5ba25d4a6df0e4d549d9 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Fri, 29 Jun 2018 19:33:02 +0200
Subject: [PATCH] Added 3d Cjr calculation

- added a bunch of 3d connectivity structures
- not yet validated
---
 src/mesh/Connectivity3D.hpp | 119 +++++++++++++++++++++++++-----------
 src/mesh/MeshData.hpp       |  58 ++++++++++++++++--
 2 files changed, 138 insertions(+), 39 deletions(-)

diff --git a/src/mesh/Connectivity3D.hpp b/src/mesh/Connectivity3D.hpp
index 94e65508b..8abc9b7b0 100644
--- a/src/mesh/Connectivity3D.hpp
+++ b/src/mesh/Connectivity3D.hpp
@@ -14,6 +14,7 @@
 #include <RefNodeList.hpp>
 #include <RefFaceList.hpp>
 
+#include <tuple>
 
 class Connectivity3D
 {
@@ -33,7 +34,8 @@ private:
   Kokkos::View<double*> m_inv_cell_nb_nodes;
 
   Kokkos::View<const unsigned short*> m_cell_nb_faces;
-  Kokkos::View<unsigned int**> m_cell_faces;
+  Kokkos::View<const unsigned int**> m_cell_faces;
+  Kokkos::View<const bool**> m_cell_faces_is_reversed;
 
   Kokkos::View<unsigned short*> m_node_nb_cells;
   Kokkos::View<unsigned int**> m_node_cells;
@@ -49,11 +51,14 @@ private:
 
   size_t m_max_nb_node_per_cell;
   size_t m_max_nb_face_per_cell;
+  size_t m_max_nb_node_per_face;
 
   struct Face
   {
+    bool reversed = false;
+
     KOKKOS_INLINE_FUNCTION
-    std::vector<unsigned int> _sort(const std::vector<unsigned int>& node_list) const
+    std::vector<unsigned int> _sort(const std::vector<unsigned int>& node_list)
     {
       const auto min_id = std::min_element(node_list.begin(), node_list.end());
       const size_t shift = std::distance(min_id, node_list.begin());
@@ -63,6 +68,7 @@ private:
         for (size_t i=0; i<node_list.size(); ++i) {
           const size_t reverse_shift = node_list.size()-shift;
           rotated_node_list[(reverse_shift+node_list.size()-i)%node_list.size()] = node_list[i];
+          reversed = true;
         }
       } else {
         for (size_t i=0; i<node_list.size(); ++i) {
@@ -113,8 +119,8 @@ private:
   {
     Kokkos::View<unsigned short*> cell_nb_faces("cell_nb_faces", m_number_of_cells);
 
-    typedef std::pair<unsigned int, unsigned short> CellFaceId;
-    std::map<Face, std::vector<CellFaceId>> face_cells_map;
+    typedef std::tuple<unsigned int, unsigned short, bool> CellFaceInfo;
+    std::map<Face, std::vector<CellFaceInfo>> face_cells_map;
     for (unsigned int j=0; j<m_number_of_cells; ++j) {
       const unsigned short cell_nb_nodes = m_cell_nb_nodes[j];
       switch (cell_nb_nodes) {
@@ -126,35 +132,46 @@ private:
         }
         case 8: { // hexahedron
           // face 0
-          face_cells_map[Face({m_cell_nodes(j,0),
-                               m_cell_nodes(j,1),
-                               m_cell_nodes(j,2),
-                               m_cell_nodes(j,3)})].push_back(std::make_pair(j,0));
+          Face f0({m_cell_nodes(j,0),
+                   m_cell_nodes(j,1),
+                   m_cell_nodes(j,2),
+                   m_cell_nodes(j,3)});
+          face_cells_map[f0].push_back(std::make_tuple(j, 0, f0.reversed));
+
           // face 1
-          face_cells_map[Face({m_cell_nodes(j,4),
-                               m_cell_nodes(j,5),
-                               m_cell_nodes(j,6),
-                               m_cell_nodes(j,7)})].push_back(std::make_pair(j,1));
+          Face f1({m_cell_nodes(j,4),
+                   m_cell_nodes(j,7),
+                   m_cell_nodes(j,6),
+                   m_cell_nodes(j,5)});
+          face_cells_map[f1].push_back(std::make_tuple(j, 1, f1.reversed));
+
           // face 2
-          face_cells_map[Face({m_cell_nodes(j,0),
-                               m_cell_nodes(j,3),
-                               m_cell_nodes(j,7),
-                               m_cell_nodes(j,4)})].push_back(std::make_pair(j,2));
+          Face f2({m_cell_nodes(j,0),
+                   m_cell_nodes(j,3),
+                   m_cell_nodes(j,7),
+                   m_cell_nodes(j,4)});
+          face_cells_map[f2].push_back(std::make_tuple(j, 2, f2.reversed));
+
           // face 3
-          face_cells_map[Face({m_cell_nodes(j,1),
-                               m_cell_nodes(j,2),
-                               m_cell_nodes(j,6),
-                               m_cell_nodes(j,5)})].push_back(std::make_pair(j,3));
+          Face f3({m_cell_nodes(j,1),
+                   m_cell_nodes(j,5),
+                   m_cell_nodes(j,6),
+                   m_cell_nodes(j,2)});
+          face_cells_map[f3].push_back(std::make_tuple(j, 3, f3.reversed));
+
           // face 4
-          face_cells_map[Face({m_cell_nodes(j,0),
-                               m_cell_nodes(j,1),
-                               m_cell_nodes(j,5),
-                               m_cell_nodes(j,4)})].push_back(std::make_pair(j,4));
+          Face f4({m_cell_nodes(j,0),
+                   m_cell_nodes(j,4),
+                   m_cell_nodes(j,5),
+                   m_cell_nodes(j,1)});
+          face_cells_map[f4].push_back(std::make_tuple(j, 4, f4.reversed));
+
           // face 5
-          face_cells_map[Face({m_cell_nodes(j,3),
-                               m_cell_nodes(j,2),
-                               m_cell_nodes(j,6),
-                               m_cell_nodes(j,7)})].push_back(std::make_pair(j,5));
+          Face f5({m_cell_nodes(j,3),
+                   m_cell_nodes(j,2),
+                   m_cell_nodes(j,6),
+                   m_cell_nodes(j,7)});
+          face_cells_map[f5].push_back(std::make_tuple(j, 5, f5.reversed));
 
           cell_nb_faces[j] = 6;
           break;
@@ -178,9 +195,9 @@ private:
     m_face_nb_nodes = face_nb_nodes;
 
     std::cerr << __FILE__ << ':' << __LINE__ << ':'
-              << rang::fg::red << " max_nb_node_per_face forced to 4" << rang::fg::reset << '\n';
-    const size_t max_nb_node_per_face = 4;
-    Kokkos::View<unsigned int**> face_nodes("face_nodes", m_number_of_faces, max_nb_node_per_face);
+              << rang::fg::red << " m_max_nb_node_per_face forced to 4" << rang::fg::reset << '\n';
+    m_max_nb_node_per_face = 4;
+    Kokkos::View<unsigned int**> face_nodes("face_nodes", m_number_of_faces, m_max_nb_node_per_face);
     {
       int l=0;
       for (const auto& face_cells_vector : face_cells_map) {
@@ -212,7 +229,7 @@ private:
       for (const auto& face_cells_vector : face_cells_map) {
         const auto& cells_vector = face_cells_vector.second;
         for (unsigned short lj=0; lj<cells_vector.size(); ++lj) {
-          unsigned int cell_number = cells_vector[lj].first;
+          const unsigned int cell_number = std::get<0>(cells_vector[lj]);
           face_cells(l,lj) = cell_number;
         }
         ++l;
@@ -229,8 +246,9 @@ private:
       for (const auto& face_cells_vector : face_cells_map) {
         const auto& cells_vector = face_cells_vector.second;
         for (unsigned short lj=0; lj<cells_vector.size(); ++lj) {
-          unsigned int cell_number = cells_vector[lj].first;
-          unsigned short cell_local_face = cells_vector[lj].second;
+          unsigned int cell_number;
+          unsigned short cell_local_face;
+          std::tie(cell_number, cell_local_face, std::ignore) = cells_vector[lj];
           cell_faces(cell_number,cell_local_face) = l;
         }
         ++l;
@@ -238,6 +256,22 @@ private:
     }
     m_cell_faces = cell_faces;
 
+    Kokkos::View<bool**> cell_faces_is_reversed("cell_faces_is_reversed", m_number_of_faces, m_max_nb_face_per_cell);
+    {
+      int l=0;
+      for (const auto& face_cells_vector : face_cells_map) {
+        const auto& cells_vector = face_cells_vector.second;
+        for (unsigned short lj=0; lj<cells_vector.size(); ++lj) {
+          unsigned int cell_number;
+          bool reversed;
+          std::tie(cell_number, std::ignore, reversed);
+          cell_faces_is_reversed(cell_number,lj) = reversed;
+        }
+        ++l;
+      }
+    }
+    m_cell_faces_is_reversed = cell_faces_is_reversed;
+
     Kokkos::View<unsigned short**> face_cell_local_face("face_cell_local_face",
                                                         m_number_of_faces, m_max_nb_node_per_cell);
     {
@@ -245,7 +279,7 @@ private:
       for (const auto& face_cells_vector : face_cells_map) {
         const auto& cells_vector = face_cells_vector.second;
         for (unsigned short lj=0; lj<cells_vector.size(); ++lj) {
-          unsigned short cell_local_face = cells_vector[lj].second;
+          unsigned short cell_local_face = std::get<1>(cells_vector[lj]);
           face_cell_local_face(l,lj) = cell_local_face;
         }
         ++l;
@@ -300,11 +334,21 @@ private:
     return m_number_of_cells;
   }
 
+  const size_t& maxNbFacePerCell() const
+  {
+    return m_max_nb_face_per_cell;
+  }
+
   const size_t& maxNbNodePerCell() const
   {
     return m_max_nb_node_per_cell;
   }
 
+  const size_t& maxNbNodePerFace() const
+  {
+    return m_max_nb_node_per_face;
+  }
+
   const Kokkos::View<const unsigned int**> cellNodes() const
   {
     return m_cell_nodes;
@@ -315,6 +359,11 @@ private:
     return m_cell_faces;
   }
 
+  const Kokkos::View<const bool**> cellFacesIsReversed() const
+  {
+    return m_cell_faces_is_reversed;
+  }
+
   const Kokkos::View<const unsigned short*> nodeNbCells() const
   {
     return m_node_nb_cells;
diff --git a/src/mesh/MeshData.hpp b/src/mesh/MeshData.hpp
index f65f3aa09..59411b7f9 100644
--- a/src/mesh/MeshData.hpp
+++ b/src/mesh/MeshData.hpp
@@ -4,6 +4,8 @@
 #include <Kokkos_Core.hpp>
 #include <TinyVector.hpp>
 
+#include <map>
+
 template <typename M>
 class MeshData
 {
@@ -116,21 +118,69 @@ private:
 
       const Kokkos::View<const Rd*> xr = m_mesh.xr();
 
-      std::cerr << "Cjr are not computed in 3D!\n";
-      Kokkos::parallel_for(m_mesh.numberOfCells(), KOKKOS_LAMBDA(const int& j){
+      Kokkos::View<Rd**> Nlr("Nlr", m_mesh.connectivity().numberOfFaces(), m_mesh.connectivity().maxNbNodePerFace());
+
+      const Kokkos::View<const unsigned int**>& face_nodes
+          = m_mesh.connectivity().faceNodes();
+      const Kokkos::View<const unsigned short*>& face_nb_nodes
+          = m_mesh.connectivity().faceNbNodes();
+      Kokkos::parallel_for(m_mesh.numberOfFaces(), KOKKOS_LAMBDA(const int& l) {
+          const size_t nb_nodes = face_nb_nodes[l];
+          std::vector<Rd> dxr(nb_nodes);
+          for (size_t r=0; r<nb_nodes; ++r) {
+            dxr[r] = xr[face_nodes(l,(r+1)%nb_nodes)] - xr[face_nodes(l,(r+nb_nodes-1)%nb_nodes)];
+          }
+          const double inv_12_nb_nodes = 1./(12.*nb_nodes);
+          for (size_t r=0; r<nb_nodes; ++r) {
+            Rd Nr = zero;
+            const Rd two_dxr = 2*dxr[r];
+            for (size_t s=0; s<nb_nodes; ++s) {
+              Nr += crossProduct((two_dxr - dxr[s]), xr[face_nodes(l,s)]);
+            }
+            Nr *= inv_12_nb_nodes;
+            Nr -= (1./6.)*crossProduct(dxr[r], xr[face_nodes(l,r)]);
+            Nlr(l,r) = Nr;
+          }
+        });
+
+      const Kokkos::View<const unsigned int**> cell_faces
+          = m_mesh.connectivity().cellFaces();
+      const Kokkos::View<const bool**> cell_faces_is_reversed
+          = m_mesh.connectivity().cellFacesIsReversed();
+
+      const Kokkos::View<const unsigned short*> cell_nb_faces
+          = m_mesh.connectivity().cellNbFaces();
+
+      Kokkos::parallel_for(m_mesh.numberOfCells(), KOKKOS_LAMBDA(const int& j) {
           for (int R=0; R<cell_nb_nodes[j]; ++R) {
             m_Cjr(j,R) = zero;
           }
+          std::map<unsigned int, unsigned short> node_id_to_local;
+          for (size_t R=0; R<cell_nb_nodes[j]; ++R) {
+            node_id_to_local[cell_nodes(j,R)] = R;
+          }
+          for (size_t L=0; L<cell_nb_faces[j]; ++L) {
+            const size_t l = cell_faces(j, L);
+            if (cell_faces_is_reversed(j, L)) {
+              for (size_t rl = 0; rl<face_nb_nodes[l]; ++rl) {
+                m_Cjr(j, node_id_to_local[face_nodes(l,rl)]) -= Nlr(l, rl);
+              }
+            } else {
+              for (size_t rl = 0; rl<face_nb_nodes[l]; ++rl) {
+                m_Cjr(j, node_id_to_local[face_nodes(l,rl)]) += Nlr(l, rl);
+              }
+            }
+          }
         });
 
-      Kokkos::parallel_for(m_mesh.numberOfCells(), KOKKOS_LAMBDA(const int& j){
+      Kokkos::parallel_for(m_mesh.numberOfCells(), KOKKOS_LAMBDA(const int& j) {
           for (int R=0; R<cell_nb_nodes[j]; ++R) {
             const Rd& Cjr = m_Cjr(j,R);
             m_ljr(j,R) = l2Norm(Cjr);
           }
         });
 
-      Kokkos::parallel_for(m_mesh.numberOfCells(), KOKKOS_LAMBDA(const int& j){
+      Kokkos::parallel_for(m_mesh.numberOfCells(), KOKKOS_LAMBDA(const int& j) {
           for (int R=0; R<cell_nb_nodes[j]; ++R) {
             const Rd& Cjr = m_Cjr(j,R);
             const double inv_ljr = 1./m_ljr(j,R);
-- 
GitLab