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>
22 #include "Parallel/AlgorithmMetafunctions.hpp"
24 #include "Parallel/NodeLock.hpp"
25 #include "Parallel/ParallelComponentHelpers.hpp"
26 #include "Parallel/PhaseDependentActionList.hpp"
27 #include "Parallel/SimpleActionVisitation.hpp"
31 #include "Utilities/NoSuchType.hpp"
32 #include "Utilities/Overloader.hpp"
36 #include "Utilities/TypeTraits.hpp"
40 struct MockNodeGroupChare;
45 #define ACTION_TESTING_CHECK_MOCK_ACTION_LIST(NAME) \
46 template <typename Component, typename = std::void_t<>> \
47 struct get_##NAME##_mocking_list { \
48 using replace_these_##NAME = tmpl::list<>; \
49 using with_these_##NAME = tmpl::list<>; \
51 template <typename Component> \
52 struct get_##NAME##_mocking_list< \
53 Component, std::void_t<typename Component::replace_these_##NAME, \
54 typename Component::with_these_##NAME>> { \
55 using replace_these_##NAME = typename Component::replace_these_##NAME; \
56 using with_these_##NAME = typename Component::with_these_##NAME; \
58 template <typename Component> \
59 using replace_these_##NAME##_t = \
60 typename get_##NAME##_mocking_list<Component>::replace_these_##NAME; \
61 template <typename Component> \
62 using with_these_##NAME##_t = \
63 typename get_##NAME##_mocking_list<Component>::with_these_##NAME
65 ACTION_TESTING_CHECK_MOCK_ACTION_LIST(simple_actions);
66 ACTION_TESTING_CHECK_MOCK_ACTION_LIST(threaded_actions);
67 #undef ACTION_TESTING_CHECK_MOCK_ACTION_LIST
69 template <
typename Component,
typename = std::
void_t<>>
70 struct get_initialization_tags_from_component {
71 using type = tmpl::list<>;
74 template <
typename Component>
75 struct get_initialization_tags_from_component<
76 Component, std::void_t<typename Component::initialization_tags>> {
77 using type =
typename Component::initialization_tags;
81 template <
typename SimpleTagsList>
82 struct ForwardAllOptionsToDataBox;
84 template <
typename... SimpleTags>
85 struct ForwardAllOptionsToDataBox<tmpl::list<SimpleTags...>> {
86 using simple_tags = tmpl::list<SimpleTags...>;
88 template <
typename DbTagsList,
typename... Args>
89 static auto apply(db::DataBox<DbTagsList>&& box, Args&&... args) noexcept {
91 sizeof...(SimpleTags) ==
sizeof...(Args),
92 "The number of arguments passed to ForwardAllOptionsToDataBox must "
93 "match the number of SimpleTags passed.");
94 return db::create_from<db::RemoveTags<>, simple_tags>(
95 std::move(box), std::forward<Args>(args)...);
102 template <
typename Tag,
typename DataBoxType,
103 bool = db::tag_is_retrievable_v<Tag, DataBoxType>>
104 struct item_type_if_contained;
106 template <
typename Tag,
typename DataBoxType>
107 struct item_type_if_contained<Tag, DataBoxType, true> {
108 using type = decltype(db::get<Tag>(DataBoxType{}));
111 template <
typename Tag,
typename DataBoxType>
112 struct item_type_if_contained<Tag, DataBoxType, false> {
116 template <
typename Tag,
typename DataBoxType>
117 using item_type_if_contained_t =
118 typename item_type_if_contained<Tag, DataBoxType>::type;
128 inline bool operator==(
const NodeId& lhs,
const NodeId& rhs) noexcept {
129 return lhs.value == rhs.value;
132 inline bool operator!=(
const NodeId& lhs,
const NodeId& rhs) noexcept {
133 return not(lhs==rhs);
153 return lhs.value == rhs.value;
156 inline bool operator!=(
const LocalCoreId& lhs,
157 const LocalCoreId& rhs) noexcept {
158 return not(lhs==rhs);
174 return lhs.value == rhs.value;
177 inline bool operator!=(
const GlobalCoreId& lhs,
178 const GlobalCoreId& rhs) noexcept {
179 return not(lhs==rhs);
226 template <
typename Component>
229 class InvokeActionBase {
231 InvokeActionBase() =
default;
232 InvokeActionBase(
const InvokeActionBase&) =
default;
233 InvokeActionBase& operator=(
const InvokeActionBase&) =
default;
234 InvokeActionBase(InvokeActionBase&&) =
default;
235 InvokeActionBase& operator=(InvokeActionBase&&) =
default;
236 virtual ~InvokeActionBase() =
default;
237 virtual void invoke_action() noexcept = 0;
246 template <
typename Action,
typename... Args>
247 class InvokeSimpleAction :
public InvokeActionBase {
251 : mock_distributed_object_(mock_distributed_object),
252 args_(std::move(args)) {}
255 : mock_distributed_object_(mock_distributed_object) {}
257 void invoke_action() noexcept
override {
260 "Cannot invoke the exact same simple action twice. This is an "
261 "internal bug in the action testing framework. Please file an "
265 invoke_action_impl(std::move(args_));
269 template <
typename Arg0,
typename... Rest>
271 mock_distributed_object_->simple_action<Action>(std::move(args),
true);
274 template <
typename... LocalArgs,
275 Requires<
sizeof...(LocalArgs) == 0> =
nullptr>
277 mock_distributed_object_->simple_action<Action>(
true);
287 template <
typename Action,
typename... Args>
288 class InvokeThreadedAction :
public InvokeActionBase {
292 : mock_distributed_object_(mock_distributed_object),
293 args_(std::move(args)) {}
295 explicit InvokeThreadedAction(
297 : mock_distributed_object_(mock_distributed_object) {}
299 void invoke_action() noexcept
override {
302 "Cannot invoke the exact same threaded action twice. This is an "
303 "internal bug in the action testing framework. Please file an "
307 invoke_action_impl(std::move(args_));
311 template <
typename Arg0,
typename... Rest>
313 mock_distributed_object_->threaded_action<Action>(std::move(args),
true);
316 template <
typename... LocalArgs,
317 Requires<
sizeof...(LocalArgs) == 0> =
nullptr>
319 mock_distributed_object_->threaded_action<Action>(
true);
328 using phase_dependent_action_lists =
329 typename Component::phase_dependent_action_list;
330 static_assert(tmpl::size<phase_dependent_action_lists>::value > 0,
331 "Must have at least one phase dependent action list "
332 "(PhaseActions) in a parallel component.");
334 using all_actions_list = tmpl::flatten<tmpl::transform<
335 phase_dependent_action_lists,
338 using metavariables =
typename Component::metavariables;
340 using inbox_tags_list =
343 using array_index =
typename Parallel::get_array_index<
344 typename Component::chare_type>::template f<Component>;
346 using parallel_component = Component;
349 typename tmpl::front<phase_dependent_action_lists>::phase_type;
352 using initialization_tags =
353 typename detail::get_initialization_tags_from_component<Component>::type;
354 using initial_tags = tmpl::flatten<tmpl::list<
360 using databox_phase_types =
361 typename Parallel::Algorithm_detail::build_databox_types<
362 tmpl::list<>, phase_dependent_action_lists, initial_databox,
363 inbox_tags_list, metavariables,
typename Component::array_index,
365 template <
typename T>
367 using type =
typename T::databox_types;
370 using databox_types = tmpl::flatten<
371 tmpl::transform<databox_phase_types, get_databox_types<tmpl::_1>>>;
372 using variant_boxes = tmpl::remove_duplicates<
373 tmpl::push_front<databox_types, db::DataBox<tmpl::list<>>>>;
383 mock_nodes_and_local_cores,
384 const array_index& index,
386 tuples::tagged_tuple_from_typelist<inbox_tags_list>* inboxes,
388 : mock_node_(node_id.value),
389 mock_local_core_(local_core_id.value),
390 mock_global_cores_(std::move(mock_global_cores)),
391 mock_nodes_and_local_cores_(std::move(mock_nodes_and_local_cores)),
393 global_cache_(
cache),
395 box_ = detail::ForwardAllOptionsToDataBox<initialization_tags>::apply(
401 std::forward<Options>(opts)...);
404 void set_phase(PhaseType phase) noexcept {
407 terminate_ = number_of_actions_in_phase(phase) == 0;
408 halt_algorithm_until_next_phase_ =
false;
410 PhaseType get_phase() const noexcept {
return phase_; }
412 void set_terminate(
bool t) noexcept { terminate_ = t; }
413 bool get_terminate() const noexcept {
return terminate_; }
417 void perform_algorithm() noexcept {}
419 size_t number_of_actions_in_phase(
const PhaseType phase)
const noexcept {
420 size_t number_of_actions = 0;
421 tmpl::for_each<phase_dependent_action_lists>(
422 [&number_of_actions, phase](
auto pdal_v) {
423 const auto pdal = tmpl::type_from<decltype(pdal_v)>{};
424 if (pdal.phase == phase) {
425 number_of_actions = pdal.number_of_actions;
428 return number_of_actions;
435 template <
typename AdditionalTagsList>
438 tmpl::flatten<tmpl::list<initial_tags, AdditionalTagsList>>>;
439 return boost::get<box_type>(box_);
442 template <
typename AdditionalTagsList>
445 tmpl::flatten<tmpl::list<initial_tags, AdditionalTagsList>>>;
446 return boost::get<box_type>(box_);
453 template <
typename Tag>
455 return get_databox_tag_visitation<Tag>(box_);
458 template <
typename Tag>
459 bool box_contains() const noexcept {
460 return box_contains_visitation<Tag>(box_);
463 template <
typename Tag>
464 bool tag_is_retrievable() const noexcept {
465 return tag_is_retrievable_visitation<Tag>(box_);
478 algorithm_step_ = next_action_id;
494 #define SIMPLE_AND_THREADED_ACTIONS(USE_SIMPLE_ACTION, NAME) \
495 template <typename Action, typename... Args, \
496 Requires<not tmpl::list_contains_v< \
497 detail::replace_these_##NAME##s_t<Component>, Action>> = \
499 void NAME(std::tuple<Args...> args, \
500 const bool direct_from_action_runner = false) noexcept { \
501 if (direct_from_action_runner) { \
502 performing_action_ = true; \
503 forward_tuple_to_##NAME<Action>( \
504 std::move(args), std::make_index_sequence<sizeof...(Args)>{}); \
505 performing_action_ = false; \
507 NAME##_queue_.push_back( \
508 std::make_unique<BOOST_PP_IF(USE_SIMPLE_ACTION, InvokeSimpleAction, \
509 InvokeThreadedAction) < Action, \
510 Args...> > (this, std::move(args))); \
513 template <typename Action, typename... Args, \
514 Requires<tmpl::list_contains_v< \
515 detail::replace_these_##NAME##s_t<Component>, Action>> = \
517 void NAME(std::tuple<Args...> args, \
518 const bool direct_from_action_runner = false) noexcept { \
519 using index_of_action = \
520 tmpl::index_of<detail::replace_these_##NAME##s_t<Component>, Action>; \
521 using new_action = tmpl::at_c<detail::with_these_##NAME##s_t<Component>, \
522 index_of_action::value>; \
523 if (direct_from_action_runner) { \
524 performing_action_ = true; \
525 forward_tuple_to_##NAME<new_action>( \
526 std::move(args), std::make_index_sequence<sizeof...(Args)>{}); \
527 performing_action_ = false; \
529 NAME##_queue_.push_back( \
530 std::make_unique<BOOST_PP_IF(USE_SIMPLE_ACTION, InvokeSimpleAction, \
531 InvokeThreadedAction) < new_action, \
532 Args...> > (this, std::move(args))); \
535 template <typename Action, \
536 Requires<not tmpl::list_contains_v< \
537 detail::replace_these_##NAME##s_t<Component>, Action>> = \
539 void NAME(const bool direct_from_action_runner = false) noexcept { \
540 if (direct_from_action_runner) { \
541 performing_action_ = true; \
542 Parallel::Algorithm_detail::simple_action_visitor<Action, Component>( \
543 box_, *global_cache_, \
544 std::as_const(array_index_) \
545 BOOST_PP_COMMA_IF(BOOST_PP_NOT(USE_SIMPLE_ACTION)) BOOST_PP_IF( \
546 USE_SIMPLE_ACTION, , make_not_null(&node_lock_))); \
547 performing_action_ = false; \
549 NAME##_queue_.push_back( \
550 std::make_unique<BOOST_PP_IF(USE_SIMPLE_ACTION, InvokeSimpleAction, \
551 InvokeThreadedAction) < Action> > \
555 template <typename Action, \
556 Requires<tmpl::list_contains_v< \
557 detail::replace_these_##NAME##s_t<Component>, Action>> = \
559 void NAME(const bool direct_from_action_runner = false) noexcept { \
560 using index_of_action = \
561 tmpl::index_of<detail::replace_these_##NAME##s_t<Component>, Action>; \
562 using new_action = tmpl::at_c<detail::with_these_##NAME##s_t<Component>, \
563 index_of_action::value>; \
564 if (direct_from_action_runner) { \
565 performing_action_ = true; \
566 Parallel::Algorithm_detail::simple_action_visitor<new_action, \
568 box_, *global_cache_, \
569 std::as_const(array_index_) \
570 BOOST_PP_COMMA_IF(BOOST_PP_NOT(USE_SIMPLE_ACTION)) BOOST_PP_IF( \
571 USE_SIMPLE_ACTION, , make_not_null(&node_lock_))); \
572 performing_action_ = false; \
574 simple_action_queue_.push_back( \
575 std::make_unique<BOOST_PP_IF(USE_SIMPLE_ACTION, InvokeSimpleAction, \
576 InvokeThreadedAction) < new_action> > \
583 #undef SIMPLE_AND_THREADED_ACTIONS
588 template <
typename Action,
typename... Args>
589 typename Action::return_type local_synchronous_action(
590 Args&&... args) noexcept {
591 static_assert(std::is_same_v<
typename Component::chare_type,
593 "Cannot call a local synchronous action on a chare that is "
595 return Parallel::Algorithm_detail::local_synchronous_action_visitor<
597 std::forward<Args>(args)...);
600 bool is_simple_action_queue_empty() const noexcept {
601 return simple_action_queue_.empty();
604 size_t simple_action_queue_size() const noexcept {
605 return simple_action_queue_.size();
608 void invoke_queued_simple_action() noexcept {
609 if (simple_action_queue_.empty()) {
611 "There are no queued simple actions to invoke. Are you sure a "
612 "previous action invoked a simple action on this component?");
614 simple_action_queue_.front()->invoke_action();
615 simple_action_queue_.pop_front();
618 bool is_threaded_action_queue_empty() const noexcept {
619 return threaded_action_queue_.empty();
622 size_t threaded_action_queue_size() const noexcept {
623 return threaded_action_queue_.size();
626 void invoke_queued_threaded_action() noexcept {
627 if (threaded_action_queue_.empty()) {
629 "There are no queued threaded actions to invoke. Are you sure a "
630 "previous action invoked a threaded action on this component?");
632 threaded_action_queue_.front()->invoke_action();
633 threaded_action_queue_.pop_front();
636 template <
typename InboxTag,
typename Data>
637 void receive_data(
const typename InboxTag::temporal_id&
id, Data&& data,
638 const bool enable_if_disabled =
false) {
642 (void)enable_if_disabled;
643 InboxTag::insert_into_inbox(
645 std::forward<Data>(data));
649 return *global_cache_;
678 int node_of(
int proc_index) const noexcept;
685 template <typename Action, typename... Args,
size_t... Is>
686 void forward_tuple_to_simple_action(
687 std::tuple<Args...>&& args,
688 std::index_sequence<Is...> ) noexcept {
689 Parallel::Algorithm_detail::simple_action_visitor<Action, Component>(
690 box_, *global_cache_, std::as_const(array_index_),
691 std::forward<Args>(std::get<Is>(args))...);
694 template <
typename Action,
typename... Args,
size_t... Is>
695 void forward_tuple_to_threaded_action(
698 Parallel::Algorithm_detail::simple_action_visitor<Action, Component>(
699 box_, *global_cache_, std::as_const(array_index_),
700 make_not_null(&node_lock_), std::forward<Args>(std::get<Is>(args))...);
703 template <
typename ThisAction,
typename ActionList,
typename DbTags>
704 void invoke_iterable_action(db::DataBox<DbTags>& my_box) noexcept {
705 auto action_return = ThisAction::apply(
706 my_box, *inboxes_, *global_cache_, std::as_const(array_index_),
710 Parallel::Algorithm_detail::check_iterable_action_return_type<
711 parallel_component, ThisAction,
713 "An iterable action has an invalid return type.\n"
714 "See the template parameters of "
715 "Algorithm_detail::check_iterable_action_return_type for details: the "
716 "first is the parallel component in question, the second is the "
717 "iterable action, and the third is the return type at fault.\n"
718 "The return type must be a tuple of length one, two, or three "
720 " first type is an updated DataBox;\n"
721 " second type is either a bool (indicating termination) or a "
722 "`Parallel::AlgorithmExecution` object;\n"
723 " third type is a size_t indicating the next action in the current"
726 constexpr
size_t tuple_size =
727 std::tuple_size<decltype(action_return)>::value;
728 if constexpr (tuple_size >= 1_st) {
729 box_ = std::move(std::get<0>(action_return));
731 if constexpr (tuple_size >= 2_st) {
732 if constexpr (std::is_same_v<decltype(std::get<1>(action_return)),
734 terminate_ = std::get<1>(action_return);
736 switch (std::get<1>(action_return)) {
737 case Parallel::AlgorithmExecution::Halt:
738 halt_algorithm_until_next_phase_ =
true;
741 case Parallel::AlgorithmExecution::Pause:
749 if constexpr (tuple_size >= 3_st) {
750 algorithm_step_ = std::get<2>(action_return);
754 template <
typename PhaseDepActions,
size_t... Is>
757 template <
typename PhaseDepActions,
size_t... Is>
760 template <
typename Tag,
typename ThisVariantBox,
typename Type,
761 typename... Variants,
763 typename ThisVariantBox::tags_list,
766 void get_databox_tag_visitation_impl(
769 const boost::variant<Variants...>& box)
const noexcept {
770 if (box.which() == *iter and not *already_visited) {
771 *result = &db::get<Tag>(boost::get<ThisVariantBox>(box));
773 *already_visited =
true;
777 template <
typename Tag,
typename ThisVariantBox,
typename Type,
778 typename... Variants,
780 typename ThisVariantBox::tags_list,
783 void get_databox_tag_visitation_impl(
786 const boost::variant<Variants...>& box)
const noexcept {
787 if (box.which() == *iter and not *already_visited) {
788 ERROR(
"Cannot retrieve tag: "
789 << db::tag_name<Tag>()
790 <<
" from the current DataBox because it is not in it.");
795 template <
typename Tag,
typename... Variants>
796 const auto& get_databox_tag_visitation(
797 const boost::variant<Variants...>& box)
const noexcept {
798 using item_types = tmpl::remove_duplicates<tmpl::remove_if<
799 tmpl::list<cpp20::remove_cvref_t<
800 detail::item_type_if_contained_t<Tag, Variants>>...>,
802 static_assert(tmpl::size<item_types>::value != 0,
803 "Could not find the tag or the tag as a base tag in any "
804 "DataBox in the get_databox_tag function.");
806 tmpl::size<item_types>::value < 2,
807 "Found the tag in or the tag as a base tag in more than one DataBox in "
808 "the get_databox_tag function. This means you need to explicitly "
809 "retrieve the DataBox type to retrieve the tag or file an issue "
810 "requesting a get_databox_tag function that can also take a type "
811 "explicitly. We have not yet encountered a need for this functionality "
812 "but it could be added.");
813 const tmpl::front<item_types>* result =
nullptr;
815 bool already_visited =
false;
817 &result, &iter, &already_visited, box));
818 if (result ==
nullptr) {
819 ERROR(
"The result pointer is nullptr, which it should never be.\n");
824 template <
typename Tag,
typename ThisVariantBox,
typename... Variants,
825 Requires<tmpl::list_contains_v<
typename ThisVariantBox::tags_list,
827 void box_contains_visitation_impl(
829 const boost::variant<Variants...>& box)
const noexcept {
830 if (box.which() == *iter) {
832 tmpl::list_contains_v<typename ThisVariantBox::tags_list, Tag>;
836 template <
typename Tag,
typename ThisVariantBox,
typename... Variants,
838 typename ThisVariantBox::tags_list, Tag>> =
nullptr>
839 void box_contains_visitation_impl(
841 const boost::variant<Variants...>& )
const noexcept {
845 template <
typename Tag,
typename... Variants>
846 bool box_contains_visitation(
847 const boost::variant<Variants...>& box)
const noexcept {
848 bool contains_tag =
false;
851 box_contains_visitation_impl<Tag, Variants>(&contains_tag, &iter, box));
855 template <
typename Tag,
typename... Variants>
856 bool tag_is_retrievable_visitation(
857 const boost::variant<Variants...>& box)
const noexcept {
858 bool is_retrievable =
false;
859 const auto helper = [&box, &is_retrievable](
auto box_type) noexcept {
860 using DataBoxType =
typename decltype(box_type)::type;
861 if (
static_cast<int>(
862 tmpl::index_of<tmpl::list<Variants...>, DataBoxType>::value) ==
864 is_retrievable = db::tag_is_retrievable_v<Tag, DataBoxType>;
868 return is_retrievable;
871 bool terminate_{
false};
872 bool halt_algorithm_until_next_phase_{
false};
875 size_t algorithm_step_ = 0;
876 bool performing_action_ =
false;
879 size_t mock_node_{0};
880 size_t mock_local_core_{0};
883 mock_global_cores_{};
886 mock_nodes_and_local_cores_{};
888 typename Component::array_index array_index_{};
891 tuples::tagged_tuple_from_typelist<inbox_tags_list>* inboxes_{
nullptr};
897 template <
typename Component>
899 bool found_matching_phase =
false;
900 const auto invoke_for_phase =
901 [
this, &found_matching_phase](
auto phase_dep_v) noexcept {
902 using PhaseDep =
typename decltype(phase_dep_v)::type;
903 constexpr PhaseType phase = PhaseDep::phase;
904 using actions_list =
typename PhaseDep::action_list;
905 if (phase_ == phase) {
906 found_matching_phase =
true;
907 this->
template next_action_impl<PhaseDep>(
911 tmpl::for_each<phase_dependent_action_lists>(invoke_for_phase);
912 if (not found_matching_phase) {
913 ERROR(
"Could not find any actions in the current phase for the component '"
914 << pretty_type::short_name<Component>() <<
"'.");
918 template <
typename Component>
919 template <
typename PhaseDepActions,
size_t... Is>
924 "Cannot call an Action while already calling an Action on the same "
925 "MockDistributedObject (an element of a parallel component array, or a "
926 "parallel component singleton).");
928 if (
UNLIKELY(halt_algorithm_until_next_phase_)) {
930 "The algorithm has been halted pending a phase change. No iterable "
931 "action can be executed until after the next change of phase.");
935 bool already_did_an_action =
false;
936 const auto helper = [
this, &already_did_an_action](
auto iteration) noexcept {
937 constexpr
size_t iter = decltype(iteration)::value;
938 if (already_did_an_action or algorithm_step_ != iter) {
942 using actions_list =
typename PhaseDepActions::action_list;
943 using this_action = tmpl::at_c<actions_list, iter>;
944 const auto check_if_ready = [
this](
auto action,
945 const auto& check_local_box) noexcept {
946 if constexpr (Parallel::Algorithm_detail::is_is_ready_callable_t<
949 tuples::tagged_tuple_from_typelist<inbox_tags_list>,
953 check_local_box, std::
as_const(*inboxes_), *global_cache_,
960 constexpr
size_t phase_index =
961 tmpl::index_of<phase_dependent_action_lists, PhaseDepActions>::value;
962 using databox_phase_type = tmpl::at_c<databox_phase_types, phase_index>;
963 using databox_types_this_phase =
typename databox_phase_type::databox_types;
967 tmpl::integral_list<size_t, 0_st,
968 tmpl::size<databox_types_this_phase>::value - 1_st>,
969 tmpl::integral_list<size_t, iter>>;
970 bool box_found =
false;
971 tmpl::for_each<potential_databox_indices>(
973 &check_if_ready](
auto potential_databox_index_v) noexcept {
974 constexpr
size_t potential_databox_index =
975 decltype(potential_databox_index_v)::type::value;
977 tmpl::at_c<databox_types_this_phase, potential_databox_index>;
978 if (not box_found and
981 tmpl::index_of<variant_boxes, this_databox>::value)) {
983 auto& box = boost::get<this_databox>(box_);
984 if (not check_if_ready(this_action{}, box)) {
985 ERROR(
"Tried to invoke the action '"
986 << pretty_type::get_name<this_action>()
987 <<
"' but have not received all the "
990 performing_action_ =
true;
992 invoke_iterable_action<this_action, actions_list>(box);
997 "The DataBox type being retrieved at algorithm step: "
998 << algorithm_step_ <<
" in phase " << phase_index
999 <<
" corresponding to action " << pretty_type::get_name<this_action>()
1000 <<
" is not the correct type but is of variant index " << box_.which()
1001 <<
". If you are using Goto and Label actions then you are using "
1002 "them incorrectly.");
1005 performing_action_ =
false;
1006 already_did_an_action =
true;
1008 if (algorithm_step_ >= tmpl::size<actions_list>::value) {
1009 algorithm_step_ = 0;
1017 template <
typename Component>
1019 bool action_is_ready =
false;
1020 bool found_matching_phase =
false;
1021 const auto invoke_for_phase = [
this, &action_is_ready, &found_matching_phase](
1022 auto phase_dep_v) noexcept {
1023 using PhaseDep =
typename decltype(phase_dep_v)::type;
1024 constexpr PhaseType phase = PhaseDep::phase;
1025 using actions_list =
typename PhaseDep::action_list;
1026 if (phase_ == phase) {
1027 found_matching_phase =
true;
1028 action_is_ready = this->
template is_ready_impl<PhaseDep>(
1032 tmpl::for_each<phase_dependent_action_lists>(invoke_for_phase);
1033 if (not found_matching_phase) {
1034 ERROR(
"Could not find any actions in the current phase for the component '"
1035 << pretty_type::short_name<Component>() <<
"'.");
1037 return action_is_ready;
1040 template <
typename Component>
1041 template <
typename PhaseDepActions,
size_t... Is>
1044 bool next_action_is_ready =
false;
1045 const auto helper = [
this, &array_index = array_index_, &inboxes = *inboxes_,
1046 &global_cache = global_cache_,
1047 &next_action_is_ready](
auto iteration) noexcept {
1048 constexpr
size_t iter = decltype(iteration)::value;
1049 using actions_list =
typename PhaseDepActions::action_list;
1050 using this_action = tmpl::at_c<actions_list, iter>;
1052 constexpr
size_t phase_index =
1053 tmpl::index_of<phase_dependent_action_lists, PhaseDepActions>::value;
1054 using databox_phase_type = tmpl::at_c<databox_phase_types, phase_index>;
1055 using databox_types_this_phase =
typename databox_phase_type::databox_types;
1056 using this_databox =
1057 tmpl::at_c<databox_types_this_phase,
1058 iter == 0 ? tmpl::size<databox_types_this_phase>::value - 1
1060 if (iter != algorithm_step_) {
1064 this_databox* box_ptr{};
1066 box_ptr = &boost::get<this_databox>(box_);
1069 "\nFailed to retrieve Databox in take_next_action:\nCaught "
1071 << e.what() <<
"'\nDataBox type: '"
1072 << pretty_type::get_name<this_databox>() <<
"'\nIteration: " << iter
1073 <<
"\nAction: '" << pretty_type::get_name<this_action>()
1074 <<
"'\nBoost::Variant id: " << box_.which()
1078 this_databox& box = *box_ptr;
1088 [&box, &array_index, &global_cache, &inboxes](
1091 std::
as_const(inboxes), *global_cache,
1096 next_action_is_ready =
1097 check_if_ready(Parallel::Algorithm_detail::is_is_ready_callable_t<
1098 this_action, this_databox,
1099 tuples::tagged_tuple_from_typelist<inbox_tags_list>,
1101 typename Component::array_index>{},
1107 return next_action_is_ready;
1110 template <
typename Component>
1112 return static_cast<int>(mock_nodes_and_local_cores_.size());
1115 template <
typename Component>
1117 return static_cast<int>(mock_global_cores_.at(
NodeId{mock_node_})
1122 template <
typename Component>
1124 return static_cast<int>(mock_global_cores_.size());
1127 template <
typename Component>
1129 return static_cast<int>(mock_node_);
1132 template <
typename Component>
1134 const int node_index)
const noexcept {
1135 return static_cast<int>(
1136 mock_global_cores_.at(
NodeId{
static_cast<size_t>(node_index)}).size());
1139 template <
typename Component>
1141 return static_cast<int>(mock_local_core_);
1144 template <
typename Component>
1146 const int node_index)
const noexcept {
1147 return static_cast<int>(
1148 mock_global_cores_.at(
NodeId{
static_cast<size_t>(node_index)})
1153 template <
typename Component>
1155 const int proc_index)
const noexcept {
1156 return static_cast<int>(mock_nodes_and_local_cores_
1161 template <
typename Component>
1163 const int proc_index)
const noexcept {
1164 return static_cast<int>(mock_nodes_and_local_cores_