Skip to content

Commit aa606b7

Browse files
nilsdeppeclaude
andcommitted
Add ProjectSpectralFilter AMR projector
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 95b1afb commit aa606b7

4 files changed

Lines changed: 194 additions & 0 deletions

File tree

src/Evolution/DiscontinuousGalerkin/Initialization/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ spectre_target_headers(
66
INCLUDE_DIRECTORY ${CMAKE_SOURCE_DIR}/src
77
HEADERS
88
Mortars.hpp
9+
ProjectSpectralFilters.hpp
910
QuadratureTag.hpp
1011
SpectralFilters.hpp
1112
SpectralFilters.tpp
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Distributed under the MIT License.
2+
// See LICENSE.txt for details.
3+
4+
#pragma once
5+
6+
#include <cstddef>
7+
#include <iterator>
8+
#include <memory>
9+
#include <unordered_map>
10+
#include <utility>
11+
12+
#include "DataStructures/TaggedTuple.hpp"
13+
#include "Domain/Structure/Element.hpp"
14+
#include "Domain/Structure/ElementId.hpp"
15+
#include "NumericalAlgorithms/LinearOperators/Filters/Filter.hpp"
16+
#include "NumericalAlgorithms/LinearOperators/Filters/Tag.hpp"
17+
#include "NumericalAlgorithms/Spectral/Mesh.hpp"
18+
#include "ParallelAlgorithms/Amr/Protocols/Projector.hpp"
19+
#include "Utilities/ErrorHandling/Error.hpp"
20+
#include "Utilities/Gsl.hpp"
21+
#include "Utilities/TMPL.hpp"
22+
23+
namespace evolution::dg::Initialization {
24+
25+
/// \brief AMR projector for `Filters::Tags::SpectralFilter<Dim, TagList>`.
26+
///
27+
/// \details
28+
/// - For p-refinement: leaves the filter unchanged.
29+
/// - For h-refinement (splitting): clones the parent's filter for the child.
30+
/// - For h-coarsening (joining): clones the first child's filter for the
31+
/// parent (all siblings share the same block and mesh basis/quadrature, so
32+
/// they carry identical filters).
33+
template <size_t Dim, typename TagList>
34+
struct ProjectSpectralFilters : tt::ConformsTo<amr::protocols::Projector> {
35+
using return_tags = tmpl::list<Filters::Tags::SpectralFilter<Dim, TagList>>;
36+
using argument_tags = tmpl::list<>;
37+
38+
// p-refinement: leave the filter unchanged.
39+
static void apply(
40+
const gsl::not_null<
41+
std::unique_ptr<Filters::Filter<Dim, TagList>>*> /*filter*/,
42+
const std::pair<Mesh<Dim>, Element<Dim>>& /*old_mesh_and_element*/) {}
43+
44+
// Splitting: clone the parent's filter for the new child.
45+
template <typename... ParentTags>
46+
static void apply(
47+
const gsl::not_null<std::unique_ptr<Filters::Filter<Dim, TagList>>*>
48+
filter,
49+
const tuples::TaggedTuple<ParentTags...>& parent_items) {
50+
*filter =
51+
tuples::get<Filters::Tags::SpectralFilter<Dim, TagList>>(parent_items)
52+
->get_clone();
53+
}
54+
55+
// Joining: clone the first child's filter for the parent.
56+
template <typename... ChildrenTags>
57+
static void apply(
58+
const gsl::not_null<std::unique_ptr<Filters::Filter<Dim, TagList>>*>
59+
filter,
60+
const std::unordered_map<ElementId<Dim>,
61+
tuples::TaggedTuple<ChildrenTags...>>&
62+
children_items) {
63+
const auto first_child_items = children_items.begin();
64+
const auto& first_filter =
65+
tuples::get<Filters::Tags::SpectralFilter<Dim, TagList>>(
66+
first_child_items->second);
67+
for (auto it = std::next(first_child_items); it != children_items.end();
68+
++it) {
69+
const auto& other_filter =
70+
tuples::get<Filters::Tags::SpectralFilter<Dim, TagList>>(it->second);
71+
if (not first_filter->is_equal(*other_filter)) {
72+
ERROR("Children do not agree on all items!");
73+
}
74+
}
75+
*filter = first_filter->get_clone();
76+
}
77+
};
78+
79+
} // namespace evolution::dg::Initialization

tests/Unit/Evolution/DiscontinuousGalerkin/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ set(LIBRARY_SOURCES
1212
Actions/Test_ComputeTimeDerivative.cpp
1313
Actions/Test_NormalCovectorAndMagnitude.cpp
1414
Initialization/Test_Mortars.cpp
15+
Initialization/Test_ProjectSpectralFilters.cpp
1516
Initialization/Test_QuadratureTag.cpp
1617
Initialization/Test_SpectralFilters.cpp
1718
Test_AtomicInboxBoundaryData.cpp
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Distributed under the MIT License.
2+
// See LICENSE.txt for details.
3+
4+
#include "Framework/TestingFramework.hpp"
5+
6+
#include <cstddef>
7+
#include <memory>
8+
#include <optional>
9+
#include <unordered_map>
10+
#include <utility>
11+
12+
#include "DataStructures/DataBox/DataBox.hpp"
13+
#include "DataStructures/DataBox/Tag.hpp"
14+
#include "DataStructures/DataVector.hpp"
15+
#include "DataStructures/TaggedTuple.hpp"
16+
#include "DataStructures/Tensor/Tensor.hpp"
17+
#include "Domain/Structure/DirectionMap.hpp"
18+
#include "Domain/Structure/Element.hpp"
19+
#include "Domain/Structure/ElementId.hpp"
20+
#include "Domain/Structure/Neighbors.hpp"
21+
#include "Evolution/DiscontinuousGalerkin/Initialization/ProjectSpectralFilters.hpp"
22+
#include "NumericalAlgorithms/LinearOperators/Filters/Filter.hpp"
23+
#include "NumericalAlgorithms/LinearOperators/Filters/Hypercube.hpp"
24+
#include "NumericalAlgorithms/LinearOperators/Filters/Hypercube.tpp"
25+
#include "NumericalAlgorithms/LinearOperators/Filters/None.hpp"
26+
#include "NumericalAlgorithms/LinearOperators/Filters/None.tpp"
27+
#include "NumericalAlgorithms/LinearOperators/Filters/Tag.hpp"
28+
#include "NumericalAlgorithms/Spectral/Basis.hpp"
29+
#include "NumericalAlgorithms/Spectral/Mesh.hpp"
30+
#include "NumericalAlgorithms/Spectral/Quadrature.hpp"
31+
#include "ParallelAlgorithms/Amr/Protocols/Projector.hpp"
32+
#include "Utilities/Gsl.hpp"
33+
#include "Utilities/ProtocolHelpers.hpp"
34+
#include "Utilities/TMPL.hpp"
35+
36+
namespace {
37+
struct ScalarVar : db::SimpleTag {
38+
using type = Scalar<DataVector>;
39+
};
40+
41+
using TagList = tmpl::list<ScalarVar>;
42+
constexpr size_t Dim = 1;
43+
using FilterTag = Filters::Tags::SpectralFilter<Dim, TagList>;
44+
using Projector =
45+
evolution::dg::Initialization::ProjectSpectralFilters<Dim, TagList>;
46+
47+
std::unique_ptr<Filters::Filter<Dim, TagList>> make_none() {
48+
return std::make_unique<Filters::None<Dim, TagList>>();
49+
}
50+
51+
std::unique_ptr<Filters::Filter<Dim, TagList>> make_hypercube() {
52+
return std::make_unique<Filters::Hypercube<Dim, TagList>>(
53+
4u, true, std::nullopt, false, false, std::nullopt, std::nullopt);
54+
}
55+
56+
void test_p_refinement() {
57+
const ElementId<Dim> element_id{0};
58+
const Element<Dim> element{element_id, DirectionMap<Dim, Neighbors<Dim>>{}};
59+
const Mesh<Dim> mesh{2, Spectral::Basis::Legendre,
60+
Spectral::Quadrature::GaussLobatto};
61+
auto box = db::create<db::AddSimpleTags<FilterTag>>(make_none());
62+
const Filters::Filter<Dim, TagList>* const ptr_before =
63+
&db::get<FilterTag>(box);
64+
db::mutate_apply<Projector>(make_not_null(&box),
65+
std::make_pair(mesh, element));
66+
CHECK(&db::get<FilterTag>(box) == ptr_before);
67+
CHECK(db::get<FilterTag>(box).is_equal(Filters::None<Dim, TagList>{}));
68+
}
69+
70+
void test_splitting() {
71+
auto box = db::DataBox<tmpl::list<FilterTag>>{};
72+
tuples::TaggedTuple<FilterTag> parent_items{make_none()};
73+
db::mutate_apply<Projector>(make_not_null(&box), parent_items);
74+
CHECK(db::get<FilterTag>(box).is_equal(Filters::None<Dim, TagList>{}));
75+
}
76+
77+
void test_joining() {
78+
auto box = db::DataBox<tmpl::list<FilterTag>>{};
79+
std::unordered_map<ElementId<Dim>, tuples::TaggedTuple<FilterTag>>
80+
children_items;
81+
children_items.emplace(ElementId<Dim>{0},
82+
tuples::TaggedTuple<FilterTag>{make_none()});
83+
children_items.emplace(ElementId<Dim>{1},
84+
tuples::TaggedTuple<FilterTag>{make_none()});
85+
db::mutate_apply<Projector>(make_not_null(&box), children_items);
86+
CHECK(db::get<FilterTag>(box).is_equal(Filters::None<Dim, TagList>{}));
87+
}
88+
89+
void test_joining_error() {
90+
CHECK_THROWS_WITH(
91+
([]() {
92+
auto box = db::DataBox<tmpl::list<FilterTag>>{};
93+
std::unordered_map<ElementId<Dim>, tuples::TaggedTuple<FilterTag>>
94+
children_items;
95+
children_items.emplace(ElementId<Dim>{0},
96+
tuples::TaggedTuple<FilterTag>{make_none()});
97+
children_items.emplace(
98+
ElementId<Dim>{1},
99+
tuples::TaggedTuple<FilterTag>{make_hypercube()});
100+
db::mutate_apply<Projector>(make_not_null(&box), children_items);
101+
})(),
102+
Catch::Matchers::ContainsSubstring("Children do not agree"));
103+
}
104+
} // namespace
105+
106+
SPECTRE_TEST_CASE("Unit.Evolution.DG.Initialization.ProjectSpectralFilters",
107+
"[Unit][Evolution]") {
108+
static_assert(tt::assert_conforms_to_v<Projector, amr::protocols::Projector>);
109+
test_p_refinement();
110+
test_splitting();
111+
test_joining();
112+
test_joining_error();
113+
}

0 commit comments

Comments
 (0)