From a143de698384b1aa89457bba0ccc0722de419ecd Mon Sep 17 00:00:00 2001
From: labourasse <labourassee@gmail.com>
Date: Tue, 21 Feb 2023 17:29:02 +0100
Subject: [PATCH] fix bugs and allow vectors and tensors

---
 src/scheme/FluxingAdvectionSolver.cpp | 81 ++++++++++++++++++++-------
 1 file changed, 60 insertions(+), 21 deletions(-)

diff --git a/src/scheme/FluxingAdvectionSolver.cpp b/src/scheme/FluxingAdvectionSolver.cpp
index 6d54194f1..b655ff74f 100644
--- a/src/scheme/FluxingAdvectionSolver.cpp
+++ b/src/scheme/FluxingAdvectionSolver.cpp
@@ -126,10 +126,10 @@ FluxingAdvectionSolver<3>::computeFluxVolume() const
   throw NotImplementedError("ViensViensViens");
 }
 
-template <typename MeshType>
+template <typename MeshType, typename DataType>
 auto
 calculateRemapCycles(const std::shared_ptr<const MeshType>& old_mesh,
-                     [[maybe_unused]] const FaceValue<double>& fluxing_volumes)
+                     [[maybe_unused]] const FaceValue<DataType>& fluxing_volumes)
 {
   constexpr size_t Dimension                               = MeshType::Dimension;
   const FaceValuePerCell<const bool> cell_face_is_reversed = old_mesh->connectivity().cellFaceIsReversed();
@@ -142,7 +142,7 @@ calculateRemapCycles(const std::shared_ptr<const MeshType>& old_mesh,
       for (size_t i_face = 0; i_face < cell_to_face.size(); ++i_face) {
         FaceId face_id = cell_to_face[i_face];
         double flux    = fluxing_volumes[face_id];
-        if (cell_face_is_reversed(cell_id, i_face)) {
+        if (!cell_face_is_reversed(cell_id, i_face)) {
           flux = -flux;
         }
         if (flux < 0) {
@@ -164,8 +164,9 @@ calculateRemapCycles(const std::shared_ptr<const MeshType>& old_mesh,
 
 template <typename MeshType, typename DataType>
 auto
-remapUsingFluxing(const std::shared_ptr<const MeshType>& new_mesh,
-                  [[maybe_unused]] const FaceValue<double>& fluxing_volumes,
+remapUsingFluxing(const std::shared_ptr<const MeshType>& old_mesh,
+                  const std::shared_ptr<const MeshType>& new_mesh,
+                  const FaceValue<double>& fluxing_volumes,
                   const size_t num,
                   const DiscreteFunctionP0<MeshType::Dimension, const DataType>& old_q)
 {
@@ -173,17 +174,26 @@ remapUsingFluxing(const std::shared_ptr<const MeshType>& new_mesh,
   //  const Connectivity<Dimension>& connectivity = new_mesh->connectivity();
   const FaceValuePerCell<const bool> cell_face_is_reversed = new_mesh->connectivity().cellFaceIsReversed();
   DiscreteFunctionP0<Dimension, DataType> new_q(new_mesh, copy(old_q.cellValues()));
-  const auto cell_to_face_matrix = new_mesh->connectivity().cellToFaceMatrix();
-  const auto face_to_cell_matrix = new_mesh->connectivity().faceToCellMatrix();
+  DiscreteFunctionP0<Dimension, DataType> previous_q(new_mesh, copy(old_q.cellValues()));
+  const auto cell_to_face_matrix      = new_mesh->connectivity().cellToFaceMatrix();
+  const auto face_to_cell_matrix      = new_mesh->connectivity().faceToCellMatrix();
+  MeshData<Dimension>& old_mesh_data  = MeshDataManager::instance().getMeshData(*old_mesh);
+  const CellValue<const double> oldVj = old_mesh_data.Vj();
+  const CellValue<double> Vjstep(new_mesh->connectivity());
+  parallel_for(
+    new_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) {
+      Vjstep[cell_id] = oldVj[cell_id];
+      new_q[cell_id] *= oldVj[cell_id];
+    });
   for (size_t jstep = 0; jstep < num; ++jstep) {
-    std::cout << " step " << jstep << "\n";
+    // std::cout << " step " << jstep << "\n";
     parallel_for(
       new_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) {
         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) {
           FaceId face_id = cell_to_face[i_face];
           double flux    = fluxing_volumes[face_id];
-          if (cell_face_is_reversed(cell_id, i_face)) {
+          if (!cell_face_is_reversed(cell_id, i_face)) {
             flux = -flux;
           }
           const auto& face_to_cell = face_to_cell_matrix[face_id];
@@ -194,30 +204,49 @@ remapUsingFluxing(const std::shared_ptr<const MeshType>& new_mesh,
           if (other_cell_id == cell_id) {
             other_cell_id = face_to_cell[1];
           }
-          DataType fluxed_q = old_q[cell_id];
+          DataType fluxed_q = previous_q[cell_id];
           if (flux > 0) {
-            fluxed_q = old_q[other_cell_id];
+            fluxed_q = previous_q[other_cell_id];
           }
+          Vjstep[cell_id] += flux / num;
           fluxed_q *= flux / num;
           new_q[cell_id] += fluxed_q;
         }
         // std::cout << " old q " << old_q[cell_id] << " new q " << new_q[cell_id] << "\n";
       });
+    parallel_for(
+      new_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) {
+        previous_q[cell_id] = 1 / Vjstep[cell_id] * new_q[cell_id];
+        //     std::cout << " old q " << old_q[cell_id] << " new q " << previous_q[cell_id] << "\n";
+        //     std::cout << " old vj " << oldVj[cell_id] << " new Vj " << Vjstep[cell_id] << "\n";
+      });
   }
+
+  MeshData<Dimension>& new_mesh_data  = MeshDataManager::instance().getMeshData(*new_mesh);
+  const CellValue<const double> newVj = new_mesh_data.Vj();
+  parallel_for(
+    new_mesh->numberOfCells(), PUGS_LAMBDA(CellId cell_id) { new_q[cell_id] = 1 / newVj[cell_id] * new_q[cell_id]; });
+  // for (CellId cell_id = 0; cell_id < new_mesh->numberOfCells(); ++cell_id) {
+  //   if (abs(newVj[cell_id] - Vjstep[cell_id]) > 1e-15) {
+  //     std::cout << " cell " << cell_id << " newVj " << newVj[cell_id] << " Vjstep " << Vjstep[cell_id] << " diff "
+  //               << abs(newVj[cell_id] - Vjstep[cell_id]) << "\n";
+  //   }
+  // }
   return new_q;
 }
 
-template <typename MeshType>
+template <typename MeshType, typename DataType>
 auto
-remapUsingFluxing(const std::shared_ptr<const MeshType>& new_mesh,
+remapUsingFluxing([[maybe_unused]] const std::shared_ptr<const MeshType>& old_mesh,
+                  const std::shared_ptr<const MeshType>& new_mesh,
                   [[maybe_unused]] const FaceValue<double>& fluxing_volumes,
                   [[maybe_unused]] const size_t num,
-                  const DiscreteFunctionP0Vector<MeshType::Dimension, const double>& old_q)
+                  const DiscreteFunctionP0Vector<MeshType::Dimension, const DataType>& old_q)
 {
   constexpr size_t Dimension = MeshType::Dimension;
   //  const Connectivity<Dimension>& connectivity = new_mesh->connectivity();
 
-  DiscreteFunctionP0Vector<Dimension, double> new_q(new_mesh, copy(old_q.cellArrays()));
+  DiscreteFunctionP0Vector<Dimension, DataType> new_q(new_mesh, copy(old_q.cellArrays()));
 
   throw NotImplementedError("DiscreteFunctionP0Vector");
 
@@ -306,11 +335,11 @@ FluxingAdvectionSolverHandler(const std::shared_ptr<const IMesh> new_mesh,
 
 std::shared_ptr<const DiscreteFunctionVariant>
 FluxingAdvectionSolverHandler(const std::shared_ptr<const IMesh> new_mesh,
-                              const std::shared_ptr<const DiscreteFunctionVariant>& remapped_variables)
+                              const std::shared_ptr<const DiscreteFunctionVariant>& remapped_variable)
 {
-  const std::shared_ptr<const IMesh> old_mesh = getCommonMesh({remapped_variables});
+  const std::shared_ptr<const IMesh> old_mesh = getCommonMesh({remapped_variable});
 
-  if (not checkDiscretizationType({remapped_variables}, DiscreteFunctionType::P0)) {
+  if (not checkDiscretizationType({remapped_variable}, DiscreteFunctionType::P0)) {
     throw NormalError("acoustic solver expects P0 functions");
   }
 
@@ -330,9 +359,19 @@ FluxingAdvectionSolverHandler(const std::shared_ptr<const IMesh> new_mesh,
 
     FaceValue<double> fluxing_volumes = solver.computeFluxVolume();
     size_t number_of_cycles           = calculateRemapCycles(old_mesh0, fluxing_volumes);
-    return std::make_shared<DiscreteFunctionVariant>(
-      remapUsingFluxing(new_mesh0, fluxing_volumes, number_of_cycles,
-                        remapped_variables->get<DiscreteFunctionP0<Dimension, const double>>()));
+
+    DiscreteFunctionVariant new_variable = std::visit(
+      [&](auto&& variable) -> DiscreteFunctionVariant {
+        using DiscreteFunctionT = std::decay_t<decltype(variable)>;
+        if constexpr (std::is_same_v<MeshType, typename DiscreteFunctionT::MeshType>) {
+          return remapUsingFluxing(old_mesh0, new_mesh0, fluxing_volumes, number_of_cycles, variable);
+        } else {
+          throw UnexpectedError("incompatible mesh types");
+        }
+      },
+      remapped_variable->discreteFunction());
+
+    return std::make_shared<DiscreteFunctionVariant>(new_variable);
   }
   case 3: {
     throw NotImplementedError("Fluxing advection solver not implemented in dimension 3");
-- 
GitLab