GlobalCache.hpp
Go to the documentation of this file.
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 /// \file
5 /// Defines class template GlobalCache.
6 
7 #pragma once
8 
9 #include <charm++.h>
10 #include <memory>
11 #include <optional>
12 #include <pup.h>
13 #include <string>
14 #include <tuple>
15 #include <vector>
16 
17 #include "DataStructures/DataBox/Tag.hpp"
18 #include "DataStructures/DataBox/TagTraits.hpp"
19 #include "Parallel/Callback.hpp"
20 #include "Parallel/CharmRegistration.hpp"
21 #include "Parallel/ParallelComponentHelpers.hpp"
22 #include "Parallel/PupStlCpp17.hpp"
25 #include "Utilities/Gsl.hpp"
26 #include "Utilities/PrettyType.hpp"
27 #include "Utilities/Requires.hpp"
28 #include "Utilities/TMPL.hpp"
29 #include "Utilities/TaggedTuple.hpp"
30 #include "Utilities/TypeTraits/IsA.hpp"
31 
32 #include "Parallel/GlobalCache.decl.h"
33 #include "Parallel/Main.decl.h"
34 
35 namespace Parallel {
36 
37 namespace GlobalCache_detail {
38 
39 template <class GlobalCacheTag, class Metavariables>
40 using get_matching_tag = typename matching_tag_helper<
41  GlobalCacheTag,
42  tmpl::append<get_const_global_cache_tags<Metavariables>,
43  get_mutable_global_cache_tags<Metavariables>>>::type;
44 
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;
48 
49 template <class T, class = std::void_t<>>
50 struct has_component_being_mocked_alias : std::false_type {};
51 
52 template <class T>
53 struct has_component_being_mocked_alias<
54  T, std::void_t<typename T::component_being_mocked>> : std::true_type {};
55 
56 template <class T>
57 constexpr bool has_component_being_mocked_alias_v =
58  has_component_being_mocked_alias<T>::value;
59 
60 template <typename ComponentToFind, typename ComponentFromList>
61 struct get_component_if_mocked_helper {
62  static_assert(
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,
70  ComponentToFind>;
71 };
72 
73 template <typename... Tags>
74 auto make_mutable_cache_tag_storage(
75  tuples::TaggedTuple<Tags...>&& input) noexcept {
77  std::make_tuple(std::move(tuples::get<Tags>(input)),
79 }
80 
81 /// In order to be able to use a mock action testing framework we need to be
82 /// able to get the correct parallel component from the global cache even when
83 /// the correct component is a mock. We do this by having the mocked
84 /// components have a member type alias `component_being_mocked`, and having
85 /// `Parallel::get_component` check if the component to be retrieved is in the
86 /// `metavariables::component_list`. If it is not in the `component_list` then
87 /// we search for a mock component that is mocking the component we are trying
88 /// to retrieve.
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>>,
93  tmpl::lazy::find<ComponentList,
94  tmpl::type_<get_component_if_mocked_helper<
95  tmpl::pin<ParallelComponent>, tmpl::_1>>>>>>;
96 } // namespace GlobalCache_detail
97 
98 /// \ingroup ParallelGroup
99 /// A Charm++ chare that caches mutable data once per Charm++ core.
100 ///
101 /// `MutableGlobalCache` is not intended to be visible to the end user; its
102 /// interface is via the `GlobalCache` member functions
103 /// `mutable_cache_item_is_ready`, `mutate`, and `get`.
104 /// Accordingly, most documentation of `MutableGlobalCache` is provided
105 /// in the relevant `GlobalCache` member functions.
106 template <typename Metavariables>
107 class MutableGlobalCache : public CBase_MutableGlobalCache<Metavariables> {
108  public:
109  explicit MutableGlobalCache(tuples::tagged_tuple_from_typelist<
111  mutable_global_cache) noexcept;
112  explicit MutableGlobalCache(CkMigrateMessage* msg)
113  : CBase_MutableGlobalCache<Metavariables>(msg) {}
114 
115  ~MutableGlobalCache() noexcept override {
118  CkIndex_MutableGlobalCache<Metavariables>>::registrar;
119  }
120  /// \cond
121  MutableGlobalCache() = default;
122  MutableGlobalCache(const MutableGlobalCache&) = default;
123  MutableGlobalCache& operator=(const MutableGlobalCache&) = default;
125  MutableGlobalCache& operator=(MutableGlobalCache&&) = default;
126  /// \endcond
127 
128  template <typename GlobalCacheTag>
129  auto get() const noexcept
130  -> const GlobalCache_detail::type_for_get<GlobalCacheTag, Metavariables>&;
131 
132  // Entry method to mutate the object indentified by `GlobalCacheTag`.
133  // Internally calls Function::apply(), where
134  // Function is a struct, and Function::apply is a user-defined
135  // static function that mutates the object. Function::apply() takes
136  // as its first argument a gsl::not_null pointer to the object named
137  // by the GlobalCacheTag, and then the contents of 'args' as
138  // subsequent arguments. Called via `GlobalCache::mutate`.
139  template <typename GlobalCacheTag, typename Function, typename... Args>
140  void mutate(const std::tuple<Args...>& args) noexcept;
141 
142  // Not an entry method, and intended to be called only from
143  // `GlobalCache` via the free function
144  // `Parallel::mutable_cache_item_is_ready`. See the free function
145  // `Parallel::mutable_cache_item_is_ready` for documentation.
146  template <typename GlobalCacheTag, typename Function>
147  bool mutable_cache_item_is_ready(const Function& function) noexcept;
148 
149  void pup(PUP::er& p) noexcept override; // NOLINT
150 
151  private:
152  tuples::tagged_tuple_from_typelist<
153  get_mutable_global_cache_tag_storage<Metavariables>>
154  mutable_global_cache_{};
155 };
156 
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))) {}
164 
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_)));
173  } else {
174  return std::get<0>(tuples::get<tag>(mutable_global_cache_));
175  }
176 }
177 
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>>;
184  std::unique_ptr<Callback> optional_callback{};
185  if constexpr (tt::is_a_v<std::unique_ptr, typename tag::tag::type>) {
186  optional_callback =
187  function(*(std::get<0>(tuples::get<tag>(mutable_global_cache_))));
188  } else {
189  optional_callback =
190  function(std::get<0>(tuples::get<tag>(mutable_global_cache_)));
191  }
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");
199  }
200  return false;
201  } else {
202  // The user-defined `function` didn't specify a callback, which
203  // means that the item is ready.
204  return true;
205  }
206 }
207 
208 template <typename Metavariables>
209 template <typename GlobalCacheTag, typename Function, typename... Args>
210 void MutableGlobalCache<Metavariables>::mutate(
211  const std::tuple<Args...>& args) noexcept {
213  Metavariables, GlobalCacheTag, Function, Args...>::registrar;
214  using tag = MutableCacheTag<GlobalCache_detail::get_matching_mutable_tag<
215  GlobalCacheTag, Metavariables>>;
216 
217  // Do the mutate.
218  std::apply(
219  [this](const auto&... local_args) noexcept {
220  Function::apply(make_not_null(&std::get<0>(
221  tuples::get<tag>(mutable_global_cache_))),
222  local_args...);
223  },
224  args);
225 
226  // Call the callbacks and clear the list of callbacks.
227  for (auto& callback : std::get<1>(tuples::get<tag>(mutable_global_cache_))) {
228  callback->invoke();
229  }
230  std::get<1>(tuples::get<tag>(mutable_global_cache_)).clear();
231  std::get<1>(tuples::get<tag>(mutable_global_cache_)).shrink_to_fit();
232 }
233 
234 template <typename Metavariables>
235 void MutableGlobalCache<Metavariables>::pup(PUP::er& p) noexcept {
236  p | mutable_global_cache_;
237 }
238 
239 /// \ingroup ParallelGroup
240 /// A Charm++ chare that caches constant data once per Charm++ node or
241 /// non-constant data once per Charm++ core.
242 ///
243 /// `Metavariables` must define the following metavariables:
244 /// - `component_list` typelist of ParallelComponents
245 /// - `const_global_cache_tags` (possibly empty) typelist of tags of
246 /// constant data
247 /// - `mutable_global_cache_tags` (possibly empty) typelist of tags of
248 /// non-constant data
249 ///
250 /// The tag lists for the const items added to the GlobalCache is created by
251 /// combining the following tag lists:
252 /// - `Metavariables::const_global_cache_tags` which should contain only those
253 /// tags that cannot be added from the other tag lists below.
254 /// - `Component::const_global_cache_tags` for each `Component` in
255 /// `Metavariables::component_list` which should contain the tags needed by
256 /// any simple actions called on the Component, as well as tags need by the
257 /// `allocate_array` function of an array component. The type alias may be
258 /// omitted for an empty list.
259 /// - `Action::const_global_cache_tags` for each `Action` in the
260 /// `phase_dependent_action_list` of each `Component` of
261 /// `Metavariables::component_list` which should contain the tags needed by
262 /// that Action. The type alias may be omitted for an empty list.
263 ///
264 /// The tag lists for the non-const items added to the GlobalCache is created
265 /// by combining exactly the same tag lists as for the const items, except with
266 /// `const_global_cache_tags` replaced by `mutable_global_cache_tags`.
267 ///
268 /// The tags in the `const_global_cache_tags` and
269 /// `mutable_global_cache_tags` type lists are db::SimpleTag%s that
270 /// have a `using option_tags` type alias and a static function
271 /// `create_from_options` that are used to create the constant data
272 /// from input file options.
273 ///
274 /// References to const items in the GlobalCache are also added to the
275 /// db::DataBox of each `Component` in the
276 /// `Metavariables::component_list` with the same tag with which they
277 /// were inserted into the GlobalCache. References to non-const items
278 /// in the GlobalCache are not added to the db::DataBox.
279 template <typename Metavariables>
280 class GlobalCache : public CBase_GlobalCache<Metavariables> {
281  using parallel_component_tag_list = tmpl::transform<
282  typename Metavariables::component_list,
283  tmpl::bind<
284  tmpl::type_,
285  tmpl::bind<Parallel::proxy_from_parallel_component, tmpl::_1>>>;
286 
287  public:
288  using proxy_type = CProxy_GlobalCache<Metavariables>;
289  using main_proxy_type = CProxy_Main<Metavariables>;
290  /// Access to the Metavariables template parameter
291  using metavariables = Metavariables;
292  /// Typelist of the ParallelComponents stored in the GlobalCache
293  using component_list = typename Metavariables::component_list;
294 
295  /// Constructor used only by the ActionTesting framework and other
296  /// non-charm++ tests that don't know about proxies.
297  GlobalCache(
298  tuples::tagged_tuple_from_typelist<
300  const_global_cache,
301  MutableGlobalCache<Metavariables>* mutable_global_cache,
302  std::optional<main_proxy_type> main_proxy = std::nullopt) noexcept;
303 
304  /// Constructor used by Main and anything else that is charm++ aware.
305  GlobalCache(
306  tuples::tagged_tuple_from_typelist<
308  const_global_cache,
309  CProxy_MutableGlobalCache<Metavariables> mutable_global_cache_proxy,
310  std::optional<main_proxy_type> main_proxy = std::nullopt) noexcept;
311 
312  explicit GlobalCache(CkMigrateMessage* msg)
313  : CBase_GlobalCache<Metavariables>(msg) {}
314 
315  ~GlobalCache() noexcept override {
318  CkIndex_GlobalCache<Metavariables>>::registrar;
319  }
320  /// \cond
321  GlobalCache() = default;
322  GlobalCache(const GlobalCache&) = default;
323  GlobalCache& operator=(const GlobalCache&) = default;
324  GlobalCache(GlobalCache&&) = default;
325  GlobalCache& operator=(GlobalCache&&) = default;
326  /// \endcond
327 
328  /// Entry method to set the ParallelComponents (should only be called once)
330  tuples::tagged_tuple_from_typelist<parallel_component_tag_list>&&
331  parallel_components,
332  const CkCallback& callback) noexcept;
333 
334  /// Returns whether the object referred to by `GlobalCacheTag`
335  /// (which must be a mutable cache tag) is ready to be accessed by a
336  /// `get` call.
337  ///
338  /// `function` is a user-defined invokable that:
339  /// - takes one argument: a const reference to the object referred to by the
340  /// `GlobalCacheTag`.
341  /// - if the data is ready, returns a default constructed
342  /// `std::unique_ptr<CallBack>`
343  /// - if the data is not ready, returns a `std::unique_ptr<CallBack>`,
344  /// where the `Callback` will re-invoke the current action on the
345  /// current parallel component.
346  template <typename GlobalCacheTag, typename Function>
347  bool mutable_cache_item_is_ready(const Function& function) noexcept;
348 
349  /// Mutates the non-const object identified by GlobalCacheTag.
350  /// \requires `GlobalCacheTag` is a tag in `mutable_global_cache_tags`
351  /// defined by the Metavariables and in Actions.
352  ///
353  /// Internally calls `Function::apply()`, where `Function` is a
354  /// user-defined struct and `Function::apply()` is a user-defined
355  /// static function that mutates the object. `Function::apply()`
356  /// takes as its first argument a `gsl::not_null` pointer to the
357  /// object named by the GlobalCacheTag, and takes the contents of
358  /// `args` as subsequent arguments.
359  template <typename GlobalCacheTag, typename Function, typename... Args>
360  void mutate(const std::tuple<Args...>& args) noexcept;
361 
362  /// Retrieve the proxy to the global cache
363  proxy_type get_this_proxy() noexcept;
364 
365  void pup(PUP::er& p) noexcept override; // NOLINT
366 
367  /// Retrieve the proxy to the Main chare (or std::nullopt if the proxy has not
368  /// been set).
369  std::optional<main_proxy_type> get_main_proxy() noexcept;
370 
371  private:
372  // clang-tidy: false positive, redundant declaration
373  template <typename GlobalCacheTag, typename MV>
374  friend auto get(const GlobalCache<MV>& cache) noexcept // NOLINT
375  -> const GlobalCache_detail::type_for_get<GlobalCacheTag, MV>&;
376 
377  // clang-tidy: false positive, redundant declaration
378  template <typename ParallelComponentTag, typename MV>
379  friend auto get_parallel_component( // NOLINT
380  GlobalCache<MV>& cache) noexcept
381  -> Parallel::proxy_from_parallel_component<
382  GlobalCache_detail::get_component_if_mocked<
383  typename MV::component_list, ParallelComponentTag>>&;
384 
385  // clang-tidy: false positive, redundant declaration
386  template <typename ParallelComponentTag, typename MV>
387  friend auto get_parallel_component( // NOLINT
388  const GlobalCache<MV>& cache) noexcept
389  -> const Parallel::proxy_from_parallel_component<
390  GlobalCache_detail::get_component_if_mocked<
391  typename MV::component_list,
392  ParallelComponentTag>>&; // NOLINT
393 
394  tuples::tagged_tuple_from_typelist<get_const_global_cache_tags<Metavariables>>
395  const_global_cache_{};
396  tuples::tagged_tuple_from_typelist<parallel_component_tag_list>
397  parallel_components_{};
398  // We store both a pointer and a proxy to the MutableGlobalCache.
399  // There is both a pointer and a proxy because we want to use
400  // MutableGlobalCache in production (where it must be charm-aware)
401  // and for simple testing (which we want to do in a non-charm-aware
402  // context for simplicity). If the charm-aware constructor is
403  // used, then the pointer is set to nullptr and the proxy is set.
404  // If the non-charm-aware constructor is used, the the pointer is
405  // set and the proxy is ignored. The member functions that need the
406  // MutableGlobalCache should use the pointer if it is not nullptr,
407  // otherwise use the proxy.
408  MutableGlobalCache<Metavariables>* mutable_global_cache_{nullptr};
409  CProxy_MutableGlobalCache<Metavariables> mutable_global_cache_proxy_{};
410  bool parallel_components_have_been_set_{false};
411  std::optional<main_proxy_type> main_proxy_;
412 };
413 
414 template <typename Metavariables>
416  tuples::tagged_tuple_from_typelist<
418  const_global_cache,
419  MutableGlobalCache<Metavariables>* mutable_global_cache,
420  std::optional<main_proxy_type> main_proxy) noexcept
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!");
426 }
427 
428 template <typename Metavariables>
430  tuples::tagged_tuple_from_typelist<
432  const_global_cache,
433  CProxy_MutableGlobalCache<Metavariables> mutable_global_cache_proxy,
434  std::optional<main_proxy_type> main_proxy) noexcept
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)) {}
439 
440 template <typename Metavariables>
442  tuples::tagged_tuple_from_typelist<parallel_component_tag_list>&&
443  parallel_components,
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);
450 }
451 
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);
459  } else {
460  return mutable_global_cache_
461  ->template mutable_cache_item_is_ready<GlobalCacheTag>(function);
462  }
463 }
464 
465 template <typename Metavariables>
466 template <typename GlobalCacheTag, typename Function, typename... Args>
468  const std::tuple<Args...>& args) noexcept {
470  Metavariables, GlobalCacheTag, Function, Args...>::registrar;
471  if (mutable_global_cache_ == nullptr) {
472  // charm-aware version: Mutate the variable on all PEs on this node.
473  for (auto pe = CkNodeFirst(CkMyNode());
474  pe < CkNodeFirst(CkMyNode()) + CkNodeSize(CkMyNode()); ++pe) {
475  mutable_global_cache_proxy_[pe].template mutate<GlobalCacheTag, Function>(
476  args);
477  }
478  } else {
479  // version that bypasses proxies. Just call the function.
480  mutable_global_cache_->template mutate<GlobalCacheTag, Function>(args);
481  }
482 }
483 
484 template <typename Metavariables>
485 typename Parallel::GlobalCache<Metavariables>::proxy_type
487  return this->thisProxy;
488 }
489 
490 template <typename Metavariables>
492  typename Parallel::GlobalCache<Metavariables>::main_proxy_type>
494  if(main_proxy_.has_value()) {
495  return main_proxy_;
496  } else {
497  ERROR(
498  "Attempting to retrieve the main proxy in a context in which the main "
499  "proxy has not been supplied to the constructor.");
500  }
501 }
502 
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>
508 void GlobalCache<Metavariables>::pup(PUP::er& p) noexcept {
509  p | const_global_cache_;
510  p | parallel_components_;
511  p | mutable_global_cache_proxy_;
512  p | main_proxy_;
513  p | parallel_components_have_been_set_;
514  if (not p.isUnpacking() and mutable_global_cache_ != nullptr) {
515  ERROR(
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.");
520  }
521 }
522 #if defined(__GNUC__) && !defined(__clang__)
523 #pragma GCC diagnostic pop
524 #endif // defined(__GNUC__) && !defined(__clang__)
525 
526 // @{
527 /// \ingroup ParallelGroup
528 /// \brief Access the Charm++ proxy associated with a ParallelComponent
529 ///
530 /// \requires ParallelComponentTag is a tag in component_list
531 ///
532 /// \returns a Charm++ proxy that can be used to call an entry method on the
533 /// chare(s)
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_);
543 }
544 
545 template <typename ParallelComponentTag, typename Metavariables>
546 auto get_parallel_component(const GlobalCache<Metavariables>& cache) noexcept
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_);
554 }
555 // @}
556 
557 // @{
558 /// \ingroup ParallelGroup
559 /// \brief Access data in the cache
560 ///
561 /// \requires GlobalCacheTag is a tag in the `mutable_global_cache_tags`
562 /// or `const_global_cache_tags` defined by the Metavariables and in Actions.
563 ///
564 /// \returns a constant reference to an object in the cache
565 template <typename GlobalCacheTag, typename Metavariables>
566 auto get(const GlobalCache<Metavariables>& cache) noexcept
567  -> const GlobalCache_detail::type_for_get<GlobalCacheTag, Metavariables>& {
568  // We check if the tag is to be retrieved directly or via a base class
569  using tag =
570  GlobalCache_detail::get_matching_tag<GlobalCacheTag, Metavariables>;
571  using tag_is_not_in_const_tags = std::is_same<
572  tmpl::filter<get_const_global_cache_tags<Metavariables>,
574  tmpl::list<>>;
575  if constexpr (tag_is_not_in_const_tags::value) {
576  // Tag is not in the const tags, so use MutableGlobalCache
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>();
581  } else {
582  return cache.mutable_global_cache_->template get<GlobalCacheTag>();
583  }
584  } else {
585  // Tag is in the const tags, so use const_global_cache_
586  if constexpr (tt::is_a_v<std::unique_ptr, typename tag::type>) {
587  return *(tuples::get<tag>(cache.const_global_cache_));
588  } else {
589  return tuples::get<tag>(cache.const_global_cache_);
590  }
591  }
592 }
593 
594 /// \ingroup ParallelGroup
595 /// \brief Returns whether the object identified by `GlobalCacheTag`
596 /// is ready to be accessed by `get`.
597 ///
598 /// \requires `GlobalCacheTag` is a tag in `mutable_global_cache_tags`
599 /// defined by the Metavariables and in Actions.
600 ///
601 /// \requires `function` is a user-defined invokable that takes one argument:
602 /// a const reference to the object referred to by the
603 /// `GlobalCacheTag`. `function` returns a
604 /// `std::unique_ptr<CallBack>` that determines the readiness. To
605 /// indicate that the item is ready, the `std::unique_ptr` returned
606 /// by `function` must be nullptr; in this case
607 /// `mutable_cache_item_is_ready` returns true. To indicate that the
608 /// item is not ready, the `std::unique_ptr` returned by `function`
609 /// must be valid; in this case, `mutable_cache_item_is_ready`
610 /// appends the `std::unique_ptr<Callback>` to an
611 /// internal list of callbacks to be called on `mutate`, and then
612 /// returns false.
613 template <typename GlobalCacheTag, typename Function, typename Metavariables>
615  const Function& function) noexcept {
616  return cache.template mutable_cache_item_is_ready<GlobalCacheTag>(function);
617 }
618 
619 /// \ingroup ParallelGroup
620 /// \brief Mutates non-const data in the cache, by calling `Function::apply()`
621 ///
622 /// \requires `GlobalCacheTag` is a tag in the `mutable_global_cache_tags`
623 /// defined by the Metavariables and in Actions.
624 /// \requires `Function` is a struct with a static void `apply()`
625 /// function that mutates the object. `Function::apply()` takes as its
626 /// first argument a `gsl::not_null` pointer to the object named by
627 /// the `GlobalCacheTag`, and takes `args` as
628 /// subsequent arguments.
629 ///
630 /// This is the version that takes a GlobalCache<Metavariables>. Used only
631 /// for tests.
632 template <typename GlobalCacheTag, typename Function, typename Metavariables,
633  typename... Args>
634 void mutate(GlobalCache<Metavariables>& cache, Args&&... args) noexcept {
635  cache.template mutate<GlobalCacheTag, Function>(
636  std::make_tuple<Args...>(std::forward<Args>(args)...));
637 }
638 
639 /// \ingroup ParallelGroup
640 ///
641 /// \brief Mutates non-const data in the cache, by calling `Function::apply()`
642 ///
643 /// \requires `GlobalCacheTag` is a tag in tag_list.
644 /// \requires `Function` is a struct with a static void `apply()`
645 /// function that mutates the object. `Function::apply()` takes as its
646 /// first argument a `gsl::not_null` pointer to the object named by
647 /// the `GlobalCacheTag`, and takes `args` as
648 /// subsequent arguments.
649 ///
650 /// This is the version that takes a charm++ proxy to the GlobalCache.
651 template <typename GlobalCacheTag, typename Function, typename Metavariables,
652  typename... Args>
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)...));
657 }
658 
659 namespace Tags {
660 /// \ingroup DataBoxTagsGroup
661 /// \ingroup ParallelGroup
662 /// Tag to retrieve the `Parallel::GlobalCache` from the DataBox.
664 
665 template <class Metavariables>
668  static std::string name() noexcept { return "GlobalCache"; }
669 };
670 
671 /// \ingroup DataBoxTagsGroup
672 /// \ingroup ParallelGroup
673 /// Tag used to retrieve data from the `Parallel::GlobalCache`. This is the
674 /// recommended way for compute tags to retrieve data out of the global cache.
675 template <class CacheTag>
676 struct FromGlobalCache : CacheTag, db::ReferenceTag {
677  static_assert(db::is_simple_tag_v<CacheTag>);
678  using base = CacheTag;
679  using parent_tag = GlobalCache;
680 
681  template <class Metavariables>
682  static const auto& get(
684  return Parallel::get<CacheTag>(*cache);
685  }
686 
687  using argument_tags = tmpl::list<parent_tag>;
688 };
689 } // namespace Tags
690 } // namespace Parallel
691 
692 namespace PUP {
693 
694 /// \ingroup ParallelGroup
695 /// Serialization of a pointer to the global cache for Charm++
696 template <typename Metavariables>
697 inline void pup(PUP::er& p, // NOLINT
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();
704  } else {
705  local_const_global_cache_proxy = t->get_this_proxy();
706  p | local_const_global_cache_proxy;
707  }
708 }
709 
710 /// \ingroup ParallelGroup
711 /// Serialization of a pointer to the global cache for Charm++
712 template <typename Metavariables>
713 inline void operator|(PUP::er& p, // NOLINT
715  pup(p, t);
716 }
717 } // namespace PUP
718 
719 #define CK_TEMPLATES_ONLY
720 #include "Parallel/GlobalCache.def.h"
721 #undef CK_TEMPLATES_ONLY
Parallel::GlobalCache::GlobalCache
GlobalCache(tuples::tagged_tuple_from_typelist< get_const_global_cache_tags< Metavariables >> const_global_cache, MutableGlobalCache< Metavariables > *mutable_global_cache, std::optional< main_proxy_type > main_proxy=std::nullopt) noexcept
Constructor used only by the ActionTesting framework and other non-charm++ tests that don't know abou...
Definition: GlobalCache.hpp:415
std::is_same
std::false_type
std::string
Parallel::GlobalCache< typename Component::metavariables >::metavariables
typename Component::metavariables metavariables
Access to the Metavariables template parameter.
Definition: GlobalCache.hpp:291
get
constexpr Tag::type & get(Variables< TagList > &v) noexcept
Return Tag::type pointing into the contiguous array.
Definition: Variables.hpp:660
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:15
Parallel::get_parallel_component
auto get_parallel_component(GlobalCache< Metavariables > &cache) noexcept -> Parallel::proxy_from_parallel_component< GlobalCache_detail::get_component_if_mocked< typename Metavariables::component_list, ParallelComponentTag >> &
Access the Charm++ proxy associated with a ParallelComponent.
Definition: GlobalCache.hpp:535
Callback.hpp
vector
Error.hpp
std::size
T size(T... args)
PrettyType.hpp
Parallel::Tags::FromGlobalCache
Definition: GlobalCache.hpp:676
Parallel::charmxx::RegisterGlobalCacheMutate
Derived class for registering GlobalCache::mutate.
Definition: CharmRegistration.hpp:595
tuple
Parallel::mutable_cache_item_is_ready
bool mutable_cache_item_is_ready(GlobalCache< Metavariables > &cache, const Function &function) noexcept
Returns whether the object identified by GlobalCacheTag is ready to be accessed by get.
Definition: GlobalCache.hpp:614
db::SimpleTag
Mark a struct as a simple tag by inheriting from this.
Definition: Tag.hpp:36
Parallel::GlobalCache::set_parallel_components
void set_parallel_components(tuples::tagged_tuple_from_typelist< parallel_component_tag_list > &&parallel_components, const CkCallback &callback) noexcept
Entry method to set the ParallelComponents (should only be called once)
Definition: GlobalCache.hpp:441
Parallel::charmxx::RegisterMutableGlobalCacheMutate
Derived class for registering MutableGlobalCache::mutate.
Definition: CharmRegistration.hpp:553
Parallel::MutableGlobalCache
Definition: GlobalCache.hpp:107
db::ReferenceTag
Mark a struct as a reference tag by inheriting from this.
Definition: Tag.hpp:188
ERROR
#define ERROR(m)
prints an error message to the standard error stream and aborts the program.
Definition: Error.hpp:36
Parallel::GlobalCache::mutable_cache_item_is_ready
bool mutable_cache_item_is_ready(const Function &function) noexcept
Returns whether the object referred to by GlobalCacheTag (which must be a mutable cache tag) is ready...
Definition: GlobalCache.hpp:454
Parallel::GlobalCache::get_this_proxy
proxy_type get_this_proxy() noexcept
Retrieve the proxy to the global cache.
Definition: GlobalCache.hpp:486
Assert.hpp
tuples::TaggedTuple< Tags... >
Parallel::Tags::GlobalCacheImpl
Definition: GlobalCache.hpp:666
memory
Parallel::mutate
void mutate(GlobalCache< Metavariables > &cache, Args &&... args) noexcept
Mutates non-const data in the cache, by calling Function::apply()
Definition: GlobalCache.hpp:634
Parallel::GlobalCache::get_main_proxy
std::optional< main_proxy_type > get_main_proxy() noexcept
Retrieve the proxy to the Main chare (or std::nullopt if the proxy has not been set).
Definition: GlobalCache.hpp:493
db::BaseTag
Mark a (usually) empty struct as a base tag by inheriting from this.
Definition: Tag.hpp:69
Parallel::Tags::GlobalCache
Definition: GlobalCache.hpp:663
ASSERT
#define ASSERT(a, m)
Assert that an expression should be true.
Definition: Assert.hpp:49
Parallel::get_const_global_cache_tags
tmpl::remove_duplicates< tmpl::flatten< tmpl::list< typename detail::get_const_global_cache_tags_from_parallel_struct< Metavariables >::type, tmpl::transform< typename Metavariables::component_list, detail::get_const_global_cache_tags_from_parallel_struct< tmpl::_1 > >, tmpl::transform< typename Metavariables::component_list, detail::get_const_global_cache_tags_from_pdal< tmpl::_1 > >> >> get_const_global_cache_tags
Given the metavariables, get a list of the unique tags that will specify the items in the GlobalCache...
Definition: ParallelComponentHelpers.hpp:117
ActionTesting::cache
Parallel::GlobalCache< Metavariables > & cache(MockRuntimeSystem< Metavariables > &runner, const ArrayIndex &array_index) noexcept
Returns the GlobalCache of Component with index array_index.
Definition: MockRuntimeSystemFreeFunctions.hpp:362
Gsl.hpp
Parallel::GlobalCache::mutate
void mutate(const std::tuple< Args... > &args) noexcept
Mutates the non-const object identified by GlobalCacheTag.
Definition: GlobalCache.hpp:467
Parallel::GlobalCache< typename Component::metavariables >::component_list
typename typename Component::metavariables ::component_list component_list
Typelist of the ParallelComponents stored in the GlobalCache.
Definition: GlobalCache.hpp:293
Requires.hpp
Parallel::get_mutable_global_cache_tags
tmpl::remove_duplicates< tmpl::flatten< tmpl::list< typename detail::get_mutable_global_cache_tags_from_parallel_struct< Metavariables >::type, tmpl::transform< typename Metavariables::component_list, detail::get_mutable_global_cache_tags_from_parallel_struct< tmpl::_1 > >, tmpl::transform< typename Metavariables::component_list, detail::get_mutable_global_cache_tags_from_pdal< tmpl::_1 > >> >> get_mutable_global_cache_tags
Given the metavariables, get a list of the unique tags that will specify the mutable items in the Glo...
Definition: ParallelComponentHelpers.hpp:135
optional
make_not_null
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion,...
Definition: Gsl.hpp:880
std::unique_ptr
Parallel::charmxx::RegisterChare
Derived class for registering chares.
Definition: CharmRegistration.hpp:194
Parallel::get
auto get(const GlobalCache< Metavariables > &cache) noexcept -> const GlobalCache_detail::type_for_get< GlobalCacheTag, Metavariables > &
Access data in the cache.
Definition: GlobalCache.hpp:566
Parallel
Functionality for parallelization.
Definition: ElementReceiveInterpPoints.hpp:13
TMPL.hpp
cpp20::find
constexpr InputIt find(InputIt first, InputIt last, const T &value)
Definition: Algorithm.hpp:136
std::is_base_of
string