Skip to content
Snippets Groups Projects
Select Git revision
  • b1d83081bcfacf2f61fe483e79de17a1ff83ccaf
  • 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

AcousticSolver.hpp

Blame
  • AcousticSolver.hpp 10.28 KiB
    #ifndef ACOUSTIC_SOLVER_HPP
    #define ACOUSTIC_SOLVER_HPP
    
    #include <rang.hpp>
    
    #include <ArrayUtils.hpp>
    
    #include <BlockPerfectGas.hpp>
    #include <PugsAssert.hpp>
    
    #include <BoundaryCondition.hpp>
    #include <FiniteVolumesEulerUnknowns.hpp>
    #include <Mesh.hpp>
    #include <MeshData.hpp>
    #include <TinyMatrix.hpp>
    #include <TinyVector.hpp>
    
    #include <ItemValueUtils.hpp>
    #include <Messenger.hpp>
    #include <SubItemValuePerItem.hpp>
    
    template <typename MeshData>
    class AcousticSolver
    {
      using MeshType     = typename MeshData::MeshType;
      using UnknownsType = FiniteVolumesEulerUnknowns<MeshData>;
    
      MeshData& m_mesh_data;
      const MeshType& m_mesh;
      const typename MeshType::Connectivity& m_connectivity;
      const std::vector<BoundaryConditionHandler>& m_boundary_condition_list;
    
      constexpr static size_t Dimension = MeshType::Dimension;
    
      using Rd  = TinyVector<Dimension>;
      using Rdd = TinyMatrix<Dimension>;
    
     private:
      PUGS_INLINE
      const CellValue<const double>
      computeRhoCj(const CellValue<const double>& rhoj,
                   const CellValue<const double>& cj)
      {
        parallel_for(m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId& j) {
          m_rhocj[j] = rhoj[j] * cj[j];
        });
        return m_rhocj;
      }
    
      PUGS_INLINE
      void
      computeAjr(const CellValue<const double>& rhocj,
                 const NodeValuePerCell<const Rd>& Cjr,
                 const NodeValuePerCell<const double>& /* ljr */,
                 const NodeValuePerCell<const Rd>& njr)
      {
        parallel_for(m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId& j) {
          const size_t& nb_nodes = m_Ajr.numberOfSubValues(j);
          const double& rho_c    = rhocj[j];
          for (size_t r = 0; r < nb_nodes; ++r) {
            m_Ajr(j, r) = tensorProduct(rho_c * Cjr(j, r), njr(j, r));
          }
        });
      }
    
      PUGS_INLINE
      const NodeValue<const Rdd>
      computeAr(const NodeValuePerCell<const Rdd>& Ajr)
      {
        const auto& node_to_cell_matrix = m_connectivity.nodeToCellMatrix();
        const auto& node_local_numbers_in_their_cells =
          m_connectivity.nodeLocalNumbersInTheirCells();
    
        parallel_for(m_mesh.numberOfNodes(), PUGS_LAMBDA(const NodeId& r) {
          Rdd sum                  = zero;
          const auto& node_to_cell = node_to_cell_matrix[r];
          const auto& node_local_number_in_its_cells =
            node_local_numbers_in_their_cells.itemValues(r);
    
          for (size_t j = 0; j < node_to_cell.size(); ++j) {
            const CellId J       = node_to_cell[j];
            const unsigned int R = node_local_number_in_its_cells[j];
            sum += Ajr(J, R);
          }
          m_Ar[r] = sum;
        });
    
        return m_Ar;
      }
    
      PUGS_INLINE
      const NodeValue<const Rd>
      computeBr(const NodeValuePerCell<Rdd>& Ajr,
                const NodeValuePerCell<const Rd>& Cjr,
                const CellValue<const Rd>& uj,
                const CellValue<const double>& pj)
      {
        const auto& node_to_cell_matrix = m_connectivity.nodeToCellMatrix();
        const auto& node_local_numbers_in_their_cells =
          m_connectivity.nodeLocalNumbersInTheirCells();
    
        parallel_for(m_mesh.numberOfNodes(), PUGS_LAMBDA(const NodeId& r) {
          Rd& br                   = m_br[r];
          br                       = zero;
          const auto& node_to_cell = node_to_cell_matrix[r];
          const auto& node_local_number_in_its_cells =
            node_local_numbers_in_their_cells.itemValues(r);
          for (size_t j = 0; j < node_to_cell.size(); ++j) {
            const CellId J       = node_to_cell[j];
            const unsigned int R = node_local_number_in_its_cells[j];
            br += Ajr(J, R) * uj[J] + pj[J] * Cjr(J, R);
          }
        });
    
        return m_br;
      }
    
      void
      applyBoundaryConditions()
      {
        for (const auto& handler : m_boundary_condition_list) {
          switch (handler.boundaryCondition().type()) {
            case BoundaryCondition::normal_velocity: {
              perr() << __FILE__ << ':' << __LINE__ << ": normal_velocity BC NIY\n";
              std::exit(0);
              break;
            }
            case BoundaryCondition::velocity: {
              perr() << __FILE__ << ':' << __LINE__ << ": velocity BC NIY\n";
              std::exit(0);
              break;
            }
            case BoundaryCondition::pressure: {
              // const PressureBoundaryCondition& pressure_bc
              //   = dynamic_cast<const
              //   PressureBoundaryCondition&>(handler.boundaryCondition());
              perr() << __FILE__ << ':' << __LINE__ << ": pressure BC NIY\n";
              std::exit(0);
              break;
            }
            case BoundaryCondition::symmetry: {
              const SymmetryBoundaryCondition<Dimension>& symmetry_bc =
                dynamic_cast<const SymmetryBoundaryCondition<Dimension>&>(
                  handler.boundaryCondition());
              const Rd& n = symmetry_bc.outgoingNormal();
    
              const Rdd I   = identity;
              const Rdd nxn = tensorProduct(n, n);
              const Rdd P   = I - nxn;
    
              const Array<const NodeId>& node_list = symmetry_bc.nodeList();
              parallel_for(symmetry_bc.numberOfNodes(),
                           PUGS_LAMBDA(const int& r_number) {
                             const NodeId r = node_list[r_number];
    
                             m_Ar[r] = P * m_Ar[r] * P + nxn;
                             m_br[r] = P * m_br[r];
                           });
              break;
            }
          }
        }
      }
    
      NodeValue<Rd>
      computeUr(const NodeValue<const Rdd>& Ar, const NodeValue<const Rd>& br)
      {
        inverse(Ar, m_inv_Ar);
        const NodeValue<const Rdd> invAr = m_inv_Ar;
        parallel_for(m_mesh.numberOfNodes(), PUGS_LAMBDA(const NodeId& r) {
          m_ur[r] = invAr[r] * br[r];
        });
    
        return m_ur;
      }
    
      void
      computeFjr(const NodeValuePerCell<Rdd>& Ajr,
                 const NodeValue<const Rd>& ur,
                 const NodeValuePerCell<const Rd>& Cjr,
                 const CellValue<const Rd>& uj,
                 const CellValue<const double>& pj)
      {
        const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();
    
        parallel_for(m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId& j) {
          const auto& cell_nodes = cell_to_node_matrix[j];
    
          for (size_t r = 0; r < cell_nodes.size(); ++r) {
            m_Fjr(j, r) =
              Ajr(j, r) * (uj[j] - ur[cell_nodes[r]]) + pj[j] * Cjr(j, r);
          }
        });
      }
    
      void
      inverse(const NodeValue<const Rdd>& A, NodeValue<Rdd>& inv_A) const
      {
        parallel_for(m_mesh.numberOfNodes(), PUGS_LAMBDA(const NodeId& r) {
          inv_A[r] = ::inverse(A[r]);
        });
      }
    
      PUGS_INLINE
      void
      computeExplicitFluxes(const CellValue<const double>& rhoj,
                            const CellValue<const Rd>& uj,
                            const CellValue<const double>& pj,
                            const CellValue<const double>& cj,
                            const NodeValuePerCell<const Rd>& Cjr,
                            const NodeValuePerCell<const double>& ljr,
                            const NodeValuePerCell<const Rd>& njr)
      {
        const CellValue<const double> rhocj = computeRhoCj(rhoj, cj);
        computeAjr(rhocj, Cjr, ljr, njr);
    
        NodeValuePerCell<const Rdd> Ajr = m_Ajr;
        this->computeAr(Ajr);
        this->computeBr(m_Ajr, Cjr, uj, pj);
    
        this->applyBoundaryConditions();
    
        synchronize(m_Ar);
        synchronize(m_br);
    
        NodeValue<Rd>& ur = m_ur;
        ur                = computeUr(m_Ar, m_br);
        computeFjr(m_Ajr, ur, Cjr, uj, pj);
      }
    
      NodeValue<Rd> m_br;
      NodeValuePerCell<Rdd> m_Ajr;
      NodeValue<Rdd> m_Ar;
      NodeValue<Rdd> m_inv_Ar;
      NodeValuePerCell<Rd> m_Fjr;
      NodeValue<Rd> m_ur;
      CellValue<double> m_rhocj;
      CellValue<double> m_Vj_over_cj;
    
     public:
      AcousticSolver(MeshData& mesh_data,
                     const std::vector<BoundaryConditionHandler>& bc_list)
        : m_mesh_data(mesh_data),
          m_mesh(mesh_data.mesh()),
          m_connectivity(m_mesh.connectivity()),
          m_boundary_condition_list(bc_list),
          m_br(m_connectivity),
          m_Ajr(m_connectivity),
          m_Ar(m_connectivity),
          m_inv_Ar(m_connectivity),
          m_Fjr(m_connectivity),
          m_ur(m_connectivity),
          m_rhocj(m_connectivity),
          m_Vj_over_cj(m_connectivity)
      {
        ;
      }
    
      PUGS_INLINE
      double
      acoustic_dt(const CellValue<const double>& Vj,
                  const CellValue<const double>& cj) const
      {
        const NodeValuePerCell<const double>& ljr = m_mesh_data.ljr();
        const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();
    
        parallel_for(m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId& j) {
          const auto& cell_nodes = cell_to_node_matrix[j];
    
          double S = 0;
          for (size_t r = 0; r < cell_nodes.size(); ++r) {
            S += ljr(j, r);
          }
          m_Vj_over_cj[j] = 2 * Vj[j] / (S * cj[j]);
        });
    
        return min(m_Vj_over_cj);
      }
    
      void
      computeNextStep(const double&, const double& dt, UnknownsType& unknowns)
      {
        CellValue<double>& rhoj = unknowns.rhoj();
        CellValue<Rd>& uj       = unknowns.uj();
        CellValue<double>& Ej   = unknowns.Ej();
    
        CellValue<double>& ej = unknowns.ej();
        CellValue<double>& pj = unknowns.pj();
        CellValue<double>& cj = unknowns.cj();
    
        const CellValue<const double>& Vj         = m_mesh_data.Vj();
        const NodeValuePerCell<const Rd>& Cjr     = m_mesh_data.Cjr();
        const NodeValuePerCell<const double>& ljr = m_mesh_data.ljr();
        const NodeValuePerCell<const Rd>& njr     = m_mesh_data.njr();
    
        computeExplicitFluxes(rhoj, uj, pj, cj, Cjr, ljr, njr);
    
        const NodeValuePerCell<Rd>& Fjr = m_Fjr;
        const NodeValue<const Rd> ur    = m_ur;
        const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix();
    
        const CellValue<const double> inv_mj = unknowns.invMj();
        parallel_for(m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId& j) {
          const auto& cell_nodes = cell_to_node_matrix[j];
    
          Rd momentum_fluxes   = zero;
          double energy_fluxes = 0;
          for (size_t R = 0; R < cell_nodes.size(); ++R) {
            const NodeId r = cell_nodes[R];
            momentum_fluxes += Fjr(j, R);
            energy_fluxes += (Fjr(j, R), ur[r]);
          }
          uj[j] -= (dt * inv_mj[j]) * momentum_fluxes;
          Ej[j] -= (dt * inv_mj[j]) * energy_fluxes;
        });
    
        parallel_for(m_mesh.numberOfCells(), PUGS_LAMBDA(const CellId& j) {
          ej[j] = Ej[j] - 0.5 * (uj[j], uj[j]);
        });
    
        NodeValue<Rd> mutable_xr = m_mesh.mutableXr();
        parallel_for(m_mesh.numberOfNodes(), PUGS_LAMBDA(const NodeId& r) {
          mutable_xr[r] += dt * ur[r];
        });
        m_mesh_data.updateAllData();
    
        const CellValue<const double> mj = unknowns.mj();
        parallel_for(m_mesh.numberOfCells(),
                     PUGS_LAMBDA(const CellId& j) { rhoj[j] = mj[j] / Vj[j]; });
      }
    };
    
    #endif   // ACOUSTIC_SOLVER_HPP