diff --git a/src/language/modules/MeshModule.hpp b/src/language/modules/MeshModule.hpp index 64e6194946b6f6f9ceed019f513730d6fd3de8c0..f2c3d3d6360e5fd378d128d3b6b57e0de5a04509 100644 --- a/src/language/modules/MeshModule.hpp +++ b/src/language/modules/MeshModule.hpp @@ -5,7 +5,7 @@ #include <language/utils/ASTNodeDataTypeTraits.hpp> #include <utils/PugsMacros.hpp> -struct IMesh; +class IMesh; template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const IMesh>> = {ASTNodeDataType::type_id_t, "mesh"}; diff --git a/src/mesh/MeshData.hpp b/src/mesh/MeshData.hpp index f8cd50f30bed85e3f905aa6efc877b2612e669e0..01eccadce6fcedb1cfaea71d87e959781190cc25 100644 --- a/src/mesh/MeshData.hpp +++ b/src/mesh/MeshData.hpp @@ -22,6 +22,7 @@ class MeshData : public IMeshData { public: static_assert(Dimension > 0, "dimension must be strictly positive"); + static_assert((Dimension <= 3), "only 1d, 2d and 3d are implemented"); using MeshType = Mesh<Connectivity<Dimension>>; @@ -36,10 +37,11 @@ class MeshData : public IMeshData std::shared_ptr<NodeValuePerCell<const Rd>> m_njr; std::shared_ptr<CellValue<const Rd>> m_xj; std::shared_ptr<CellValue<const double>> m_Vj; + std::shared_ptr<NodeValuePerFace<const Rd>> m_Nlr; PUGS_INLINE void - _updateCenter() + _computeIsobarycenter() { // Computes vertices isobarycenter if constexpr (Dimension == 1) { const NodeValue<const Rd>& xr = m_mesh.xr(); @@ -75,11 +77,13 @@ class MeshData : public IMeshData PUGS_INLINE void - _updateVolume() + _computeCellVolume() { const NodeValue<const Rd>& xr = m_mesh.xr(); const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix(); + auto Cjr = this->Cjr(); + CellValue<double> Vj(m_mesh.connectivity()); parallel_for( m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { @@ -87,7 +91,7 @@ class MeshData : public IMeshData const auto& cell_nodes = cell_to_node_matrix[j]; for (size_t R = 0; R < cell_nodes.size(); ++R) { - sum_cjr_xr += (xr[cell_nodes[R]], (*m_Cjr)(j, R)); + sum_cjr_xr += (xr[cell_nodes[R]], Cjr(j, R)); } Vj[j] = inv_Dimension * sum_cjr_xr; }); @@ -96,43 +100,13 @@ class MeshData : public IMeshData PUGS_INLINE void - _updateCjr() + _computeNlr() { if constexpr (Dimension == 1) { - // Cjr/njr/ljr are constant overtime + static_assert(Dimension != 1, "Nlr does not make sense in 1d"); } else if constexpr (Dimension == 2) { - const NodeValue<const Rd>& xr = m_mesh.xr(); - const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix(); - - { - NodeValuePerCell<Rd> Cjr(m_mesh.connectivity()); - parallel_for( - m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { - const auto& cell_nodes = cell_to_node_matrix[j]; - for (size_t R = 0; R < cell_nodes.size(); ++R) { - int Rp1 = (R + 1) % cell_nodes.size(); - int Rm1 = (R + cell_nodes.size() - 1) % cell_nodes.size(); - Rd half_xrp_xrm = 0.5 * (xr[cell_nodes[Rp1]] - xr[cell_nodes[Rm1]]); - Cjr(j, R) = Rd{half_xrp_xrm[1], -half_xrp_xrm[0]}; - } - }); - m_Cjr = std::make_shared<NodeValuePerCell<const Rd>>(Cjr); - } - - { - NodeValuePerCell<double> ljr(m_mesh.connectivity()); - parallel_for( - m_Cjr->numberOfValues(), PUGS_LAMBDA(size_t jr) { ljr[jr] = l2Norm((*m_Cjr)[jr]); }); - m_ljr = std::make_shared<NodeValuePerCell<const double>>(ljr); - } - - { - NodeValuePerCell<Rd> njr(m_mesh.connectivity()); - parallel_for( - m_Cjr->numberOfValues(), PUGS_LAMBDA(size_t jr) { njr[jr] = (1. / (*m_ljr)[jr]) * (*m_Cjr)[jr]; }); - m_njr = std::make_shared<NodeValuePerCell<const Rd>>(njr); - } - } else if (Dimension == 3) { + throw NotImplementedError("Nlr are not yet computed in 2d"); + } else { const NodeValue<const Rd>& xr = m_mesh.xr(); NodeValuePerFace<Rd> Nlr(m_mesh.connectivity()); @@ -158,78 +132,133 @@ class MeshData : public IMeshData Nlr(l, r) = Nr; } }); + m_Nlr = std::make_shared<NodeValuePerFace<const Rd>>(Nlr); + } + } + PUGS_INLINE + void + _computeCjr() + { + if constexpr (Dimension == 1) { + NodeValuePerCell<Rd> Cjr(m_mesh.connectivity()); + parallel_for( + m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { + Cjr(j, 0) = -1; + Cjr(j, 1) = 1; + }); + m_Cjr = std::make_shared<NodeValuePerCell<const Rd>>(Cjr); + } else if constexpr (Dimension == 2) { + const NodeValue<const Rd>& xr = m_mesh.xr(); const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix(); - const auto& cell_to_face_matrix = m_mesh.connectivity().cellToFaceMatrix(); + NodeValuePerCell<Rd> Cjr(m_mesh.connectivity()); + parallel_for( + m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { + const auto& cell_nodes = cell_to_node_matrix[j]; + for (size_t R = 0; R < cell_nodes.size(); ++R) { + int Rp1 = (R + 1) % cell_nodes.size(); + int Rm1 = (R + cell_nodes.size() - 1) % cell_nodes.size(); + Rd half_xrp_xrm = 0.5 * (xr[cell_nodes[Rp1]] - xr[cell_nodes[Rm1]]); + Cjr(j, R) = Rd{half_xrp_xrm[1], -half_xrp_xrm[0]}; + } + }); + m_Cjr = std::make_shared<NodeValuePerCell<const Rd>>(Cjr); + } else if (Dimension == 3) { + auto Nlr = this->Nlr(); + const auto& face_to_node_matrix = m_mesh.connectivity().faceToNodeMatrix(); + const auto& cell_to_node_matrix = m_mesh.connectivity().cellToNodeMatrix(); + const auto& cell_to_face_matrix = m_mesh.connectivity().cellToFaceMatrix(); const auto& cell_face_is_reversed = m_mesh.connectivity().cellFaceIsReversed(); - { - NodeValuePerCell<Rd> Cjr(m_mesh.connectivity()); - parallel_for( - Cjr.numberOfValues(), PUGS_LAMBDA(size_t jr) { Cjr[jr] = zero; }); + NodeValuePerCell<Rd> Cjr(m_mesh.connectivity()); + parallel_for( + Cjr.numberOfValues(), PUGS_LAMBDA(size_t jr) { Cjr[jr] = zero; }); - parallel_for( - m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { - const auto& cell_nodes = cell_to_node_matrix[j]; + parallel_for( + m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { + const auto& cell_nodes = cell_to_node_matrix[j]; - const auto& cell_faces = cell_to_face_matrix[j]; - const auto& face_is_reversed = cell_face_is_reversed.itemValues(j); + const auto& cell_faces = cell_to_face_matrix[j]; + const auto& face_is_reversed = cell_face_is_reversed.itemValues(j); - for (size_t L = 0; L < cell_faces.size(); ++L) { - const FaceId& l = cell_faces[L]; - const auto& face_nodes = face_to_node_matrix[l]; + for (size_t L = 0; L < cell_faces.size(); ++L) { + const FaceId& l = cell_faces[L]; + const auto& face_nodes = face_to_node_matrix[l]; - auto local_node_number_in_cell = [&](NodeId node_number) { - for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) { - if (node_number == cell_nodes[i_node]) { - return i_node; - } + auto local_node_number_in_cell = [&](NodeId node_number) { + for (size_t i_node = 0; i_node < cell_nodes.size(); ++i_node) { + if (node_number == cell_nodes[i_node]) { + return i_node; } - return std::numeric_limits<size_t>::max(); - }; + } + return std::numeric_limits<size_t>::max(); + }; - if (face_is_reversed[L]) { - for (size_t rl = 0; rl < face_nodes.size(); ++rl) { - const size_t R = local_node_number_in_cell(face_nodes[rl]); - Cjr(j, R) -= Nlr(l, rl); - } - } else { - for (size_t rl = 0; rl < face_nodes.size(); ++rl) { - const size_t R = local_node_number_in_cell(face_nodes[rl]); - Cjr(j, R) += Nlr(l, rl); - } + if (face_is_reversed[L]) { + for (size_t rl = 0; rl < face_nodes.size(); ++rl) { + const size_t R = local_node_number_in_cell(face_nodes[rl]); + Cjr(j, R) -= Nlr(l, rl); + } + } else { + for (size_t rl = 0; rl < face_nodes.size(); ++rl) { + const size_t R = local_node_number_in_cell(face_nodes[rl]); + Cjr(j, R) += Nlr(l, rl); } } - }); + } + }); - m_Cjr = std::make_shared<NodeValuePerCell<const Rd>>(Cjr); - } + m_Cjr = std::make_shared<NodeValuePerCell<const Rd>>(Cjr); + } + } - { - NodeValuePerCell<double> ljr(m_mesh.connectivity()); - parallel_for( - m_Cjr->numberOfValues(), PUGS_LAMBDA(size_t jr) { ljr[jr] = l2Norm((*m_Cjr)[jr]); }); - m_ljr = std::make_shared<NodeValuePerCell<const double>>(ljr); - } + PUGS_INLINE + void + _compute_ljr() + { + auto Cjr = this->Cjr(); + if constexpr (Dimension == 1) { + NodeValuePerCell<double> ljr(m_mesh.connectivity()); + parallel_for( + ljr.numberOfValues(), PUGS_LAMBDA(size_t jr) { ljr[jr] = 1; }); + m_ljr = std::make_shared<NodeValuePerCell<const double>>(ljr); - { - NodeValuePerCell<Rd> njr(m_mesh.connectivity()); - parallel_for( - m_Cjr->numberOfValues(), PUGS_LAMBDA(size_t jr) { njr[jr] = (1. / (*m_ljr)[jr]) * (*m_Cjr)[jr]; }); - m_njr = std::make_shared<NodeValuePerCell<const Rd>>(njr); - } + } else { + NodeValuePerCell<double> ljr(m_mesh.connectivity()); + parallel_for( + Cjr.numberOfValues(), PUGS_LAMBDA(size_t jr) { ljr[jr] = l2Norm(Cjr[jr]); }); + m_ljr = std::make_shared<NodeValuePerCell<const double>>(ljr); } - static_assert((Dimension <= 3), "only 1d, 2d and 3d are implemented"); } + PUGS_INLINE void - _checkCellVolume() const + _compute_njr() { + auto Cjr = this->Cjr(); + if constexpr (Dimension == 1) { + // in 1d njr=Cjr (here performs a shallow copy) + m_njr = m_Cjr; + } else { + auto ljr = this->ljr(); + + NodeValuePerCell<Rd> njr(m_mesh.connectivity()); + parallel_for( + Cjr.numberOfValues(), PUGS_LAMBDA(size_t jr) { njr[jr] = (1. / ljr[jr]) * Cjr[jr]; }); + m_njr = std::make_shared<NodeValuePerCell<const Rd>>(njr); + } + } + + void + _checkCellVolume() + { + auto Vj = this->Vj(); + bool is_valid = [&] { for (CellId j = 0; j < m_mesh.numberOfCells(); ++j) { - if ((*m_Vj)[j] <= 0) { + if (Vj[j] <= 0) { return false; } } @@ -250,76 +279,73 @@ class MeshData : public IMeshData } PUGS_INLINE - const NodeValuePerCell<const Rd> - Cjr() const + NodeValuePerFace<const Rd> + Nlr() + { + if (not m_Nlr) { + this->_computeNlr(); + } + return *m_Nlr; + } + + PUGS_INLINE + NodeValuePerCell<const Rd> + Cjr() { + if (not m_Cjr) { + this->_computeCjr(); + } return *m_Cjr; } PUGS_INLINE - const NodeValuePerCell<const double> - ljr() const + NodeValuePerCell<const double> + ljr() { + if (not m_ljr) { + this->_compute_ljr(); + } return *m_ljr; } PUGS_INLINE - const NodeValuePerCell<const Rd> - njr() const + NodeValuePerCell<const Rd> + njr() { + if (not m_njr) { + this->_compute_njr(); + } return *m_njr; } PUGS_INLINE - const CellValue<const Rd> + CellValue<const Rd> xj() { if (not m_xj) { - this->_updateCenter(); + this->_computeIsobarycenter(); } return *m_xj; } PUGS_INLINE - const CellValue<const double> - Vj() const + CellValue<const double> + Vj() { + if (not m_Vj) { + this->_computeCellVolume(); + this->_checkCellVolume(); + } return *m_Vj; } void updateAllData() { - this->_updateCjr(); - // this->_updateCenter(); - this->_updateVolume(); - this->_checkCellVolume(); + ; } - MeshData(const MeshType& mesh) : m_mesh(mesh) - { - if constexpr (Dimension == 1) { - // in 1d Cjr are computed once for all - { - NodeValuePerCell<Rd> Cjr(m_mesh.connectivity()); - parallel_for( - m_mesh.numberOfCells(), PUGS_LAMBDA(CellId j) { - Cjr(j, 0) = -1; - Cjr(j, 1) = 1; - }); - m_Cjr = std::make_shared<NodeValuePerCell<const Rd>>(Cjr); - } - // in 1d njr=Cjr (here performs a shallow copy) - m_njr = m_Cjr; - { - NodeValuePerCell<double> ljr(m_mesh.connectivity()); - parallel_for( - ljr.numberOfValues(), PUGS_LAMBDA(size_t jr) { ljr[jr] = 1; }); - m_ljr = std::make_shared<NodeValuePerCell<const double>>(ljr); - } - } - this->updateAllData(); - } + MeshData(const MeshType& mesh) : m_mesh(mesh) {} MeshData() = delete; diff --git a/src/scheme/AcousticSolver.hpp b/src/scheme/AcousticSolver.hpp index c531154bd5db52a3f102dfc8e0dd455157e01351..971c8fd2458c35d55013a084a4919d7dce026ad6 100644 --- a/src/scheme/AcousticSolver.hpp +++ b/src/scheme/AcousticSolver.hpp @@ -279,7 +279,7 @@ class AcousticSolver CellValue<double>& pj = unknowns.pj(); CellValue<double>& cj = unknowns.cj(); - const MeshData<Dimension>& mesh_data = MeshDataManager::instance().getMeshData(*m_mesh); + MeshData<Dimension>& mesh_data = MeshDataManager::instance().getMeshData(*m_mesh); const CellValue<const double> Vj = mesh_data.Vj(); const NodeValuePerCell<const Rd> Cjr = mesh_data.Cjr();