Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include "Parallel/Reduction.hpp" 7 : #include "Utilities/Serialization/Serialize.hpp" 8 : #include "Utilities/TMPL.hpp" 9 : #include "Utilities/TaggedTuple.hpp" 10 : 11 : namespace PhaseControl { 12 : 13 : /// A type for denoting a piece of data for deciding a phase change. 14 : /// 15 : /// `Tag` is intended to be a tag (with a type) for indexing a 16 : /// `tuples::TaggedTuple`, and `CombineMethod` is intended to be a 17 : /// `Parallel::ReductionDatum`-compatible invokable for combining the `type` of 18 : /// the `Tag`. The `MainCombineMethod` is provided to give flexibility for a 19 : /// different method of combination at the top level of the hierarchy (so, in 20 : /// the case of phase control reductions, performed by the main chare to combine 21 : /// reductions from different chares) 22 : template <typename Tag, typename CombineMethod, 23 : typename MainCombineMethod = CombineMethod> 24 1 : struct TagAndCombine : Tag { 25 0 : using tag = Tag; 26 0 : using combine_method = CombineMethod; 27 0 : using main_combine_method = MainCombineMethod; 28 : }; 29 : 30 : /// A flexible combine invokable that combines into a `tuples::TaggedTuple` a 31 : /// new `tuples::TaggedTuple`, and combines according to type aliases 32 : /// `combination_method`s that are required to be defined in each tag. 33 1 : struct TaggedTupleCombine { 34 : template <typename... Tags> 35 0 : tuples::TaggedTuple<Tags...> operator()( 36 : tuples::TaggedTuple<Tags...> current_state, 37 : const tuples::TaggedTuple<Tags...>& element) { 38 : tmpl::for_each<tmpl::list<Tags...>>([¤t_state, &element](auto tag_v) { 39 : using tag = typename decltype(tag_v)::type; 40 : tuples::get<tag>(current_state) = typename tag::combine_method{}( 41 : tuples::get<tag>(current_state), tuples::get<tag>(element)); 42 : }); 43 : return current_state; 44 : } 45 : }; 46 : 47 : /// A flexible combine invokable that combines into a `tuples::TaggedTuple` a 48 : /// new `tuples::TaggedTuple` with a subset of the original tags, and combines 49 : /// according to type aliases `main_combine_method`s that are required to be 50 : /// defined in each tag. 51 : /// 52 : /// \note This is _not_ usable with charm++ reductions; it mutates the current 53 : /// state in-place. This is constructed for the use-case where the main chare 54 : /// stores a persistent data structure and combines reduction data as it arrives 55 : /// from the other chares. 56 1 : struct TaggedTupleMainCombine { 57 : template <typename... CurrentTags, typename... CombineTags> 58 0 : static void apply( 59 : const gsl::not_null<tuples::TaggedTuple<CurrentTags...>*> current_state, 60 : const tuples::TaggedTuple<CombineTags...>& element) { 61 : tmpl::for_each<tmpl::list<CombineTags...>>([¤t_state, 62 : &element](auto tag_v) { 63 : using tag = typename decltype(tag_v)::type; 64 : tuples::get<tag>(*current_state) = typename tag::main_combine_method{}( 65 : tuples::get<tag>(*current_state), tuples::get<tag>(element)); 66 : }); 67 : } 68 : }; 69 : 70 : /// A `Parallel::ReductionData` with a single `Parallel::ReductionDatum` for a 71 : /// given tagged tuple type determined by `TagsPresent`, and performs the 72 : /// combine according to `TagsAndCombines`, which must be a `tmpl::list` of 73 : /// `PhaseControl::TagAndCombine`s. 74 : /// 75 : /// Each tag in the `TagsAndCombinesPresent` may either be a `TagsAndCombines` 76 : /// or otherise define all three type traits `type`, `combine_method`, and 77 : /// `main_combine_method`. 78 : template <typename TagsAndCombinesPresent, typename TagsAndCombines> 79 1 : using reduction_data = Parallel::ReductionData<Parallel::ReductionDatum< 80 : tuples::tagged_tuple_from_typelist<TagsAndCombinesPresent>, 81 : TaggedTupleCombine>>; 82 : } // namespace PhaseControl