8 #include <boost/preprocessor/control/if.hpp>
9 #include <boost/preprocessor/logical/compl.hpp>
10 #include <boost/preprocessor/logical/not.hpp>
11 #include <boost/preprocessor/punctuation/comma_if.hpp>
12 #include <boost/preprocessor/repetition/repeat.hpp>
21 #include "Parallel/AlgorithmMetafunctions.hpp"
23 #include "Parallel/NodeLock.hpp"
24 #include "Parallel/ParallelComponentHelpers.hpp"
25 #include "Parallel/PhaseDependentActionList.hpp"
26 #include "Parallel/SimpleActionVisitation.hpp"
30 #include "Utilities/NoSuchType.hpp"
31 #include "Utilities/Overloader.hpp"
35 #include "Utilities/TypeTraits.hpp"
41 #define ACTION_TESTING_CHECK_MOCK_ACTION_LIST(NAME) \
42 template <typename Component, typename = std::void_t<>> \
43 struct get_##NAME##_mocking_list { \
44 using replace_these_##NAME = tmpl::list<>; \
45 using with_these_##NAME = tmpl::list<>; \
47 template <typename Component> \
48 struct get_##NAME##_mocking_list< \
49 Component, std::void_t<typename Component::replace_these_##NAME, \
50 typename Component::with_these_##NAME>> { \
51 using replace_these_##NAME = typename Component::replace_these_##NAME; \
52 using with_these_##NAME = typename Component::with_these_##NAME; \
54 template <typename Component> \
55 using replace_these_##NAME##_t = \
56 typename get_##NAME##_mocking_list<Component>::replace_these_##NAME; \
57 template <typename Component> \
58 using with_these_##NAME##_t = \
59 typename get_##NAME##_mocking_list<Component>::with_these_##NAME
61 ACTION_TESTING_CHECK_MOCK_ACTION_LIST(simple_actions);
62 ACTION_TESTING_CHECK_MOCK_ACTION_LIST(threaded_actions);
63 #undef ACTION_TESTING_CHECK_MOCK_ACTION_LIST
65 template <
typename Component,
typename = std::
void_t<>>
66 struct get_initialization_tags_from_component {
67 using type = tmpl::list<>;
70 template <
typename Component>
71 struct get_initialization_tags_from_component<
72 Component, std::void_t<typename Component::initialization_tags>> {
73 using type =
typename Component::initialization_tags;
77 template <
typename SimpleTagsList>
78 struct ForwardAllOptionsToDataBox;
80 template <
typename... SimpleTags>
81 struct ForwardAllOptionsToDataBox<tmpl::list<SimpleTags...>> {
82 using simple_tags = tmpl::list<SimpleTags...>;
84 template <
typename DbTagsList,
typename... Args>
85 static auto apply(db::DataBox<DbTagsList>&& box, Args&&... args) noexcept {
87 sizeof...(SimpleTags) ==
sizeof...(Args),
88 "The number of arguments passed to ForwardAllOptionsToDataBox must "
89 "match the number of SimpleTags passed.");
90 return db::create_from<db::RemoveTags<>, simple_tags>(
91 std::move(box), std::forward<Args>(args)...);
98 template <
typename Tag,
typename DataBoxType,
99 bool = db::tag_is_retrievable_v<Tag, DataBoxType>>
100 struct item_type_if_contained;
102 template <
typename Tag,
typename DataBoxType>
103 struct item_type_if_contained<Tag, DataBoxType, true> {
104 using type = decltype(db::get<Tag>(DataBoxType{}));
107 template <
typename Tag,
typename DataBoxType>
108 struct item_type_if_contained<Tag, DataBoxType, false> {
112 template <
typename Tag,
typename DataBoxType>
113 using item_type_if_contained_t =
114 typename item_type_if_contained<Tag, DataBoxType>::type;
138 template <
typename Component>
141 class InvokeActionBase {
143 InvokeActionBase() =
default;
144 InvokeActionBase(
const InvokeActionBase&) =
default;
145 InvokeActionBase& operator=(
const InvokeActionBase&) =
default;
146 InvokeActionBase(InvokeActionBase&&) =
default;
147 InvokeActionBase& operator=(InvokeActionBase&&) =
default;
148 virtual ~InvokeActionBase() =
default;
149 virtual void invoke_action() noexcept = 0;
158 template <
typename Action,
typename... Args>
159 class InvokeSimpleAction :
public InvokeActionBase {
163 : mock_distributed_object_(mock_distributed_object),
164 args_(std::move(args)) {}
167 : mock_distributed_object_(mock_distributed_object) {}
169 void invoke_action() noexcept
override {
172 "Cannot invoke the exact same simple action twice. This is an "
173 "internal bug in the action testing framework. Please file an "
177 invoke_action_impl(std::move(args_));
181 template <
typename Arg0,
typename... Rest>
183 mock_distributed_object_->simple_action<Action>(std::move(args),
true);
186 template <
typename... LocalArgs,
187 Requires<
sizeof...(LocalArgs) == 0> =
nullptr>
189 mock_distributed_object_->simple_action<Action>(
true);
199 template <
typename Action,
typename... Args>
200 class InvokeThreadedAction :
public InvokeActionBase {
204 : mock_distributed_object_(mock_distributed_object),
205 args_(std::move(args)) {}
207 explicit InvokeThreadedAction(
209 : mock_distributed_object_(mock_distributed_object) {}
211 void invoke_action() noexcept
override {
214 "Cannot invoke the exact same threaded action twice. This is an "
215 "internal bug in the action testing framework. Please file an "
219 invoke_action_impl(std::move(args_));
223 template <
typename Arg0,
typename... Rest>
225 mock_distributed_object_->threaded_action<Action>(std::move(args),
true);
228 template <
typename... LocalArgs,
229 Requires<
sizeof...(LocalArgs) == 0> =
nullptr>
231 mock_distributed_object_->threaded_action<Action>(
true);
240 using phase_dependent_action_lists =
241 typename Component::phase_dependent_action_list;
242 static_assert(tmpl::size<phase_dependent_action_lists>::value > 0,
243 "Must have at least one phase dependent action list "
244 "(PhaseActions) in a parallel component.");
246 using all_actions_list = tmpl::flatten<tmpl::transform<
247 phase_dependent_action_lists,
250 using metavariables =
typename Component::metavariables;
252 using inbox_tags_list =
255 using array_index =
typename Parallel::get_array_index<
256 typename Component::chare_type>::template f<Component>;
258 using parallel_component = Component;
261 typename tmpl::front<phase_dependent_action_lists>::phase_type;
264 using initialization_tags =
265 typename detail::get_initialization_tags_from_component<Component>::type;
266 using initial_tags = tmpl::flatten<tmpl::list<
272 using databox_phase_types =
273 typename Parallel::Algorithm_detail::build_databox_types<
274 tmpl::list<>, phase_dependent_action_lists, initial_databox,
275 inbox_tags_list, metavariables,
typename Component::array_index,
277 template <
typename T>
279 using type =
typename T::databox_types;
282 using databox_types = tmpl::flatten<
283 tmpl::transform<databox_phase_types, get_databox_types<tmpl::_1>>>;
284 using variant_boxes = tmpl::remove_duplicates<
285 tmpl::push_front<databox_types, db::DataBox<tmpl::list<>>>>;
291 const array_index& index,
293 tuples::tagged_tuple_from_typelist<inbox_tags_list>* inboxes,
295 : array_index_(index), global_cache_(cache), inboxes_(inboxes) {
296 box_ = detail::ForwardAllOptionsToDataBox<initialization_tags>::apply(
302 std::forward<Options>(opts)...);
305 void set_phase(PhaseType phase) noexcept {
308 terminate_ = number_of_actions_in_phase(phase) == 0;
310 PhaseType get_phase() const noexcept {
return phase_; }
312 void set_terminate(
bool t) noexcept { terminate_ = t; }
313 bool get_terminate() const noexcept {
return terminate_; }
317 void perform_algorithm() noexcept {}
319 size_t number_of_actions_in_phase(
const PhaseType phase)
const noexcept {
320 size_t number_of_actions = 0;
321 tmpl::for_each<phase_dependent_action_lists>(
322 [&number_of_actions, phase](
auto pdal_v) {
323 const auto pdal = tmpl::type_from<decltype(pdal_v)>{};
324 if (pdal.phase == phase) {
325 number_of_actions = pdal.number_of_actions;
328 return number_of_actions;
335 template <
typename AdditionalTagsList>
338 tmpl::flatten<tmpl::list<initial_tags, AdditionalTagsList>>>;
339 return boost::get<box_type>(box_);
342 template <
typename AdditionalTagsList>
345 tmpl::flatten<tmpl::list<initial_tags, AdditionalTagsList>>>;
346 return boost::get<box_type>(box_);
353 template <
typename Tag>
355 return get_databox_tag_visitation<Tag>(box_);
358 template <
typename Tag>
359 bool box_contains() const noexcept {
360 return box_contains_visitation<Tag>(box_);
363 template <
typename Tag>
364 bool tag_is_retrievable() const noexcept {
365 return tag_is_retrievable_visitation<Tag>(box_);
378 algorithm_step_ = next_action_id;
394 #define SIMPLE_AND_THREADED_ACTIONS(USE_SIMPLE_ACTION, NAME) \
395 template <typename Action, typename... Args, \
396 Requires<not tmpl::list_contains_v< \
397 detail::replace_these_##NAME##s_t<Component>, Action>> = \
399 void NAME(std::tuple<Args...> args, \
400 const bool direct_from_action_runner = false) noexcept { \
401 if (direct_from_action_runner) { \
402 performing_action_ = true; \
403 forward_tuple_to_##NAME<Action>( \
404 std::move(args), std::make_index_sequence<sizeof...(Args)>{}); \
405 performing_action_ = false; \
407 NAME##_queue_.push_back( \
408 std::make_unique<BOOST_PP_IF(USE_SIMPLE_ACTION, InvokeSimpleAction, \
409 InvokeThreadedAction) < Action, \
410 Args...> > (this, std::move(args))); \
413 template <typename Action, typename... Args, \
414 Requires<tmpl::list_contains_v< \
415 detail::replace_these_##NAME##s_t<Component>, Action>> = \
417 void NAME(std::tuple<Args...> args, \
418 const bool direct_from_action_runner = false) noexcept { \
419 using index_of_action = \
420 tmpl::index_of<detail::replace_these_##NAME##s_t<Component>, Action>; \
421 using new_action = tmpl::at_c<detail::with_these_##NAME##s_t<Component>, \
422 index_of_action::value>; \
423 if (direct_from_action_runner) { \
424 performing_action_ = true; \
425 forward_tuple_to_##NAME<new_action>( \
426 std::move(args), std::make_index_sequence<sizeof...(Args)>{}); \
427 performing_action_ = false; \
429 NAME##_queue_.push_back( \
430 std::make_unique<BOOST_PP_IF(USE_SIMPLE_ACTION, InvokeSimpleAction, \
431 InvokeThreadedAction) < new_action, \
432 Args...> > (this, std::move(args))); \
435 template <typename Action, \
436 Requires<not tmpl::list_contains_v< \
437 detail::replace_these_##NAME##s_t<Component>, Action>> = \
439 void NAME(const bool direct_from_action_runner = false) noexcept { \
440 if (direct_from_action_runner) { \
441 performing_action_ = true; \
442 Parallel::Algorithm_detail::simple_action_visitor<Action, Component>( \
443 box_, *global_cache_, \
444 std::as_const(array_index_) \
445 BOOST_PP_COMMA_IF(BOOST_PP_NOT(USE_SIMPLE_ACTION)) BOOST_PP_IF( \
446 USE_SIMPLE_ACTION, , make_not_null(&node_lock_))); \
447 performing_action_ = false; \
449 NAME##_queue_.push_back( \
450 std::make_unique<BOOST_PP_IF(USE_SIMPLE_ACTION, InvokeSimpleAction, \
451 InvokeThreadedAction) < Action> > \
455 template <typename Action, \
456 Requires<tmpl::list_contains_v< \
457 detail::replace_these_##NAME##s_t<Component>, Action>> = \
459 void NAME(const bool direct_from_action_runner = false) noexcept { \
460 using index_of_action = \
461 tmpl::index_of<detail::replace_these_##NAME##s_t<Component>, Action>; \
462 using new_action = tmpl::at_c<detail::with_these_##NAME##s_t<Component>, \
463 index_of_action::value>; \
464 if (direct_from_action_runner) { \
465 performing_action_ = true; \
466 Parallel::Algorithm_detail::simple_action_visitor<new_action, \
468 box_, *global_cache_, \
469 std::as_const(array_index_) \
470 BOOST_PP_COMMA_IF(BOOST_PP_NOT(USE_SIMPLE_ACTION)) BOOST_PP_IF( \
471 USE_SIMPLE_ACTION, , make_not_null(&node_lock_))); \
472 performing_action_ = false; \
474 simple_action_queue_.push_back( \
475 std::make_unique<BOOST_PP_IF(USE_SIMPLE_ACTION, InvokeSimpleAction, \
476 InvokeThreadedAction) < new_action> > \
483 #undef SIMPLE_AND_THREADED_ACTIONS
485 bool is_simple_action_queue_empty() const noexcept {
486 return simple_action_queue_.empty();
489 void invoke_queued_simple_action() noexcept {
490 if (simple_action_queue_.empty()) {
492 "There are no queued simple actions to invoke. Are you sure a "
493 "previous action invoked a simple action on this component?");
495 simple_action_queue_.front()->invoke_action();
496 simple_action_queue_.pop_front();
499 bool is_threaded_action_queue_empty() const noexcept {
500 return threaded_action_queue_.empty();
503 void invoke_queued_threaded_action() noexcept {
504 if (threaded_action_queue_.empty()) {
506 "There are no queued threaded actions to invoke. Are you sure a "
507 "previous action invoked a threaded action on this component?");
509 threaded_action_queue_.front()->invoke_action();
510 threaded_action_queue_.pop_front();
513 template <
typename InboxTag,
typename Data>
514 void receive_data(
const typename InboxTag::temporal_id&
id, Data&& data,
515 const bool enable_if_disabled =
false) {
519 (void)enable_if_disabled;
520 InboxTag::insert_into_inbox(
522 std::forward<Data>(data));
526 template <
typename Action,
typename... Args,
size_t... Is>
527 void forward_tuple_to_simple_action(
530 Parallel::Algorithm_detail::simple_action_visitor<Action, Component>(
531 box_, *global_cache_, std::as_const(array_index_),
532 std::forward<Args>(std::get<Is>(args))...);
535 template <
typename Action,
typename... Args,
size_t... Is>
536 void forward_tuple_to_threaded_action(
539 Parallel::Algorithm_detail::simple_action_visitor<Action, Component>(
540 box_, *global_cache_, std::as_const(array_index_),
541 make_not_null(&node_lock_), std::forward<Args>(std::get<Is>(args))...);
544 template <
typename PhaseDepActions,
size_t... Is>
547 template <
typename PhaseDepActions,
size_t... Is>
550 template <
typename Tag,
typename ThisVariantBox,
typename Type,
551 typename... Variants,
553 typename ThisVariantBox::tags_list,
556 void get_databox_tag_visitation_impl(
559 const boost::variant<Variants...>& box)
const noexcept {
560 if (box.which() == *iter and not *already_visited) {
561 *result = &db::get<Tag>(boost::get<ThisVariantBox>(box));
563 *already_visited =
true;
567 template <
typename Tag,
typename ThisVariantBox,
typename Type,
568 typename... Variants,
570 typename ThisVariantBox::tags_list,
573 void get_databox_tag_visitation_impl(
576 const boost::variant<Variants...>& box)
const noexcept {
577 if (box.which() == *iter and not *already_visited) {
578 ERROR(
"Cannot retrieve tag: "
579 << db::tag_name<Tag>()
580 <<
" from the current DataBox because it is not in it.");
585 template <
typename Tag,
typename... Variants>
586 const auto& get_databox_tag_visitation(
587 const boost::variant<Variants...>& box)
const noexcept {
588 using item_types = tmpl::remove_duplicates<tmpl::remove_if<
589 tmpl::list<cpp20::remove_cvref_t<
590 detail::item_type_if_contained_t<Tag, Variants>>...>,
592 static_assert(tmpl::size<item_types>::value != 0,
593 "Could not find the tag or the tag as a base tag in any "
594 "DataBox in the get_databox_tag function.");
596 tmpl::size<item_types>::value < 2,
597 "Found the tag in or the tag as a base tag in more than one DataBox in "
598 "the get_databox_tag function. This means you need to explicitly "
599 "retrieve the DataBox type to retrieve the tag or file an issue "
600 "requesting a get_databox_tag function that can also take a type "
601 "explicitly. We have not yet encountered a need for this functionality "
602 "but it could be added.");
603 const tmpl::front<item_types>* result =
nullptr;
605 bool already_visited =
false;
607 &result, &iter, &already_visited, box));
608 if (result ==
nullptr) {
609 ERROR(
"The result pointer is nullptr, which it should never be.\n");
614 template <
typename Tag,
typename ThisVariantBox,
typename... Variants,
615 Requires<tmpl::list_contains_v<
typename ThisVariantBox::tags_list,
617 void box_contains_visitation_impl(
619 const boost::variant<Variants...>& box)
const noexcept {
620 if (box.which() == *iter) {
622 tmpl::list_contains_v<typename ThisVariantBox::tags_list, Tag>;
626 template <
typename Tag,
typename ThisVariantBox,
typename... Variants,
628 typename ThisVariantBox::tags_list, Tag>> =
nullptr>
629 void box_contains_visitation_impl(
631 const boost::variant<Variants...>& )
const noexcept {
635 template <
typename Tag,
typename... Variants>
636 bool box_contains_visitation(
637 const boost::variant<Variants...>& box)
const noexcept {
638 bool contains_tag =
false;
641 box_contains_visitation_impl<Tag, Variants>(&contains_tag, &iter, box));
645 template <
typename Tag,
typename... Variants>
646 bool tag_is_retrievable_visitation(
647 const boost::variant<Variants...>& box)
const noexcept {
648 bool is_retrievable =
false;
649 const auto helper = [&box, &is_retrievable](
auto box_type) noexcept {
650 using DataBoxType =
typename decltype(box_type)::type;
651 if (
static_cast<int>(
652 tmpl::index_of<tmpl::list<Variants...>, DataBoxType>::value) ==
654 is_retrievable = db::tag_is_retrievable_v<Tag, DataBoxType>;
658 return is_retrievable;
661 bool terminate_{
false};
664 size_t algorithm_step_ = 0;
665 bool performing_action_ =
false;
668 typename Component::array_index array_index_{};
671 tuples::tagged_tuple_from_typelist<inbox_tags_list>* inboxes_{
nullptr};
677 template <
typename Component>
679 bool found_matching_phase =
false;
680 const auto invoke_for_phase =
681 [
this, &found_matching_phase](
auto phase_dep_v) noexcept {
682 using PhaseDep =
typename decltype(phase_dep_v)::type;
683 constexpr PhaseType phase = PhaseDep::phase;
684 using actions_list =
typename PhaseDep::action_list;
685 if (phase_ == phase) {
686 found_matching_phase =
true;
687 this->
template next_action_impl<PhaseDep>(
691 tmpl::for_each<phase_dependent_action_lists>(invoke_for_phase);
692 if (not found_matching_phase) {
693 ERROR(
"Could not find any actions in the current phase for the component '"
694 << pretty_type::short_name<Component>() <<
"'.");
698 template <
typename Component>
699 template <
typename PhaseDepActions,
size_t... Is>
704 "Cannot call an Action while already calling an Action on the same "
705 "MockDistributedObject (an element of a parallel component array, or a "
706 "parallel component singleton).");
710 bool already_did_an_action =
false;
711 const auto helper = [
this, &already_did_an_action](
auto iteration) noexcept {
712 constexpr
size_t iter = decltype(iteration)::value;
713 if (already_did_an_action or algorithm_step_ != iter) {
717 using actions_list =
typename PhaseDepActions::action_list;
718 using this_action = tmpl::at_c<actions_list, iter>;
737 std::tie(box_) = this_action::apply(
738 my_box, *inboxes_, *global_cache_, std::as_const(array_index_),
743 std::tie(box_, terminate_) = this_action::apply(
744 my_box, *inboxes_, *global_cache_, std::as_const(array_index_),
749 std::tie(box_, terminate_, algorithm_step_) = this_action::apply(
750 my_box, *inboxes_, *global_cache_, std::as_const(array_index_),
763 const auto& check_local_box) noexcept {
765 check_local_box, std::
as_const(*inboxes_), *global_cache_,
769 const auto& ) noexcept {
return true; });
771 constexpr
size_t phase_index =
772 tmpl::index_of<phase_dependent_action_lists, PhaseDepActions>::value;
773 using databox_phase_type = tmpl::at_c<databox_phase_types, phase_index>;
774 using databox_types_this_phase =
typename databox_phase_type::databox_types;
776 const auto display_databox_error = [
this]() noexcept {
778 "The DataBox type being retrieved at algorithm step: "
779 << algorithm_step_ <<
" in phase " << phase_index
780 <<
" corresponding to action " << pretty_type::get_name<this_action>()
781 <<
" is not the correct type but is of variant index " << box_.which()
783 <<
"\nIf you are using Goto and Label actions then you are using "
784 "them incorrectly.");
795 [
this, &check_if_ready, &invoke_this_action, &
796 display_databox_error ](
auto current_iter) noexcept
798 decltype(current_iter)>::value> {
802 using first_databox = tmpl::at_c<databox_types_this_phase, 0>;
804 tmpl::at_c<databox_types_this_phase,
805 tmpl::size<databox_types_this_phase>::value - 1>;
806 using local_this_action =
807 tmpl::at_c<actions_list, decltype(current_iter)::value>;
810 tmpl::index_of<variant_boxes, first_databox>::value)) {
811 using this_databox = first_databox;
812 auto& box = boost::get<this_databox>(box_);
813 if (not check_if_ready(
814 Parallel::Algorithm_detail::is_is_ready_callable_t<
815 local_this_action, this_databox,
816 tuples::tagged_tuple_from_typelist<inbox_tags_list>,
818 local_this_action{}, box)) {
819 ERROR(
"Tried to invoke the action '"
820 << pretty_type::get_name<local_this_action>()
821 <<
"' but have not received all the "
824 performing_action_ =
true;
828 typename std::tuple_size<decltype(local_this_action::apply(
829 box, *inboxes_, *global_cache_, std::as_const(array_index_),
831 }
else if (box_.which() ==
833 tmpl::index_of<variant_boxes, last_databox>::value)) {
834 using this_databox = last_databox;
835 auto& box = boost::get<this_databox>(box_);
836 if (not check_if_ready(
837 Parallel::Algorithm_detail::is_is_ready_callable_t<
838 local_this_action, this_databox,
839 tuples::tagged_tuple_from_typelist<inbox_tags_list>,
841 local_this_action{}, box)) {
842 ERROR(
"Tried to invoke the action '"
843 << pretty_type::get_name<local_this_action>()
844 <<
"' but have not received all the "
847 performing_action_ =
true;
851 typename std::tuple_size<decltype(local_this_action::apply(
852 box, *inboxes_, *global_cache_, std::as_const(array_index_),
855 display_databox_error();
860 [
this, &check_if_ready, &invoke_this_action, &
861 display_databox_error ](
auto current_iter) noexcept
863 decltype(current_iter)>::value> {
866 using this_databox = tmpl::at_c<databox_types_this_phase,
867 decltype(current_iter)::value>;
868 using local_this_action =
869 tmpl::at_c<actions_list, decltype(current_iter)::value>;
872 tmpl::index_of<variant_boxes, this_databox>::value)) {
873 auto& box = boost::get<this_databox>(box_);
874 if (not check_if_ready(
875 Parallel::Algorithm_detail::is_is_ready_callable_t<
876 local_this_action, this_databox,
877 tuples::tagged_tuple_from_typelist<inbox_tags_list>,
879 local_this_action{}, box)) {
880 ERROR(
"Tried to invoke the action '"
881 << pretty_type::get_name<local_this_action>()
882 <<
"' but have not received all the "
885 performing_action_ =
true;
889 typename std::tuple_size<decltype(local_this_action::apply(
890 box, *inboxes_, *global_cache_, std::as_const(array_index_),
893 display_databox_error();
898 performing_action_ =
false;
899 already_did_an_action =
true;
901 if (algorithm_step_ >= tmpl::size<actions_list>::value) {
910 template <
typename Component>
912 bool action_is_ready =
false;
913 bool found_matching_phase =
false;
914 const auto invoke_for_phase = [
this, &action_is_ready, &found_matching_phase](
915 auto phase_dep_v) noexcept {
916 using PhaseDep =
typename decltype(phase_dep_v)::type;
917 constexpr PhaseType phase = PhaseDep::phase;
918 using actions_list =
typename PhaseDep::action_list;
919 if (phase_ == phase) {
920 found_matching_phase =
true;
921 action_is_ready = this->
template is_ready_impl<PhaseDep>(
925 tmpl::for_each<phase_dependent_action_lists>(invoke_for_phase);
926 if (not found_matching_phase) {
927 ERROR(
"Could not find any actions in the current phase for the component '"
928 << pretty_type::short_name<Component>() <<
"'.");
930 return action_is_ready;
933 template <
typename Component>
934 template <
typename PhaseDepActions,
size_t... Is>
937 bool next_action_is_ready =
false;
938 const auto helper = [
this, &array_index = array_index_, &inboxes = *inboxes_,
939 &global_cache = global_cache_,
940 &next_action_is_ready](
auto iteration) noexcept {
941 constexpr
size_t iter = decltype(iteration)::value;
942 using actions_list =
typename PhaseDepActions::action_list;
943 using this_action = tmpl::at_c<actions_list, iter>;
945 constexpr
size_t phase_index =
946 tmpl::index_of<phase_dependent_action_lists, PhaseDepActions>::value;
947 using databox_phase_type = tmpl::at_c<databox_phase_types, phase_index>;
948 using databox_types_this_phase =
typename databox_phase_type::databox_types;
950 tmpl::at_c<databox_types_this_phase,
951 iter == 0 ? tmpl::size<databox_types_this_phase>::value - 1
953 if (iter != algorithm_step_) {
957 this_databox* box_ptr{};
959 box_ptr = &boost::get<this_databox>(box_);
962 "\nFailed to retrieve Databox in take_next_action:\nCaught "
964 << e.what() <<
"'\nDataBox type: '"
965 << pretty_type::get_name<this_databox>() <<
"'\nIteration: " << iter
966 <<
"\nAction: '" << pretty_type::get_name<this_action>()
967 <<
"'\nBoost::Variant id: " << box_.which()
971 this_databox& box = *box_ptr;
981 [&box, &array_index, &global_cache, &inboxes](
984 std::
as_const(inboxes), *global_cache,
989 next_action_is_ready =
990 check_if_ready(Parallel::Algorithm_detail::is_is_ready_callable_t<
991 this_action, this_databox,
992 tuples::tagged_tuple_from_typelist<inbox_tags_list>,
994 typename Component::array_index>{},
1000 return next_action_is_ready;