SpECTRE Documentation Coverage Report
Current view: top level - Parallel - CharmRegistration.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 10.7 % 149 16
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <boost/container/small_vector.hpp>
       7              : #include <cstddef>
       8              : #include <memory>
       9              : #include <string>
      10              : #include <unordered_map>
      11              : #include <unordered_set>
      12              : 
      13              : #include "Parallel/ParallelComponentHelpers.hpp"
      14              : #include "Parallel/ReductionDeclare.hpp"
      15              : #include "Parallel/TypeTraits.hpp"
      16              : #include "Utilities/Functional.hpp"
      17              : 
      18              : /// \cond
      19              : namespace db {
      20              : template <typename TagsList>
      21              : class DataBox;
      22              : }  // namespace db
      23              : template <size_t MaxSize, class Key, class ValueType, class Hash,
      24              :           class KeyEqual>
      25              : class FixedHashMap;
      26              : template <size_t Dim, class ValueType>
      27              : class DirectionalIdMap;
      28              : template <size_t Dim>
      29              : class DirectionalId;
      30              : namespace Parallel {
      31              : template <typename Metavariables>
      32              : class CProxy_GlobalCache;
      33              : template <typename Metavariables>
      34              : class CProxy_Main;
      35              : template <typename Metavariables>
      36              : class CkIndex_GlobalCache;
      37              : template <typename Metavariables>
      38              : class CkIndex_Main;
      39              : template <typename Metavariables>
      40              : class GlobalCache;
      41              : template <typename Metavariables>
      42              : class Main;
      43              : }  // namespace Parallel
      44              : /// \endcond
      45              : 
      46              : namespace Parallel {
      47            0 : namespace charmxx {
      48              : /*!
      49              :  * \ingroup CharmExtensionsGroup
      50              :  * \brief Class to mark a constructor as a constructor for the main chare.
      51              :  *
      52              :  * The main chare must have a constructor that takes a `const
      53              :  * Parallel::charmxx::MainChareRegistrationConstructor&` as its only argument.
      54              :  * This constructor is only used to trigger the `RegisterChare::registrar` code
      55              :  * needed for automatic registration.
      56              :  * \see RegisterChare
      57              :  */
      58            1 : struct MainChareRegistrationConstructor {};
      59              : 
      60              : /// \cond
      61              : struct RegistrationHelper;
      62              : extern std::unique_ptr<RegistrationHelper>* charm_register_list;
      63              : extern size_t charm_register_list_capacity;
      64              : extern size_t charm_register_list_size;
      65              : /// \endcond
      66              : 
      67            0 : std::string get_template_parameters_as_string_impl(
      68              :     const std::string& function_name);
      69              : 
      70              : /*!
      71              :  * \ingroup CharmExtensionsGroup
      72              :  * \brief Returns the template parameter as a `std::string`
      73              :  *
      74              :  * Uses the __PRETTY_FUNCTION__ compiler intrinsic to extract the template
      75              :  * parameter names in the same form that Charm++ uses to register entry methods.
      76              :  * This is used by the generated Singleton, Array, Group and Nodegroup headers,
      77              :  * as well as in CharmMain.tpp.
      78              :  */
      79              : template <class... Args>
      80            1 : std::string get_template_parameters_as_string() {
      81              :   std::string function_name(static_cast<char const*>(__PRETTY_FUNCTION__));
      82              :   return get_template_parameters_as_string_impl(function_name);
      83              : }
      84              : 
      85              : /*!
      86              :  * \ingroup CharmExtensionsGroup
      87              :  * \brief The base class used for automatic registration of entry methods.
      88              :  *
      89              :  * Entry methods are automatically registered by building a list of the entry
      90              :  * methods that need to be registered in the `charm_register_list`. All entry
      91              :  * methods in the list are later registered in the
      92              :  * `register_parallel_components` function, at which point the list is also
      93              :  * deleted.
      94              :  *
      95              :  * The reason for using an abstract base class mechanism is that we need to be
      96              :  * able to register entry method templates. The derived classes keep track of
      97              :  * the template parameters and override the `register_with_charm` function.
      98              :  * The result is that there must be one derived class template for each entry
      99              :  * method template, but since we only have a few entry method templates this is
     100              :  * not an issue.
     101              :  */
     102            1 : struct RegistrationHelper {
     103            0 :   RegistrationHelper() = default;
     104            0 :   RegistrationHelper(const RegistrationHelper&) = default;
     105            0 :   RegistrationHelper& operator=(const RegistrationHelper&) = default;
     106            0 :   RegistrationHelper(RegistrationHelper&&) = default;
     107            0 :   RegistrationHelper& operator=(RegistrationHelper&&) = default;
     108            0 :   virtual ~RegistrationHelper() = default;
     109              : 
     110            0 :   virtual void register_with_charm() const = 0;
     111            0 :   virtual std::string name() const = 0;
     112            0 :   virtual bool is_registering_chare() const { return false; };
     113              : };
     114              : 
     115              : /*!
     116              :  * \ingroup CharmExtensionsGroup
     117              :  * \brief Class used for automatic registration of Charm++ messages.
     118              :  *
     119              :  * Entry methods that use Charm++ messages are responsible for registering those
     120              :  * messages by calling the static `register_with_charm()` function of this
     121              :  * struct. Because an entry method can be templated on the message type, we
     122              :  * don't want to accidentally register the same message-type twice. This struct
     123              :  * will take care of that, rather than having the logic in the entry method
     124              :  * registration logic.
     125              :  */
     126              : template <typename MessageType>
     127            1 : struct RegisterCharmMessage {
     128            0 :   static void register_with_charm() {
     129              :     static bool done_registration = false;
     130              :     if (done_registration) {
     131              :       return;  // LCOV_EXCL_LINE
     132              :     }
     133              :     done_registration = true;
     134              : 
     135              :     // NOTE: Assumes custom pack/unpack but default allocate.
     136              :     static std::string name = MessageType::name();
     137              :     MessageType::base::__register(
     138              :         name.c_str(), sizeof(MessageType),
     139              :         reinterpret_cast<CkPackFnPtr>(MessageType::pack),
     140              :         reinterpret_cast<CkUnpackFnPtr>(MessageType::unpack));
     141              :   }
     142              : };
     143              : 
     144              : /*!
     145              :  * \ingroup CharmExtensionsGroup
     146              :  * \brief Derived class for registering parallel components.
     147              :  *
     148              :  * Calls the appropriate Charm++ function to register a parallel component.
     149              :  */
     150              : template <typename ParallelComponent>
     151            1 : struct RegisterParallelComponent : RegistrationHelper {
     152            0 :   using chare_type = typename ParallelComponent::chare_type;
     153            0 :   using charm_type = charm_types_with_parameters<
     154              :       ParallelComponent,
     155              :       typename get_array_index<chare_type>::template f<ParallelComponent>>;
     156            0 :   using ckindex = typename charm_type::ckindex;
     157            0 :   using algorithm = typename charm_type::algorithm;
     158              : 
     159            0 :   RegisterParallelComponent() = default;
     160            0 :   RegisterParallelComponent(const RegisterParallelComponent&) = default;
     161            0 :   RegisterParallelComponent& operator=(const RegisterParallelComponent&) =
     162              :       default;
     163            0 :   RegisterParallelComponent(RegisterParallelComponent&&) = default;
     164            0 :   RegisterParallelComponent& operator=(RegisterParallelComponent&&) = default;
     165            0 :   ~RegisterParallelComponent() override = default;
     166              : 
     167            0 :   void register_with_charm() const override {
     168              :     static bool done_registration{false};
     169              :     if (done_registration) {
     170              :       return;  // LCOV_EXCL_LINE
     171              :     }
     172              :     done_registration = true;
     173              :     static const std::string parallel_component_name = name();
     174              :     ckindex::__register(parallel_component_name.c_str(), sizeof(algorithm));
     175              :   }
     176              : 
     177            0 :   bool is_registering_chare() const override { return true; }
     178              : 
     179            0 :   std::string name() const override {
     180              :     return get_template_parameters_as_string<algorithm>();
     181              :   }
     182              : 
     183            0 :   static bool registrar;
     184              : };
     185              : 
     186              : /*!
     187              :  * \ingroup CharmExtensionsGroup
     188              :  * \brief Derived class for registering chares.
     189              :  *
     190              :  * Calls the appropriate Charm++ function to register a chare
     191              :  *
     192              :  * The chare that is being registered must have the following in the destructor:
     193              :  * \code
     194              :  * (void)Parallel::charmxx::RegisterChare<ChareName,
     195              :  *     CkIndex_ChareName>::registrar;
     196              :  * \endcode
     197              :  *
     198              :  * The main chare must also have a constructor that takes a `const
     199              :  * Parallel::charmxx::MainChareRegistrationConstructor&` as its only argument.
     200              :  * This constructor is only used to trigger the `RegisterChare::registrar` code
     201              :  * needed for automatic registration. The main chare is set up in
     202              :  * `Parallel::charmxx::register_main_module<Metavariables>`.
     203              :  */
     204              : template <typename Chare, typename CkIndex>
     205            1 : struct RegisterChare : RegistrationHelper {
     206            0 :   RegisterChare() = default;
     207            0 :   RegisterChare(const RegisterChare&) = default;
     208            0 :   RegisterChare& operator=(const RegisterChare&) = default;
     209            0 :   RegisterChare(RegisterChare&&) = default;
     210            0 :   RegisterChare& operator=(RegisterChare&&) = default;
     211            0 :   ~RegisterChare() override = default;
     212              : 
     213            0 :   void register_with_charm() const override {
     214              :     static bool done_registration{false};
     215              :     if (done_registration) {
     216              :       return;  // LCOV_EXCL_LINE
     217              :     }
     218              :     done_registration = true;
     219              :     static const std::string chare_name = name();
     220              :     CkIndex::__register(chare_name.c_str(), sizeof(Chare));
     221              :   }
     222              : 
     223            0 :   bool is_registering_chare() const override { return true; }
     224              : 
     225            0 :   std::string name() const override {
     226              :     return get_template_parameters_as_string<Chare>();
     227              :   }
     228              : 
     229            0 :   static bool registrar;
     230              : };
     231              : 
     232              : /*!
     233              :  * \ingroup CharmExtensionsGroup
     234              :  * \brief Derived class for registering simple actions.
     235              :  *
     236              :  * Calls the appropriate Charm++ function to register a simple action.
     237              :  */
     238              : template <typename ParallelComponent, typename Action, typename... Args>
     239            1 : struct RegisterSimpleAction : RegistrationHelper {
     240            0 :   using chare_type = typename ParallelComponent::chare_type;
     241            0 :   using charm_type = charm_types_with_parameters<
     242              :       ParallelComponent,
     243              :       typename get_array_index<chare_type>::template f<ParallelComponent>>;
     244            0 :   using cproxy = typename charm_type::cproxy;
     245            0 :   using ckindex = typename charm_type::ckindex;
     246            0 :   using algorithm = typename charm_type::algorithm;
     247              : 
     248            0 :   RegisterSimpleAction() = default;
     249            0 :   RegisterSimpleAction(const RegisterSimpleAction&) = default;
     250            0 :   RegisterSimpleAction& operator=(const RegisterSimpleAction&) = default;
     251            0 :   RegisterSimpleAction(RegisterSimpleAction&&) = default;
     252            0 :   RegisterSimpleAction& operator=(RegisterSimpleAction&&) = default;
     253            0 :   ~RegisterSimpleAction() override = default;
     254              : 
     255            0 :   void register_with_charm() const override {
     256              :     static bool done_registration{false};
     257              :     if (done_registration) {
     258              :       return;  // LCOV_EXCL_LINE
     259              :     }
     260              :     done_registration = true;
     261              :     ckindex::template idx_simple_action<Action>(
     262              :         static_cast<void (algorithm::*)(const std::tuple<Args...>&)>(nullptr));
     263              :   }
     264              : 
     265            0 :   std::string name() const override {
     266              :     return get_template_parameters_as_string<RegisterSimpleAction>();
     267              :   }
     268              : 
     269            0 :   static bool registrar;
     270              : };
     271              : 
     272              : /// \cond
     273              : template <typename ParallelComponent, typename Action>
     274              : struct RegisterSimpleAction<ParallelComponent, Action> : RegistrationHelper {
     275              :   using chare_type = typename ParallelComponent::chare_type;
     276              :   using charm_type = charm_types_with_parameters<
     277              :       ParallelComponent,
     278              :       typename get_array_index<chare_type>::template f<ParallelComponent>>;
     279              :   using cproxy = typename charm_type::cproxy;
     280              :   using ckindex = typename charm_type::ckindex;
     281              :   using algorithm = typename charm_type::algorithm;
     282              : 
     283              :   RegisterSimpleAction() = default;
     284              :   RegisterSimpleAction(const RegisterSimpleAction&) = default;
     285              :   RegisterSimpleAction& operator=(const RegisterSimpleAction&) = default;
     286              :   RegisterSimpleAction(RegisterSimpleAction&&) = default;
     287              :   RegisterSimpleAction& operator=(RegisterSimpleAction&&) = default;
     288              :   ~RegisterSimpleAction() override = default;
     289              : 
     290              :   void register_with_charm() const override {
     291              :     static bool done_registration{false};
     292              :     if (done_registration) {
     293              :       return;  // LCOV_EXCL_LINE
     294              :     }
     295              :     done_registration = true;
     296              :     ckindex::template idx_simple_action<Action>(
     297              :         static_cast<void (algorithm::*)()>(nullptr));
     298              :   }
     299              : 
     300              :   std::string name() const override {
     301              :     return get_template_parameters_as_string<RegisterSimpleAction>();
     302              :   }
     303              : 
     304              :   static bool registrar;
     305              : };
     306              : /// \endcond
     307              : 
     308              : /*!
     309              :  * \ingroup CharmExtensionsGroup
     310              :  * \brief Derived class for registering threaded actions.
     311              :  *
     312              :  * Calls the appropriate Charm++ function to register a threaded action.
     313              :  */
     314              : template <typename ParallelComponent, typename Action, typename... Args>
     315            1 : struct RegisterThreadedAction : RegistrationHelper {
     316            0 :   using chare_type = typename ParallelComponent::chare_type;
     317            0 :   using charm_type = charm_types_with_parameters<
     318              :       ParallelComponent,
     319              :       typename get_array_index<chare_type>::template f<ParallelComponent>>;
     320            0 :   using cproxy = typename charm_type::cproxy;
     321            0 :   using ckindex = typename charm_type::ckindex;
     322            0 :   using algorithm = typename charm_type::algorithm;
     323              : 
     324            0 :   RegisterThreadedAction() = default;
     325            0 :   RegisterThreadedAction(const RegisterThreadedAction&) = default;
     326            0 :   RegisterThreadedAction& operator=(const RegisterThreadedAction&) = default;
     327            0 :   RegisterThreadedAction(RegisterThreadedAction&&) = default;
     328            0 :   RegisterThreadedAction& operator=(RegisterThreadedAction&&) = default;
     329            0 :   ~RegisterThreadedAction() override = default;
     330              : 
     331            0 :   void register_with_charm() const override {
     332              :     static bool done_registration{false};
     333              :     if (done_registration) {
     334              :       return;  // LCOV_EXCL_LINE
     335              :     }
     336              :     done_registration = true;
     337              :     ckindex::template idx_threaded_action<Action>(
     338              :         static_cast<void (algorithm::*)(const std::tuple<Args...>&)>(nullptr));
     339              :   }
     340              : 
     341            0 :   std::string name() const override {
     342              :     return get_template_parameters_as_string<RegisterThreadedAction>();
     343              :   }
     344              : 
     345            0 :   static bool registrar;
     346              : };
     347              : 
     348              : /// \cond
     349              : template <typename ParallelComponent, typename Action>
     350              : struct RegisterThreadedAction<ParallelComponent, Action> : RegistrationHelper {
     351              :   using chare_type = typename ParallelComponent::chare_type;
     352              :   using charm_type = charm_types_with_parameters<
     353              :       ParallelComponent,
     354              :       typename get_array_index<chare_type>::template f<ParallelComponent>>;
     355              :   using cproxy = typename charm_type::cproxy;
     356              :   using ckindex = typename charm_type::ckindex;
     357              :   using algorithm = typename charm_type::algorithm;
     358              : 
     359              :   RegisterThreadedAction() = default;
     360              :   RegisterThreadedAction(const RegisterThreadedAction&) = default;
     361              :   RegisterThreadedAction& operator=(const RegisterThreadedAction&) = default;
     362              :   RegisterThreadedAction(RegisterThreadedAction&&) = default;
     363              :   RegisterThreadedAction& operator=(RegisterThreadedAction&&) = default;
     364              :   ~RegisterThreadedAction() override = default;
     365              : 
     366              :   void register_with_charm() const override {
     367              :     static bool done_registration{false};
     368              :     if (done_registration) {
     369              :       return;  // LCOV_EXCL_LINE
     370              :     }
     371              :     done_registration = true;
     372              :     ckindex::template idx_threaded_action<Action>(
     373              :         static_cast<void (algorithm::*)()>(nullptr));
     374              :   }
     375              : 
     376              :   std::string name() const override {
     377              :     return get_template_parameters_as_string<RegisterThreadedAction>();
     378              :   }
     379              : 
     380              :   static bool registrar;
     381              : };
     382              : /// \endcond
     383              : 
     384              : namespace detail {
     385              : template <class T>
     386              : struct get_value_type {
     387              :   using type = T;
     388              : };
     389              : 
     390              : template <class T>
     391              : struct get_value_type<std::vector<T>> {
     392              :   using type = T;
     393              : };
     394              : 
     395              : template <class T, size_t N>
     396              : struct get_value_type<boost::container::small_vector<T, N>> {
     397              :   using type = T;
     398              : };
     399              : 
     400              : template <class Key, class Mapped, class Hash, class KeyEqual, class Allocator>
     401              : struct get_value_type<
     402              :     std::unordered_map<Key, Mapped, Hash, KeyEqual, Allocator>> {
     403              :   // When sending data it is typical to use `std::make_pair(a, b)` which results
     404              :   // in a non-const Key type, which is different from what
     405              :   // `unordered_map::value_type` is (e.g. `std::pair<const Key, Mapped>`). This
     406              :   // difference leads to issues with function registration with Charm++ because
     407              :   // when registering `receive_data` methods we register the `inbox_type`'s
     408              :   // `value_type` (`std::pair<const Key, Mapped>` in this case), not the type
     409              :   // passed to `receive_data`.
     410              :   using type = std::pair<Key, Mapped>;
     411              : };
     412              : 
     413              : template <size_t Size, class Key, class Mapped, class Hash, class KeyEqual>
     414              : struct get_value_type<FixedHashMap<Size, Key, Mapped, Hash, KeyEqual>> {
     415              :   // When sending data it is typical to use `std::make_pair(a, b)` which results
     416              :   // in a non-const Key type, which is different from what
     417              :   // `FixedHashMap::value_type` is (e.g. `std::pair<const Key, Mapped>`). This
     418              :   // difference leads to issues with function registration with Charm++ because
     419              :   // when registering `receive_data` methods we register the `inbox_type`'s
     420              :   // `value_type` (`std::pair<const Key, Mapped>` in this case), not the type
     421              :   // passed to `receive_data`.
     422              :   using type = std::pair<Key, Mapped>;
     423              : };
     424              : 
     425              : template <size_t Dim, class Mapped>
     426              : struct get_value_type<DirectionalIdMap<Dim, Mapped>> {
     427              :   // When sending data it is typical to use `std::make_pair(a, b)` which results
     428              :   // in a non-const Key type, which is different from what
     429              :   // `FixedHashMap::value_type` is (e.g. `std::pair<const Key, Mapped>`). This
     430              :   // difference leads to issues with function registration with Charm++ because
     431              :   // when registering `receive_data` methods we register the `inbox_type`'s
     432              :   // `value_type` (`std::pair<const Key, Mapped>` in this case), not the type
     433              :   // passed to `receive_data`.
     434              :   using type = std::pair<DirectionalId<Dim>, Mapped>;
     435              : };
     436              : 
     437              : template <class Key, class Hash, class KeyEqual, class Allocator>
     438              : struct get_value_type<std::unordered_multiset<Key, Hash, KeyEqual, Allocator>> {
     439              :   using type = Key;
     440              : };
     441              : 
     442              : template <class T>
     443              : using get_value_type_t = typename get_value_type<T>::type;
     444              : }  // namespace detail
     445              : 
     446              : /*!
     447              :  * \ingroup CharmExtensionsGroup
     448              :  * \brief Derived class for registering receive_data functions
     449              :  *
     450              :  * Calls the appropriate Charm++ function to register a receive_data function.
     451              :  * There is a bug in Charm++ that doesn't allow default values for entry method
     452              :  * arguments for groups and nodegroups, so we have to handle the (node)group
     453              :  * cases separately from the singleton and array cases.
     454              :  */
     455              : template <typename ParallelComponent, typename ReceiveTag, bool UsingMessages>
     456            1 : struct RegisterReceiveData : RegistrationHelper {
     457            0 :   using chare_type = typename ParallelComponent::chare_type;
     458            0 :   using charm_type = charm_types_with_parameters<
     459              :       ParallelComponent,
     460              :       typename get_array_index<chare_type>::template f<ParallelComponent>>;
     461            0 :   using cproxy = typename charm_type::cproxy;
     462            0 :   using ckindex = typename charm_type::ckindex;
     463            0 :   using algorithm = typename charm_type::algorithm;
     464              : 
     465            0 :   RegisterReceiveData() = default;
     466            0 :   RegisterReceiveData(const RegisterReceiveData&) = default;
     467            0 :   RegisterReceiveData& operator=(const RegisterReceiveData&) = default;
     468            0 :   RegisterReceiveData(RegisterReceiveData&&) = default;
     469            0 :   RegisterReceiveData& operator=(RegisterReceiveData&&) = default;
     470            0 :   ~RegisterReceiveData() override = default;
     471              : 
     472            0 :   void register_with_charm() const override {
     473              :     static bool done_registration{false};
     474              :     if (done_registration) {
     475              :       return;  // LCOV_EXCL_LINE
     476              :     }
     477              :     done_registration = true;
     478              :     if constexpr (UsingMessages) {
     479              :       using message_type = typename ReceiveTag::message_type;
     480              :       ckindex::template idx_receive_data<ReceiveTag>(
     481              :           static_cast<void (algorithm::*)(message_type*)>(nullptr));
     482              :       RegisterCharmMessage<message_type>::register_with_charm();
     483              :     } else {
     484              :       ckindex::template idx_receive_data<ReceiveTag>(
     485              :           static_cast<void (algorithm::*)(
     486              :               const typename ReceiveTag::temporal_id&,
     487              :               const detail::get_value_type_t<
     488              :                   typename ReceiveTag::type::mapped_type>&,
     489              :               bool)>(nullptr));
     490              :     }
     491              :   }
     492              : 
     493            0 :   std::string name() const override {
     494              :     return get_template_parameters_as_string<RegisterReceiveData>();
     495              :   }
     496              : 
     497            0 :   static bool registrar;
     498              : };
     499              : 
     500              : /*!
     501              :  * \ingroup CharmExtensionsGroup
     502              :  * \brief Derived class for registering reduction actions
     503              :  *
     504              :  * Calls the appropriate Charm++ functions to register a reduction action.
     505              :  */
     506              : template <typename ParallelComponent, typename Action, typename ReductionType>
     507            1 : struct RegisterReductionAction : RegistrationHelper {
     508            0 :   using chare_type = typename ParallelComponent::chare_type;
     509            0 :   using charm_type = charm_types_with_parameters<
     510              :       ParallelComponent,
     511              :       typename get_array_index<chare_type>::template f<ParallelComponent>>;
     512            0 :   using cproxy = typename charm_type::cproxy;
     513            0 :   using ckindex = typename charm_type::ckindex;
     514            0 :   using algorithm = typename charm_type::algorithm;
     515              : 
     516            0 :   RegisterReductionAction() = default;
     517            0 :   RegisterReductionAction(const RegisterReductionAction&) = default;
     518            0 :   RegisterReductionAction& operator=(const RegisterReductionAction&) = default;
     519            0 :   RegisterReductionAction(RegisterReductionAction&&) = default;
     520            0 :   RegisterReductionAction& operator=(RegisterReductionAction&&) = default;
     521            0 :   ~RegisterReductionAction() override = default;
     522              : 
     523            0 :   void register_with_charm() const override {
     524              :     static bool done_registration{false};
     525              :     if (done_registration) {
     526              :       return;  // LCOV_EXCL_LINE
     527              :     }
     528              :     done_registration = true;
     529              :     ckindex::template idx_reduction_action<Action, ReductionType>(
     530              :         static_cast<void (algorithm::*)(const ReductionType&)>(nullptr));
     531              :     ckindex::template redn_wrapper_reduction_action<Action, ReductionType>(
     532              :         nullptr);
     533              :   }
     534              : 
     535            0 :   std::string name() const override {
     536              :     return get_template_parameters_as_string<RegisterReductionAction>();
     537              :   }
     538              : 
     539            0 :   static bool registrar;
     540              : };
     541              : 
     542              : template <typename Metavariables, typename InvokeCombine, typename... Tags>
     543            0 : struct RegisterPhaseChangeReduction : RegistrationHelper {
     544            0 :   using cproxy = CProxy_Main<Metavariables>;
     545            0 :   using ckindex = CkIndex_Main<Metavariables>;
     546            0 :   using algorithm = Main<Metavariables>;
     547              : 
     548            0 :   RegisterPhaseChangeReduction() = default;
     549            0 :   RegisterPhaseChangeReduction(const RegisterPhaseChangeReduction&) = default;
     550            0 :   RegisterPhaseChangeReduction& operator=(const RegisterPhaseChangeReduction&) =
     551              :       default;
     552            0 :   RegisterPhaseChangeReduction(RegisterPhaseChangeReduction&&) = default;
     553            0 :   RegisterPhaseChangeReduction& operator=(RegisterPhaseChangeReduction&&) =
     554              :       default;
     555            0 :   ~RegisterPhaseChangeReduction() override = default;
     556              : 
     557            0 :   void register_with_charm() const override {
     558              :     static bool done_registration{false};
     559              :     if (done_registration) {
     560              :       return;  // LCOV_EXCL_LINE
     561              :     }
     562              :     done_registration = true;
     563              :     ckindex::template idx_phase_change_reduction<InvokeCombine, Tags...>(
     564              :         static_cast<void (algorithm::*)(
     565              :             const ReductionData<
     566              :                 ReductionDatum<tuples::TaggedTuple<Tags...>, InvokeCombine,
     567              :                                funcl::Identity, std::index_sequence<>>>&)>(
     568              :             nullptr));
     569              :     ckindex::template redn_wrapper_phase_change_reduction<InvokeCombine,
     570              :                                                           Tags...>(nullptr);
     571              :   }
     572              : 
     573            0 :   std::string name() const override {
     574              :     return get_template_parameters_as_string<RegisterPhaseChangeReduction>();
     575              :   }
     576              : 
     577            0 :   static bool registrar;
     578              : };
     579              : 
     580              : /*!
     581              :  * \ingroup CharmExtensionsGroup
     582              :  * \brief Derived class for registering GlobalCache::mutate
     583              :  *
     584              :  * Calls the appropriate Charm++ function to register the mutate function.
     585              :  */
     586              : template <typename Metavariables, typename GlobalCacheTag, typename Function,
     587              :           typename... Args>
     588            1 : struct RegisterGlobalCacheMutate : RegistrationHelper {
     589            0 :   using cproxy = CProxy_GlobalCache<Metavariables>;
     590            0 :   using ckindex = CkIndex_GlobalCache<Metavariables>;
     591            0 :   using algorithm = GlobalCache<Metavariables>;
     592              : 
     593            0 :   RegisterGlobalCacheMutate() = default;
     594            0 :   RegisterGlobalCacheMutate(const RegisterGlobalCacheMutate&) = default;
     595            0 :   RegisterGlobalCacheMutate& operator=(const RegisterGlobalCacheMutate&) =
     596              :       default;
     597            0 :   RegisterGlobalCacheMutate(RegisterGlobalCacheMutate&&) = default;
     598            0 :   RegisterGlobalCacheMutate& operator=(RegisterGlobalCacheMutate&&) = default;
     599            0 :   ~RegisterGlobalCacheMutate() override = default;
     600              : 
     601            0 :   void register_with_charm() const override {
     602              :     static bool done_registration{false};
     603              :     if (done_registration) {
     604              :       return;  // LCOV_EXCL_LINE
     605              :     }
     606              :     done_registration = true;
     607              :     ckindex::template idx_mutate<GlobalCacheTag, Function>(
     608              :         static_cast<void (algorithm::*)(const std::tuple<Args...>&)>(nullptr));
     609              :   }
     610              : 
     611            0 :   std::string name() const override {
     612              :     return get_template_parameters_as_string<RegisterGlobalCacheMutate>();
     613              :   }
     614              : 
     615            0 :   static bool registrar;
     616              : };
     617              : 
     618              : /*!
     619              :  * \ingroup CharmExtensionsGroup
     620              :  * \brief Derived class for registering the invoke_iterable_action entry method.
     621              :  * This is a `local` entry method that is only used for tracing the code with
     622              :  * Charm++'s Projections.
     623              :  *
     624              :  * Calls the appropriate Charm++ function to register the invoke_iterable_action
     625              :  * function.
     626              :  */
     627              : template <typename ParallelComponent, typename Action, typename PhaseIndex,
     628              :           typename DataBoxIndex>
     629            1 : struct RegisterInvokeIterableAction : RegistrationHelper {
     630            0 :   using chare_type = typename ParallelComponent::chare_type;
     631            0 :   using charm_type = charm_types_with_parameters<
     632              :       ParallelComponent,
     633              :       typename get_array_index<chare_type>::template f<ParallelComponent>>;
     634            0 :   using cproxy = typename charm_type::cproxy;
     635            0 :   using ckindex = typename charm_type::ckindex;
     636            0 :   using algorithm = typename charm_type::algorithm;
     637              : 
     638            0 :   RegisterInvokeIterableAction() = default;
     639            0 :   RegisterInvokeIterableAction(const RegisterInvokeIterableAction&) = default;
     640            0 :   RegisterInvokeIterableAction& operator=(const RegisterInvokeIterableAction&) =
     641              :       default;
     642            0 :   RegisterInvokeIterableAction(RegisterInvokeIterableAction&&) = default;
     643            0 :   RegisterInvokeIterableAction& operator=(RegisterInvokeIterableAction&&) =
     644              :       default;
     645            0 :   ~RegisterInvokeIterableAction() override = default;
     646              : 
     647            0 :   void register_with_charm() const override {
     648              :     static bool done_registration{false};
     649              :     if (done_registration) {
     650              :       return;  // LCOV_EXCL_LINE
     651              :     }
     652              :     done_registration = true;
     653              :     ckindex::template idx_invoke_iterable_action<Action, PhaseIndex,
     654              :                                                  DataBoxIndex>(
     655              :         static_cast<bool (algorithm::*)()>(nullptr));
     656              :   }
     657              : 
     658            0 :   std::string name() const override {
     659              :     return get_template_parameters_as_string<RegisterInvokeIterableAction>();
     660              :   }
     661              : 
     662            0 :   static bool registrar;
     663              : };
     664              : 
     665              : /*!
     666              :  * \ingroup CharmExtensionsGroup
     667              :  * \brief Function that adds a pointer to a specific derived class to the
     668              :  * `charm_register_list`
     669              :  *
     670              :  * Used to initialize the `registrar` bool of derived classes of
     671              :  * `RegistrationHelper`. When the function is invoked it appends the derived
     672              :  * class to the `charm_register_list`.
     673              :  *
     674              :  * \note The reason for not using a `std::vector` is that this did not behave
     675              :  * correctly when calling `push_back`. Specifically, the final vector was always
     676              :  * size 1, even though multiple elements were pushed back. The reason for that
     677              :  * behavior was never tracked down and so in the future it could be possible to
     678              :  * use a `std::vector`.
     679              :  */
     680              : template <typename Derived>
     681            1 : bool register_func_with_charm() {
     682              : #ifdef SPECTRE_CHARM_HAS_MAIN
     683              :   if (charm_register_list_size >= charm_register_list_capacity) {
     684              :     // clang-tidy: use gsl::owner (we don't use raw owning pointers unless
     685              :     // necessary)
     686              :     auto* const t =  // NOLINT
     687              :         new std::unique_ptr<RegistrationHelper>[charm_register_list_capacity +
     688              :                                                 10];
     689              :     for (size_t i = 0; i < charm_register_list_capacity; ++i) {
     690              :       // clang-tidy: do not use pointer arithmetic
     691              :       t[i] = std::move(charm_register_list[i]);  // NOLINT
     692              :     }
     693              :     // clang-tidy: use gsl::owner (we don't use raw owning pointers unless
     694              :     // necessary)
     695              :     delete[] charm_register_list;  // NOLINT
     696              :     charm_register_list = t;
     697              :     charm_register_list_capacity += 10;
     698              :   }
     699              :   charm_register_list_size++;
     700              :   // clang-tidy: do not use pointer arithmetic
     701              :   charm_register_list[charm_register_list_size - 1] =  // NOLINT
     702              :       std::make_unique<Derived>();
     703              : #endif  // SPECTRE_CHARM_HAS_MAIN
     704              :   return true;
     705              : }
     706              : }  // namespace charmxx
     707              : }  // namespace Parallel
     708              : 
     709              : // clang-tidy: redundant declaration
     710              : template <typename ParallelComponent>
     711              : bool Parallel::charmxx::RegisterParallelComponent<
     712              :     ParallelComponent>::registrar =  // NOLINT
     713              :     Parallel::charmxx::register_func_with_charm<
     714              :         RegisterParallelComponent<ParallelComponent>>();
     715              : 
     716              : // clang-tidy: redundant declaration
     717              : template <typename Chare, typename CkIndex>
     718              : bool Parallel::charmxx::RegisterChare<Chare, CkIndex>::registrar =  // NOLINT
     719              :     Parallel::charmxx::register_func_with_charm<
     720              :         RegisterChare<Chare, CkIndex>>();
     721              : 
     722              : // clang-tidy: redundant declaration
     723              : template <typename ParallelComponent, typename Action, typename... Args>
     724              : bool Parallel::charmxx::RegisterSimpleAction<ParallelComponent, Action,
     725              :                                              Args...>::registrar =  // NOLINT
     726              :     Parallel::charmxx::register_func_with_charm<
     727              :         RegisterSimpleAction<ParallelComponent, Action, Args...>>();
     728              : 
     729              : // clang-tidy: redundant declaration
     730              : template <typename ParallelComponent, typename Action>
     731              : bool Parallel::charmxx::RegisterSimpleAction<ParallelComponent,
     732              :                                              Action>::registrar =  // NOLINT
     733              :     Parallel::charmxx::register_func_with_charm<
     734              :         RegisterSimpleAction<ParallelComponent, Action>>();
     735              : 
     736              : // clang-tidy: redundant declaration
     737              : template <typename ParallelComponent, typename Action, typename... Args>
     738              : bool Parallel::charmxx::RegisterThreadedAction<ParallelComponent, Action,
     739              :                                                Args...>::registrar =  // NOLINT
     740              :     Parallel::charmxx::register_func_with_charm<
     741              :         RegisterThreadedAction<ParallelComponent, Action, Args...>>();
     742              : 
     743              : // clang-tidy: redundant declaration
     744              : template <typename ParallelComponent, typename Action>
     745              : bool Parallel::charmxx::RegisterThreadedAction<ParallelComponent,
     746              :                                                Action>::registrar =  // NOLINT
     747              :     Parallel::charmxx::register_func_with_charm<
     748              :         RegisterThreadedAction<ParallelComponent, Action>>();
     749              : 
     750              : // clang-tidy: redundant declaration
     751              : template <typename ParallelComponent, typename ReceiveTag, bool UsingMessages>
     752              : bool Parallel::charmxx::RegisterReceiveData<
     753              :     ParallelComponent, ReceiveTag, UsingMessages>::registrar =  // NOLINT
     754              :     Parallel::charmxx::register_func_with_charm<
     755              :         RegisterReceiveData<ParallelComponent, ReceiveTag, UsingMessages>>();
     756              : 
     757              : // clang-tidy: redundant declaration
     758              : template <typename ParallelComponent, typename Action, typename ReductionType>
     759              : bool Parallel::charmxx::RegisterReductionAction<
     760              :     ParallelComponent, Action, ReductionType>::registrar =  // NOLINT
     761              :     Parallel::charmxx::register_func_with_charm<
     762              :         RegisterReductionAction<ParallelComponent, Action, ReductionType>>();
     763              : 
     764              : // clang-tidy: redundant declaration
     765              : template <typename Metavariables, typename Invokable, typename... Tags>
     766              : bool Parallel::charmxx::RegisterPhaseChangeReduction<
     767              :     Metavariables, Invokable, Tags...>::registrar =  // NOLINT
     768              :     Parallel::charmxx::register_func_with_charm<
     769              :         RegisterPhaseChangeReduction<Metavariables, Invokable, Tags...>>();
     770              : 
     771              : // clang-tidy: redundant declaration
     772              : template <typename Metavariables, typename GlobalCacheTag, typename Function,
     773              :           typename... Args>
     774              : bool Parallel::charmxx::RegisterGlobalCacheMutate<
     775              :     Metavariables, GlobalCacheTag, Function,
     776              :     Args...>::registrar =  // NOLINT
     777              :     Parallel::charmxx::register_func_with_charm<RegisterGlobalCacheMutate<
     778              :         Metavariables, GlobalCacheTag, Function, Args...>>();
     779              : 
     780              : // clang-tidy: redundant declaration
     781              : template <typename ParallelComponent, typename Action, typename PhaseIndex,
     782              :           typename DataBoxIndex>
     783              : bool Parallel::charmxx::RegisterInvokeIterableAction<
     784              :     ParallelComponent, Action, PhaseIndex, DataBoxIndex>::registrar =  // NOLINT
     785              :     Parallel::charmxx::register_func_with_charm<RegisterInvokeIterableAction<
     786              :         ParallelComponent, Action, PhaseIndex, DataBoxIndex>>();
     787              : 
     788              : /// \cond
     789              : class CkReductionMsg;
     790              : /// \endcond
     791              : 
     792              : namespace Parallel {
     793              : namespace charmxx {
     794              : /*!
     795              :  * \ingroup CharmExtensionsGroup
     796              :  * \brief The type of a function pointer to a Charm++ custom reduction function.
     797              :  */
     798            1 : using ReducerFunctions = CkReductionMsg* (*)(int, CkReductionMsg**);
     799              : /// \cond
     800              : extern ReducerFunctions* charm_reducer_functions_list;
     801              : extern size_t charm_reducer_functions_capacity;
     802              : extern size_t charm_reducer_functions_size;
     803              : extern std::unordered_map<size_t, CkReduction::reducerType>
     804              :     charm_reducer_functions;
     805              : /// \endcond
     806              : 
     807              : /*!
     808              :  * \ingroup CharmExtensionsGroup
     809              :  * \brief Class used for registering custom reduction function
     810              :  *
     811              :  * The static member variable is initialized before main is entered. This means
     812              :  * we are able to inject code into the beginning of the execution of an
     813              :  * executable by "using" the variable (casting to void counts) the function that
     814              :  * initializes the variable is called. We "use" `registrar` inside the
     815              :  * `Parallel::contribute_to_reduction` function.
     816              :  */
     817              : template <ReducerFunctions>
     818            1 : struct RegisterReducerFunction {
     819            0 :   static bool registrar;
     820              : };
     821              : 
     822              : /*!
     823              :  * \ingroup CharmExtensionsGroup
     824              :  * \brief Function that stores a function pointer to the custom reduction
     825              :  * function to be registered later.
     826              :  *
     827              :  * Used to initialize the `registrar` bool of `RegisterReducerFunction`. When
     828              :  * invoked it adds the function `F` of type `ReducerFunctions` to the list
     829              :  * `charm_reducer_functions_list`.
     830              :  *
     831              :  * \note The reason for not using a `std::vector<ReducerFunctions>` is that this
     832              :  * did not behave correctly when calling `push_back`. Specifically, the final
     833              :  * vector was always size 1, even though multiple elements were pushed back. The
     834              :  * reason for that behavior was never tracked down and so in the future it could
     835              :  * be possible to use a `std::vector`.
     836              :  */
     837              : template <ReducerFunctions F>
     838            1 : bool register_reducer_function() {
     839              : #ifdef SPECTRE_CHARM_HAS_MAIN
     840              :   if (charm_reducer_functions_size >= charm_reducer_functions_capacity) {
     841              :     // clang-tidy: use gsl::owner (we don't use raw owning pointers unless
     842              :     // necessary)
     843              :     auto* const t =  // NOLINT
     844              :         new ReducerFunctions[charm_reducer_functions_capacity + 10];
     845              :     for (size_t i = 0; i < charm_reducer_functions_capacity; ++i) {
     846              :       // clang-tidy: do not use pointer arithmetic
     847              :       t[i] = std::move(charm_reducer_functions_list[i]);  // NOLINT
     848              :     }
     849              :     // clang-tidy: use gsl::owner (we don't use raw owning pointers unless
     850              :     // necessary)
     851              :     delete[] charm_reducer_functions_list;  // NOLINT
     852              :     charm_reducer_functions_list = t;
     853              :     charm_reducer_functions_capacity += 10;
     854              :   }
     855              :   charm_reducer_functions_size++;
     856              :   // clang-tidy: do not use pointer arithmetic
     857              :   charm_reducer_functions_list[charm_reducer_functions_size - 1] = F;  // NOLINT
     858              : #endif  // SPECTRE_CHARM_HAS_MAIN
     859              :   return true;
     860              : }
     861              : }  // namespace charmxx
     862              : }  // namespace Parallel
     863              : 
     864              : // clang-tidy: do not use pointer arithmetic
     865              : template <Parallel::charmxx::ReducerFunctions F>
     866              : bool Parallel::charmxx::RegisterReducerFunction<F>::registrar =  // NOLINT
     867              :     Parallel::charmxx::register_reducer_function<F>();
        

Generated by: LCOV version 2.0-1