17 #include "DataStructures/DataBox/Tag.hpp"
18 #include "DataStructures/DataBox/TagTraits.hpp"
20 #include "Parallel/CharmRegistration.hpp"
21 #include "Parallel/ParallelComponentHelpers.hpp"
22 #include "Parallel/PupStlCpp17.hpp"
29 #include "Utilities/TaggedTuple.hpp"
30 #include "Utilities/TypeTraits/IsA.hpp"
32 #include "Parallel/GlobalCache.decl.h"
33 #include "Parallel/Main.decl.h"
37 namespace GlobalCache_detail {
39 template <
class GlobalCacheTag,
class Metavariables>
40 using get_matching_tag =
typename matching_tag_helper<
42 tmpl::append<get_const_global_cache_tags<Metavariables>,
43 get_mutable_global_cache_tags<Metavariables>>>::type;
45 template <
class GlobalCacheTag,
class Metavariables>
46 using type_for_get =
typename type_for_get_helper<
47 typename get_matching_tag<GlobalCacheTag, Metavariables>::type>::type;
49 template <
class T,
class = std::
void_t<>>
53 struct has_component_being_mocked_alias<
54 T, std::void_t<typename T::component_being_mocked>> :
std::true_type {};
57 constexpr
bool has_component_being_mocked_alias_v =
58 has_component_being_mocked_alias<T>::value;
60 template <
typename ComponentToFind,
typename ComponentFromList>
61 struct get_component_if_mocked_helper {
63 has_component_being_mocked_alias_v<ComponentFromList>,
64 "The parallel component was not found, and it looks like it is not being "
65 "mocked. Did you forget to add it to the "
66 "'Metavariables::component_list'? See the first template parameter for "
67 "the component that we are looking for and the second template parameter "
68 "for the component that is being checked for mocking it.");
69 using type =
std::is_same<
typename ComponentFromList::component_being_mocked,
73 template <
typename... Tags>
74 auto make_mutable_cache_tag_storage(
77 std::make_tuple(std::move(tuples::get<Tags>(input)),
89 template <
typename ComponentList,
typename ParallelComponent>
90 using get_component_if_mocked = tmpl::front<tmpl::type_from<tmpl::conditional_t<
91 tmpl::list_contains_v<ComponentList, ParallelComponent>,
92 tmpl::type_<tmpl::list<ParallelComponent>>,
94 tmpl::type_<get_component_if_mocked_helper<
95 tmpl::pin<ParallelComponent>, tmpl::_1>>>>>>;
106 template <
typename Metavariables>
111 mutable_global_cache) noexcept;
113 : CBase_MutableGlobalCache<Metavariables>(msg) {}
118 CkIndex_MutableGlobalCache<Metavariables>>::registrar;
128 template <
typename GlobalCacheTag>
129 auto get()
const noexcept
130 ->
const GlobalCache_detail::type_for_get<GlobalCacheTag, Metavariables>&;
139 template <
typename GlobalCacheTag,
typename Function,
typename... Args>
146 template <
typename GlobalCacheTag,
typename Function>
147 bool mutable_cache_item_is_ready(
const Function&
function) noexcept;
149 void pup(PUP::er& p) noexcept
override;
152 tuples::tagged_tuple_from_typelist<
153 get_mutable_global_cache_tag_storage<Metavariables>>
154 mutable_global_cache_{};
157 template <
typename Metavariables>
159 tuples::tagged_tuple_from_typelist<
161 mutable_global_cache) noexcept
162 : mutable_global_cache_(GlobalCache_detail::make_mutable_cache_tag_storage(
163 std::move(mutable_global_cache))) {}
165 template <
typename Metavariables>
166 template <
typename GlobalCacheTag>
167 auto MutableGlobalCache<Metavariables>::get() const noexcept
168 -> const GlobalCache_detail::type_for_get<GlobalCacheTag, Metavariables>& {
169 using tag = MutableCacheTag<
170 GlobalCache_detail::get_matching_tag<GlobalCacheTag, Metavariables>>;
171 if constexpr (tt::is_a_v<std::unique_ptr, typename tag::tag::type>) {
172 return *(std::get<0>(tuples::get<tag>(mutable_global_cache_)));
174 return std::get<0>(tuples::get<tag>(mutable_global_cache_));
178 template <
typename Metavariables>
179 template <
typename GlobalCacheTag,
typename Function>
180 bool MutableGlobalCache<Metavariables>::mutable_cache_item_is_ready(
181 const Function&
function) noexcept {
182 using tag = MutableCacheTag<GlobalCache_detail::get_matching_mutable_tag<
183 GlobalCacheTag, Metavariables>>;
185 if constexpr (tt::is_a_v<std::unique_ptr, typename tag::tag::type>) {
187 function(*(std::get<0>(tuples::get<tag>(mutable_global_cache_))));
190 function(std::get<0>(tuples::get<tag>(mutable_global_cache_)));
192 if (optional_callback) {
193 std::get<1>(tuples::get<tag>(mutable_global_cache_))
194 .push_back(std::move(optional_callback));
195 if (std::get<1>(tuples::get<tag>(mutable_global_cache_)).
size() > 20000) {
196 ERROR(
"The number of callbacks in MutableGlobalCache for tag "
197 << pretty_type::short_name<GlobalCacheTag>()
198 <<
" has gotten too large, and may be growing without bound");
208 template <
typename Metavariables>
209 template <
typename GlobalCacheTag,
typename Function,
typename... Args>
210 void MutableGlobalCache<Metavariables>::mutate(
213 Metavariables, GlobalCacheTag, Function, Args...>::registrar;
214 using tag = MutableCacheTag<GlobalCache_detail::get_matching_mutable_tag<
215 GlobalCacheTag, Metavariables>>;
219 [
this](
const auto&... local_args) noexcept {
221 tuples::get<tag>(mutable_global_cache_))),
227 for (
auto& callback : std::get<1>(tuples::get<tag>(mutable_global_cache_))) {
230 std::get<1>(tuples::get<tag>(mutable_global_cache_)).clear();
231 std::get<1>(tuples::get<tag>(mutable_global_cache_)).shrink_to_fit();
234 template <
typename Metavariables>
235 void MutableGlobalCache<Metavariables>::pup(PUP::er& p) noexcept {
236 p | mutable_global_cache_;
279 template <
typename Metavariables>
280 class GlobalCache :
public CBase_GlobalCache<Metavariables> {
281 using parallel_component_tag_list = tmpl::transform<
282 typename Metavariables::component_list,
285 tmpl::bind<Parallel::proxy_from_parallel_component, tmpl::_1>>>;
288 using proxy_type = CProxy_GlobalCache<Metavariables>;
289 using main_proxy_type = CProxy_Main<Metavariables>;
298 tuples::tagged_tuple_from_typelist<
306 tuples::tagged_tuple_from_typelist<
309 CProxy_MutableGlobalCache<Metavariables> mutable_global_cache_proxy,
313 : CBase_GlobalCache<Metavariables>(msg) {}
318 CkIndex_GlobalCache<Metavariables>>::registrar;
330 tuples::tagged_tuple_from_typelist<parallel_component_tag_list>&&
332 const CkCallback& callback) noexcept;
346 template <
typename GlobalCacheTag,
typename Function>
359 template <
typename GlobalCacheTag,
typename Function,
typename... Args>
365 void pup(PUP::er& p) noexcept override;
373 template <typename GlobalCacheTag, typename MV>
375 -> const GlobalCache_detail::type_for_get<GlobalCacheTag, MV>&;
378 template <typename ParallelComponentTag, typename MV>
379 friend auto get_parallel_component(
381 ->
Parallel::proxy_from_parallel_component<
382 GlobalCache_detail::get_component_if_mocked<
386 template <typename ParallelComponentTag, typename MV>
387 friend auto get_parallel_component(
389 -> const
Parallel::proxy_from_parallel_component<
390 GlobalCache_detail::get_component_if_mocked<
392 ParallelComponentTag>>&;
395 const_global_cache_{};
396 tuples::tagged_tuple_from_typelist<parallel_component_tag_list>
397 parallel_components_{};
408 MutableGlobalCache<Metavariables>* mutable_global_cache_{
nullptr};
409 CProxy_MutableGlobalCache<Metavariables> mutable_global_cache_proxy_{};
410 bool parallel_components_have_been_set_{
false};
414 template <
typename Metavariables>
416 tuples::tagged_tuple_from_typelist<
421 : const_global_cache_(std::move(const_global_cache)),
422 mutable_global_cache_(mutable_global_cache),
423 main_proxy_(std::move(main_proxy)) {
424 ASSERT(mutable_global_cache_ !=
nullptr,
425 "GlobalCache: Do not construct with a nullptr!");
428 template <
typename Metavariables>
430 tuples::tagged_tuple_from_typelist<
433 CProxy_MutableGlobalCache<Metavariables> mutable_global_cache_proxy,
435 : const_global_cache_(std::move(const_global_cache)),
436 mutable_global_cache_(
nullptr),
437 mutable_global_cache_proxy_(std::move(mutable_global_cache_proxy)),
438 main_proxy_(std::move(main_proxy)) {}
440 template <
typename Metavariables>
442 tuples::tagged_tuple_from_typelist<parallel_component_tag_list>&&
444 const CkCallback& callback) noexcept {
445 ASSERT(!parallel_components_have_been_set_,
446 "Can only set the parallel_components once");
447 parallel_components_ = std::move(parallel_components);
448 parallel_components_have_been_set_ =
true;
449 this->contribute(callback);
452 template <
typename Metavariables>
453 template <
typename GlobalCacheTag,
typename Function>
455 const Function&
function) noexcept {
456 if (mutable_global_cache_ ==
nullptr) {
457 return mutable_global_cache_proxy_.ckLocalBranch()
458 ->template mutable_cache_item_is_ready<GlobalCacheTag>(
function);
460 return mutable_global_cache_
461 ->template mutable_cache_item_is_ready<GlobalCacheTag>(
function);
465 template <
typename Metavariables>
466 template <
typename GlobalCacheTag,
typename Function,
typename... Args>
470 Metavariables, GlobalCacheTag, Function, Args...>::registrar;
471 if (mutable_global_cache_ ==
nullptr) {
473 for (
auto pe = CkNodeFirst(CkMyNode());
474 pe < CkNodeFirst(CkMyNode()) + CkNodeSize(CkMyNode()); ++pe) {
475 mutable_global_cache_proxy_[pe].template mutate<GlobalCacheTag, Function>(
480 mutable_global_cache_->template mutate<GlobalCacheTag, Function>(args);
484 template <
typename Metavariables>
485 typename Parallel::GlobalCache<Metavariables>::proxy_type
487 return this->thisProxy;
490 template <
typename Metavariables>
492 typename Parallel::GlobalCache<Metavariables>::main_proxy_type>
494 if(main_proxy_.has_value()) {
498 "Attempting to retrieve the main proxy in a context in which the main "
499 "proxy has not been supplied to the constructor.");
503 #if defined(__GNUC__) && !defined(__clang__)
504 #pragma GCC diagnostic push
505 #pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
506 #endif // defined(__GNUC__) && !defined(__clang__)
507 template <
typename Metavariables>
509 p | const_global_cache_;
510 p | parallel_components_;
511 p | mutable_global_cache_proxy_;
513 p | parallel_components_have_been_set_;
514 if (not p.isUnpacking() and mutable_global_cache_ !=
nullptr) {
516 "Cannot serialize the const global cache when the mutable global cache "
517 "is set to a local pointer. If this occurs in a unit test, avoid the "
518 "serialization. If this occurs in a production executable, be sure "
519 "that the MutableGlobalCache is accessed by a charm proxy.");
522 #if defined(__GNUC__) && !defined(__clang__)
523 #pragma GCC diagnostic pop
524 #endif // defined(__GNUC__) && !defined(__clang__)
534 template <
typename ParallelComponentTag,
typename Metavariables>
536 -> Parallel::proxy_from_parallel_component<
537 GlobalCache_detail::get_component_if_mocked<
538 typename Metavariables::component_list, ParallelComponentTag>>& {
539 return tuples::get<tmpl::type_<Parallel::proxy_from_parallel_component<
540 GlobalCache_detail::get_component_if_mocked<
541 typename Metavariables::component_list, ParallelComponentTag>>>>(
542 cache.parallel_components_);
545 template <
typename ParallelComponentTag,
typename Metavariables>
547 ->
const Parallel::proxy_from_parallel_component<
548 GlobalCache_detail::get_component_if_mocked<
549 typename Metavariables::component_list, ParallelComponentTag>>& {
550 return tuples::get<tmpl::type_<Parallel::proxy_from_parallel_component<
551 GlobalCache_detail::get_component_if_mocked<
552 typename Metavariables::component_list, ParallelComponentTag>>>>(
553 cache.parallel_components_);
565 template <
typename GlobalCacheTag,
typename Metavariables>
567 ->
const GlobalCache_detail::type_for_get<GlobalCacheTag, Metavariables>& {
570 GlobalCache_detail::get_matching_tag<GlobalCacheTag, Metavariables>;
572 tmpl::filter<get_const_global_cache_tags<Metavariables>,
575 if constexpr (tag_is_not_in_const_tags::value) {
577 if (
cache.mutable_global_cache_ ==
nullptr) {
578 const auto& local_mutable_cache =
579 *
cache.mutable_global_cache_proxy_.ckLocalBranch();
580 return local_mutable_cache.template get<GlobalCacheTag>();
582 return cache.mutable_global_cache_->template get<GlobalCacheTag>();
586 if constexpr (tt::is_a_v<std::unique_ptr, typename tag::type>) {
587 return *(tuples::get<tag>(
cache.const_global_cache_));
589 return tuples::get<tag>(
cache.const_global_cache_);
613 template <
typename GlobalCacheTag,
typename Function,
typename Metavariables>
615 const Function&
function) noexcept {
616 return cache.template mutable_cache_item_is_ready<GlobalCacheTag>(
function);
632 template <
typename GlobalCacheTag,
typename Function,
typename Metavariables,
635 cache.template mutate<GlobalCacheTag, Function>(
636 std::make_tuple<Args...>(std::forward<Args>(args)...));
651 template <
typename GlobalCacheTag,
typename Function,
typename Metavariables,
653 void mutate(CProxy_GlobalCache<Metavariables>& cache_proxy,
654 Args&&... args) noexcept {
655 cache_proxy.template mutate<GlobalCacheTag, Function>(
656 std::make_tuple<Args...>(std::forward<Args>(args)...));
665 template <
class Metavariables>
668 static std::string name() noexcept {
return "GlobalCache"; }
675 template <
class CacheTag>
677 static_assert(db::is_simple_tag_v<CacheTag>);
678 using base = CacheTag;
681 template <
class Metavariables>
682 static const auto& get(
684 return Parallel::get<CacheTag>(*
cache);
687 using argument_tags = tmpl::list<parent_tag>;
696 template <
typename Metavariables>
697 inline void pup(PUP::er& p,
699 typename Parallel::GlobalCache<Metavariables>::proxy_type
700 local_const_global_cache_proxy;
701 if (p.isUnpacking()) {
702 p | local_const_global_cache_proxy;
703 t = local_const_global_cache_proxy.ckLocalBranch();
706 p | local_const_global_cache_proxy;
712 template <
typename Metavariables>
713 inline void operator|(PUP::er& p,
719 #define CK_TEMPLATES_ONLY
720 #include "Parallel/GlobalCache.def.h"
721 #undef CK_TEMPLATES_ONLY