From a751f5c42ccc21b12bbcdd7e03d79c2d12d1ad5c Mon Sep 17 00:00:00 2001
From: Julie PATELA <julie.patela.ocre@cea.fr>
Date: Tue, 18 Aug 2020 11:43:22 +0200
Subject: [PATCH] Add mesh matrix for elasticity equation

---
 .../algorithms/ElasticityDiamondAlgorithm.cpp | 129 +++++++++++++++++-
 1 file changed, 126 insertions(+), 3 deletions(-)

diff --git a/src/language/algorithms/ElasticityDiamondAlgorithm.cpp b/src/language/algorithms/ElasticityDiamondAlgorithm.cpp
index 6ec5f17b0..f51e7678e 100644
--- a/src/language/algorithms/ElasticityDiamondAlgorithm.cpp
+++ b/src/language/algorithms/ElasticityDiamondAlgorithm.cpp
@@ -359,10 +359,13 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme(
                                                                                                   diamond_mesh_data
                                                                                                     .xj());
 
-      CellValue<double> fj =
-        InterpolateItemValue<double(TinyVector<Dimension>)>::template interpolate<ItemType::cell>(f_id, mesh_data.xj());
+      CellValue<TinyVector<Dimension>> fj = InterpolateItemValue<TinyVector<Dimension>(
+        TinyVector<Dimension>)>::template interpolate<ItemType::cell>(f_id, mesh_data.xj());
 
-      VTKWriter vtk_writer("D_" + std::to_string(Dimension), 0.01);
+      VTKWriter vtk_writer2("f_" + std::to_string(Dimension), 0.01);
+
+      vtk_writer2.write(mesh, {NamedItemValue{"f", fj}}, 0,
+                        true);   // forces last output
 
       const CellValue<const double> dual_Vj = diamond_mesh_data.Vj();
 
@@ -384,7 +387,127 @@ ElasticityDiamondScheme<Dimension>::ElasticityDiamondScheme(
       }();
 
       const CellValue<const double> primal_Vj = mesh_data.Vj();
+
+      FaceValue<const double> alpha_lambda_l = [&] {
+        CellValue<double> alpha_j{diamond_mesh->connectivity()};
+
+        parallel_for(
+          diamond_mesh->numberOfCells(), PUGS_LAMBDA(CellId diamond_cell_id) {
+            alpha_j[diamond_cell_id] =
+              dual_mes_l_j[diamond_cell_id] * dual_lambdaj[diamond_cell_id] / dual_Vj[diamond_cell_id];
+          });
+
+        FaceValue<double> computed_alpha_l{mesh->connectivity()};
+        mapper->fromDualCell(alpha_j, computed_alpha_l);
+        return computed_alpha_l;
+      }();
+
+      FaceValue<const double> alpha_mu_l = [&] {
+        CellValue<double> alpha_j{diamond_mesh->connectivity()};
+
+        parallel_for(
+          diamond_mesh->numberOfCells(), PUGS_LAMBDA(CellId diamond_cell_id) {
+            alpha_j[diamond_cell_id] =
+              dual_mes_l_j[diamond_cell_id] * dual_muj[diamond_cell_id] / dual_Vj[diamond_cell_id];
+          });
+
+        FaceValue<double> computed_alpha_l{mesh->connectivity()};
+        mapper->fromDualCell(alpha_j, computed_alpha_l);
+        return computed_alpha_l;
+      }();
+
+      FaceValue<const CellId> face_dual_cell_id = [=]() {
+        FaceValue<CellId> computed_face_dual_cell_id{mesh->connectivity()};
+        CellValue<CellId> dual_cell_id{diamond_mesh->connectivity()};
+        parallel_for(
+          diamond_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { dual_cell_id[cell_id] = cell_id; });
+
+        mapper->fromDualCell(dual_cell_id, computed_face_dual_cell_id);
+
+        return computed_face_dual_cell_id;
+      }();
+
+      TinyMatrix<Dimension, double> eye = zero;
+      for (size_t i = 0; i < Dimension; ++i) {
+        eye(i, i) = 1;
+      }
+
+      const NodeValuePerFace<const TinyVector<Dimension>> primal_nlr = mesh_data.nlr();
+      const auto& primal_face_cell_is_reversed                       = mesh->connectivity().cellFaceIsReversed();
+      const auto& face_local_numbers_in_their_cells = mesh->connectivity().faceLocalNumbersInTheirCells();
+      SparseMatrixDescriptor S{number_of_dof * Dimension};
+      for (FaceId face_id = 0; face_id < mesh->numberOfFaces(); ++face_id) {
+        if (not primal_face_is_on_boundary[face_id]) {
+          const double beta_mu_l          = (1. / Dimension) * alpha_mu_l[face_id] * mes_l[face_id];
+          const double beta_lambda_l      = (1. / Dimension) * alpha_lambda_l[face_id] * mes_l[face_id];
+          const auto& primal_face_to_cell = face_to_cell_matrix[face_id];
+          for (size_t i_cell = 0; i_cell < primal_face_to_cell.size(); ++i_cell) {
+            const CellId i_id = primal_face_to_cell[i_cell];
+            const bool is_face_reversed_for_cell_i =
+              primal_face_cell_is_reversed(i_id, face_local_numbers_in_their_cells(face_id, i_cell));
+            const TinyVector<Dimension> nil = [&] {
+              if (is_face_reversed_for_cell_i) {
+                return -primal_nlr(face_id, 0);
+              } else {
+                return primal_nlr(face_id, 0);
+              }
+            }();
+            for (size_t j_cell = 0; j_cell < primal_face_to_cell.size(); ++j_cell) {
+              const CellId j_id = primal_face_to_cell[j_cell];
+              TinyMatrix<Dimension, double> M =
+                beta_mu_l * eye + beta_mu_l * tensorProduct(nil, nil) + beta_lambda_l * tensorProduct(nil, nil);
+              if (i_cell == j_cell) {
+                for (size_t i = 0; i < Dimension; ++i) {
+                  for (size_t j = 0; j < Dimension; ++j) {
+                    S((cell_dof_number[i_id] * Dimension) + i, (cell_dof_number[j_id] * Dimension) + j) += M(i, j);
+                  }
+                }
+              } else {
+                for (size_t i = 0; i < Dimension; ++i) {
+                  for (size_t j = 0; j < Dimension; ++j) {
+                    S((cell_dof_number[i_id] * Dimension) + i, (cell_dof_number[j_id] * Dimension) + j) -= M(i, j);
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      // for (size_t i = 0; i < S.numberOfRows(); ++i) {
+      //   for (size_t j = 0; j < S.numberOfRows(); ++j) {
+      //     std::cout << S(i, j) << " ; ";
+      //   }
+      //   std::cout << "\n";
+      // }
+      // std::exit(0);
+      CRSMatrix A{S};
+      Vector<double> b{number_of_dof * Dimension};
+      for (CellId cell_id = 0; cell_id < mesh->numberOfCells(); ++cell_id) {
+        for (size_t i = 0; i < Dimension; ++i) {
+          b[(cell_dof_number[cell_id] * Dimension) + i] = primal_Vj[cell_id] * fj[cell_id][i];
+        }
+      }
+
+      Vector<double> U{number_of_dof * Dimension};
+      U = 0;
+
+      BiCGStab{b, A, U, 1000, 1e-15};
+
+      Vector r = A * U - b;
+
+      std::cout << "real residu = " << std::sqrt((r, r)) << '\n';
+
+      CellValue<double> Speed{mesh->connectivity()};
+
+      parallel_for(
+        mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { Speed[cell_id] = U[cell_dof_number[cell_id]]; });
+
+      VTKWriter vtk_writer("Speed_" + std::to_string(Dimension), 0.01);
+
+      vtk_writer.write(mesh, {NamedItemValue{"U", Speed}}, 0,
+                       true);   // forces last output
     }
+
   } else {
     throw NotImplementedError("not done in 1d");
   }
-- 
GitLab