Skip to content

Commit

Permalink
Merge pull request #6414 from wthrowe/time_step_volume_fot
Browse files Browse the repository at this point in the history
Check FoTs are ready in ObserveConstantsPerElement
  • Loading branch information
nilsdeppe authored Dec 16, 2024
2 parents e7e48dc + dacb94c commit 970e70d
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 110 deletions.
110 changes: 47 additions & 63 deletions src/ParallelAlgorithms/Actions/FunctionsOfTimeAreReady.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,29 +119,6 @@ bool functions_of_time_are_ready_impl(
}
} // namespace detail

/// \ingroup ComputationalDomainGroup
/// Check that functions of time are up-to-date.
///
/// Check that functions of time in \p CacheTag with names in \p
/// functions_to_check are ready at time \p time. If \p functions_to_check is
/// a `std::nullopt`, checks all functions in \p CacheTag. If any function is
/// not ready, schedules a `Parallel::PerformAlgorithmCallback` with the
/// GlobalCache..
template <typename CacheTag, typename Metavariables, typename ArrayIndex,
typename Component>
bool functions_of_time_are_ready_algorithm_callback(
Parallel::GlobalCache<Metavariables>& cache, const ArrayIndex& array_index,
const Component* component_p, const double time,
const std::optional<std::unordered_set<std::string>>& functions_to_check =
std::nullopt) {
using ProxyType =
std::decay_t<decltype(::Parallel::get_parallel_component<Component>(
cache)[array_index])>;
return detail::functions_of_time_are_ready_impl<
CacheTag, Parallel::PerformAlgorithmCallback<ProxyType>>(
cache, array_index, component_p, time, functions_to_check);
}

/// \ingroup ComputationalDomainGroup
/// Check that functions of time are up-to-date.
///
Expand Down Expand Up @@ -194,6 +171,47 @@ bool functions_of_time_are_ready_threaded_action_callback(
std::forward<Args>(args)...);
}

/// \ingroup ComputationalDomainGroup
/// Check that functions of time are up-to-date.
///
/// Check that functions of time in \p CacheTag with names in \p
/// functions_to_check are ready at time \p time. If \p functions_to_check is
/// a `std::nullopt`, checks all functions in \p CacheTag. If any function is
/// not ready, schedules a `Parallel::PerformAlgorithmCallback` or
/// `Parallel::Actions::PerformAlgorithmOnElement<false>` callback with the
/// GlobalCache.
template <typename CacheTag, size_t Dim, typename Metavariables,
typename ArrayIndex, typename Component>
bool functions_of_time_are_ready_algorithm_callback(
Parallel::GlobalCache<Metavariables>& cache, const ArrayIndex& array_index,
const Component* component_p, const double time,
const std::optional<std::unordered_set<std::string>>& functions_to_check =
std::nullopt) {
if constexpr (Parallel::is_dg_element_collection_v<Component>) {
const auto element_location =
static_cast<int>(Parallel::local_synchronous_action<
Parallel::Actions::GetItemFromDistributedOject<
Parallel::Tags::ElementLocations<Dim>>>(
Parallel::get_parallel_component<Component>(cache))
->at(array_index));
ASSERT(element_location == Parallel::my_node<int>(cache),
"Expected to be running on node "
<< Parallel::my_node<int>(cache)
<< " but the record says it is on node " << element_location);
return functions_of_time_are_ready_threaded_action_callback<
domain::Tags::FunctionsOfTime,
Parallel::Actions::PerformAlgorithmOnElement<false>>(
cache, element_location, component_p, time, std::nullopt, array_index);
} else {
using ProxyType =
std::decay_t<decltype(::Parallel::get_parallel_component<Component>(
cache)[array_index])>;
return detail::functions_of_time_are_ready_impl<
CacheTag, Parallel::PerformAlgorithmCallback<ProxyType>>(
cache, array_index, component_p, time, functions_to_check);
}
}

namespace Actions {
/// \ingroup ComputationalDomainGroup
/// Check that functions of time are up-to-date.
Expand All @@ -212,29 +230,9 @@ struct CheckFunctionsOfTimeAreReady {
Parallel::GlobalCache<Metavariables>& cache,
const ArrayIndex& array_index, ActionList /*meta*/,
const ParallelComponent* component) {
bool ready = false;

if constexpr (Parallel::is_dg_element_collection_v<ParallelComponent>) {
const auto element_location = static_cast<int>(
Parallel::local_synchronous_action<
Parallel::Actions::GetItemFromDistributedOject<
Parallel::Tags::ElementLocations<Dim>>>(
Parallel::get_parallel_component<ParallelComponent>(cache))
->at(array_index));
ASSERT(element_location == Parallel::my_node<int>(cache),
"Expected to be running on node "
<< Parallel::my_node<int>(cache)
<< " but the record says it is on node " << element_location);
ready = domain::functions_of_time_are_ready_threaded_action_callback<
domain::Tags::FunctionsOfTime,
Parallel::Actions::PerformAlgorithmOnElement<false>>(
cache, element_location, component, db::get<::Tags::Time>(box),
std::nullopt, array_index);
} else {
ready = functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime>(cache, array_index, component,
db::get<::Tags::Time>(box));
}
const bool ready = functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime, Dim>(cache, array_index, component,
db::get<::Tags::Time>(box));

return {ready ? Parallel::AlgorithmExecution::Continue
: Parallel::AlgorithmExecution::Retry,
Expand Down Expand Up @@ -264,23 +262,9 @@ struct CheckFunctionsOfTimeAreReadyPostprocessor {
const gsl::not_null<tuples::TaggedTuple<InboxTags...>*> /*inboxes*/,
Parallel::GlobalCache<Metavariables>& cache,
const ArrayIndex& array_index, const ParallelComponent* component) {
if constexpr (Parallel::is_dg_element_collection_v<ParallelComponent>) {
const auto element_location = static_cast<int>(
Parallel::local_synchronous_action<
Parallel::Actions::GetItemFromDistributedOject<
Parallel::Tags::ElementLocations<Dim>>>(
Parallel::get_parallel_component<ParallelComponent>(cache))
->at(array_index));
return domain::functions_of_time_are_ready_threaded_action_callback<
domain::Tags::FunctionsOfTime,
Parallel::Actions::PerformAlgorithmOnElement<false>>(
cache, element_location, component, db::get<::Tags::Time>(*box),
std::nullopt, array_index);
} else {
return functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime>(cache, array_index, component,
db::get<::Tags::Time>(*box));
}
return functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime, Dim>(cache, array_index, component,
db::get<::Tags::Time>(*box));
}
};
} // namespace domain
19 changes: 14 additions & 5 deletions src/ParallelAlgorithms/Events/ObserveConstantsPerElement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "Parallel/Invoke.hpp"
#include "Parallel/Local.hpp"
#include "Parallel/TypeTraits.hpp"
#include "ParallelAlgorithms/Actions/FunctionsOfTimeAreReady.hpp"
#include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
#include "Utilities/TMPL.hpp"

Expand All @@ -34,6 +35,9 @@ class Domain;
namespace domain::FunctionsOfTime {
class FunctionOfTime;
} // namespace domain::FunctionsOfTime
namespace domain::Tags {
struct FunctionsOfTime;
} // namespace domain::Tags
namespace observers {
class ObservationKey;
enum class TypeOfObservation;
Expand All @@ -45,6 +49,9 @@ class GlobalCache;
namespace PUP {
class er;
} // namespace PUP
namespace Tags {
struct Time;
} // namespace Tags
/// \endcond

namespace dg::Events {
Expand Down Expand Up @@ -98,13 +105,15 @@ class ObserveConstantsPerElement : public Event {
std::pair<observers::TypeOfObservation, observers::ObservationKey>>
get_observation_type_and_key_for_registration() const;

using is_ready_argument_tags = tmpl::list<>;
using is_ready_argument_tags = tmpl::list<::Tags::Time>;

template <typename Metavariables, typename ArrayIndex, typename Component>
bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/,
const ArrayIndex& /*array_index*/,
const Component* const /*meta*/) const {
return true;
bool is_ready(const double time, Parallel::GlobalCache<Metavariables>& cache,
const ArrayIndex& array_index,
const Component* const component) const {
return ::domain::functions_of_time_are_ready_algorithm_callback<
::domain::Tags::FunctionsOfTime, VolumeDim>(cache, array_index,
component, time);
}

void pup(PUP::er& p) override;
Expand Down
28 changes: 5 additions & 23 deletions src/ParallelAlgorithms/Interpolation/Events/Interpolate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include "Parallel/ArrayCollection/PerformAlgorithmOnElement.hpp"
#include "Parallel/ArrayCollection/Tags/ElementLocations.hpp"
#include "Parallel/GlobalCache.hpp"
#include "ParallelAlgorithms/Actions/FunctionsOfTimeAreReady.hpp"
#include "ParallelAlgorithms/Actions/GetItemFromDistributedObject.hpp"
#include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
#include "ParallelAlgorithms/Interpolation/Events/GetComputeItemsOnSource.hpp"
Expand All @@ -34,9 +33,6 @@ class GlobalCache;
namespace Tags {
struct Time;
} // namespace Tags
namespace domain::Tags {
struct FunctionsOfTime;
} // namespace domain::Tags
namespace Events::Tags {
template <size_t Dim>
struct ObserverMesh;
Expand Down Expand Up @@ -111,27 +107,13 @@ class Interpolate<VolumeDim, InterpolationTargetTag,
}
}

using is_ready_argument_tags = tmpl::list<::Tags::Time>;
using is_ready_argument_tags = tmpl::list<>;

template <typename Metavariables, typename ArrayIndex, typename Component>
bool is_ready(const double time, Parallel::GlobalCache<Metavariables>& cache,
const ArrayIndex& array_index,
const Component* const component) const {
if constexpr (Parallel::is_dg_element_collection_v<Component>) {
const auto element_location = static_cast<int>(
Parallel::local_synchronous_action<
Parallel::Actions::GetItemFromDistributedOject<
Parallel::Tags::ElementLocations<VolumeDim>>>(
Parallel::get_parallel_component<Component>(cache))
->at(array_index));
return domain::functions_of_time_are_ready_threaded_action_callback<
domain::Tags::FunctionsOfTime,
Parallel::Actions::PerformAlgorithmOnElement<false>>(
cache, element_location, component, time, std::nullopt, array_index);
} else {
return domain::functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime>(cache, array_index, component, time);
}
bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/,
const ArrayIndex& /*array_index*/,
const Component* const /*component*/) const {
return true;
}

bool needs_evolved_variables() const override { return true; }
Expand Down
29 changes: 17 additions & 12 deletions tests/Unit/Domain/FunctionsOfTime/Test_FunctionsOfTimeAreReady.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Framework/TestingFramework.hpp"

#include <array>
#include <limits>
#include <memory>
#include <string>
#include <utility>
Expand Down Expand Up @@ -138,6 +139,8 @@ SPECTRE_TEST_CASE("Unit.Domain.FunctionsOfTimeAreReady", "[Domain][Unit]") {
using component1 = Component<Metavariables, 1_st>;
const component0* const component_0_p = nullptr;
const component1* const component_1_p = nullptr;
// Not used when not using nodegroup element components
constexpr size_t dim = std::numeric_limits<size_t>::max();

const std::array<DataVector, 3> fot_init{{{0.0}, {0.0}, {0.0}}};
FunctionMap functions_of_time{};
Expand Down Expand Up @@ -175,29 +178,31 @@ SPECTRE_TEST_CASE("Unit.Domain.FunctionsOfTimeAreReady", "[Domain][Unit]") {
INFO("Testing perform algorithm callback support");
// Neither function ready
CHECK(not domain::functions_of_time_are_ready_algorithm_callback<
OtherFunctionsOfTime>(cache, 0, component_0_p, 0.5, std::nullopt));
OtherFunctionsOfTime, dim>(cache, 0, component_0_p, 0.5,
std::nullopt));
CHECK(not domain::functions_of_time_are_ready_algorithm_callback<
OtherFunctionsOfTime>(cache, 0, component_0_p, 0.5,
std::unordered_set{"OtherA"s}));
OtherFunctionsOfTime, dim>(cache, 0, component_0_p, 0.5,
std::unordered_set{"OtherA"s}));

// Make OtherA ready
Parallel::mutate<OtherFunctionsOfTime, UpdateFoT>(cache, "OtherA"s, 123.0);

CHECK(domain::functions_of_time_are_ready_algorithm_callback<
OtherFunctionsOfTime>(cache, 0, component_0_p, 0.5,
std::unordered_set{"OtherA"s}));
OtherFunctionsOfTime, dim>(cache, 0, component_0_p, 0.5,
std::unordered_set{"OtherA"s}));
CHECK(not domain::functions_of_time_are_ready_algorithm_callback<
OtherFunctionsOfTime>(cache, 0, component_0_p, 0.5,
std::unordered_set{"OtherA"s, "OtherB"s}));
OtherFunctionsOfTime, dim>(cache, 0, component_0_p, 0.5,
std::unordered_set{"OtherA"s, "OtherB"s}));

// Make OtherB ready
Parallel::mutate<OtherFunctionsOfTime, UpdateFoT>(cache, "OtherB"s, 456.0);

CHECK(domain::functions_of_time_are_ready_algorithm_callback<
OtherFunctionsOfTime>(cache, 0, component_0_p, 0.5,
std::unordered_set{"OtherA"s, "OtherB"s}));
OtherFunctionsOfTime, dim>(cache, 0, component_0_p, 0.5,
std::unordered_set{"OtherA"s, "OtherB"s}));
CHECK(domain::functions_of_time_are_ready_algorithm_callback<
OtherFunctionsOfTime>(cache, 0, component_0_p, 0.5, std::nullopt));
OtherFunctionsOfTime, dim>(cache, 0, component_0_p, 0.5,
std::nullopt));
}

// Test the action. This should automatically look at
Expand Down Expand Up @@ -480,8 +485,8 @@ SPECTRE_TEST_CASE("Unit.Domain.FunctionsOfTimeAreReady", "[Domain][Unit]") {

auto& empty_cache = ActionTesting::cache<empty_comp>(empty_runner, 0);
CHECK(domain::functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime>(empty_cache, 0, empty_component_p,
6.0));
domain::Tags::FunctionsOfTime, dim>(empty_cache, 0, empty_component_p,
6.0));
CHECK(domain::functions_of_time_are_ready_simple_action_callback<
domain::Tags::FunctionsOfTime, SimpleActionNoArgs>(
empty_cache, 0, empty_component_p, 6.0, std::nullopt));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,20 +289,13 @@ SPECTRE_TEST_CASE("Unit.NumericalAlgorithms.Interpolator.InterpolateEvent",

metavars::event event{};

// Functions of time aren't ready yet.
CHECK_FALSE(static_cast<const Event&>(event).is_ready(
box, cache, array_index, std::add_pointer_t<elem_component>{}));

// Update time in box and functions of time
db::mutate<::Tags::Time>([](gsl::not_null<double*> time) { *time = 1.0; },
make_not_null(&box));
Parallel::mutate<domain::Tags::FunctionsOfTime,
control_system::UpdateSingleFunctionOfTime>(
cache, name, initial_expr_time, DataVector{1, 0.0}, observation_time);

// Now everything should be ready
CHECK(static_cast<const Event&>(event).is_ready(
box, cache, array_index, std::add_pointer_t<elem_component>{}));
CHECK(event.needs_evolved_variables());

auto obs_box = make_observation_box<
Expand Down

0 comments on commit 970e70d

Please sign in to comment.