From 7fd7d9614b3ac267367f0ab9c8dcb67d0c1ef949 Mon Sep 17 00:00:00 2001
From: Compte local pour Alexandre GANGLOFF <alexandre.gangloff@cea.fr>
Date: Wed, 6 Nov 2024 17:57:12 +0100
Subject: [PATCH] Add scalar and vector limiters for AcousticSolveur

---
 src/scheme/Order2AcousticSolver.cpp | 143 +++++++++++++++++++++++++++-
 1 file changed, 140 insertions(+), 3 deletions(-)

diff --git a/src/scheme/Order2AcousticSolver.cpp b/src/scheme/Order2AcousticSolver.cpp
index d59676359..92f13f2c0 100644
--- a/src/scheme/Order2AcousticSolver.cpp
+++ b/src/scheme/Order2AcousticSolver.cpp
@@ -349,6 +349,137 @@ class Order2AcousticSolverHandler::Order2AcousticSolver final : public Order2Aco
     return F;
   }
 
+  void
+  _scalar_limiter(const MeshType& mesh,
+                  const DiscreteFunctionP0<const double>& f,
+                  DiscreteFunctionDPk<Dimension, double>& DPk_fh) const
+  {
+    MeshData<MeshType>& mesh_data = MeshDataManager::instance().getMeshData(mesh);
+    StencilManager::BoundaryDescriptorList symmetry_boundary_descriptor_list;
+    StencilDescriptor stencil_descriptor{1, StencilDescriptor::ConnectionType::by_nodes};
+    auto stencil = StencilManager::instance().getCellToCellStencilArray(mesh.connectivity(), stencil_descriptor, symmetry_boundary_descriptor_list);
+
+    const auto xj = mesh_data.xj();
+
+    parallel_for(mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id){
+      const double fj = f[cell_id];
+
+      double f_min = fj;
+      double f_max = fj;
+
+      const auto cell_stencil = stencil[cell_id];
+      for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+        f_min = std::min(f_min, f[cell_stencil[i_cell]]);
+        f_max = std::max(f_max, f[cell_stencil[i_cell]]);
+      }
+
+      double f_bar_min = fj;
+      double f_bar_max = fj;
+
+      for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+        const CellId cell_k_id = cell_stencil[i_cell];
+        const double f_xk    = DPk_fh[cell_id](xj[cell_k_id]);
+
+        f_bar_min = std::min(f_bar_min, f_xk);
+        f_bar_max = std::max(f_bar_max, f_xk);
+      }
+
+      const double eps = 1E-14;
+      double coef1     = 1;
+      if (std::abs(f_bar_max - fj) > eps) {
+        coef1 = (f_max - fj) / ((f_bar_max - fj));
+      }
+
+      double coef2 = 1.;
+      if (std::abs(f_bar_min - fj) > eps) {
+        coef2 = (f_min - fj) / ((f_bar_min - fj));
+      }
+
+      const double lambda = std::max(0., std::min(1., std::min(coef1, coef2)));
+
+      auto coefficients = DPk_fh.coefficients(cell_id);
+
+      coefficients[0] = (1 - lambda) * f[cell_id] + lambda * coefficients[0];
+      for (size_t i = 1; i < coefficients.size(); ++i) {
+        coefficients[i] *= lambda;
+      }
+    });
+  }
+
+  void
+  _vector_limiter(const MeshType& mesh,
+                  const DiscreteFunctionP0<const Rd>& f,
+                  DiscreteFunctionDPk<Dimension, Rd>& DPk_fh) const
+  {
+    MeshData<MeshType>& mesh_data = MeshDataManager::instance().getMeshData(mesh);
+    StencilManager::BoundaryDescriptorList symmetry_boundary_descriptor_list;
+    StencilDescriptor stencil_descriptor{1, StencilDescriptor::ConnectionType::by_nodes};
+    auto stencil = StencilManager::instance().getCellToCellStencilArray(mesh.connectivity(), stencil_descriptor, symmetry_boundary_descriptor_list);
+
+    const auto xj = mesh_data.xj();
+
+    parallel_for(mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_id){
+      const Rd fj = f[cell_id];
+
+      Rd f_min = fj;
+      Rd f_max = fj;
+
+      const auto cell_stencil = stencil[cell_id];
+      for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+        for(size_t dim = 0; dim < Dimension; ++dim){
+          f_min[dim] = std::min(f_min[dim], f[cell_stencil[i_cell]][dim]);
+          f_max[dim] = std::max(f_max[dim], f[cell_stencil[i_cell]][dim]);
+        }
+      }
+
+      Rd f_bar_min = fj;
+      Rd f_bar_max = fj;
+
+      for(size_t i_cell = 0; i_cell < cell_stencil.size(); ++i_cell){
+        const CellId cell_k_id = cell_stencil[i_cell];
+        const Rd f_xk    = DPk_fh[cell_id](xj[cell_k_id]);
+
+        for(size_t dim = 0; dim < Dimension; ++dim){
+          f_bar_min[dim] = std::min(f_bar_min[dim], f_xk[dim]);
+          f_bar_max[dim] = std::max(f_bar_max[dim], f_xk[dim]);
+        }
+      }
+
+      const double eps = 1E-14;
+      Rd coef1;
+      for(size_t dim = 0; dim < Dimension; ++dim){
+        coef1[dim] = 1;
+        if (std::abs(f_bar_max[dim] - fj[dim]) > eps) {
+          coef1[dim] = (f_max[dim] - fj[dim]) / ((f_bar_max[dim] - fj[dim]));
+        }
+      }
+
+      Rd coef2;
+      for(size_t dim = 0; dim < Dimension; ++dim){
+        coef2[dim] = 1;
+        if (std::abs(f_bar_min[dim] - fj[dim]) > eps) {
+          coef2[dim] = (f_min[dim] - fj[dim]) / ((f_bar_min[dim] - fj[dim]));
+        }
+      }
+
+      double min_coef1 = coef1[0];
+      double min_coef2 = coef2[0];
+      for(size_t dim = 1; dim < Dimension; ++dim){
+        min_coef1 = std::min(min_coef1,coef1[dim]);
+        min_coef2 = std::min(min_coef2,coef2[dim]);
+      }
+
+      const double lambda = std::max(0., std::min(1., std::min(min_coef1, min_coef2)));
+
+      auto coefficients = DPk_fh.coefficients(cell_id);
+
+      coefficients[0] = (1 - lambda) * f[cell_id] + lambda * coefficients[0];
+      for (size_t i = 1; i < coefficients.size(); ++i) {
+        coefficients[i] *= lambda;
+      }
+    });
+  }
+
  public:
   std::tuple<const std::shared_ptr<const ItemValueVariant>, const std::shared_ptr<const SubItemValuePerItemVariant>>
   compute_fluxes(const SolverType& solver_type,
@@ -392,10 +523,16 @@ class Order2AcousticSolverHandler::Order2AcousticSolver final : public Order2Aco
     auto DPk_uh = reconstruction[0]->get<DiscreteFunctionDPk<Dimension, const Rd>>();
     auto DPk_ph = reconstruction[1]->get<DiscreteFunctionDPk<Dimension, const double>>();
 
+    DiscreteFunctionDPk<Dimension, Rd> u_lim     = copy(DPk_uh);
+    DiscreteFunctionDPk<Dimension, double> p_lim = copy(DPk_ph);
+
+    this->_scalar_limiter(mesh,p,p_lim);
+    this->_vector_limiter(mesh,u,u_lim);
+
     NodeValuePerCell<const Rdxd> Ajr = this->_computeAjr(solver_type, mesh, rho * c);
 
     NodeValue<Rdxd> Ar = this->_computeAr(mesh, Ajr);
-    NodeValue<Rd> br   = this->_computeBr(mesh, Ajr, DPk_uh, DPk_ph);
+    NodeValue<Rd> br   = this->_computeBr(mesh, Ajr, u_lim, p_lim);
 
     const BoundaryConditionList bc_list = this->_getBCList(mesh, bc_descriptor_list);
     this->_applyBoundaryConditions(bc_list, mesh, Ar, br);
@@ -405,7 +542,7 @@ class Order2AcousticSolverHandler::Order2AcousticSolver final : public Order2Aco
     synchronize(br);
 
     NodeValue<const Rd> ur         = this->_computeUr(mesh, Ar, br);
-    NodeValuePerCell<const Rd> Fjr = this->_computeFjr(mesh, Ajr, ur, DPk_uh, DPk_ph);
+    NodeValuePerCell<const Rd> Fjr = this->_computeFjr(mesh, Ajr, ur, u_lim, p_lim);
 
     return std::make_tuple(std::make_shared<const ItemValueVariant>(ur),
                            std::make_shared<const SubItemValuePerItemVariant>(Fjr));
@@ -519,7 +656,7 @@ class Order2AcousticSolverHandler::Order2AcousticSolver final : public Order2Aco
     auto [ur, Fjr] = compute_fluxes(solver_type, rho, c, u, p, bc_descriptor_list);
     std::tie(m_app,rho_app,u_app,E_app) = apply_fluxes(dt/2, rho, u, E, ur, Fjr);
 
-    const double& gamma = 3;
+    const double& gamma = 1.4;
 
     const DiscreteScalarFunction& rho_d = rho_app->get<DiscreteScalarFunction>();
     const DiscreteVectorFunction& u_d   = u_app->get<DiscreteVectorFunction>();
-- 
GitLab