Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <mutex>
7 : #include <unordered_map>
8 : #include <utility>
9 :
10 : #include "DataStructures/TaggedTuple.hpp"
11 : #include "Parallel/ArrayComponentId.hpp"
12 : #include "Parallel/Callback.hpp"
13 : #include "Parallel/Phase.hpp"
14 : #include "Parallel/PhaseDependentActionList.hpp"
15 : #include "Parallel/TypeTraits.hpp"
16 : #include "Utilities/PrettyType.hpp"
17 : #include "Utilities/TMPL.hpp"
18 : #include "Utilities/TypeTraits.hpp"
19 :
20 : namespace Parallel {
21 : namespace detail {
22 : template <class Action, class = std::void_t<>>
23 : struct get_inbox_tags_from_action {
24 : using type = tmpl::list<>;
25 : };
26 :
27 : template <class Action>
28 : struct get_inbox_tags_from_action<Action,
29 : std::void_t<typename Action::inbox_tags>> {
30 : using type = typename Action::inbox_tags;
31 : };
32 : } // namespace detail
33 :
34 : /*!
35 : * \ingroup ParallelGroup
36 : * \brief Given a list of Actions, get a list of the unique inbox tags
37 : */
38 : template <class ActionsList>
39 1 : using get_inbox_tags = tmpl::remove_duplicates<tmpl::join<tmpl::transform<
40 : ActionsList, detail::get_inbox_tags_from_action<tmpl::_1>>>>;
41 :
42 : namespace detail {
43 : // ParallelStruct is a metavariables, component, or action struct
44 : template <class ParallelStruct, class = std::void_t<>>
45 : struct get_const_global_cache_tags_from_parallel_struct {
46 : using type = tmpl::list<>;
47 : };
48 :
49 : template <class ParallelStruct>
50 : struct get_const_global_cache_tags_from_parallel_struct<
51 : ParallelStruct,
52 : std::void_t<typename ParallelStruct::const_global_cache_tags>> {
53 : using type = typename ParallelStruct::const_global_cache_tags;
54 : };
55 :
56 : template <class PhaseDependentActionList>
57 : struct get_const_global_cache_tags_from_pdal {
58 : using type = tmpl::join<tmpl::transform<
59 : tmpl::flatten<tmpl::transform<
60 : PhaseDependentActionList,
61 : get_action_list_from_phase_dep_action_list<tmpl::_1>>>,
62 : get_const_global_cache_tags_from_parallel_struct<tmpl::_1>>>;
63 : };
64 :
65 : template <class Component>
66 : struct get_const_global_cache_tags_from_component {
67 : using type = typename get_const_global_cache_tags_from_pdal<
68 : typename Component::phase_dependent_action_list>::type;
69 : };
70 :
71 : template <class ParallelStruct, class = std::void_t<>>
72 : struct get_mutable_global_cache_tags_from_parallel_struct {
73 : using type = tmpl::list<>;
74 : };
75 :
76 : template <class ParallelStruct>
77 : struct get_mutable_global_cache_tags_from_parallel_struct<
78 : ParallelStruct,
79 : std::void_t<typename ParallelStruct::mutable_global_cache_tags>> {
80 : using type = typename ParallelStruct::mutable_global_cache_tags;
81 : };
82 :
83 : template <class PhaseDependentActionList>
84 : struct get_mutable_global_cache_tags_from_pdal {
85 : using type = tmpl::join<tmpl::transform<
86 : tmpl::flatten<tmpl::transform<
87 : PhaseDependentActionList,
88 : get_action_list_from_phase_dep_action_list<tmpl::_1>>>,
89 : get_mutable_global_cache_tags_from_parallel_struct<tmpl::_1>>>;
90 : };
91 :
92 : template <class Component>
93 : struct get_mutable_global_cache_tags_from_component {
94 : using type = typename get_mutable_global_cache_tags_from_pdal<
95 : typename Component::phase_dependent_action_list>::type;
96 : };
97 :
98 : } // namespace detail
99 :
100 : /*!
101 : * \ingroup ParallelGroup
102 : * \brief Given a list of Actions, get a list of the unique tags specified in
103 : * the actions' `const_global_cache_tags` aliases.
104 : */
105 : template <class ActionsList>
106 1 : using get_const_global_cache_tags_from_actions =
107 : tmpl::remove_duplicates<tmpl::join<tmpl::transform<
108 : ActionsList,
109 : detail::get_const_global_cache_tags_from_parallel_struct<tmpl::_1>>>>;
110 :
111 : /*!
112 : * \ingroup ParallelGroup
113 : * \brief Given a list of Actions, get a list of the unique tags specified in
114 : * the actions' `mutable_global_cache_tags` aliases.
115 : */
116 : template <class ActionsList>
117 1 : using get_mutable_global_cache_tags_from_actions =
118 : tmpl::remove_duplicates<tmpl::join<tmpl::transform<
119 : ActionsList,
120 : detail::get_mutable_global_cache_tags_from_parallel_struct<tmpl::_1>>>>;
121 :
122 : /*!
123 : * \ingroup ParallelGroup
124 : * \brief Given the metavariables, get a list of the unique tags that will
125 : * specify the items in the GlobalCache.
126 : */
127 : template <typename Metavariables>
128 1 : using get_const_global_cache_tags =
129 : tmpl::remove_duplicates<tmpl::flatten<tmpl::list<
130 : typename detail::get_const_global_cache_tags_from_parallel_struct<
131 : Metavariables>::type,
132 : tmpl::transform<
133 : typename Metavariables::component_list,
134 : detail::get_const_global_cache_tags_from_parallel_struct<tmpl::_1>>,
135 : tmpl::transform<
136 : typename Metavariables::component_list,
137 : detail::get_const_global_cache_tags_from_component<tmpl::_1>>>>>;
138 :
139 : /*!
140 : * \ingroup ParallelGroup
141 : * \brief Given the metavariables, get a list of the unique tags that will
142 : * specify the mutable items in the GlobalCache.
143 : */
144 : template <typename Metavariables>
145 1 : using get_mutable_global_cache_tags =
146 : tmpl::remove_duplicates<tmpl::flatten<tmpl::list<
147 : typename detail::get_mutable_global_cache_tags_from_parallel_struct<
148 : Metavariables>::type,
149 : tmpl::transform<
150 : typename Metavariables::component_list,
151 : detail::get_mutable_global_cache_tags_from_parallel_struct<
152 : tmpl::_1>>,
153 : tmpl::transform<
154 : typename Metavariables::component_list,
155 : detail::get_mutable_global_cache_tags_from_component<tmpl::_1>>>>>;
156 :
157 : /*!
158 : * \ingroup ParallelGroup
159 : * \brief Check whether a tag is retrievable from the const portion of
160 : * the global cache.
161 : */
162 : template <typename Metavariables, typename Tag>
163 1 : constexpr bool is_in_const_global_cache =
164 : tmpl::size<tmpl::filter<get_const_global_cache_tags<Metavariables>,
165 : std::is_base_of<tmpl::pin<Tag>, tmpl::_1>>>::value >
166 : 0;
167 :
168 : /*!
169 : * \ingroup ParallelGroup
170 : * \brief Check whether a tag is retrievable from the mutable portion of
171 : * the global cache.
172 : */
173 : template <typename Metavariables, typename Tag>
174 1 : constexpr bool is_in_mutable_global_cache =
175 : tmpl::size<tmpl::filter<get_mutable_global_cache_tags<Metavariables>,
176 : std::is_base_of<tmpl::pin<Tag>, tmpl::_1>>>::value >
177 : 0;
178 :
179 : /*!
180 : * \ingroup ParallelGroup
181 : * \brief Check whether a tag is retrievable from the global cache.
182 : */
183 : template <typename Metavariables, typename Tag>
184 1 : constexpr bool is_in_global_cache =
185 : is_in_const_global_cache<Metavariables, Tag> or
186 : is_in_mutable_global_cache<Metavariables, Tag>;
187 :
188 : template <typename Tag>
189 0 : struct MutexTag {
190 0 : using type = std::pair<std::mutex, std::mutex>;
191 : };
192 :
193 : template <typename Tag>
194 0 : struct MutableCacheTag {
195 0 : using tag = Tag;
196 0 : using type =
197 : std::tuple<typename Tag::type,
198 : std::unordered_map<Parallel::ArrayComponentId,
199 : std::vector<std::unique_ptr<Callback>>>>;
200 : };
201 :
202 : template <typename Tag>
203 0 : struct get_mutable_cache_tag {
204 0 : using type = MutableCacheTag<Tag>;
205 : };
206 :
207 : template <typename Metavariables>
208 0 : using get_mutable_global_cache_tag_storage =
209 : tmpl::transform<get_mutable_global_cache_tags<Metavariables>,
210 : get_mutable_cache_tag<tmpl::_1>>;
211 :
212 : namespace GlobalCache_detail {
213 :
214 : template <typename T>
215 : struct type_for_get_helper {
216 : using type = T;
217 : };
218 :
219 : template <typename T, typename D>
220 : struct type_for_get_helper<std::unique_ptr<T, D>> {
221 : using type = T;
222 : };
223 :
224 : // This struct provides a better error message if
225 : // an unknown tag is requested from the GlobalCache.
226 : template <typename GlobalCacheTag, typename ListOfPossibleTags>
227 : struct matching_tag_helper {
228 : using found_tags =
229 : tmpl::filter<ListOfPossibleTags,
230 : std::is_base_of<tmpl::pin<GlobalCacheTag>, tmpl::_1>>;
231 : static_assert(not std::is_same_v<found_tags, tmpl::list<>>,
232 : "Trying to get a nonexistent tag from the GlobalCache. "
233 : "To diagnose the problem, search for "
234 : "'matching_tag_helper' in the error message. "
235 : "The first template parameter of "
236 : "'matching_tag_helper' is the requested tag, and "
237 : "the second template parameter is a tmpl::list of all the "
238 : "tags in the GlobalCache. One possible bug that may "
239 : "lead to this error message is a missing or misspelled "
240 : "const_global_cache_tags or mutable_global_cache_tags "
241 : "type alias.");
242 : static_assert(tmpl::size<found_tags>::value == 1,
243 : "Found more than one matching tag. "
244 : "To diagnose the problem, search for "
245 : "'matching_tag_helper' in the error message. "
246 : "The first template parameter of "
247 : "'matching_tag_helper' is the requested tag, and "
248 : "the second template parameter is a tmpl::list of all the "
249 : "tags in the GlobalCache.");
250 : using type = tmpl::front<found_tags>;
251 : };
252 :
253 : template <class GlobalCacheTag, class Metavariables>
254 : using get_matching_mutable_tag = typename matching_tag_helper<
255 : GlobalCacheTag, get_mutable_global_cache_tags<Metavariables>>::type;
256 : } // namespace GlobalCache_detail
257 :
258 : namespace detail {
259 : template <typename PhaseAction>
260 : struct get_initialization_actions_list {
261 : using type = tmpl::list<>;
262 : };
263 :
264 : template <typename InitializationActionsList>
265 : struct get_initialization_actions_list<Parallel::PhaseActions<
266 : Parallel::Phase::Initialization, InitializationActionsList>> {
267 : using type = InitializationActionsList;
268 : };
269 : } // namespace detail
270 :
271 : /// \ingroup ParallelGroup
272 : /// \brief Given the phase dependent action list, return the list of
273 : /// actions in the Initialization phase (or an empty list if the Initialization
274 : /// phase is absent from the phase dependent action list)
275 : template <typename PhaseDepActionList>
276 1 : using get_initialization_actions_list = tmpl::flatten<tmpl::transform<
277 : PhaseDepActionList, detail::get_initialization_actions_list<tmpl::_1>>>;
278 :
279 : namespace detail {
280 : template <typename Action, typename = std::void_t<>>
281 : struct get_simple_tags_from_options_from_action {
282 : using type = tmpl::list<>;
283 : };
284 :
285 : template <typename Action>
286 : struct get_simple_tags_from_options_from_action<
287 : Action, std::void_t<typename Action::simple_tags_from_options>> {
288 : using type = typename Action::simple_tags_from_options;
289 : };
290 : } // namespace detail
291 :
292 : /// \ingroup ParallelGroup
293 : /// \brief Given a list of initialization actions, returns a list of the
294 : /// unique simple_tags_from_options for all the actions.
295 : template <typename InitializationActionsList>
296 1 : using get_simple_tags_from_options =
297 : tmpl::remove_duplicates<tmpl::flatten<tmpl::transform<
298 : InitializationActionsList,
299 : detail::get_simple_tags_from_options_from_action<tmpl::_1>>>>;
300 :
301 : /// Collect all initialization tags required by the metavariables.
302 : ///
303 : /// Initialization tags are the tags in the global cache, the
304 : /// `simple_tags_from_options` from each component, and the
305 : /// `array_allocation_tags` from each array component.
306 : template <typename Metavariables>
307 1 : struct all_initialization_tags {
308 : private:
309 : template <typename T>
310 0 : using simple_tags_from_options = typename T::simple_tags_from_options;
311 : template <typename T>
312 0 : using array_allocation_tags = typename T::array_allocation_tags;
313 :
314 : public:
315 0 : using type = tmpl::remove_duplicates<tmpl::append<
316 : get_const_global_cache_tags<Metavariables>,
317 : get_mutable_global_cache_tags<Metavariables>,
318 : tmpl::join<
319 : tmpl::transform<typename Metavariables::component_list,
320 : tmpl::bind<simple_tags_from_options, tmpl::_1>>>,
321 : tmpl::join<
322 : tmpl::transform<tmpl::filter<typename Metavariables::component_list,
323 : Parallel::is_array<tmpl::_1>>,
324 : tmpl::bind<array_allocation_tags, tmpl::_1>>>>>;
325 : };
326 :
327 : /// \copydoc all_initialization_tags
328 : template <typename Metavariables>
329 1 : using all_initialization_tags_t =
330 : typename all_initialization_tags<Metavariables>::type;
331 :
332 : namespace detail {
333 : template <typename SimpleTag, typename Metavariables,
334 : bool PassMetavariables = SimpleTag::pass_metavariables>
335 : struct get_option_tags_from_simple_tag_impl {
336 : using type = typename SimpleTag::option_tags;
337 : };
338 : template <typename SimpleTag, typename Metavariables>
339 : struct get_option_tags_from_simple_tag_impl<SimpleTag, Metavariables, true> {
340 : using type = typename SimpleTag::template option_tags<Metavariables>;
341 : };
342 : template <typename Metavariables>
343 : struct get_option_tags_from_simple_tag {
344 : template <typename SimpleTag>
345 : using f = tmpl::type_from<
346 : get_option_tags_from_simple_tag_impl<SimpleTag, Metavariables>>;
347 : };
348 : } // namespace detail
349 :
350 : /// \ingroup ParallelGroup
351 : /// \brief Given a list of simple tags, returns a list of the
352 : /// unique option tags required to construct them.
353 : template <typename SimpleTagsList, typename Metavariables>
354 1 : using get_option_tags = tmpl::remove_duplicates<tmpl::flatten<tmpl::transform<
355 : SimpleTagsList, tmpl::bind<detail::get_option_tags_from_simple_tag<
356 : Metavariables>::template f,
357 : tmpl::_1>>>>;
358 :
359 : namespace detail {
360 : template <typename Tag, typename = std::void_t<>>
361 : struct is_tag_overlayable : std::false_type {};
362 :
363 : template <typename Tag>
364 : struct is_tag_overlayable<Tag, std::void_t<decltype(Tag::is_overlayable)>>
365 : : std::bool_constant<Tag::is_overlayable> {};
366 : } // namespace detail
367 :
368 : /// Get the subset of `const_global_cache_tags` that are overlayable.
369 : ///
370 : /// Note this is a list of tags in the GlobalCache, but is not a list of option
371 : /// tags.
372 : ///
373 : /// By default, tags are not overlayable, i.e., can not be reparsed to update
374 : /// a simulation value after a restart from checkpoint. Any tag can "opt in"
375 : /// and become overlayable by specifying a member variable
376 : /// `static constexpr bool is_overlayable = true`.
377 : /// This should be done with caution: changing the value of this tag
378 : /// must not have any side effects that might invalidate past of current
379 : /// simulation data. For example, the parameters determining the time stepper
380 : /// should not be overlayable, because it interacts with the time stepper
381 : /// history data. But parameters determining the frequency
382 : /// for (non-dense) reductions to file can be updated on restarts.
383 : template <typename Metavariables>
384 1 : using get_overlayable_tag_list =
385 : tmpl::filter<get_const_global_cache_tags<Metavariables>,
386 : detail::is_tag_overlayable<tmpl::_1>>;
387 :
388 : /// Get the overlayable option tags.
389 : ///
390 : /// These are the option tags that are only used to construct things
391 : /// in `get_overlayable_tag_list`.
392 : template <typename Metavariables>
393 1 : using get_overlayable_option_list = tmpl::list_difference<
394 : get_option_tags<get_const_global_cache_tags<Metavariables>, Metavariables>,
395 : get_option_tags<
396 : tmpl::remove_if<all_initialization_tags_t<Metavariables>,
397 : tmpl::and_<tmpl::lazy::list_contains<
398 : tmpl::pin<get_const_global_cache_tags<
399 : Metavariables>>,
400 : tmpl::_1>,
401 : detail::is_tag_overlayable<tmpl::_1>>>,
402 : Metavariables>>;
403 :
404 : /// \cond
405 : namespace Algorithms {
406 : struct Singleton;
407 : struct Array;
408 : struct Group;
409 : struct Nodegroup;
410 : } // namespace Algorithms
411 :
412 : template <class ChareType>
413 : struct get_array_index;
414 :
415 : template <>
416 : struct get_array_index<Parallel::Algorithms::Singleton> {
417 : template <class ParallelComponent>
418 : using f = int;
419 : };
420 :
421 : template <>
422 : struct get_array_index<Parallel::Algorithms::Array> {
423 : template <class ParallelComponent>
424 : using f = typename ParallelComponent::array_index;
425 : };
426 :
427 : template <>
428 : struct get_array_index<Parallel::Algorithms::Group> {
429 : template <class ParallelComponent>
430 : using f = int;
431 : };
432 :
433 : template <>
434 : struct get_array_index<Parallel::Algorithms::Nodegroup> {
435 : template <class ParallelComponent>
436 : using f = int;
437 : };
438 :
439 : template <typename ParallelComponent>
440 : using proxy_from_parallel_component =
441 : typename ParallelComponent::chare_type::template cproxy<
442 : ParallelComponent,
443 : typename get_array_index<typename ParallelComponent::chare_type>::
444 : template f<ParallelComponent>>;
445 :
446 : template <typename ParallelComponent>
447 : using index_from_parallel_component =
448 : typename ParallelComponent::chare_type::template ckindex<
449 : ParallelComponent,
450 : typename get_array_index<typename ParallelComponent::chare_type>::
451 : template f<ParallelComponent>>;
452 :
453 : template <typename ParallelComponent>
454 : using proxy_element_from_component =
455 : typename proxy_from_parallel_component<ParallelComponent>::element_t;
456 :
457 : template <class ParallelComponent, class... Args>
458 : struct charm_types_with_parameters {
459 : using cproxy =
460 : typename ParallelComponent::chare_type::template cproxy<ParallelComponent,
461 : Args...>;
462 : using cbase =
463 : typename ParallelComponent::chare_type::template cbase<ParallelComponent,
464 : Args...>;
465 : using algorithm =
466 : typename ParallelComponent::chare_type::template algorithm_type<
467 : ParallelComponent, Args...>;
468 : using ckindex = typename ParallelComponent::chare_type::template ckindex<
469 : ParallelComponent, Args...>;
470 : using cproxy_section =
471 : typename ParallelComponent::chare_type::template cproxy_section<
472 : ParallelComponent, Args...>;
473 : };
474 : /// \endcond
475 : } // namespace Parallel
|