-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add refinement criteria DriveToTargetAndOscillate
This is useful for testing AMR actions.
- Loading branch information
Showing
5 changed files
with
338 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
src/ParallelAlgorithms/Amr/Criteria/DriveToTargetAndOscillate.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Distributed under the MIT License. | ||
// See LICENSE.txt for details. | ||
|
||
#include "ParallelAlgorithms/Amr/Criteria/DriveToTargetAndOscillate.hpp" | ||
|
||
#include <array> | ||
#include <cstddef> | ||
#include <pup.h> | ||
#include <pup_stl.h> | ||
|
||
#include "Domain/Amr/Flag.hpp" | ||
|
||
namespace amr::Criteria { | ||
template <size_t Dim> | ||
DriveToTargetAndOscillate<Dim>::DriveToTargetAndOscillate( | ||
const std::array<size_t, Dim>& target_resolution, | ||
const std::array<size_t, Dim>& target_refinement_levels, | ||
const std::array<domain::Flag, Dim>& flags_at_target) | ||
: target_resolution_(target_resolution), | ||
target_refinement_levels_(target_refinement_levels), | ||
flags_at_target_(flags_at_target) {} | ||
|
||
template <size_t Dim> | ||
DriveToTargetAndOscillate<Dim>::DriveToTargetAndOscillate(CkMigrateMessage* msg) | ||
: Criterion(msg) {} | ||
|
||
// NOLINTNEXTLINE(google-runtime-references) | ||
template <size_t Dim> | ||
void DriveToTargetAndOscillate<Dim>::pup(PUP::er& p) { | ||
Criterion::pup(p); | ||
p | target_resolution_; | ||
p | target_refinement_levels_; | ||
p | flags_at_target_; | ||
} | ||
|
||
template <size_t Dim> | ||
PUP::able::PUP_ID DriveToTargetAndOscillate<Dim>::my_PUP_ID = 0; // NOLINT | ||
|
||
template class DriveToTargetAndOscillate<1>; | ||
template class DriveToTargetAndOscillate<2>; | ||
template class DriveToTargetAndOscillate<3>; | ||
} // namespace amr::Criteria |
122 changes: 122 additions & 0 deletions
122
src/ParallelAlgorithms/Amr/Criteria/DriveToTargetAndOscillate.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
// Distributed under the MIT License. | ||
// See LICENSE.txt for details. | ||
|
||
#pragma once | ||
|
||
#include <array> | ||
#include <cstddef> | ||
#include <pup.h> | ||
|
||
#include "Domain/Amr/Flag.hpp" | ||
#include "Domain/Structure/ElementId.hpp" | ||
#include "Domain/Tags.hpp" | ||
#include "NumericalAlgorithms/Spectral/Mesh.hpp" | ||
#include "ParallelAlgorithms/Amr/Criteria/Criterion.hpp" | ||
#include "Utilities/Gsl.hpp" | ||
#include "Utilities/TMPL.hpp" | ||
|
||
namespace amr::Criteria { | ||
/*! | ||
* \brief Refine the grid towards the target resolution and refinement levels in | ||
* each dimension and then oscillate about the target. | ||
* | ||
* \details If the grid is at neither target in a given dimension, the | ||
* flag chosen will be in the priority order Split, | ||
* IncreaseResolution, DecreaseResolution, Join. | ||
* | ||
* \note This criterion is primarily for testing the mechanics of refinement. | ||
*/ | ||
template <size_t Dim> | ||
class DriveToTargetAndOscillate : public Criterion { | ||
public: | ||
/// The target resolution | ||
struct TargetResolution { | ||
using type = std::array<size_t, Dim>; | ||
static constexpr Options::String help = { | ||
"The target resolution in each dimension."}; | ||
}; | ||
|
||
/// The target resolution | ||
struct TargetRefinementLevels { | ||
using type = std::array<size_t, Dim>; | ||
static constexpr Options::String help = { | ||
"The target refinement levels in each dimension."}; | ||
}; | ||
|
||
/// The AMR flags chosen when the target resolution and refinement levels are | ||
/// reached | ||
struct DecisionAtTarget { | ||
using type = std::array<domain::Flag, Dim>; | ||
static constexpr Options::String help = { | ||
"The flags returned when at the target."}; | ||
}; | ||
|
||
using options = | ||
tmpl::list<TargetResolution, TargetRefinementLevels, DecisionAtTarget>; | ||
|
||
static constexpr Options::String help = { | ||
"Refine the grid towards the TargetResolution and " | ||
"TargetRefinementLevels, and then oscillate about them by applying " | ||
"DecisionAtTarget."}; | ||
|
||
DriveToTargetAndOscillate() = default; | ||
|
||
explicit DriveToTargetAndOscillate( | ||
const std::array<size_t, Dim>& target_resolution, | ||
const std::array<size_t, Dim>& target_refinement_levels, | ||
const std::array<domain::Flag, Dim>& flags_at_target); | ||
|
||
/// \cond | ||
explicit DriveToTargetAndOscillate(CkMigrateMessage* msg); | ||
using PUP::able::register_constructor; | ||
WRAPPED_PUPable_decl_template(DriveToTargetAndOscillate); // NOLINT | ||
/// \endcond | ||
|
||
using compute_tags_for_observation_box = tmpl::list<>; | ||
|
||
using argument_tags = tmpl::list<::domain::Tags::Mesh<Dim>>; | ||
|
||
template <typename ArrayIndex, typename Metavariables> | ||
auto operator()(const Mesh<Dim>& current_mesh, | ||
Parallel::GlobalCache<Metavariables>& /*cache*/, | ||
const ArrayIndex& array_index) const; | ||
|
||
void pup(PUP::er& p) override; | ||
|
||
private: | ||
std::array<size_t, Dim> target_resolution_{}; | ||
std::array<size_t, Dim> target_refinement_levels_{}; | ||
std::array<domain::Flag, Dim> flags_at_target_{}; | ||
}; | ||
|
||
template <size_t Dim> | ||
template <typename ArrayIndex, typename Metavariables> | ||
auto DriveToTargetAndOscillate<Dim>::operator()( | ||
const Mesh<Dim>& current_mesh, | ||
Parallel::GlobalCache<Metavariables>& /*cache*/, | ||
const ArrayIndex& array_index) const { | ||
auto result = make_array<Dim>(domain::Flag::DoNothing); | ||
const std::array<size_t, Dim> levels = array_index.refinement_levels(); | ||
bool is_at_target = true; | ||
for (size_t d = 0; d < Dim; ++d) { | ||
if (gsl::at(levels, d) < gsl::at(target_refinement_levels_, d)) { | ||
gsl::at(result, d) = domain::Flag::Split; | ||
is_at_target = false; | ||
} else if (current_mesh.extents(d) < gsl::at(target_resolution_, d)) { | ||
gsl::at(result, d) = domain::Flag::IncreaseResolution; | ||
is_at_target = false; | ||
} else if (current_mesh.extents(d) > gsl::at(target_resolution_, d)) { | ||
gsl::at(result, d) = domain::Flag::DecreaseResolution; | ||
is_at_target = false; | ||
} else if (gsl::at(levels, d) > gsl::at(target_refinement_levels_, d)) { | ||
gsl::at(result, d) = domain::Flag::Join; | ||
is_at_target = false; | ||
} | ||
} | ||
if (is_at_target) { | ||
return flags_at_target_; | ||
} | ||
|
||
return result; | ||
} | ||
} // namespace amr::Criteria |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
170 changes: 170 additions & 0 deletions
170
tests/Unit/ParallelAlgorithms/Amr/Criteria/Test_DriveToTargetAndOscillate.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
// Distributed under the MIT License. | ||
// See LICENSE.txt for details. | ||
|
||
#include "Framework/TestingFramework.hpp" | ||
|
||
#include <cstddef> | ||
#include <memory> | ||
|
||
#include "DataStructures/DataBox/DataBox.hpp" | ||
#include "DataStructures/DataBox/ObservationBox.hpp" | ||
#include "Domain/Amr/Flag.hpp" | ||
#include "Domain/Structure/ElementId.hpp" | ||
#include "Domain/Structure/SegmentId.hpp" | ||
#include "Framework/TestCreation.hpp" | ||
#include "Framework/TestHelpers.hpp" | ||
#include "Helpers/DataStructures/DataBox/TestHelpers.hpp" | ||
#include "Options/Protocols/FactoryCreation.hpp" | ||
#include "Parallel/GlobalCache.hpp" | ||
#include "Parallel/RegisterDerivedClassesWithCharm.hpp" | ||
#include "ParallelAlgorithms/Amr/Criteria/Criterion.hpp" | ||
#include "ParallelAlgorithms/Amr/Criteria/DriveToTargetAndOscillate.hpp" | ||
#include "ParallelAlgorithms/Amr/Criteria/Tags/Criteria.hpp" | ||
#include "Utilities/MakeArray.hpp" | ||
#include "Utilities/TMPL.hpp" | ||
|
||
namespace { | ||
template <size_t VolumeDim> | ||
struct Metavariables { | ||
static constexpr size_t volume_dim = VolumeDim; | ||
using component_list = tmpl::list<>; | ||
using const_global_cache_tags = tmpl::list<>; | ||
struct factory_creation | ||
: tt::ConformsTo<Options::protocols::FactoryCreation> { | ||
using factory_classes = tmpl::map<tmpl::pair< | ||
amr::Criterion, | ||
tmpl::list<amr::Criteria::DriveToTargetAndOscillate<VolumeDim>>>>; | ||
}; | ||
}; | ||
struct TestComponent {}; | ||
|
||
template <size_t VolumeDim> | ||
void test_criterion( | ||
const amr::Criterion& criterion, | ||
const std::array<size_t, VolumeDim> mesh_extents, | ||
const std::array<size_t, VolumeDim>& element_refinement_levels, | ||
const std::array<amr::domain::Flag, VolumeDim>& expected_flags) { | ||
Parallel::GlobalCache<Metavariables<VolumeDim>> empty_cache{}; | ||
const auto databox = db::create<tmpl::list<::domain::Tags::Mesh<VolumeDim>>>( | ||
Mesh<VolumeDim>{mesh_extents, Spectral::Basis::Legendre, | ||
Spectral::Quadrature::GaussLobatto}); | ||
ObservationBox<tmpl::list<>, | ||
db::DataBox<tmpl::list<::domain::Tags::Mesh<VolumeDim>>>> | ||
box{databox}; | ||
|
||
std::array<SegmentId, VolumeDim> segment_ids; | ||
alg::transform(element_refinement_levels, segment_ids.begin(), | ||
[](const size_t extent) { | ||
return SegmentId{extent, 0_st}; | ||
}); | ||
ElementId<VolumeDim> element_id{0, segment_ids}; | ||
auto flags = criterion.evaluate(box, empty_cache, element_id); | ||
CHECK(flags == expected_flags); | ||
} | ||
|
||
template <size_t VolumeDim> | ||
void test( | ||
const std::array<size_t, VolumeDim>& target_extents, | ||
const std::array<size_t, VolumeDim>& target_levels, | ||
const std::array<amr::domain::Flag, VolumeDim>& flags_at_target, | ||
const std::vector< | ||
std::tuple<std::array<size_t, VolumeDim>, std::array<size_t, VolumeDim>, | ||
std::array<amr::domain::Flag, VolumeDim>>>& test_cases, | ||
const std::string& option_string) { | ||
Parallel::register_factory_classes_with_charm<Metavariables<VolumeDim>>(); | ||
|
||
const amr::Criteria::DriveToTargetAndOscillate criterion{ | ||
target_extents, target_levels, flags_at_target}; | ||
const auto criterion_from_option_string = | ||
TestHelpers::test_creation<std::unique_ptr<amr::Criterion>, | ||
Metavariables<VolumeDim>>(option_string); | ||
for (const auto& [extents, levels, expected_flags] : test_cases) { | ||
test_criterion(criterion, extents, levels, expected_flags); | ||
test_criterion(*criterion_from_option_string, extents, levels, | ||
expected_flags); | ||
test_criterion(*serialize_and_deserialize(criterion_from_option_string), | ||
extents, levels, expected_flags); | ||
} | ||
} | ||
} // namespace | ||
|
||
SPECTRE_TEST_CASE("Unit.Amr.Criteria.DriveToTargetAndOscillate", | ||
"[Unit][ParallelAlgorithms]") { | ||
const std::array target_extents_1d{4_st}; | ||
const std::array target_levels_1d{3_st}; | ||
const std::array flags_at_target_1d{amr::domain::Flag::Join}; | ||
const auto test_cases_1d = std::vector{ | ||
std::tuple{std::array{4_st}, std::array{3_st}, | ||
std::array{amr::domain::Flag::Join}}, | ||
std::tuple{std::array{3_st}, std::array{3_st}, | ||
std::array{amr::domain::Flag::IncreaseResolution}}, | ||
std::tuple{std::array{5_st}, std::array{3_st}, | ||
std::array{amr::domain::Flag::DecreaseResolution}}, | ||
std::tuple{std::array{4_st}, std::array{2_st}, | ||
std::array{amr::domain::Flag::Split}}, | ||
std::tuple{std::array{3_st}, std::array{2_st}, | ||
std::array{amr::domain::Flag::Split}}, | ||
std::tuple{std::array{5_st}, std::array{2_st}, | ||
std::array{amr::domain::Flag::Split}}, | ||
std::tuple{std::array{4_st}, std::array{4_st}, | ||
std::array{amr::domain::Flag::Join}}, | ||
std::tuple{std::array{3_st}, std::array{4_st}, | ||
std::array{amr::domain::Flag::IncreaseResolution}}, | ||
std::tuple{std::array{5_st}, std::array{4_st}, | ||
std::array{amr::domain::Flag::DecreaseResolution}}}; | ||
const std::string option_1d = | ||
"DriveToTargetAndOscillate:\n" | ||
" TargetResolution: [4]\n" | ||
" TargetRefinementLevels: [3]\n" | ||
" DecisionAtTarget: [Join]\n"; | ||
test(target_extents_1d, target_levels_1d, flags_at_target_1d, test_cases_1d, | ||
option_1d); | ||
const std::array target_extents_2d{4_st, 6_st}; | ||
const std::array target_levels_2d{8_st, 3_st}; | ||
const std::array flags_at_target_2d{amr::domain::Flag::IncreaseResolution, | ||
amr::domain::Flag::Split}; | ||
const auto test_cases_2d = std::vector{ | ||
std::tuple{std::array{4_st, 6_st}, std::array{8_st, 3_st}, | ||
std::array{amr::domain::Flag::IncreaseResolution, | ||
amr::domain::Flag::Split}}, | ||
std::tuple{std::array{5_st, 6_st}, std::array{8_st, 3_st}, | ||
std::array{amr::domain::Flag::DecreaseResolution, | ||
amr::domain::Flag::DoNothing}}, | ||
std::tuple{std::array{3_st, 6_st}, std::array{7_st, 4_st}, | ||
std::array{amr::domain::Flag::Split, amr::domain::Flag::Join}}, | ||
std::tuple{ | ||
std::array{4_st, 6_st}, std::array{8_st, 2_st}, | ||
std::array{amr::domain::Flag::DoNothing, amr::domain::Flag::Split}}}; | ||
const std::string option_2d = | ||
"DriveToTargetAndOscillate:\n" | ||
" TargetResolution: [4, 6]\n" | ||
" TargetRefinementLevels: [8, 3]\n" | ||
" DecisionAtTarget: [IncreaseResolution, Split]\n"; | ||
test(target_extents_2d, target_levels_2d, flags_at_target_2d, test_cases_2d, | ||
option_2d); | ||
const std::array target_extents_3d{3_st, 9_st, 5_st}; | ||
const std::array target_levels_3d{5_st, 2_st, 4_st}; | ||
const std::array flags_at_target_3d{amr::domain::Flag::Split, | ||
amr::domain::Flag::DecreaseResolution, | ||
amr::domain::Flag::DoNothing}; | ||
const auto test_cases_3d = std::vector{ | ||
std::tuple{std::array{3_st, 9_st, 5_st}, std::array{5_st, 2_st, 4_st}, | ||
std::array{amr::domain::Flag::Split, | ||
amr::domain::Flag::DecreaseResolution, | ||
amr::domain::Flag::DoNothing}}, | ||
std::tuple{ | ||
std::array{3_st, 9_st, 5_st}, std::array{5_st, 5_st, 4_st}, | ||
std::array{amr::domain::Flag::DoNothing, amr::domain::Flag::Join, | ||
amr::domain::Flag::DoNothing}}, | ||
std::tuple{ | ||
std::array{3_st, 9_st, 3_st}, std::array{5_st, 2_st, 4_st}, | ||
std::array{amr::domain::Flag::DoNothing, amr::domain::Flag::DoNothing, | ||
amr::domain::Flag::IncreaseResolution}}}; | ||
const std::string option_3d = | ||
"DriveToTargetAndOscillate:\n" | ||
" TargetResolution: [3, 9, 5]\n" | ||
" TargetRefinementLevels: [5, 2, 4]\n" | ||
" DecisionAtTarget: [Split, DecreaseResolution, DoNothing]\n"; | ||
test(target_extents_3d, target_levels_3d, flags_at_target_3d, test_cases_3d, | ||
option_3d); | ||
} |