diff --git a/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp b/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp index 8d35d2ff9541fbfab7e8e6e30976bd5f88970f56..ae67abf3c10b977b2ecaac8e8eda71cf4f99492e 100644 --- a/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp +++ b/src/mesh/ConnectivityToDiamondDualConnectivityDataMapper.hpp @@ -2,23 +2,14 @@ #define CONNECTIVITY_TO_DIAMOND_DUAL_CONNECTIVITY_DATA_MAPPER_HPP #include <mesh/Connectivity.hpp> +#include <mesh/IConnectivityToDualConnectivityDataMapper.hpp> #include <mesh/ItemIdToItemIdMap.hpp> #include <mesh/ItemValue.hpp> #include <utils/Array.hpp> #include <utils/PugsAssert.hpp> -class IConnectivityToDiamondDualConnectivityDataMapper -{ - public: - IConnectivityToDiamondDualConnectivityDataMapper(const IConnectivityToDiamondDualConnectivityDataMapper&) = delete; - IConnectivityToDiamondDualConnectivityDataMapper(IConnectivityToDiamondDualConnectivityDataMapper&&) = delete; - - IConnectivityToDiamondDualConnectivityDataMapper() = default; - virtual ~IConnectivityToDiamondDualConnectivityDataMapper() = default; -}; - template <size_t Dimension> -class ConnectivityToDiamondDualConnectivityDataMapper : public IConnectivityToDiamondDualConnectivityDataMapper +class ConnectivityToDiamondDualConnectivityDataMapper : public IConnectivityToDualConnectivityDataMapper { private: const IConnectivity* m_primal_connectivity; diff --git a/src/mesh/DiamondDualConnectivityBuilder.hpp b/src/mesh/DiamondDualConnectivityBuilder.hpp index f6768af63fd7c4ab9f03370acdb9dcdeb64e864c..1ce888e24d9aaff77a60ad68cfafe4f74fe0b678 100644 --- a/src/mesh/DiamondDualConnectivityBuilder.hpp +++ b/src/mesh/DiamondDualConnectivityBuilder.hpp @@ -2,6 +2,7 @@ #define DIAMOND_DUAL_CONNECTIVITY_BUILDER_HPP #include <mesh/ConnectivityBuilderBase.hpp> +#include <mesh/IConnectivityToDualConnectivityDataMapper.hpp> #include <mesh/ItemIdToItemIdMap.hpp> #include <memory> @@ -10,8 +11,6 @@ template <size_t> class Connectivity; class ConnectivityDescriptor; -class IConnectivityToDiamondDualConnectivityDataMapper; - class DiamondDualConnectivityBuilder : public ConnectivityBuilderBase { private: @@ -19,7 +18,7 @@ class DiamondDualConnectivityBuilder : public ConnectivityBuilderBase CellIdToNodeIdMap m_primal_cell_to_dual_node_map; FaceIdToCellIdMap m_primal_face_to_dual_cell_map; - std::shared_ptr<IConnectivityToDiamondDualConnectivityDataMapper> m_mapper; + std::shared_ptr<IConnectivityToDualConnectivityDataMapper> m_mapper; template <size_t Dimension> void _buildDiamondConnectivityDescriptor(const Connectivity<Dimension>&, ConnectivityDescriptor&); @@ -31,7 +30,7 @@ class DiamondDualConnectivityBuilder : public ConnectivityBuilderBase DiamondDualConnectivityBuilder(const IConnectivity&); public: - std::shared_ptr<IConnectivityToDiamondDualConnectivityDataMapper> + std::shared_ptr<IConnectivityToDualConnectivityDataMapper> mapper() const { return m_mapper; diff --git a/src/mesh/DualConnectivityManager.cpp b/src/mesh/DualConnectivityManager.cpp index c3a2011d8b2f8517cf9072edf6dbbf75e4a4e2e3..60a4279810ccdb19c3ff6f160a87839e09fb872b 100644 --- a/src/mesh/DualConnectivityManager.cpp +++ b/src/mesh/DualConnectivityManager.cpp @@ -22,12 +22,13 @@ DualConnectivityManager::destroy() { Assert(m_instance != nullptr, "DualConnectivityManager was not created!"); - if (m_instance->m_connectivity_to_diamond_dual_connectivity_info_map.size() > 0) { + if (m_instance->m_connectivity_to_dual_connectivity_info_map.size() > 0) { std::stringstream error; error << ": some connectivities are still registered\n"; - for (const auto& [connectivity, diamond_dual_connectivity_info] : - m_instance->m_connectivity_to_diamond_dual_connectivity_info_map) { - error << " - connectivity " << rang::fgB::magenta << connectivity << rang::style::reset << '\n'; + for (const auto& [key, diamond_dual_connectivity_info] : m_instance->m_connectivity_to_dual_connectivity_info_map) { + error << " - connectivity " << rang::fgB::magenta << key.second << rang::style::reset << ": " << name(key.first) + << " dual connectivity of " << rang::fgB::yellow << diamond_dual_connectivity_info.dualConnectivity().get() + << rang::style::reset << '\n'; } throw UnexpectedError(error.str()); } @@ -38,23 +39,35 @@ DualConnectivityManager::destroy() void DualConnectivityManager::deleteConnectivity(const IConnectivity* p_connectivity) { - m_connectivity_to_diamond_dual_connectivity_info_map.erase(p_connectivity); + bool has_removed = false; + do { + has_removed = false; + for (const auto& [key, dual_connectivity] : m_connectivity_to_dual_connectivity_info_map) { + const auto& [type, p_parent_connectivity] = key; + if (p_connectivity == p_parent_connectivity) { + m_connectivity_to_dual_connectivity_info_map.erase(key); + has_removed = true; + break; + } + } + } while (has_removed); } -DualConnectivityManager::DiamondDualConnectivityInfo -DualConnectivityManager::_getDiamondDualConnectivityInfo(const IConnectivity& connectivity) +DualConnectivityManager::DualConnectivityInfo +DualConnectivityManager::_getDualConnectivityInfo(const DualMeshType& type, const IConnectivity& connectivity) { const IConnectivity* p_connectivity = &connectivity; - if (auto i_connectivity = m_connectivity_to_diamond_dual_connectivity_info_map.find(p_connectivity); - i_connectivity != m_connectivity_to_diamond_dual_connectivity_info_map.end()) { + auto key = std::make_pair(type, p_connectivity); + if (auto i_connectivity = m_connectivity_to_dual_connectivity_info_map.find(key); + i_connectivity != m_connectivity_to_dual_connectivity_info_map.end()) { return i_connectivity->second; } else { DiamondDualConnectivityBuilder builder{connectivity}; - DiamondDualConnectivityInfo connectivity_info{builder.connectivity(), builder.mapper()}; + DualConnectivityInfo connectivity_info{builder.connectivity(), builder.mapper()}; - m_connectivity_to_diamond_dual_connectivity_info_map[p_connectivity] = connectivity_info; + m_connectivity_to_dual_connectivity_info_map[key] = connectivity_info; return connectivity_info; } @@ -65,15 +78,23 @@ std::shared_ptr<const Connectivity<Dimension>> DualConnectivityManager::getDiamondDualConnectivity(const Connectivity<Dimension>& connectivity) { return std::dynamic_pointer_cast<const Connectivity<Dimension>>( - this->_getDiamondDualConnectivityInfo(connectivity).diamondDualConnectivity()); + this->_getDualConnectivityInfo(DualMeshType::Diamond, connectivity).dualConnectivity()); } template <size_t Dimension> std::shared_ptr<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>> DualConnectivityManager::getConnectivityToDiamondDualConnectivityDataMapper(const Connectivity<Dimension>& connectivity) { - return std::dynamic_pointer_cast<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>( - this->_getDiamondDualConnectivityInfo(connectivity).connectivityToDiamondDualConnectivityDataMapper()); + auto i_data_mapper = + this->_getDualConnectivityInfo(DualMeshType::Diamond, connectivity).connectivityToDualConnectivityDataMapper(); + auto diamond_data_mapper = + std::dynamic_pointer_cast<const ConnectivityToDiamondDualConnectivityDataMapper<Dimension>>(i_data_mapper); + + if (diamond_data_mapper.use_count() > 0) { + return diamond_data_mapper; + } else { + throw UnexpectedError("invalid connectivity data mapper type"); + } } template std::shared_ptr<const Connectivity<1>> DualConnectivityManager::getDiamondDualConnectivity( diff --git a/src/mesh/DualConnectivityManager.hpp b/src/mesh/DualConnectivityManager.hpp index ef2812ea75c9271c3607d55d2414a7e45e27a245..eb6e0cad10862df32bf330deefab00b5c7aaf658 100644 --- a/src/mesh/DualConnectivityManager.hpp +++ b/src/mesh/DualConnectivityManager.hpp @@ -1,7 +1,9 @@ #ifndef DUAL_CONNECTIVITY_MANAGER_HPP #define DUAL_CONNECTIVITY_MANAGER_HPP +#include <mesh/DualMeshType.hpp> #include <mesh/IConnectivity.hpp> +#include <mesh/IConnectivityToDualConnectivityDataMapper.hpp> #include <memory> #include <unordered_map> @@ -9,57 +11,63 @@ template <size_t Dimension> class Connectivity; -class IConnectivityToDiamondDualConnectivityDataMapper; - template <size_t Dimension> class ConnectivityToDiamondDualConnectivityDataMapper; class DualConnectivityManager { private: - class DiamondDualConnectivityInfo + class DualConnectivityInfo { private: - std::shared_ptr<const IConnectivity> m_diamond_dual_connectivity; - std::shared_ptr<const IConnectivityToDiamondDualConnectivityDataMapper> - m_connectivity_to_diamond_dual_connectivity_data_mapper; + std::shared_ptr<const IConnectivity> m_dual_connectivity; + std::shared_ptr<const IConnectivityToDualConnectivityDataMapper> m_connectivity_to_dual_connectivity_data_mapper; public: PUGS_INLINE std::shared_ptr<const IConnectivity> - diamondDualConnectivity() const + dualConnectivity() const { - return m_diamond_dual_connectivity; + return m_dual_connectivity; } PUGS_INLINE - std::shared_ptr<const IConnectivityToDiamondDualConnectivityDataMapper> - connectivityToDiamondDualConnectivityDataMapper() + std::shared_ptr<const IConnectivityToDualConnectivityDataMapper> + connectivityToDualConnectivityDataMapper() { - return m_connectivity_to_diamond_dual_connectivity_data_mapper; + return m_connectivity_to_dual_connectivity_data_mapper; } - DiamondDualConnectivityInfo& operator=(const DiamondDualConnectivityInfo&) = default; - DiamondDualConnectivityInfo& operator=(DiamondDualConnectivityInfo&&) = default; + DualConnectivityInfo& operator=(const DualConnectivityInfo&) = default; + DualConnectivityInfo& operator=(DualConnectivityInfo&&) = default; - DiamondDualConnectivityInfo() = default; - DiamondDualConnectivityInfo(const DiamondDualConnectivityInfo&) = default; - DiamondDualConnectivityInfo(DiamondDualConnectivityInfo&&) = default; + DualConnectivityInfo() = default; + DualConnectivityInfo(const DualConnectivityInfo&) = default; + DualConnectivityInfo(DualConnectivityInfo&&) = default; - DiamondDualConnectivityInfo(const std::shared_ptr<const IConnectivity>& diamond_dual_connectivity, - const std::shared_ptr<const IConnectivityToDiamondDualConnectivityDataMapper>& - connectivity_to_diamond_dual_connectivity_data_mapper) - : m_diamond_dual_connectivity{diamond_dual_connectivity}, - m_connectivity_to_diamond_dual_connectivity_data_mapper{connectivity_to_diamond_dual_connectivity_data_mapper} + DualConnectivityInfo(const std::shared_ptr<const IConnectivity>& dual_connectivity, + const std::shared_ptr<const IConnectivityToDualConnectivityDataMapper>& + connectivity_to_dual_connectivity_data_mapper) + : m_dual_connectivity{dual_connectivity}, + m_connectivity_to_dual_connectivity_data_mapper{connectivity_to_dual_connectivity_data_mapper} {} - ~DiamondDualConnectivityInfo() = default; + ~DualConnectivityInfo() = default; }; - DiamondDualConnectivityInfo _getDiamondDualConnectivityInfo(const IConnectivity& connectivity); + DualConnectivityInfo _getDualConnectivityInfo(const DualMeshType& type, const IConnectivity& connectivity); + + using Key = std::pair<DualMeshType, const IConnectivity*>; + struct HashKey + { + size_t + operator()(const Key& key) const + { + return (std::hash<typename Key::first_type>()(key.first)) ^ (std::hash<typename Key::second_type>()(key.second)); + } + }; - std::unordered_map<const IConnectivity*, DiamondDualConnectivityInfo> - m_connectivity_to_diamond_dual_connectivity_info_map; + std::unordered_map<Key, DualConnectivityInfo, HashKey> m_connectivity_to_dual_connectivity_info_map; static DualConnectivityManager* m_instance; diff --git a/src/mesh/DualMeshManager.cpp b/src/mesh/DualMeshManager.cpp index 683cfbfb9c79af995c333b9b39ca05145f4bbe3c..cf903145b65709d53aec0210b731c57e51fe878d 100644 --- a/src/mesh/DualMeshManager.cpp +++ b/src/mesh/DualMeshManager.cpp @@ -22,11 +22,12 @@ DualMeshManager::destroy() { Assert(m_instance != nullptr, "DualMeshManager was not created!"); - if (m_instance->m_mesh_to_diamond_dual_mesh_map.size() > 0) { + if (m_instance->m_mesh_to_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'; + for (const auto& [key, parent_mesh] : m_instance->m_mesh_to_dual_mesh_map) { + error << " - mesh " << rang::fgB::magenta << key.second << rang::style::reset << ": " << name(key.first) + << " dual mesh of " << rang::fgB::yellow << parent_mesh.get() << rang::style::reset << '\n'; } throw UnexpectedError(error.str()); } @@ -37,7 +38,18 @@ DualMeshManager::destroy() void DualMeshManager::deleteMesh(const IMesh* p_mesh) { - m_mesh_to_diamond_dual_mesh_map.erase(p_mesh); + bool has_removed = false; + do { + has_removed = false; + for (const auto& [key, dual_mesh] : m_mesh_to_dual_mesh_map) { + const auto& [type, p_parent_mesh] = key; + if (p_mesh == p_parent_mesh) { + m_mesh_to_dual_mesh_map.erase(key); + has_removed = true; + break; + } + } + } while (has_removed); } template <size_t Dimension> @@ -46,13 +58,13 @@ DualMeshManager::getDiamondDualMesh(std::shared_ptr<const Mesh<Connectivity<Dime { 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()) { + auto key = std::make_pair(DualMeshType::Diamond, p_mesh); + if (auto i_mesh_data = m_mesh_to_dual_mesh_map.find(key); i_mesh_data != m_mesh_to_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(); + m_mesh_to_dual_mesh_map[key] = builder.mesh(); return std::dynamic_pointer_cast<const Mesh<Connectivity<Dimension>>>(builder.mesh()); } } diff --git a/src/mesh/DualMeshManager.hpp b/src/mesh/DualMeshManager.hpp index 5ae476ff314a00186a0dcc6bea12b87258508117..e2b92b599254bbac404478fd590df6747281ae29 100644 --- a/src/mesh/DualMeshManager.hpp +++ b/src/mesh/DualMeshManager.hpp @@ -1,6 +1,7 @@ #ifndef DUAL_MESH_MANAGER_HPP #define DUAL_MESH_MANAGER_HPP +#include <mesh/DualMeshType.hpp> #include <mesh/IMesh.hpp> #include <utils/PugsAssert.hpp> #include <utils/PugsMacros.hpp> @@ -14,16 +15,20 @@ class Connectivity; template <typename ConnectivityType> class Mesh; -enum class DualMeshType -{ - Diamond, - Classic -}; - class DualMeshManager { private: - std::unordered_map<const IMesh*, std::shared_ptr<const IMesh>> m_mesh_to_diamond_dual_mesh_map; + using Key = std::pair<DualMeshType, const IMesh*>; + struct HashKey + { + size_t + operator()(const Key& key) const + { + return (std::hash<typename Key::first_type>()(key.first)) ^ (std::hash<typename Key::second_type>()(key.second)); + } + }; + + std::unordered_map<Key, std::shared_ptr<const IMesh>, HashKey> m_mesh_to_dual_mesh_map; static DualMeshManager* m_instance; diff --git a/src/mesh/DualMeshType.hpp b/src/mesh/DualMeshType.hpp new file mode 100644 index 0000000000000000000000000000000000000000..5e599a0004fd44a1ab9375d07315f3bd8225c797 --- /dev/null +++ b/src/mesh/DualMeshType.hpp @@ -0,0 +1,32 @@ +#ifndef DUAL_MESH_TYPE_HPP +#define DUAL_MESH_TYPE_HPP + +#include <utils/Exceptions.hpp> +#include <utils/PugsMacros.hpp> + +#include <string> + +enum class DualMeshType +{ + Classic, + Diamond +}; + +PUGS_INLINE +std::string +name(DualMeshType type) +{ + switch (type) { + case DualMeshType::Classic: { + return "classic"; + } + case DualMeshType::Diamond: { + return "diamond"; + } + default: { + throw UnexpectedError("unexpected dual mesh type"); + } + } +} + +#endif // DUAL_MESH_TYPE_HPP diff --git a/src/mesh/IConnectivityToDualConnectivityDataMapper.hpp b/src/mesh/IConnectivityToDualConnectivityDataMapper.hpp new file mode 100644 index 0000000000000000000000000000000000000000..4248a15665d2e3acd6dafc4f2081f8bec7f03dfd --- /dev/null +++ b/src/mesh/IConnectivityToDualConnectivityDataMapper.hpp @@ -0,0 +1,14 @@ +#ifndef I_CONNECTIVITY_TO_DUAL_CONNECTIVITY_DATA_MAPPER_HPP +#define I_CONNECTIVITY_TO_DUAL_CONNECTIVITY_DATA_MAPPER_HPP + +class IConnectivityToDualConnectivityDataMapper +{ + public: + IConnectivityToDualConnectivityDataMapper(const IConnectivityToDualConnectivityDataMapper&) = delete; + IConnectivityToDualConnectivityDataMapper(IConnectivityToDualConnectivityDataMapper&&) = delete; + + IConnectivityToDualConnectivityDataMapper() = default; + virtual ~IConnectivityToDualConnectivityDataMapper() = default; +}; + +#endif // I_CONNECTIVITY_TO_DUAL_CONNECTIVITY_DATA_MAPPER_HPP