diff --git a/src/language/modules/MeshModule.cpp b/src/language/modules/MeshModule.cpp index b9a65729637128081a7206ad6fa5d98ad95e9978..89e678c3fb4095350842b19a9145502cd7f558a8 100644 --- a/src/language/modules/MeshModule.cpp +++ b/src/language/modules/MeshModule.cpp @@ -9,7 +9,7 @@ #include <language/utils/TypeDescriptor.hpp> #include <mesh/CartesianMeshBuilder.hpp> #include <mesh/Connectivity.hpp> -#include <mesh/DiamondDualMeshBuilder.hpp> +#include <mesh/DiamondDualMeshManager.hpp> #include <mesh/GmshReader.hpp> #include <mesh/Mesh.hpp> #include <utils/Exceptions.hpp> @@ -184,9 +184,30 @@ MeshModule::MeshModule() std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>( const std::shared_ptr<const IMesh>&)>>( - [](const std::shared_ptr<const IMesh>& p_mesh) -> std::shared_ptr<const IMesh> { - DiamondDualMeshBuilder builder{p_mesh}; - return builder.mesh(); + [](const std::shared_ptr<const IMesh>& i_mesh) -> std::shared_ptr<const IMesh> { + switch (i_mesh->dimension()) { + case 1: { + using MeshType = Mesh<Connectivity<1>>; + + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh); + return DiamondDualMeshManager::instance().getDiamondDualMesh(p_mesh); + } + case 2: { + using MeshType = Mesh<Connectivity<2>>; + + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh); + return DiamondDualMeshManager::instance().getDiamondDualMesh(p_mesh); + } + case 3: { + using MeshType = Mesh<Connectivity<3>>; + + std::shared_ptr p_mesh = std::dynamic_pointer_cast<const MeshType>(i_mesh); + return DiamondDualMeshManager::instance().getDiamondDualMesh(p_mesh); + } + default: { + throw UnexpectedError("invalid dimension"); + } + } } )); diff --git a/src/main.cpp b/src/main.cpp index 9b853028133fd9035f67f743c62ee2a0a298202a..aad67d58a5d228cdc502e9b024cfc497fef23291 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,8 @@ #include <utils/PugsUtils.hpp> #include <language/PugsParser.hpp> +#include <mesh/DiamondDualConnectivityManager.hpp> +#include <mesh/DiamondDualMeshManager.hpp> #include <mesh/MeshDataManager.hpp> #include <mesh/SynchronizerManager.hpp> @@ -11,9 +13,13 @@ main(int argc, char* argv[]) SynchronizerManager::create(); MeshDataManager::create(); + DiamondDualConnectivityManager::create(); + DiamondDualMeshManager::create(); parser(filename); + DiamondDualMeshManager::destroy(); + DiamondDualConnectivityManager::destroy(); MeshDataManager::destroy(); SynchronizerManager::destroy(); finalize(); diff --git a/src/mesh/CMakeLists.txt b/src/mesh/CMakeLists.txt index 92c865c599767db0d5e5fed84e7d16d0cbec8579..6c0088831c86023e31914b953c9ea137e5411d21 100644 --- a/src/mesh/CMakeLists.txt +++ b/src/mesh/CMakeLists.txt @@ -8,8 +8,11 @@ add_library( ConnectivityComputer.cpp ConnectivityDispatcher.cpp DiamondDualConnectivityBuilder.cpp + DiamondDualConnectivityManager.cpp DiamondDualMeshBuilder.cpp + DiamondDualMeshManager.cpp GmshReader.cpp + IConnectivity.cpp IMesh.cpp LogicalConnectivityBuilder.cpp MeshBuilderBase.cpp diff --git a/src/mesh/Connectivity.hpp b/src/mesh/Connectivity.hpp index 5a888190841e7886d4548a5405dc3126223318ac..3bf5cd4201c574749e5b6a67a2b6c4d667bd88f1 100644 --- a/src/mesh/Connectivity.hpp +++ b/src/mesh/Connectivity.hpp @@ -12,7 +12,6 @@ #include <mesh/RefId.hpp> #include <mesh/RefItemList.hpp> #include <mesh/SubItemValuePerItem.hpp> -#include <mesh/SynchronizerManager.hpp> #include <utils/CSRGraph.hpp> #include <utils/Exceptions.hpp> #include <utils/PugsAssert.hpp> @@ -651,11 +650,7 @@ class Connectivity final : public IConnectivity void _buildFrom(const ConnectivityDescriptor& descriptor); public: - ~Connectivity() - { - auto& manager = SynchronizerManager::instance(); - manager.deleteConnectivitySynchronizer(this); - } + ~Connectivity() = default; }; template <size_t Dim> diff --git a/src/mesh/DiamondDualConnectivityBuilder.hpp b/src/mesh/DiamondDualConnectivityBuilder.hpp index 670372df9e53d3bfa8dd3f1b03545d9264b41dc4..e0c18457a20f5317a8e775535a2b5ee4f44bce60 100644 --- a/src/mesh/DiamondDualConnectivityBuilder.hpp +++ b/src/mesh/DiamondDualConnectivityBuilder.hpp @@ -18,8 +18,10 @@ class DiamondDualConnectivityBuilder : public ConnectivityBuilderBase template <size_t Dimension> void _buildDiamondConnectivityFrom(const IConnectivity&); - public: + friend class DiamondDualConnectivityManager; DiamondDualConnectivityBuilder(const IConnectivity&); + + public: ~DiamondDualConnectivityBuilder() = default; }; diff --git a/src/mesh/DiamondDualConnectivityManager.cpp b/src/mesh/DiamondDualConnectivityManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2f0ff4019f90a6db20a6ad75abda52df289fd243 --- /dev/null +++ b/src/mesh/DiamondDualConnectivityManager.cpp @@ -0,0 +1,66 @@ +#include <utils/PugsAssert.hpp> + +#include <mesh/Connectivity.hpp> +#include <mesh/DiamondDualConnectivityBuilder.hpp> +#include <mesh/DiamondDualConnectivityManager.hpp> +#include <utils/Exceptions.hpp> + +#include <sstream> + +DiamondDualConnectivityManager* DiamondDualConnectivityManager::m_instance{nullptr}; + +void +DiamondDualConnectivityManager::create() +{ + Assert(m_instance == nullptr, "DiamondDualConnectivityManager is already created"); + m_instance = new DiamondDualConnectivityManager; +} + +void +DiamondDualConnectivityManager::destroy() +{ + Assert(m_instance != nullptr, "DiamondDualConnectivityManager was not created!"); + + if (m_instance->m_connectivity_to_diamond_dual_connectivity_map.size() > 0) { + std::stringstream error; + error << ": some connectivities are still registered\n"; + for (const auto& i_mesh_data : m_instance->m_connectivity_to_diamond_dual_connectivity_map) { + error << " - connectivity " << rang::fgB::magenta << i_mesh_data.first << rang::style::reset << '\n'; + } + throw UnexpectedError(error.str()); + } + delete m_instance; + m_instance = nullptr; +} + +void +DiamondDualConnectivityManager::deleteConnectivity(const IConnectivity* p_connectivity) +{ + m_connectivity_to_diamond_dual_connectivity_map.erase(p_connectivity); +} + +template <size_t Dimension> +std::shared_ptr<const Connectivity<Dimension>> +DiamondDualConnectivityManager::getDiamondDualConnectivity(const Connectivity<Dimension>& connectivity) +{ + const IConnectivity* p_connectivity = &connectivity; + + if (auto i_mesh_data = m_connectivity_to_diamond_dual_connectivity_map.find(p_connectivity); + i_mesh_data != m_connectivity_to_diamond_dual_connectivity_map.end()) { + return std::dynamic_pointer_cast<const Connectivity<Dimension>>(i_mesh_data->second); + } else { + DiamondDualConnectivityBuilder builder{connectivity}; + + m_connectivity_to_diamond_dual_connectivity_map[p_connectivity] = builder.connectivity(); + return std::dynamic_pointer_cast<const Connectivity<Dimension>>(builder.connectivity()); + } +} + +template std::shared_ptr<const Connectivity<1>> DiamondDualConnectivityManager::getDiamondDualConnectivity( + const Connectivity<1>& connectivity); + +template std::shared_ptr<const Connectivity<2>> DiamondDualConnectivityManager::getDiamondDualConnectivity( + const Connectivity<2>& connectivity); + +template std::shared_ptr<const Connectivity<3>> DiamondDualConnectivityManager::getDiamondDualConnectivity( + const Connectivity<3>& connectivity); diff --git a/src/mesh/DiamondDualConnectivityManager.hpp b/src/mesh/DiamondDualConnectivityManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6c45d646256c63977be2535e30cf387aa7f6220a --- /dev/null +++ b/src/mesh/DiamondDualConnectivityManager.hpp @@ -0,0 +1,44 @@ +#ifndef DIAMOND_DUAL_CONNECTIVITY_MANAGER_HPP +#define DIAMOND_DUAL_CONNECTIVITY_MANAGER_HPP + +#include <mesh/IConnectivity.hpp> + +#include <memory> +#include <unordered_map> + +template <size_t Dimension> +class Connectivity; + +class DiamondDualConnectivityManager +{ + private: + std::unordered_map<const IConnectivity*, std::shared_ptr<const IConnectivity>> + m_connectivity_to_diamond_dual_connectivity_map; + + static DiamondDualConnectivityManager* m_instance; + + DiamondDualConnectivityManager(const DiamondDualConnectivityManager&) = delete; + DiamondDualConnectivityManager(DiamondDualConnectivityManager&&) = delete; + + DiamondDualConnectivityManager() = default; + ~DiamondDualConnectivityManager() = default; + + public: + static void create(); + static void destroy(); + + PUGS_INLINE + static DiamondDualConnectivityManager& + instance() + { + Assert(m_instance != nullptr, "DiamondDualConnectivityManager was not created!"); + return *m_instance; + } + + void deleteConnectivity(const IConnectivity*); + + template <size_t Dimension> + std::shared_ptr<const Connectivity<Dimension>> getDiamondDualConnectivity(const Connectivity<Dimension>&); +}; + +#endif // DIAMOND_DUAL_CONNECTIVITY_MANAGER_HPP diff --git a/src/mesh/DiamondDualMeshBuilder.cpp b/src/mesh/DiamondDualMeshBuilder.cpp index 2218541b338e196a913b3c0859b882ad668d252e..3865414c1dcf51e42dbf19aa69e4eb63474e2ce1 100644 --- a/src/mesh/DiamondDualMeshBuilder.cpp +++ b/src/mesh/DiamondDualMeshBuilder.cpp @@ -1,10 +1,10 @@ #include <mesh/DiamondDualMeshBuilder.hpp> -#include <mesh/DiamondDualConnectivityBuilder.hpp> - #include <mesh/Connectivity.hpp> #include <mesh/ConnectivityDescriptor.hpp> #include <mesh/ConnectivityDispatcher.hpp> +#include <mesh/DiamondDualConnectivityBuilder.hpp> +#include <mesh/DiamondDualConnectivityManager.hpp> #include <mesh/ItemValueUtils.hpp> #include <mesh/Mesh.hpp> #include <mesh/MeshData.hpp> @@ -77,15 +77,19 @@ DiamondDualMeshBuilder::_buildDualDiamondMeshFrom(const Mesh<Connectivity<1>>& p DiamondDualMeshBuilder::DiamondDualMeshBuilder(const std::shared_ptr<const IMesh>& p_mesh) { + std::cout << "building DiamondDualMesh\n"; + switch (p_mesh->dimension()) { case 1: { using ConnectivityType = Connectivity<1>; using MeshType = Mesh<ConnectivityType>; std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(p_mesh); - DiamondDualConnectivityBuilder builder(mesh->connectivity()); - std::shared_ptr p_diamond_connectivity = std::dynamic_pointer_cast<const ConnectivityType>(builder.connectivity()); + DiamondDualConnectivityManager& manager = DiamondDualConnectivityManager::instance(); + + std::shared_ptr<const ConnectivityType> p_diamond_connectivity = + manager.getDiamondDualConnectivity(mesh->connectivity()); this->_buildDualDiamondMeshFrom(*mesh, p_diamond_connectivity); break; @@ -95,9 +99,11 @@ DiamondDualMeshBuilder::DiamondDualMeshBuilder(const std::shared_ptr<const IMesh using MeshType = Mesh<ConnectivityType>; std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(p_mesh); - DiamondDualConnectivityBuilder builder(mesh->connectivity()); - std::shared_ptr p_diamond_connectivity = std::dynamic_pointer_cast<const ConnectivityType>(builder.connectivity()); + DiamondDualConnectivityManager& manager = DiamondDualConnectivityManager::instance(); + + std::shared_ptr<const ConnectivityType> p_diamond_connectivity = + manager.getDiamondDualConnectivity(mesh->connectivity()); this->_buildDualDiamondMeshFrom(*mesh, p_diamond_connectivity); break; @@ -107,9 +113,11 @@ DiamondDualMeshBuilder::DiamondDualMeshBuilder(const std::shared_ptr<const IMesh using MeshType = Mesh<ConnectivityType>; std::shared_ptr mesh = std::dynamic_pointer_cast<const MeshType>(p_mesh); - DiamondDualConnectivityBuilder builder(mesh->connectivity()); - std::shared_ptr p_diamond_connectivity = std::dynamic_pointer_cast<const ConnectivityType>(builder.connectivity()); + DiamondDualConnectivityManager& manager = DiamondDualConnectivityManager::instance(); + + std::shared_ptr<const ConnectivityType> p_diamond_connectivity = + manager.getDiamondDualConnectivity(mesh->connectivity()); this->_buildDualDiamondMeshFrom(*mesh, p_diamond_connectivity); break; diff --git a/src/mesh/DiamondDualMeshBuilder.hpp b/src/mesh/DiamondDualMeshBuilder.hpp index ded3cfb0f40ca4d1b1bd9dc06f7981391f9401c6..cdb0d7a1c5433692fe3e66de6aa925bf6a36f16f 100644 --- a/src/mesh/DiamondDualMeshBuilder.hpp +++ b/src/mesh/DiamondDualMeshBuilder.hpp @@ -18,8 +18,10 @@ class DiamondDualMeshBuilder : public MeshBuilderBase void _buildDualDiamondMeshFrom(const Mesh<Connectivity<Dimension>>&, const std::shared_ptr<const Connectivity<Dimension>>&); - public: + friend class DiamondDualMeshManager; DiamondDualMeshBuilder(const std::shared_ptr<const IMesh>&); + + public: ~DiamondDualMeshBuilder() = default; }; diff --git a/src/mesh/DiamondDualMeshManager.cpp b/src/mesh/DiamondDualMeshManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0619736753f2b49a4229c60492ea6fd4c0de7212 --- /dev/null +++ b/src/mesh/DiamondDualMeshManager.cpp @@ -0,0 +1,65 @@ +#include <mesh/DiamondDualMeshManager.hpp> + +#include <mesh/Connectivity.hpp> +#include <mesh/DiamondDualMeshBuilder.hpp> +#include <mesh/Mesh.hpp> +#include <utils/Exceptions.hpp> +#include <utils/PugsAssert.hpp> + +#include <sstream> + +DiamondDualMeshManager* DiamondDualMeshManager::m_instance{nullptr}; + +void +DiamondDualMeshManager::create() +{ + Assert(m_instance == nullptr, "DiamondDualMeshManager is already created"); + m_instance = new DiamondDualMeshManager; +} + +void +DiamondDualMeshManager::destroy() +{ + Assert(m_instance != nullptr, "DiamondDualMeshManager was not created!"); + + if (m_instance->m_mesh_to_diamond_dual_mesh_map.size() > 0) { + std::stringstream error; + error << ": some meshes are still registered\n"; + for (const auto& i_mesh_data : m_instance->m_mesh_to_diamond_dual_mesh_map) { + error << " - mesh " << rang::fgB::magenta << i_mesh_data.first << rang::style::reset << '\n'; + } + throw UnexpectedError(error.str()); + } + delete m_instance; + m_instance = nullptr; +} + +void +DiamondDualMeshManager::deleteMesh(const IMesh* p_mesh) +{ + m_mesh_to_diamond_dual_mesh_map.erase(p_mesh); +} + +template <size_t Dimension> +std::shared_ptr<const Mesh<Connectivity<Dimension>>> +DiamondDualMeshManager::getDiamondDualMesh(std::shared_ptr<const Mesh<Connectivity<Dimension>>> mesh) +{ + const IMesh* p_mesh = mesh.get(); + + if (auto i_mesh_data = m_mesh_to_diamond_dual_mesh_map.find(p_mesh); + i_mesh_data != m_mesh_to_diamond_dual_mesh_map.end()) { + return std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(i_mesh_data->second); + } else { + DiamondDualMeshBuilder builder{mesh}; + + m_mesh_to_diamond_dual_mesh_map[p_mesh] = builder.mesh(); + return std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(builder.mesh()); + } +} + +template std::shared_ptr<const Mesh<Connectivity<1>>> DiamondDualMeshManager::getDiamondDualMesh( + std::shared_ptr<const Mesh<Connectivity<1>>>); +template std::shared_ptr<const Mesh<Connectivity<2>>> DiamondDualMeshManager::getDiamondDualMesh( + std::shared_ptr<const Mesh<Connectivity<2>>>); +template std::shared_ptr<const Mesh<Connectivity<3>>> DiamondDualMeshManager::getDiamondDualMesh( + std::shared_ptr<const Mesh<Connectivity<3>>>); diff --git a/src/mesh/DiamondDualMeshManager.hpp b/src/mesh/DiamondDualMeshManager.hpp new file mode 100644 index 0000000000000000000000000000000000000000..9f802eb96d13704235f50e82ad75e84ba9be8a64 --- /dev/null +++ b/src/mesh/DiamondDualMeshManager.hpp @@ -0,0 +1,49 @@ +#ifndef DIAMOND_DUAL_MESH_MANAGER_HPP +#define DIAMOND_DUAL_MESH_MANAGER_HPP + +#include <mesh/IMesh.hpp> +#include <utils/PugsAssert.hpp> +#include <utils/PugsMacros.hpp> + +#include <memory> +#include <unordered_map> + +template <size_t Dimension> +class Connectivity; + +template <typename ConnectivityType> +class Mesh; + +class DiamondDualMeshManager +{ + private: + std::unordered_map<const IMesh*, std::shared_ptr<const IMesh>> m_mesh_to_diamond_dual_mesh_map; + + static DiamondDualMeshManager* m_instance; + + DiamondDualMeshManager(const DiamondDualMeshManager&) = delete; + DiamondDualMeshManager(DiamondDualMeshManager&&) = delete; + + DiamondDualMeshManager() = default; + ~DiamondDualMeshManager() = default; + + public: + static void create(); + static void destroy(); + + PUGS_INLINE + static DiamondDualMeshManager& + instance() + { + Assert(m_instance != nullptr, "DiamondDualMeshManager was not created!"); + return *m_instance; + } + + void deleteMesh(const IMesh*); + + template <size_t Dimension> + std::shared_ptr<const Mesh<Connectivity<Dimension>>> getDiamondDualMesh( + std::shared_ptr<const Mesh<Connectivity<Dimension>>>); +}; + +#endif // DIAMOND_DUAL_MESH_MANAGER_HPP diff --git a/src/mesh/IConnectivity.cpp b/src/mesh/IConnectivity.cpp new file mode 100644 index 0000000000000000000000000000000000000000..48cf57d55ebceb7818f755fd9214807a247f6575 --- /dev/null +++ b/src/mesh/IConnectivity.cpp @@ -0,0 +1,10 @@ +#include <mesh/IConnectivity.hpp> + +#include <mesh/DiamondDualConnectivityManager.hpp> +#include <mesh/SynchronizerManager.hpp> + +IConnectivity::~IConnectivity() +{ + SynchronizerManager::instance().deleteConnectivitySynchronizer(this); + DiamondDualConnectivityManager::instance().deleteConnectivity(this); +} diff --git a/src/mesh/IConnectivity.hpp b/src/mesh/IConnectivity.hpp index 27be707cbcc4976b17e9db1e7bf6f37195c9d63a..9bfb8e5043088a18880440235cd72b1677c1f519 100644 --- a/src/mesh/IConnectivity.hpp +++ b/src/mesh/IConnectivity.hpp @@ -35,7 +35,7 @@ class IConnectivity : public std::enable_shared_from_this<IConnectivity> IConnectivity() = default; IConnectivity(IConnectivity&&) = delete; IConnectivity(const IConnectivity&) = delete; - ~IConnectivity() = default; + virtual ~IConnectivity(); }; template <> diff --git a/src/mesh/IMesh.cpp b/src/mesh/IMesh.cpp index cb2accc141ed09c778237587373494797fee726d..f315f4b74b01eb371c42eb4bf029f81e93ae6016 100644 --- a/src/mesh/IMesh.cpp +++ b/src/mesh/IMesh.cpp @@ -1,8 +1,10 @@ #include <mesh/IMesh.hpp> +#include <mesh/DiamondDualMeshManager.hpp> #include <mesh/MeshDataManager.hpp> IMesh::~IMesh() { - MeshDataManager::instance().deleteMeshData(*this); + MeshDataManager::instance().deleteMeshData(this); + DiamondDualMeshManager::instance().deleteMesh(this); } diff --git a/src/mesh/MeshDataManager.cpp b/src/mesh/MeshDataManager.cpp index 281e7517aa704e6c4352769e88f854b86cbc7366..8ca184a6013c083f5e8df7412d19f80b8f50f95a 100644 --- a/src/mesh/MeshDataManager.cpp +++ b/src/mesh/MeshDataManager.cpp @@ -35,9 +35,9 @@ MeshDataManager::destroy() } void -MeshDataManager::deleteMeshData(const IMesh& mesh) +MeshDataManager::deleteMeshData(const IMesh* p_mesh) { - m_mesh_mesh_data_map.erase(&mesh); + m_mesh_mesh_data_map.erase(p_mesh); } template <size_t Dimension> diff --git a/src/mesh/MeshDataManager.hpp b/src/mesh/MeshDataManager.hpp index 31beecb1b16c95ae5d151c26de7486460a6dcedb..fd04101dea29a2d15e0feb2193f22f785ff65dc3 100644 --- a/src/mesh/MeshDataManager.hpp +++ b/src/mesh/MeshDataManager.hpp @@ -44,7 +44,7 @@ class MeshDataManager return *m_instance; } - void deleteMeshData(const IMesh&); + void deleteMeshData(const IMesh*); template <size_t Dimension> MeshData<Dimension>& getMeshData(const Mesh<Connectivity<Dimension>>&);