Skip to content

Commit

Permalink
Merge pull request #5513 from knelli2/simple_action_fot_ready
Browse files Browse the repository at this point in the history
Add FoTAreReady function for simple actions
  • Loading branch information
wthrowe authored Oct 2, 2023
2 parents 4de07c1 + d8969fb commit 626e0da
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 84 deletions.
5 changes: 2 additions & 3 deletions src/ControlSystem/Event.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,8 @@ class Event : public ::Event {
// measurement is being made for. We need all of them to access
// coordinate-dependent quantities, which almost all control
// measurements will need.
const bool ready =
domain::functions_of_time_are_ready<domain::Tags::FunctionsOfTime>(
cache, array_index, component, time);
const bool ready = domain::functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime>(cache, array_index, component, time);

if (Parallel::get<Tags::Verbosity>(cache) >= ::Verbosity::Debug) {
Parallel::printf("%s, time = %.16f: Control system events are%s ready.\n",
Expand Down
9 changes: 6 additions & 3 deletions src/ControlSystem/Trigger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "ControlSystem/CombinedName.hpp"
Expand Down Expand Up @@ -134,9 +135,11 @@ class Trigger : public DenseTrigger {
std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
measurement_timescales) {
// At least one control system is active
const bool is_ready = domain::functions_of_time_are_ready<
control_system::Tags::MeasurementTimescales>(
cache, array_index, component, time, std::array{measurement_name_});
const bool is_ready =
domain::functions_of_time_are_ready_algorithm_callback<
control_system::Tags::MeasurementTimescales>(
cache, array_index, component, time,
std::unordered_set{measurement_name_});
if (not is_ready) {
if (Parallel::get<Tags::Verbosity>(cache) >= ::Verbosity::Debug) {
Parallel::printf(
Expand Down
149 changes: 102 additions & 47 deletions src/Domain/FunctionsOfTime/FunctionsOfTimeAreReady.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>

#include "DataStructures/DataBox/DataBox.hpp"
Expand All @@ -18,6 +19,7 @@
#include "Parallel/ArrayComponentId.hpp"
#include "Parallel/Callback.hpp"
#include "Parallel/GlobalCache.hpp"
#include "Parallel/ParallelComponentHelpers.hpp"
#include "Utilities/Algorithm.hpp"
#include "Utilities/ErrorHandling/Assert.hpp"
#include "Utilities/StdHelpers.hpp"
Expand All @@ -36,55 +38,107 @@ class TaggedTuple;
/// \endcond

namespace domain {
namespace detail {
template <typename CacheTag, typename Callback, typename Metavariables,
typename ArrayIndex, typename Component, typename... Args>
bool functions_of_time_are_ready_impl(
Parallel::GlobalCache<Metavariables>& cache, const ArrayIndex& array_index,
const Component* /*meta*/, const double time,
const std::optional<std::unordered_set<std::string>>& functions_to_check,
Args&&... args) {
if constexpr (Parallel::is_in_global_cache<Metavariables, CacheTag>) {
const auto& proxy =
::Parallel::get_parallel_component<Component>(cache)[array_index];
const Parallel::ArrayComponentId array_component_id =
Parallel::make_array_component_id<Component>(array_index);

return Parallel::mutable_cache_item_is_ready<CacheTag>(
cache, array_component_id,
[&functions_to_check, &proxy, &time,
&args...](const std::unordered_map<
std::string,
std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
functions_of_time) {
using ::operator<<;
ASSERT(
alg::all_of(
functions_to_check.value_or(
std::unordered_set<std::string>{}),
[&functions_of_time](const std::string& function_to_check) {
return functions_of_time.count(function_to_check) == 1;
}),
"Not all functions to check ("
<< functions_to_check.value() << ") are in the global cache ("
<< keys_of(functions_of_time) << ")");
for (const auto& [name, f_of_t] : functions_of_time) {
if (functions_to_check.has_value() and
functions_to_check->count(name) == 0) {
continue;
}
const double expiration_time = f_of_t->time_bounds()[1];
if (time > expiration_time) {
return std::unique_ptr<Parallel::Callback>(
new Callback(proxy, std::forward<Args>(args)...));
}
}
return std::unique_ptr<Parallel::Callback>{};
});
} else {
(void)cache;
(void)array_index;
(void)time;
(void)functions_to_check;
EXPAND_PACK_LEFT_TO_RIGHT((void)args);
return true;
}
}
} // 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 no names are
/// listed in \p functions_to_check, checks all functions in \p
/// CacheTag. If any function is not ready, schedules a
/// `Parallel::PerformAlgorithmCallback` with the GlobalCache.
/// 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, size_t N = 0>
bool functions_of_time_are_ready(
typename Component>
bool functions_of_time_are_ready_algorithm_callback(
Parallel::GlobalCache<Metavariables>& cache, const ArrayIndex& array_index,
const Component* /*meta*/, const double time,
const std::array<std::string, N>& functions_to_check =
std::array<std::string, 0>{}) {
const auto& proxy =
::Parallel::get_parallel_component<Component>(cache)[array_index];
const Parallel::ArrayComponentId array_component_id =
Parallel::make_array_component_id<Component>(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);
}

return Parallel::mutable_cache_item_is_ready<CacheTag>(
cache, array_component_id,
[&functions_to_check, &proxy,
&time](const std::unordered_map<
std::string,
std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>&
functions_of_time) {
using ::operator<<;
ASSERT(alg::all_of(
functions_to_check,
[&functions_of_time](const std::string& function_to_check) {
return functions_of_time.count(function_to_check) == 1;
}),
"Not all functions to check ("
<< functions_to_check << ") are in the global cache ("
<< keys_of(functions_of_time) << ")");
for (const auto& [name, f_of_t] : functions_of_time) {
if ((not functions_to_check.empty()) and
alg::find(functions_to_check, name) == functions_to_check.end()) {
continue;
}
const double expiration_time = f_of_t->time_bounds()[1];
if (time > expiration_time) {
return std::unique_ptr<Parallel::Callback>(
new Parallel::PerformAlgorithmCallback(proxy));
}
}
return std::unique_ptr<Parallel::Callback>{};
});
/// \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
/// ready, schedules a `Parallel::SimpleActionCallback` with the GlobalCache
/// which calls the simple action passed in as a template parameter. The `Args`
/// are moved into the callback.
template <typename CacheTag, typename SimpleAction, typename Metavariables,
typename ArrayIndex, typename Component, typename... Args>
bool functions_of_time_are_ready_simple_action_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,
Args&&... args) {
using ProxyType = std::decay_t<decltype(
::Parallel::get_parallel_component<Component>(cache)[array_index])>;
return detail::functions_of_time_are_ready_impl<
CacheTag,
Parallel::SimpleActionCallback<SimpleAction, ProxyType, Args...>>(
cache, array_index, component_p, time, functions_to_check,
std::forward<Args>(args)...);
}

namespace Actions {
Expand All @@ -104,9 +158,9 @@ struct CheckFunctionsOfTimeAreReady {
Parallel::GlobalCache<Metavariables>& cache,
const ArrayIndex& array_index, ActionList /*meta*/,
const ParallelComponent* component) {
const bool ready =
functions_of_time_are_ready<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>(cache, array_index, component,
db::get<::Tags::Time>(box));
return {ready ? Parallel::AlgorithmExecution::Continue
: Parallel::AlgorithmExecution::Retry,
std::nullopt};
Expand Down Expand Up @@ -134,8 +188,9 @@ struct CheckFunctionsOfTimeAreReadyPostprocessor {
const gsl::not_null<tuples::TaggedTuple<InboxTags...>*> /*inboxes*/,
Parallel::GlobalCache<Metavariables>& cache,
const ArrayIndex& array_index, const ParallelComponent* component) {
return functions_of_time_are_ready<domain::Tags::FunctionsOfTime>(
cache, array_index, component, db::get<::Tags::Time>(*box));
return functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime>(cache, array_index, component,
db::get<::Tags::Time>(*box));
}
};
} // namespace domain
8 changes: 4 additions & 4 deletions src/Parallel/Callback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ class SimpleActionCallback : public Callback {
public:
WRAPPED_PUPable_decl_template(SimpleActionCallback); // NOLINT
SimpleActionCallback() = default;
SimpleActionCallback(Proxy proxy, Args&&... args)
: proxy_(proxy),
args_(std::make_tuple<Args...>(std::forward<Args>(args)...)) {}
// NOLINTNEXTLINE(google-explicit-constructor)
SimpleActionCallback(Proxy proxy, std::decay_t<Args>... args)
: proxy_(proxy), args_(std::move(args)...) {}
SimpleActionCallback(CkMigrateMessage* msg) : Callback(msg) {}
using PUP::able::register_constructor;
void invoke() override {
Expand All @@ -56,7 +56,7 @@ class SimpleActionCallback : public Callback {

private:
Proxy proxy_{};
std::tuple<Args...> args_{};
std::tuple<std::decay_t<Args>...> args_{};
};

/// Wraps a call to a simple action without arguments.
Expand Down
4 changes: 2 additions & 2 deletions src/ParallelAlgorithms/Interpolation/Events/Interpolate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ class Interpolate<VolumeDim, InterpolationTargetTag,
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<domain::Tags::FunctionsOfTime>(
cache, array_index, component, time);
return domain::functions_of_time_are_ready_algorithm_callback<
domain::Tags::FunctionsOfTime>(cache, array_index, component, time);
}

bool needs_evolved_variables() const override { return true; }
Expand Down
Loading

0 comments on commit 626e0da

Please sign in to comment.