Skip to content
Snippets Groups Projects
Select Git revision
  • b24312838a4becbc6655ccef07a0829b8664b95f
  • develop default protected
  • feature/advection
  • feature/composite-scheme-other-fluxes
  • origin/stage/bouguettaia
  • save_clemence
  • feature/local-dt-fsi
  • feature/variational-hydro
  • feature/gmsh-reader
  • feature/reconstruction
  • feature/kinetic-schemes
  • feature/composite-scheme-sources
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

FPEManager.cpp

Blame
  • PolynomialReconstruction.cpp 20.76 KiB
    #include <scheme/PolynomialReconstruction.hpp>
    
    #include <scheme/DiscreteFunctionUtils.hpp>
    #include <scheme/DiscreteFunctionVariant.hpp>
    
    class MutableDiscreteFunctionDPkVariant
    {
     public:
      using Variant = std::variant<DiscreteFunctionDPk<1, double>,
                                   DiscreteFunctionDPk<1, TinyVector<1>>,
                                   DiscreteFunctionDPk<1, TinyVector<2>>,
                                   DiscreteFunctionDPk<1, TinyVector<3>>,
                                   DiscreteFunctionDPk<1, TinyMatrix<1>>,
                                   DiscreteFunctionDPk<1, TinyMatrix<2>>,
                                   DiscreteFunctionDPk<1, TinyMatrix<3>>,
    
                                   DiscreteFunctionDPk<2, double>,
                                   DiscreteFunctionDPk<2, TinyVector<1>>,
                                   DiscreteFunctionDPk<2, TinyVector<2>>,
                                   DiscreteFunctionDPk<2, TinyVector<3>>,
                                   DiscreteFunctionDPk<2, TinyMatrix<1>>,
                                   DiscreteFunctionDPk<2, TinyMatrix<2>>,
                                   DiscreteFunctionDPk<2, TinyMatrix<3>>,
    
                                   DiscreteFunctionDPk<3, double>,
                                   DiscreteFunctionDPk<3, TinyVector<1>>,
                                   DiscreteFunctionDPk<3, TinyVector<2>>,
                                   DiscreteFunctionDPk<3, TinyVector<3>>,
                                   DiscreteFunctionDPk<3, TinyMatrix<1>>,
                                   DiscreteFunctionDPk<3, TinyMatrix<2>>,
                                   DiscreteFunctionDPk<3, TinyMatrix<3>>>;
    
    #warning add DiscreteFunctionDPkVector to the variant
    
     private:
      Variant m_mutable_discrete_function_dpk;
    
     public:
      PUGS_INLINE
      const Variant&
      mutableDiscreteFunctionDPk() const
      {
        return m_mutable_discrete_function_dpk;
      }
    
      template <typename DiscreteFunctionDPkT>
      PUGS_INLINE auto&&
      get() const
      {
        static_assert(is_discrete_function_dpk_v<DiscreteFunctionDPkT>, "invalid template argument");
    
    #ifndef NDEBUG
        if (not std::holds_alternative<DiscreteFunctionDPkT>(this->m_mutable_discrete_function_dpk)) {
          std::ostringstream error_msg;
          error_msg << "invalid discrete function type\n";
          error_msg << "- required " << rang::fgB::red << demangle<DiscreteFunctionDPkT>() << rang::fg::reset << '\n';
          error_msg << "- contains " << rang::fgB::yellow
                    << std::visit([](auto&& f) -> std::string { return demangle<decltype(f)>(); },
                                  this->m_mutable_discrete_function_dpk)
                    << rang::fg::reset;
          throw NormalError(error_msg.str());
        }
    #endif   // NDEBUG
    
        return std::get<DiscreteFunctionDPkT>(this->mutableDiscreteFunctionDPk());
      }
    
      template <size_t Dimension, typename DataType>
      MutableDiscreteFunctionDPkVariant(const DiscreteFunctionDPk<Dimension, DataType>& discrete_function_dpk)
        : m_mutable_discrete_function_dpk{DiscreteFunctionDPk<Dimension, DataType>{discrete_function_dpk}}
      {
        static_assert(std::is_same_v<std::remove_const_t<DataType>, double> or                       //
                        std::is_same_v<std::remove_const_t<DataType>, TinyVector<1, double>> or      //
                        std::is_same_v<std::remove_const_t<DataType>, TinyVector<2, double>> or      //
                        std::is_same_v<std::remove_const_t<DataType>, TinyVector<3, double>> or      //
                        std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<1, 1, double>> or   //
                        std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<2, 2, double>> or   //
                        std::is_same_v<std::remove_const_t<DataType>, TinyMatrix<3, 3, double>>,
                      "DiscreteFunctionDPk with this DataType is not allowed in variant");
      }
    
      MutableDiscreteFunctionDPkVariant& operator=(MutableDiscreteFunctionDPkVariant&&)      = default;
      MutableDiscreteFunctionDPkVariant& operator=(const MutableDiscreteFunctionDPkVariant&) = default;
    
      MutableDiscreteFunctionDPkVariant(const MutableDiscreteFunctionDPkVariant&) = default;
      MutableDiscreteFunctionDPkVariant(MutableDiscreteFunctionDPkVariant&&)      = default;
    
      MutableDiscreteFunctionDPkVariant()  = delete;
      ~MutableDiscreteFunctionDPkVariant() = default;
    };
    
    template <MeshConcept MeshType>
    [[nodiscard]] std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>>
    PolynomialReconstruction::_build(
      const std::shared_ptr<const MeshType>& p_mesh,
      const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const
    {
      const MeshType& mesh = *p_mesh;
    
      using Rd = TinyVector<MeshType::Dimension>;
    
      const size_t number_of_columns = [&]() {
        size_t n = 0;
        for (auto discrete_function_variant_p : discrete_function_variant_list) {
          n += std::visit(
            [](auto&& discrete_function) -> size_t {
              using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>;
              if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) {
                using data_type = std::decay_t<typename DiscreteFunctionT::data_type>;
                if constexpr (std::is_same_v<data_type, double>) {
                  return 1;
                } else if constexpr (is_tiny_vector_v<data_type> or is_tiny_matrix_v<data_type>) {
                  return data_type::Dimension;
                } else {
                  throw UnexpectedError("unexpected data type " + demangle<data_type>());
                }
              } else if constexpr (is_discrete_function_P0_vector_v<DiscreteFunctionT>) {
                return discrete_function.size();
              } else {
                throw UnexpectedError("unexpected discrete function type");
              }
            },
            discrete_function_variant_p->discreteFunction());
        }
        return n;
      }();
    
      const size_t degree    = 1;
      const Stencil& stencil = StencilManager::instance().getStencil(mesh.connectivity());
    
      auto xj            = MeshDataManager::instance().getMeshData(mesh).xj();
      auto cell_is_owned = mesh.connectivity().cellIsOwned();
    
      const size_t max_stencil_size = [&]() {
        size_t max_size = 0;
        for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) {
          auto stencil_cell_list = stencil[cell_id];
          if (cell_is_owned[cell_id] and stencil_cell_list.size() > max_size) {
            max_size = stencil_cell_list.size();
          }
        }
        return max_size;
      }();
    
      Kokkos::Experimental::UniqueToken<Kokkos::DefaultExecutionSpace::execution_space,
                                        Kokkos::Experimental::UniqueTokenScope::Global>
        tokens;
    
      std::vector<MutableDiscreteFunctionDPkVariant> mutable_discrete_function_dpk_variant_list;
      for (size_t i_discrete_function_variant = 0; i_discrete_function_variant < discrete_function_variant_list.size();
           ++i_discrete_function_variant) {
        auto discrete_function_variant = discrete_function_variant_list[i_discrete_function_variant];
    
        std::visit(
          [&](auto&& discrete_function) {
            using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>;
            if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) {
              using DataType = std::remove_const_t<std::decay_t<typename DiscreteFunctionT::data_type>>;
              mutable_discrete_function_dpk_variant_list.push_back(
                DiscreteFunctionDPk<MeshType::Dimension, DataType>(p_mesh, degree));
            } else {
              throw NotImplementedError("discrete function type");
            }
          },
          discrete_function_variant->discreteFunction());
      }
    
      SmallArray<SmallMatrix<double>> A_pool(Kokkos::DefaultExecutionSpace::concurrency());
      SmallArray<SmallMatrix<double>> B_pool(Kokkos::DefaultExecutionSpace::concurrency());
      SmallArray<SmallMatrix<double>> X_pool(Kokkos::DefaultExecutionSpace::concurrency());
    
      for (size_t i = 0; i < A_pool.size(); ++i) {
        A_pool[i] = SmallMatrix<double>(max_stencil_size, MeshType::Dimension);
        B_pool[i] = SmallMatrix<double>(max_stencil_size, number_of_columns);
        X_pool[i] = SmallMatrix<double>(MeshType::Dimension, number_of_columns);
      }
    
      parallel_for(
        mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_j_id) {
          if (cell_is_owned[cell_j_id]) {
            const int32_t t = tokens.acquire();
    
            auto stencil_cell_list = stencil[cell_j_id];
    
            ShrinkMatrixView B(B_pool[t], stencil_cell_list.size());
    
            for (size_t i_discrete_function_variant = 0;
                 i_discrete_function_variant < discrete_function_variant_list.size(); ++i_discrete_function_variant) {
              const auto& discrete_function_variant = discrete_function_variant_list[i_discrete_function_variant];
    
              std::visit(
                [&](auto&& discrete_function) {
                  using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>;
                  if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) {
                    using DataType      = std::decay_t<typename DiscreteFunctionT::data_type>;
                    size_t column_begin = 0;
                    const DataType& pj  = discrete_function[cell_j_id];
                    for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
                      const CellId cell_i_id = stencil_cell_list[i];
                      const DataType& pi_pj  = discrete_function[cell_i_id] - pj;
                      if constexpr (std::is_arithmetic_v<DataType>) {
                        B(i, column_begin) = pi_pj;
                      } else if constexpr (is_tiny_vector_v<DataType>) {
                        for (size_t kB = column_begin, k = 0; k < DataType::Dimension; ++k, ++kB) {
                          B(i, kB) = pi_pj[k];
                        }
                      } else if constexpr (is_tiny_matrix_v<DataType>) {
                        for (size_t k = 0; k < DataType::NumberOfRows; ++k) {
                          for (size_t l = 0; l < DataType::NumberOfColumns; ++l) {
                            B(i, column_begin + k * DataType::NumberOfColumns + l) = pi_pj(k, l);
                          }
                        }
                      }
                    }
    
                    if constexpr (std::is_arithmetic_v<DataType>) {
                      ++column_begin;
                    } else if constexpr (is_tiny_vector_v<DataType> or is_tiny_matrix_v<DataType>) {
                      column_begin += DataType::Dimension;
                    }
                  }
                },
                discrete_function_variant->discreteFunction());
            }
    
            // for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
            //   const CellId cell_i_id = stencil_cell_list[i];
            //   for (size_t j = 0; j < number_of_columns; ++j) {
            //     B(i, j) = values[cell_i_id][j] - values[cell_j_id][j];
            //   }
            // }
    
            ShrinkMatrixView A(A_pool[t], stencil_cell_list.size());
    
            const Rd& Xj = xj[cell_j_id];
    
            for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
              const CellId cell_i_id = stencil_cell_list[i];
              const Rd Xi_Xj         = xj[cell_i_id] - Xj;
              for (size_t l = 0; l < MeshType::Dimension; ++l) {
                A(i, l) = Xi_Xj[l];
              }
            }
    
            const SmallMatrix<double>& X = X_pool[t];
            Givens::solveCollectionInPlace(A, X, B);
    
            size_t column_begin = 0;
            for (size_t i_dpk_variant = 0; i_dpk_variant < mutable_discrete_function_dpk_variant_list.size();
                 ++i_dpk_variant) {
              const auto& dpk_variant = mutable_discrete_function_dpk_variant_list[i_dpk_variant];
    
              const auto& discrete_function_variant = discrete_function_variant_list[i_dpk_variant];
    
              std::visit(
                [&](auto&& dpk_function, auto&& p0_function) {
                  using DPkFunctionT = std::decay_t<decltype(dpk_function)>;
                  using P0FunctionT  = std::decay_t<decltype(p0_function)>;
                  using DataType     = std::remove_const_t<std::decay_t<typename DPkFunctionT::data_type>>;
                  using P0DataType   = std::remove_const_t<std::decay_t<typename P0FunctionT::data_type>>;
    
                  if constexpr (std::is_same_v<DataType, P0DataType>) {
                    if constexpr (is_discrete_function_P0_v<P0FunctionT>) {
                      auto dpk_j = dpk_function.coefficients(cell_j_id);
                      dpk_j[0]   = p0_function[cell_j_id];
    
                      if constexpr (std::is_arithmetic_v<DataType>) {
                        for (size_t i = 0; i < MeshType::Dimension; ++i) {
                          auto& dpk_j_ip1 = dpk_j[i + 1];
                          dpk_j_ip1       = X(i, column_begin);
                        }
                        ++column_begin;
                      } else if constexpr (is_tiny_vector_v<DataType>) {
                        for (size_t i = 0; i < MeshType::Dimension; ++i) {
                          auto& dpk_j_ip1 = dpk_j[i + 1];
                          for (size_t k = 0; k < DataType::Dimension; ++k) {
                            dpk_j_ip1[k] = X(i, column_begin + k);
                          }
                        }
                        column_begin += DataType::Dimension;
                      } else if constexpr (is_tiny_matrix_v<DataType>) {
                        for (size_t i = 0; i < MeshType::Dimension; ++i) {
                          auto& dpk_j_ip1 = dpk_j[i + 1];
                          for (size_t k = 0; k < DataType::NumberOfRows; ++k) {
                            for (size_t l = 0; l < DataType::NumberOfColumns; ++l) {
                              dpk_j_ip1(k, l) = X(i, column_begin + k * DataType::NumberOfColumns + l);
                            }
                          }
                        }
                        column_begin += DataType::Dimension;
                      } else {
                        throw NotImplementedError("unexpected data type");
                      }
                    } else {
                      throw NotImplementedError("non scalar P0 functions");
                    }
                  } else {
                    throw UnexpectedError("incompatible data types");
                  }
                },
                dpk_variant.mutableDiscreteFunctionDPk(), discrete_function_variant->discreteFunction());
            }
    
            tokens.release(t);
          }
        });
    
      return {};
    
      // parallel_for(
      //   mesh.numberOfCells(), PUGS_LAMBDA(const CellId cell_j_id) {
      //     if (cell_is_owned[cell_j_id]) {
      //       const int32_t t = tokens.acquire();
    
      //       auto stencil_cell_list = stencil[cell_j_id];
      //       ShrinkMatrixView B(B_pool[t], stencil_cell_list.size());
    
      //       size_t column_begin = 0;
      //       for (size_t i_discrete_function_variant = 0;
      //            i_discrete_function_variant < discrete_function_variant_list.size(); ++i_discrete_function_variant) {
      //         // const auto& discrete_function_variant = discrete_function_variant_list[i_discrete_function_variant];
    
      //         // std::visit(
      //         //   [&](auto&& discrete_function) {
      //         //     using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>;
      //         //     if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) {
      //         //       using DataType = std::decay_t<typename DiscreteFunctionT::data_type>;
    
      //         //       const DataType& pj = discrete_function[cell_j_id];
      //         //       for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
      //         //         const CellId cell_i_id = stencil_cell_list[i];
      //         //         const DataType& pi_pj  = discrete_function[cell_i_id] - pj;
      //         //         if constexpr (std::is_arithmetic_v<DataType>) {
      //         //           B(i, column_begin) = pi_pj;
      //         //         } else if constexpr (is_tiny_vector_v<DataType>) {
      //         //           for (size_t kB = column_begin, k = 0; k < DataType::Dimension; ++k, ++kB) {
      //         //             B(i, kB) = pi_pj[k];
      //         //           }
      //         //         } else if constexpr (is_tiny_matrix_v<DataType>) {
      //         //           for (size_t k = 0; k < DataType::NumberOfRows; ++k) {
      //         //             for (size_t l = 0; l < DataType::NumberOfColumns; ++l) {
      //         //               B(i, column_begin + k * DataType::NumberOfColumns + l) = pi_pj(k, l);
      //         //             }
      //         //           }
      //         //         }
      //         //       }
    
      //         //       if constexpr (std::is_arithmetic_v<DataType>) {
      //         //         ++column_begin;
      //         //       } else if constexpr (is_tiny_vector_v<DataType> or is_tiny_matrix_v<DataType>) {
      //         //         column_begin += DataType::Dimension;
      //         //       }
      //         //     }
      //         //   },
      //         //   discrete_function_variant->discreteFunction());
    
      //         using DataType = double;
    
      //         const DataType& pj = my_discrete_function[cell_j_id];
      //         for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
      //           const CellId cell_i_id = stencil_cell_list[i];
      //           const DataType& pi_pj  = my_discrete_function[cell_i_id] - pj;
      //           B(i, column_begin)     = pi_pj;
      //         }
    
      //         ++column_begin;
      //       }
      //       ShrinkMatrixView A(A_pool[t], stencil_cell_list.size());
    
      //       const Rd& Xj = xj[cell_j_id];
    
      //       for (size_t i = 0; i < stencil_cell_list.size(); ++i) {
      //         const CellId cell_i_id = stencil_cell_list[i];
      //         const Rd Xi_Xj         = xj[cell_i_id] - Xj;
      //         for (size_t l = 0; l < MeshType::Dimension; ++l) {
      //           A(i, l) = Xi_Xj[l];
      //         }
      //       }
    
      //       const SmallMatrix<double>& X = X_pool[t];
      //       Givens::solveCollectionInPlace(A, X, B);
    
      //       column_begin = 0;
      //       for (size_t i_discrete_function_variant = 0;
      //            i_discrete_function_variant < discrete_function_variant_list.size(); ++i_discrete_function_variant) {
      //         auto discrete_function_variant = discrete_function_variant_list[i_discrete_function_variant];
    
      //         std::visit(
      //           [&](auto&& discrete_function) {
      //             using DiscreteFunctionT = std::decay_t<decltype(discrete_function)>;
      //             if constexpr (is_discrete_function_P0_v<DiscreteFunctionT>) {
      //               using DataType = std::decay_t<typename DiscreteFunctionT::data_type>;
    
      //               const DataType& pj         = discrete_function[cell_j_id];
      //               auto discrete_function_dpk = mutable_discrete_function_dpk_variant_list[i_discrete_function_variant]
      //                                              .get<DiscreteFunctionDPk<MeshType::Dimension, DataType>>();
      //               auto dpk_j = discrete_function_dpk.coefficients(cell_j_id);
      //               dpk_j[0]   = pj;
    
      //               if constexpr (std::is_arithmetic_v<DataType>) {
      //                 for (size_t i = 0; i < MeshType::Dimension; ++i) {
      //                   auto& dpk_j_ip1 = dpk_j[i + 1];
      //                   dpk_j_ip1       = X(i, column_begin);
      //                 }
      //                 ++column_begin;
      //               } else if constexpr (is_tiny_vector_v<DataType>) {
      //                 for (size_t i = 0; i < MeshType::Dimension; ++i) {
      //                   auto& dpk_j_ip1 = dpk_j[i + 1];
      //                   for (size_t k = 0; k < DataType::Dimension; ++k) {
      //                     dpk_j_ip1[k] = X(i, column_begin + k);
      //                   }
      //                 }
      //                 column_begin += DataType::Dimension;
      //               } else if constexpr (is_tiny_matrix_v<DataType>) {
      //                 for (size_t i = 0; i < MeshType::Dimension; ++i) {
      //                   auto& dpk_j_ip1 = dpk_j[i + 1];
      //                   for (size_t k = 0; k < DataType::NumberOfRows; ++k) {
      //                     for (size_t l = 0; l < DataType::NumberOfColumns; ++l) {
      //                       dpk_j_ip1(k, l) = X(i, column_begin + k * DataType::NumberOfColumns + l);
      //                     }
      //                   }
      //                 }
      //                 column_begin += DataType::Dimension;
      //               }
    
      //             } else {
      //               throw NotImplementedError("discrete function type");
      //             }
      //           },
      //           discrete_function_variant->discreteFunction());
      //       }
    
      //       tokens.release(t);
      //     }
      //   });
    
      std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>> discrete_function_dpk_variant_list;
    
      // for (auto discrete_function_dpk_variant_p : mutable_discrete_function_dpk_variant_list) {
      //   discrete_function_dpk_variant_list.push_back(
      //     std::make_shared<const DiscreteFunctionDPkVariant>(discrete_function_dpk_variant_p));
      // }
    
      return discrete_function_dpk_variant_list;
    }
    
    std::vector<std::shared_ptr<const DiscreteFunctionDPkVariant>>
    PolynomialReconstruction::build(
      const std::vector<std::shared_ptr<const DiscreteFunctionVariant>>& discrete_function_variant_list) const
    {
      if (not hasSameMesh(discrete_function_variant_list)) {
        throw NormalError("cannot reconstruct functions living of different mesh simultaneously");
      }
    
      auto mesh_v = getCommonMesh(discrete_function_variant_list);
    
      return std::visit([&](auto&& p_mesh) { return this->_build(p_mesh, discrete_function_variant_list); },
                        mesh_v->variant());
    }