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