From 3a1cc197c9fcbe1f0bb9e473dbc528eaf52bf54b Mon Sep 17 00:00:00 2001
From: Drouard <axelle.drouard@orange.fr>
Date: Fri, 23 Sep 2022 16:47:02 +0200
Subject: [PATCH] Beggining of Neumann BC for 3D

---
 src/scheme/ScalarHybridScheme.cpp | 251 +++++++++++++++++++++++-------
 1 file changed, 199 insertions(+), 52 deletions(-)

diff --git a/src/scheme/ScalarHybridScheme.cpp b/src/scheme/ScalarHybridScheme.cpp
index a9bafc3e2..e6fee0492 100644
--- a/src/scheme/ScalarHybridScheme.cpp
+++ b/src/scheme/ScalarHybridScheme.cpp
@@ -492,22 +492,22 @@ class ScalarHybridSchemeHandler::ScalarHybridScheme : public ScalarHybridSchemeH
       return compute_node_is_corner;
     }();
 
-    const NodeValue<const bool> node_is_straight_border = [&] {
-      NodeValue<bool> compute_node_is_straight_border{mesh->connectivity()};
-      compute_node_is_straight_border.fill(false);
+    const NodeValue<const bool> node_is_edge = [&] {
+      NodeValue<bool> compute_node_is_edge{mesh->connectivity()};
+      compute_node_is_edge.fill(false);
       parallel_for(
         mesh->numberOfNodes(), PUGS_LAMBDA(NodeId node_id) {
           if (is_boundary_node[node_id]) {
             const auto& node_to_cell = node_to_cell_matrix[node_id];
             if ((Dimension == 3) && (node_to_cell.size() == 2)) {
-              compute_node_is_straight_border[node_id] = true;
-              //// std::cout << "node_is_straight_border : " << node_id << "; " <<
-              // compute_node_is_straight_border[node_id]
+              compute_node_is_edge[node_id] = true;
+              //// std::cout << "node_is_edge : " << node_id << "; " <<
+              // compute_node_is_edge[node_id]
               //           << "\n";
             }
           }
         });
-      return compute_node_is_straight_border;
+      return compute_node_is_edge;
     }();
     // std::cout << "Test 1.9 \n";
 
@@ -1088,14 +1088,14 @@ class ScalarHybridSchemeHandler::ScalarHybridScheme : public ScalarHybridSchemeH
               Cjr2[0]       = -0.5 * (xrp2[1] - xrp1[1]);
               Cjr2[1]       = 0.5 * (xrp2[0] - xrp1[0]);
               beta[node_id] = tensorProduct(Cjr1, (xr[node_id] - xj1)) + tensorProduct(Cjr2, (xr[node_id] - xj2));
-            } else if (Dimension == 3 && not node_is_straight_border[node_id]) {
+            } else if (Dimension == 3 && not node_is_edge[node_id]) {
               // std::cout << "Test 1.24.2 \n";
               // std::cout << "coin : " << node_id << "  " << Vj[cell_id] << "\n";
               const TinyMatrix<Dimension> I = identity;
 
               beta[node_id] = 0.125 * Vj[cell_id] * I;
               // throw NotImplementedError("The scheme is not implemented in this dimension.");
-            } else if (Dimension == 3 && node_is_straight_border[node_id]) {
+            } else if (Dimension == 3 && node_is_edge[node_id]) {
               // std::cout << "Test 1.24.3 \n";
               // std::cout << " bord droit : " << node_id << "  " << Vj[cell_id] << "\n";
               const TinyMatrix<Dimension> I = identity;
@@ -1246,52 +1246,123 @@ class ScalarHybridSchemeHandler::ScalarHybridScheme : public ScalarHybridSchemeH
             }
           }
         }
-      } else if ((node_is_neumann[node_id]) && (not node_is_corner[node_id]) && (not node_is_dirichlet[node_id])) {
-        const TinyMatrix<Dimension> I   = identity;
-        const TinyVector<Dimension> n   = exterior_normal[node_id];
-        const TinyMatrix<Dimension> nxn = tensorProduct(n, n);
-        const TinyMatrix<Dimension> Q   = I - nxn;
-
-        for (size_t i_cell_j = 0; i_cell_j < node_to_cell.size(); ++i_cell_j) {
-          const CellId cell_id_j = node_to_cell[i_cell_j];
-          const size_t i_node_j  = node_local_number_in_its_cells[i_cell_j];
+      } else if ((node_is_neumann[node_id]) && (not node_is_dirichlet[node_id])) {
+        if (not node_is_corner[node_id]) {
+          const TinyMatrix<Dimension> I   = identity;
+          const TinyVector<Dimension> n   = exterior_normal[node_id];
+          const TinyMatrix<Dimension> nxn = tensorProduct(n, n);
+          const TinyMatrix<Dimension> Q   = I - nxn;
 
-          for (size_t i_cell_k = 0; i_cell_k < node_to_cell.size(); ++i_cell_k) {
-            const CellId cell_id_k = node_to_cell[i_cell_k];
-            const size_t i_node_k  = node_local_number_in_its_cells[i_cell_k];
+          for (size_t i_cell_j = 0; i_cell_j < node_to_cell.size(); ++i_cell_j) {
+            const CellId cell_id_j = node_to_cell[i_cell_j];
+            const size_t i_node_j  = node_local_number_in_its_cells[i_cell_j];
 
-            S1(cell_id_j, cell_id_k) +=
-              (1 - lambda) * dt * (1. - cn_coeff / 2.) *
-              dot(kappar_invBetar[node_id] *
-                    (Cjr(cell_id_k, i_node_k) - theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
-                  Q * Cjr(cell_id_j, i_node_j));
-            S2(cell_id_j, cell_id_k) -=
-              (1 - lambda) * dt * (cn_coeff / 2.) *
-              dot(kappar_invBetar[node_id] *
-                    (Cjr(cell_id_k, i_node_k) - theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
-                  Q * Cjr(cell_id_j, i_node_j));
+            for (size_t i_cell_k = 0; i_cell_k < node_to_cell.size(); ++i_cell_k) {
+              const CellId cell_id_k = node_to_cell[i_cell_k];
+              const size_t i_node_k  = node_local_number_in_its_cells[i_cell_k];
 
-            const auto& cell_to_face = cell_to_face_matrix[cell_id_j];
+              S1(cell_id_j, cell_id_k) +=
+                (1 - lambda) * dt * (1. - cn_coeff / 2.) *
+                dot(kappar_invBetar[node_id] *
+                      (Cjr(cell_id_k, i_node_k) - theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
+                    Q * Cjr(cell_id_j, i_node_j));
+              S2(cell_id_j, cell_id_k) -=
+                (1 - lambda) * dt * (cn_coeff / 2.) *
+                dot(kappar_invBetar[node_id] *
+                      (Cjr(cell_id_k, i_node_k) - theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
+                    Q * Cjr(cell_id_j, i_node_j));
+
+              const auto& cell_to_face = cell_to_face_matrix[cell_id_j];
+
+              for (size_t i_face = 0; i_face < cell_to_face.size(); ++i_face) {
+                const FaceId face_id              = cell_to_face[i_face];
+                const auto& face_to_node          = face_to_node_matrix[face_id];
+                const size_t numberOfNodesPerFace = face_to_node.size();
+                if (not is_boundary_face[face_id]) {
+                  for (size_t i_face_to_node = 0; i_face_to_node < face_to_node.size(); ++i_face_to_node) {
+                    if (face_to_node[i_face_to_node] == node_id) {
+                      S1(cell_id_j, cell_id_k) +=
+                        lambda * dt * (1. - cn_coeff / 2.) * mes_l[face_id] / numberOfNodesPerFace *
+                        dot(inverse(node_betar[node_id]) *
+                              (Cjr(cell_id_k, i_node_k) -
+                               theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
+                            base_xj1_xj2_orth(cell_id_j, i_face));
+                      S2(cell_id_j, cell_id_k) -=
+                        lambda * dt * (cn_coeff / 2.) * mes_l[face_id] / numberOfNodesPerFace *
+                        dot(inverse(node_betar[node_id]) *
+                              (Cjr(cell_id_k, i_node_k) -
+                               theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
+                            base_xj1_xj2_orth(cell_id_j, i_face));
+                    }
+                  }
+                }
+              }
+            }
+          }
+        } else if (node_is_edge[node_id]) {
+          for (size_t i_cell_j = 0; i_cell_j < node_to_cell.size(); ++i_cell_j) {
+            const CellId cell_id_j = node_to_cell[i_cell_j];
+            const size_t i_node_j  = node_local_number_in_its_cells[i_cell_j];
 
-            for (size_t i_face = 0; i_face < cell_to_face.size(); ++i_face) {
-              const FaceId face_id              = cell_to_face[i_face];
-              const auto& face_to_node          = face_to_node_matrix[face_id];
-              const size_t numberOfNodesPerFace = face_to_node.size();
-              if (not is_boundary_face[face_id]) {
-                for (size_t i_face_to_node = 0; i_face_to_node < face_to_node.size(); ++i_face_to_node) {
-                  if (face_to_node[i_face_to_node] == node_id) {
-                    S1(cell_id_j, cell_id_k) +=
-                      lambda * dt * (1. - cn_coeff / 2.) * mes_l[face_id] / numberOfNodesPerFace *
-                      dot(inverse(node_betar[node_id]) *
-                            (Cjr(cell_id_k, i_node_k) -
-                             theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
-                          base_xj1_xj2_orth(cell_id_j, i_face));
-                    S2(cell_id_j, cell_id_k) -=
-                      lambda * dt * (cn_coeff / 2.) * mes_l[face_id] / numberOfNodesPerFace *
-                      dot(inverse(node_betar[node_id]) *
-                            (Cjr(cell_id_k, i_node_k) -
-                             theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
-                          base_xj1_xj2_orth(cell_id_j, i_face));
+            for (size_t i_cell_k = 0; i_cell_k < node_to_cell.size(); ++i_cell_k) {
+              const CellId cell_id_k   = node_to_cell[i_cell_k];
+              const size_t i_node_k    = node_local_number_in_its_cells[i_cell_k];
+              const auto& cell_to_face = cell_to_face_matrix[cell_id_j];
+
+              for (size_t i_face = 0; i_face < cell_to_face.size(); ++i_face) {
+                const FaceId face_id              = cell_to_face[i_face];
+                const auto& face_to_node          = face_to_node_matrix[face_id];
+                const size_t numberOfNodesPerFace = face_to_node.size();
+                if (not is_boundary_face[face_id]) {
+                  bool l1_OK = false;
+                  FaceId l1;
+                  FaceId l2;
+                  TinyVector<Dimension> n1;
+                  TinyVector<Dimension> n2;
+                  TinyVector<Dimension> t;
+                  for (size_t j_face = 0; j_face < cell_to_face.size(); ++j_face) {
+                    const FaceId face_id_j     = cell_to_face[j_face];
+                    const auto& face_to_node_j = face_to_node_matrix[face_id_j];
+                    for (size_t j_face_to_node = 0; j_face_to_node < face_to_node_j.size(); ++j_face_to_node) {
+                      if (is_boundary_face[face_id_j]) {
+                        if (not l1_OK) {
+                          l1    = face_id_j;
+                          l1_OK = true;
+                        } else {
+                          l2 = face_id_j;
+                        }
+                        if (dot(nl[l1], xl[l1] - xj[cell_id_j]) <= 0) {
+                          n1 = -nl[l1];
+                        } else {
+                          n1 = nl[l1];
+                        }
+                        if (dot(nl[l2], xl[l2] - xj[cell_id_j]) <= 0) {
+                          n2 = -nl[l2];
+                        } else {
+                          n2 = nl[l2];
+                        }
+                        t[0] = n1[1] * n2[2] - n1[2] * n2[1];
+                        t[1] = n1[2] * n2[0] - n1[0] * n2[2];
+                        t[2] = n1[0] * n2[1] - n1[1] * n2[0];
+                      }
+                    }
+                  }
+                  // ICI
+                  for (size_t i_face_to_node = 0; i_face_to_node < face_to_node.size(); ++i_face_to_node) {
+                    if (face_to_node[i_face_to_node] == node_id) {
+                      S1(cell_id_j, cell_id_k) +=
+                        lambda * dt * (1. - cn_coeff / 2.) * mes_l[face_id] / numberOfNodesPerFace *
+                        dot(inverse(node_betar[node_id]) *
+                              (Cjr(cell_id_k, i_node_k) -
+                               theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
+                            base_xj1_xj2_orth(cell_id_j, i_face));
+                      S2(cell_id_j, cell_id_k) -=
+                        lambda * dt * (cn_coeff / 2.) * mes_l[face_id] / numberOfNodesPerFace *
+                        dot(inverse(node_betar[node_id]) *
+                              (Cjr(cell_id_k, i_node_k) -
+                               theta(cell_id_k, i_node_k) / sum_theta[node_id] * sum_Cjr[node_id]),
+                            base_xj1_xj2_orth(cell_id_j, i_face));
+                    }
                   }
                 }
               }
@@ -1494,7 +1565,7 @@ class ScalarHybridSchemeHandler::ScalarHybridScheme : public ScalarHybridSchemeH
             }
           }
 
-        } else if (node_is_corner[node_id]) {
+        } else if (node_is_corner[node_id] && not node_is_edge[node_id]) {
           const auto& node_to_face = node_to_face_matrix[node_id];
           const CellId cell_id     = node_to_cell[0];
           double sum_mes_l         = 0;
@@ -1504,6 +1575,82 @@ class ScalarHybridSchemeHandler::ScalarHybridScheme : public ScalarHybridSchemeH
           }
           b[cell_id] += (1 - lambda) * 0.5 * node_boundary_values[node_id] * sum_mes_l;
           b_prev[cell_id] += (1 - lambda) * 0.5 * node_boundary_prev_values[node_id] * sum_mes_l;
+
+        } else if (node_is_edge[node_id]) {
+          const auto& node_to_cell = node_to_cell_matrix[node_id];
+          for (size_t i_cell = 0; i_cell < node_to_cell.size(); ++i_cell) {
+            const CellId cell_id = node_to_cell[i_cell];
+
+            const auto& cell_to_face = cell_to_face_matrix[cell_id];
+
+            for (size_t i_face = 0; i_face < cell_to_face.size(); ++i_face) {
+              const FaceId face_id              = cell_to_face[i_face];
+              const auto& face_to_node          = face_to_node_matrix[face_id];
+              const size_t numberOfNodesPerFace = face_to_node.size();
+              if (not is_boundary_face[face_id]) {
+                bool l1_OK = false;
+                FaceId l1;
+                FaceId l2;
+                TinyVector<Dimension> n1;
+                TinyVector<Dimension> n2;
+                TinyVector<Dimension> t;
+                for (size_t j_face = 0; j_face < cell_to_face.size(); ++j_face) {
+                  const FaceId face_id_j     = cell_to_face[j_face];
+                  const auto& face_to_node_j = face_to_node_matrix[face_id_j];
+                  for (size_t j_face_to_node = 0; j_face_to_node < face_to_node_j.size(); ++j_face_to_node) {
+                    if (is_boundary_face[face_id_j]) {
+                      if (not l1_OK) {
+                        l1    = face_id_j;
+                        l1_OK = true;
+                      } else {
+                        l2 = face_id_j;
+                      }
+                      if (dot(nl[l1], xl[l1] - xj[cell_id]) <= 0) {
+                        n1 = -nl[l1];
+                      } else {
+                        n1 = nl[l1];
+                      }
+                      if (dot(nl[l2], xl[l2] - xj[cell_id]) <= 0) {
+                        n2 = -nl[l2];
+                      } else {
+                        n2 = nl[l2];
+                      }
+                      t[0] = n1[1] * n2[2] - n1[2] * n2[1];
+                      t[1] = n1[2] * n2[0] - n1[0] * n2[2];
+                      t[2] = n1[0] * n2[1] - n1[1] * n2[0];
+                    }
+                  }
+                }
+                b[cell_id] +=
+                  lambda * mes_l[face_id] / numberOfNodesPerFace *
+                  dot(face_boundary_values[l1] / pow(l2Norm(node_kappar[node_id] * n1), 2) * node_kappar[node_id] * n1 +
+                        face_boundary_values[l2] / pow(l2Norm(node_kappar[node_id] * n2), 2) * node_kappar[node_id] *
+                          n2 -
+                        1. / dot(xj1_xj2(cell_id, i_face), node_kappar[node_id] * t) *
+                          dot(xj1_xj2(cell_id, i_face),
+                              face_boundary_values[l1] / pow(l2Norm(node_kappar[node_id] * n1), 2) *
+                                  node_kappar[node_id] * n1 +
+                                face_boundary_values[l2] / pow(l2Norm(node_kappar[node_id] * n2), 2) *
+                                  node_kappar[node_id] * n2) /
+                          pow(l2Norm(node_kappar[node_id] * t), 2) * node_kappar[node_id] * t,
+                      base_xj1_xj2_orth(cell_id, i_face));
+                b_prev[cell_id] +=
+                  lambda * mes_l[face_id] / numberOfNodesPerFace *
+                  dot(face_boundary_prev_values[l1] / pow(l2Norm(node_kappar[node_id] * n1), 2) * node_kappar[node_id] *
+                          n1 +
+                        face_boundary_prev_values[l2] / pow(l2Norm(node_kappar[node_id] * n2), 2) *
+                          node_kappar[node_id] * n2 -
+                        1. / dot(xj1_xj2(cell_id, i_face), node_kappar[node_id] * t) *
+                          dot(xj1_xj2(cell_id, i_face),
+                              face_boundary_prev_values[l1] / pow(l2Norm(node_kappar[node_id] * n1), 2) *
+                                  node_kappar[node_id] * n1 +
+                                face_boundary_prev_values[l2] / pow(l2Norm(node_kappar[node_id] * n2), 2) *
+                                  node_kappar[node_id] * n2) /
+                          pow(l2Norm(node_kappar[node_id] * t), 2) * node_kappar[node_id] * t,
+                      base_xj1_xj2_orth(cell_id, i_face));
+              }
+            }
+          }
         }
 
       } else if (node_is_dirichlet[node_id]) {
-- 
GitLab