From 2cc75d955d37dac5b5260b43f44a185711e503d4 Mon Sep 17 00:00:00 2001 From: Nils Deppe Date: Mon, 17 Jun 2024 15:05:26 -0400 Subject: [PATCH 1/2] Move ChildSize hash to Spectral --- .../DiscontinuousGalerkin/MortarHelpers.hpp | 39 ------------------- .../Spectral/Projection.cpp | 39 ++++++++++++++++++- .../Spectral/Projection.hpp | 21 ++++++++++ .../Test_MortarHelpers.cpp | 30 -------------- .../Spectral/Test_Projection.cpp | 30 ++++++++++++++ 5 files changed, 89 insertions(+), 70 deletions(-) diff --git a/src/NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp b/src/NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp index eb22a6cd052c..569b5eec7380 100644 --- a/src/NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp +++ b/src/NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp @@ -128,43 +128,4 @@ Variables project_from_mortar(const Variables& vars, return result; } /// @} - -/// @{ -/// \brief Performs a perfect hash of the mortars into $2^{d-1}$ slots on the -/// range $[0, 2^{d-1})$. -/// -/// This is particularly useful when hashing into statically-sized maps based -/// on the number of dimensions. -template -size_t hash(const std::array& mortar_size) { - if constexpr (DimMinusOne == 2) { - ASSERT(mortar_size[0] != Spectral::ChildSize::Uninitialized and - mortar_size[1] != Spectral::ChildSize::Uninitialized, - "Cannot hash an uninitialized mortar_size: " << mortar_size[0] << " " - << mortar_size[1]); - return (static_cast(mortar_size[0]) - 1) % 2 + - 2 * ((static_cast(mortar_size[1]) - 1) % 2); - } else if constexpr (DimMinusOne == 1) { - ASSERT(mortar_size[0] != Spectral::ChildSize::Uninitialized, - "Cannot hash an uninitialized mortar_size: " << mortar_size[0]); - return (static_cast(mortar_size[0]) - 1) % 2; - } else if constexpr (DimMinusOne == 0) { - (void)mortar_size; - return 0; - } else { - static_assert(DimMinusOne == 2 or DimMinusOne == 1 or DimMinusOne == 0); - } -} - -template -struct MortarSizeHash { - template - static constexpr bool is_perfect = MaxSize == two_to_the(Dim); - - size_t operator()( - const std::array& mortar_size) { - return hash(mortar_size); - } -}; -/// @} } // namespace dg diff --git a/src/NumericalAlgorithms/Spectral/Projection.cpp b/src/NumericalAlgorithms/Spectral/Projection.cpp index 2a40d73286ec..bca029093b50 100644 --- a/src/NumericalAlgorithms/Spectral/Projection.cpp +++ b/src/NumericalAlgorithms/Spectral/Projection.cpp @@ -15,6 +15,7 @@ #include "NumericalAlgorithms/Spectral/Mesh.hpp" #include "NumericalAlgorithms/Spectral/Spectral.hpp" #include "Utilities/Algorithm.hpp" +#include "Utilities/ConstantExpressions.hpp" #include "Utilities/ErrorHandling/Assert.hpp" #include "Utilities/ErrorHandling/Error.hpp" #include "Utilities/GenerateInstantiations.hpp" @@ -419,6 +420,33 @@ std::array, Dim> p_projection_matrices( return projection_matrices; } +template +size_t hash(const std::array& mortar_size) { + if constexpr (DimMinusOne == 2) { + ASSERT(mortar_size[0] != Spectral::ChildSize::Uninitialized and + mortar_size[1] != Spectral::ChildSize::Uninitialized, + "Cannot hash an uninitialized mortar_size: " << mortar_size[0] << " " + << mortar_size[1]); + return (static_cast(mortar_size[0]) - 1) % 2 + + 2 * ((static_cast(mortar_size[1]) - 1) % 2); + } else if constexpr (DimMinusOne == 1) { + ASSERT(mortar_size[0] != Spectral::ChildSize::Uninitialized, + "Cannot hash an uninitialized mortar_size: " << mortar_size[0]); + return (static_cast(mortar_size[0]) - 1) % 2; + } else if constexpr (DimMinusOne == 0) { + (void)mortar_size; + return 0; + } else { + static_assert(DimMinusOne == 2 or DimMinusOne == 1 or DimMinusOne == 0); + } +} + +template +size_t MortarSizeHash::operator()( + const std::array& mortar_size) { + return hash(mortar_size); +} + #define DIM(data) BOOST_PP_TUPLE_ELEM(0, data) #define INSTANTIATE(r, data) \ template bool needs_projection( \ @@ -438,8 +466,17 @@ std::array, Dim> p_projection_matrices( const Mesh& target_mesh); GENERATE_INSTANTIATIONS(INSTANTIATE, (0, 1, 2, 3)) +#undef INSTANTIATE -#undef DIM +#define INSTANTIATE(r, data) template class MortarSizeHash; +GENERATE_INSTANTIATIONS(INSTANTIATE, (1, 2, 3)) #undef INSTANTIATE +#define INSTANTIATE(r, data) \ + template size_t hash( \ + const std::array& mortar_size); +GENERATE_INSTANTIATIONS(INSTANTIATE, (0, 1, 2)) +#undef INSTANTIATE + +#undef DIM } // namespace Spectral diff --git a/src/NumericalAlgorithms/Spectral/Projection.hpp b/src/NumericalAlgorithms/Spectral/Projection.hpp index 35cc6ae09304..fc0efd7ba8e6 100644 --- a/src/NumericalAlgorithms/Spectral/Projection.hpp +++ b/src/NumericalAlgorithms/Spectral/Projection.hpp @@ -8,6 +8,8 @@ #include #include +#include "Utilities/ConstantExpressions.hpp" + /// \cond class Matrix; template @@ -111,4 +113,23 @@ projection_matrix_parent_to_child( template std::array, Dim> p_projection_matrices( const Mesh& source_mesh, const Mesh& target_mesh); + +/// @{ +/// \brief Performs a perfect hash of the mortars into $2^{d-1}$ slots on the +/// range $[0, 2^{d-1})$. +/// +/// This is particularly useful when hashing into statically-sized maps based +/// on the number of dimensions. +template +size_t hash(const std::array& mortar_size); + +template +struct MortarSizeHash { + template + static constexpr bool is_perfect = MaxSize == two_to_the(Dim); + + size_t operator()( + const std::array& mortar_size); +}; +/// @} } // namespace Spectral diff --git a/tests/Unit/NumericalAlgorithms/DiscontinuousGalerkin/Test_MortarHelpers.cpp b/tests/Unit/NumericalAlgorithms/DiscontinuousGalerkin/Test_MortarHelpers.cpp index 19a9205741f1..ccf6297f18f5 100644 --- a/tests/Unit/NumericalAlgorithms/DiscontinuousGalerkin/Test_MortarHelpers.cpp +++ b/tests/Unit/NumericalAlgorithms/DiscontinuousGalerkin/Test_MortarHelpers.cpp @@ -317,40 +317,10 @@ void test_projections() { } } } - -void test_hash() { - CHECK(dg::MortarSizeHash<1>{}({}) == 0); - - CHECK(dg::MortarSizeHash<2>{}({Spectral::ChildSize::LowerHalf}) == 0); - CHECK(dg::MortarSizeHash<2>{}({Spectral::ChildSize::Full}) == 0); - CHECK(dg::MortarSizeHash<2>{}({Spectral::ChildSize::UpperHalf}) == 1); - - CHECK(dg::MortarSizeHash<3>{}({Spectral::ChildSize::LowerHalf, - Spectral::ChildSize::LowerHalf}) == 0); - CHECK(dg::MortarSizeHash<3>{}({Spectral::ChildSize::UpperHalf, - Spectral::ChildSize::LowerHalf}) == 1); - CHECK(dg::MortarSizeHash<3>{}( - {Spectral::ChildSize::Full, Spectral::ChildSize::LowerHalf}) == 0); - - CHECK(dg::MortarSizeHash<3>{}({Spectral::ChildSize::LowerHalf, - Spectral::ChildSize::UpperHalf}) == 2); - CHECK(dg::MortarSizeHash<3>{}({Spectral::ChildSize::UpperHalf, - Spectral::ChildSize::UpperHalf}) == 3); - CHECK(dg::MortarSizeHash<3>{}( - {Spectral::ChildSize::Full, Spectral::ChildSize::UpperHalf}) == 2); - - CHECK(dg::MortarSizeHash<3>{}( - {Spectral::ChildSize::LowerHalf, Spectral::ChildSize::Full}) == 0); - CHECK(dg::MortarSizeHash<3>{}( - {Spectral::ChildSize::UpperHalf, Spectral::ChildSize::Full}) == 1); - CHECK(dg::MortarSizeHash<3>{}( - {Spectral::ChildSize::Full, Spectral::ChildSize::Full}) == 0); -} } // namespace SPECTRE_TEST_CASE("Unit.DG.MortarHelpers", "[Unit][NumericalAlgorithms]") { test_mortar_mesh(); test_mortar_size(); test_projections(); - test_hash(); } diff --git a/tests/Unit/NumericalAlgorithms/Spectral/Test_Projection.cpp b/tests/Unit/NumericalAlgorithms/Spectral/Test_Projection.cpp index ec5b3f2a0803..b3786805be77 100644 --- a/tests/Unit/NumericalAlgorithms/Spectral/Test_Projection.cpp +++ b/tests/Unit/NumericalAlgorithms/Spectral/Test_Projection.cpp @@ -532,6 +532,35 @@ void test_p_projection_matrices() { } } } + +void test_hash() { + CHECK(Spectral::MortarSizeHash<1>{}({}) == 0); + + CHECK(Spectral::MortarSizeHash<2>{}({Spectral::ChildSize::LowerHalf}) == 0); + CHECK(Spectral::MortarSizeHash<2>{}({Spectral::ChildSize::Full}) == 0); + CHECK(Spectral::MortarSizeHash<2>{}({Spectral::ChildSize::UpperHalf}) == 1); + + CHECK(Spectral::MortarSizeHash<3>{}({Spectral::ChildSize::LowerHalf, + Spectral::ChildSize::LowerHalf}) == 0); + CHECK(Spectral::MortarSizeHash<3>{}({Spectral::ChildSize::UpperHalf, + Spectral::ChildSize::LowerHalf}) == 1); + CHECK(Spectral::MortarSizeHash<3>{}( + {Spectral::ChildSize::Full, Spectral::ChildSize::LowerHalf}) == 0); + + CHECK(Spectral::MortarSizeHash<3>{}({Spectral::ChildSize::LowerHalf, + Spectral::ChildSize::UpperHalf}) == 2); + CHECK(Spectral::MortarSizeHash<3>{}({Spectral::ChildSize::UpperHalf, + Spectral::ChildSize::UpperHalf}) == 3); + CHECK(Spectral::MortarSizeHash<3>{}( + {Spectral::ChildSize::Full, Spectral::ChildSize::UpperHalf}) == 2); + + CHECK(Spectral::MortarSizeHash<3>{}( + {Spectral::ChildSize::LowerHalf, Spectral::ChildSize::Full}) == 0); + CHECK(Spectral::MortarSizeHash<3>{}( + {Spectral::ChildSize::UpperHalf, Spectral::ChildSize::Full}) == 1); + CHECK(Spectral::MortarSizeHash<3>{}( + {Spectral::ChildSize::Full, Spectral::ChildSize::Full}) == 0); +} } // namespace SPECTRE_TEST_CASE("Unit.Numerical.Spectral.Projection", @@ -557,6 +586,7 @@ SPECTRE_TEST_CASE("Unit.Numerical.Spectral.Projection", test_p_projection_matrices<1>(); test_p_projection_matrices<2>(); test_p_projection_matrices<3>(); + test_hash(); } } // namespace Spectral From 7097b29e42fb8cfb3fa37c219234fc9e626404d6 Mon Sep 17 00:00:00 2001 From: Nils Deppe Date: Mon, 17 Jun 2024 16:36:07 -0400 Subject: [PATCH 2/2] Add test for DirectionalId --- tests/Unit/Domain/Structure/CMakeLists.txt | 1 + .../Domain/Structure/Test_DirectionalId.cpp | 113 ++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 tests/Unit/Domain/Structure/Test_DirectionalId.cpp diff --git a/tests/Unit/Domain/Structure/CMakeLists.txt b/tests/Unit/Domain/Structure/CMakeLists.txt index 1b2cfd84d671..6ced2d52961a 100644 --- a/tests/Unit/Domain/Structure/CMakeLists.txt +++ b/tests/Unit/Domain/Structure/CMakeLists.txt @@ -9,6 +9,7 @@ set(LIBRARY_SOURCES Test_ChildSize.cpp Test_CreateInitialMesh.cpp Test_Direction.cpp + Test_DirectionalId.cpp Test_Element.cpp Test_ElementId.cpp Test_Hypercube.cpp diff --git a/tests/Unit/Domain/Structure/Test_DirectionalId.cpp b/tests/Unit/Domain/Structure/Test_DirectionalId.cpp new file mode 100644 index 000000000000..a08ca473905b --- /dev/null +++ b/tests/Unit/Domain/Structure/Test_DirectionalId.cpp @@ -0,0 +1,113 @@ +// Distributed under the MIT License. +// See LICENSE.txt for details. + +#include "Framework/TestingFramework.hpp" + +#include +#include +#include + +#include "Domain/Structure/Direction.hpp" +#include "Domain/Structure/DirectionalId.hpp" +#include "Domain/Structure/ElementId.hpp" +#include "Domain/Structure/Side.hpp" +#include "Framework/TestHelpers.hpp" + +namespace { +void test_retrieval() { + const auto check = [](const Direction& direction, + const ElementId& element_id) { + const auto check_impl = [&element_id, + &direction](const DirectionalId& did) { + CHECK(did.id() == element_id); + CHECK(hash_value(did.id()) == hash_value(element_id)); + CHECK(hash_value(did) != hash_value(element_id)); + CHECK(did.direction() == direction); + CHECK(hash_value(did.direction()) == hash_value(direction)); + CHECK(hash_value(did) != hash_value(direction)); + }; + const DirectionalId did0{direction, element_id}; + check_impl(did0); + const DirectionalId did1 = serialize_and_deserialize(did0); + check_impl(did1); + }; + const std::array uls{Side::Upper, Side::Lower}; + std::vector element_ids_1d{ + ElementId<1>{0, {{{0, 0}}}}, ElementId<1>{0, {{{1, 0}}}}, + ElementId<1>{0, {{{1, 1}}}}, ElementId<1>{0, {{{2, 0}}}}, + ElementId<1>{0, {{{2, 1}}}}, ElementId<1>{0, {{{2, 3}}}}}; + for (const auto ul : uls) { + INFO("Test 1d"); + for (size_t dim = 0; dim < 1; ++dim) { + for (const auto& element_id : element_ids_1d) { + check(Direction<1>(dim, ul), element_id); + } + } + } + + const std::vector element_ids_2d{ + ElementId<2>{0, {{{0, 0}, {0, 0}}}}, ElementId<2>{0, {{{1, 0}, {0, 0}}}}, + ElementId<2>{0, {{{0, 0}, {1, 0}}}}, ElementId<2>{0, {{{1, 0}, {1, 0}}}}, + ElementId<2>{0, {{{1, 1}, {1, 0}}}}, ElementId<2>{0, {{{1, 0}, {1, 1}}}}, + ElementId<2>{0, {{{2, 0}, {1, 0}}}}, ElementId<2>{0, {{{2, 3}, {1, 0}}}}, + ElementId<2>{0, {{{1, 0}, {2, 0}}}}, ElementId<2>{0, {{{1, 0}, {2, 3}}}}, + ElementId<2>{0, {{{2, 1}, {1, 0}}}}, ElementId<2>{0, {{{1, 0}, {2, 2}}}}, + ElementId<2>{0, {{{2, 0}, {2, 0}}}}, ElementId<2>{0, {{{2, 0}, {2, 2}}}}, + ElementId<2>{0, {{{2, 2}, {2, 0}}}}, ElementId<2>{0, {{{2, 3}, {2, 0}}}}, + ElementId<2>{0, {{{2, 0}, {2, 3}}}}, ElementId<2>{0, {{{2, 3}, {2, 3}}}}}; + for (const auto ul : uls) { + INFO("Test 2d"); + for (size_t dim = 0; dim < 2; ++dim) { + for (const auto& element_id : element_ids_2d) { + check(Direction<2>(dim, ul), element_id); + } + } + } + + const std::vector element_ids_3d{ElementId<3>{0, {{{0, 0}, {0, 0}, {0, 0}}}}, + ElementId<3>{0, {{{1, 0}, {0, 0}, {0, 0}}}}, + ElementId<3>{0, {{{0, 0}, {1, 0}, {0, 0}}}}, + ElementId<3>{0, {{{0, 0}, {0, 0}, {1, 0}}}}, + ElementId<3>{0, {{{1, 1}, {0, 0}, {0, 0}}}}, + ElementId<3>{0, {{{0, 0}, {1, 1}, {0, 0}}}}, + ElementId<3>{0, {{{0, 0}, {0, 0}, {1, 1}}}}, + ElementId<3>{0, {{{1, 0}, {1, 0}, {0, 0}}}}, + ElementId<3>{0, {{{1, 0}, {0, 0}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {1, 0}, {1, 0}}}}, + ElementId<3>{0, {{{1, 1}, {1, 0}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {1, 1}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {1, 0}, {1, 1}}}}, + ElementId<3>{0, {{{2, 0}, {1, 0}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {2, 0}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {1, 0}, {2, 0}}}}, + ElementId<3>{0, {{{2, 3}, {1, 0}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {2, 3}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {1, 0}, {2, 3}}}}, + ElementId<3>{0, {{{2, 1}, {1, 0}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {2, 1}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {1, 0}, {2, 1}}}}, + ElementId<3>{0, {{{2, 1}, {2, 0}, {1, 0}}}}, + ElementId<3>{0, {{{2, 1}, {1, 0}, {2, 0}}}}, + ElementId<3>{0, {{{2, 0}, {2, 1}, {1, 0}}}}, + ElementId<3>{0, {{{1, 0}, {2, 1}, {2, 0}}}}, + ElementId<3>{0, {{{2, 0}, {1, 0}, {2, 1}}}}, + ElementId<3>{0, {{{1, 0}, {2, 0}, {2, 1}}}}, + ElementId<3>{0, {{{2, 0}, {2, 0}, {2, 1}}}}, + ElementId<3>{0, {{{2, 1}, {2, 0}, {2, 1}}}}, + ElementId<3>{0, {{{2, 0}, {2, 1}, {2, 1}}}}, + ElementId<3>{0, {{{2, 1}, {2, 1}, {2, 0}}}}, + ElementId<3>{0, {{{2, 1}, {2, 1}, {2, 1}}}}}; + for (const auto ul : uls) { + INFO("Test 3d"); + for (size_t dim = 0; dim < 3; ++dim) { + for (const auto& element_id : element_ids_3d) { + check(Direction<3>(dim, ul), element_id); + } + } + } +} +} // namespace + +SPECTRE_TEST_CASE("Unit.Domain.Structure.DirectionalId", "[Domain][Unit]") { + test_retrieval(); +}