Skip to content

Commit

Permalink
Merge pull request #6099 from nilsdeppe/add_threading_19
Browse files Browse the repository at this point in the history
Move MortarSizeHash to Spectral and add several tests for DirectionalId
  • Loading branch information
kidder authored Jun 21, 2024
2 parents d3f13e1 + 7097b29 commit 9e8e4b1
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 70 deletions.
39 changes: 0 additions & 39 deletions src/NumericalAlgorithms/DiscontinuousGalerkin/MortarHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,43 +128,4 @@ Variables<Tags> project_from_mortar(const Variables<Tags>& 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 DimMinusOne>
size_t hash(const std::array<Spectral::ChildSize, DimMinusOne>& 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<size_t>(mortar_size[0]) - 1) % 2 +
2 * ((static_cast<size_t>(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<size_t>(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 Dim>
struct MortarSizeHash {
template <size_t MaxSize>
static constexpr bool is_perfect = MaxSize == two_to_the(Dim);

size_t operator()(
const std::array<Spectral::ChildSize, Dim - 1>& mortar_size) {
return hash(mortar_size);
}
};
/// @}
} // namespace dg
39 changes: 38 additions & 1 deletion src/NumericalAlgorithms/Spectral/Projection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -419,6 +420,33 @@ std::array<std::reference_wrapper<const Matrix>, Dim> p_projection_matrices(
return projection_matrices;
}

template <size_t DimMinusOne>
size_t hash(const std::array<Spectral::ChildSize, DimMinusOne>& 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<size_t>(mortar_size[0]) - 1) % 2 +
2 * ((static_cast<size_t>(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<size_t>(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 Dim>
size_t MortarSizeHash<Dim>::operator()(
const std::array<Spectral::ChildSize, Dim - 1>& mortar_size) {
return hash(mortar_size);
}

#define DIM(data) BOOST_PP_TUPLE_ELEM(0, data)
#define INSTANTIATE(r, data) \
template bool needs_projection( \
Expand All @@ -438,8 +466,17 @@ std::array<std::reference_wrapper<const Matrix>, Dim> p_projection_matrices(
const Mesh<DIM(data)>& target_mesh);

GENERATE_INSTANTIATIONS(INSTANTIATE, (0, 1, 2, 3))
#undef INSTANTIATE

#undef DIM
#define INSTANTIATE(r, data) template class MortarSizeHash<DIM(data)>;
GENERATE_INSTANTIATIONS(INSTANTIATE, (1, 2, 3))
#undef INSTANTIATE

#define INSTANTIATE(r, data) \
template size_t hash<DIM(data)>( \
const std::array<Spectral::ChildSize, DIM(data)>& mortar_size);
GENERATE_INSTANTIATIONS(INSTANTIATE, (0, 1, 2))
#undef INSTANTIATE

#undef DIM
} // namespace Spectral
21 changes: 21 additions & 0 deletions src/NumericalAlgorithms/Spectral/Projection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <functional>
#include <ostream>

#include "Utilities/ConstantExpressions.hpp"

/// \cond
class Matrix;
template <size_t Dim>
Expand Down Expand Up @@ -111,4 +113,23 @@ projection_matrix_parent_to_child(
template <size_t Dim>
std::array<std::reference_wrapper<const Matrix>, Dim> p_projection_matrices(
const Mesh<Dim>& source_mesh, const Mesh<Dim>& 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 DimMinusOne>
size_t hash(const std::array<Spectral::ChildSize, DimMinusOne>& mortar_size);

template <size_t Dim>
struct MortarSizeHash {
template <size_t MaxSize>
static constexpr bool is_perfect = MaxSize == two_to_the(Dim);

size_t operator()(
const std::array<Spectral::ChildSize, Dim - 1>& mortar_size);
};
/// @}
} // namespace Spectral
1 change: 1 addition & 0 deletions tests/Unit/Domain/Structure/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
113 changes: 113 additions & 0 deletions tests/Unit/Domain/Structure/Test_DirectionalId.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Distributed under the MIT License.
// See LICENSE.txt for details.

#include "Framework/TestingFramework.hpp"

#include <array>
#include <cstddef>
#include <vector>

#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 = []<size_t Dim>(const Direction<Dim>& direction,
const ElementId<Dim>& element_id) {
const auto check_impl = [&element_id,
&direction](const DirectionalId<Dim>& 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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
30 changes: 30 additions & 0 deletions tests/Unit/NumericalAlgorithms/Spectral/Test_Projection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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

0 comments on commit 9e8e4b1

Please sign in to comment.