SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/Amr/Actions - ElementsRegistration.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 5.6 % 18 1
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            1 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : /// \file
       5              : /// The actions in this file keep track of all element IDs during AMR and update
       6              : /// the array sections that represent the grid hierarchy.
       7              : 
       8              : #pragma once
       9              : 
      10              : #include <algorithm>
      11              : #include <charm++.h>
      12              : #include <cstddef>
      13              : #include <optional>
      14              : #include <unordered_map>
      15              : #include <unordered_set>
      16              : #include <vector>
      17              : 
      18              : #include "Domain/Structure/ElementId.hpp"
      19              : #include "Parallel/AlgorithmExecution.hpp"
      20              : #include "Parallel/ElementRegistration.hpp"
      21              : #include "Parallel/GlobalCache.hpp"
      22              : #include "Parallel/Invoke.hpp"
      23              : #include "Parallel/Local.hpp"
      24              : #include "Parallel/Printf/Printf.hpp"
      25              : #include "Parallel/Protocols/ElementRegistrar.hpp"
      26              : #include "Parallel/Section.hpp"
      27              : #include "Parallel/Tags/Section.hpp"
      28              : #include "ParallelAlgorithms/Amr/Protocols/Projector.hpp"
      29              : #include "ParallelAlgorithms/Amr/Tags.hpp"
      30              : #include "Utilities/ProtocolHelpers.hpp"
      31              : #include "Utilities/TMPL.hpp"
      32              : 
      33              : namespace amr {
      34              : template <typename Metavariables>
      35              : struct Component;
      36              : }  // namespace amr
      37              : 
      38              : namespace amr::Actions {
      39              : 
      40              : template <size_t Dim>
      41            0 : struct InitializeElementsRegistration {
      42            0 :   using simple_tags = tmpl::list<Tags::AllElementIds<Dim>>;
      43            0 :   using compute_tags = tmpl::list<>;
      44              : 
      45              :   template <typename DbTagsList, typename... InboxTags, typename ArrayIndex,
      46              :             typename Metavariables, typename ActionList,
      47              :             typename ParallelComponent>
      48            0 :   static Parallel::iterable_action_return_t apply(
      49              :       db::DataBox<DbTagsList>& /*box*/,
      50              :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
      51              :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
      52              :       const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
      53              :       const ParallelComponent* const /*meta*/) {
      54              :     return {Parallel::AlgorithmExecution::Pause, std::nullopt};
      55              :   }
      56              : };
      57              : 
      58            0 : struct RegisterOrDeregisterElement {
      59              :   template <typename ParallelComponent, typename DbTagsList,
      60              :             typename Metavariables, typename ArrayIndex, size_t Dim>
      61            0 :   static void apply(db::DataBox<DbTagsList>& box,
      62              :                     const Parallel::GlobalCache<Metavariables>& /*cache*/,
      63              :                     const ArrayIndex& /*array_index*/,
      64              :                     const ElementId<Dim>& element_id,
      65              :                     const bool register_or_deregister) {
      66              :     db::mutate<Tags::AllElementIds<Dim>>(
      67              :         [&element_id, register_or_deregister](const auto all_element_ids) {
      68              :           auto& element_ids = (*all_element_ids)[element_id.grid_index()];
      69              :           if (register_or_deregister) {
      70              :             element_ids.insert(element_id);
      71              :           } else {
      72              :             element_ids.erase(element_id);
      73              :           }
      74              :         },
      75              :         make_not_null(&box));
      76              :   }
      77              : };
      78              : 
      79            0 : struct RegisterElement : tt::ConformsTo<Parallel::protocols::ElementRegistrar> {
      80              :  public:  // ElementRegistrar protocol
      81              :   template <typename ParallelComponent, typename DbTagList,
      82              :             typename Metavariables, size_t Dim>
      83            0 :   static void perform_registration(const db::DataBox<DbTagList>& /*box*/,
      84              :                                    Parallel::GlobalCache<Metavariables>& cache,
      85              :                                    const ElementId<Dim>& element_id) {
      86              :     Parallel::simple_action<RegisterOrDeregisterElement>(
      87              :         Parallel::get_parallel_component<::amr::Component<Metavariables>>(
      88              :             cache),
      89              :         element_id, true);
      90              :   }
      91              : 
      92              :   template <typename ParallelComponent, typename DbTagList,
      93              :             typename Metavariables, size_t Dim>
      94            0 :   static void perform_deregistration(
      95              :       const db::DataBox<DbTagList>& /*box*/,
      96              :       Parallel::GlobalCache<Metavariables>& cache,
      97              :       const ElementId<Dim>& element_id) {
      98              :     Parallel::simple_action<RegisterOrDeregisterElement>(
      99              :         Parallel::get_parallel_component<::amr::Component<Metavariables>>(
     100              :             cache),
     101              :         element_id, false);
     102              :   }
     103              : 
     104              :  public:  // Iterable action
     105              :   template <typename DbTagList, typename... InboxTags, typename Metavariables,
     106              :             typename ActionList, typename ParallelComponent, size_t Dim>
     107            0 :   static Parallel::iterable_action_return_t apply(
     108              :       db::DataBox<DbTagList>& box,
     109              :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     110              :       Parallel::GlobalCache<Metavariables>& cache,
     111              :       const ElementId<Dim>& element_id, const ActionList /*meta*/,
     112              :       const ParallelComponent* const /*meta*/) {
     113              :     perform_registration<ParallelComponent>(box, cache, element_id);
     114              :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     115              :   }
     116              : };
     117              : 
     118            0 : struct UpdateSectionsOnElement {
     119              :   template <typename ParallelComponent, typename DbTagsList,
     120              :             typename Metavariables, size_t Dim>
     121            0 :   static void apply(
     122              :       db::DataBox<DbTagsList>& box,
     123              :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
     124              :       const ElementId<Dim>& element_id, const size_t grid_index,
     125              :       Parallel::Section<ParallelComponent, Tags::GridIndex> grid_index_section,
     126              :       std::optional<Parallel::Section<ParallelComponent, Tags::IsFinestGrid>>
     127              :           finest_grid_section) {
     128              :     if (grid_index != element_id.grid_index()) {
     129              :       // Discard broadcast to elements that are not part of the section. This
     130              :       // happens because we broadcast to all elements, not just to the section.
     131              :       // Broadcasting to the section fails with a segfault for some reason.
     132              :       return;
     133              :     }
     134              :     db::mutate<Parallel::Tags::Section<ParallelComponent, Tags::GridIndex>,
     135              :                Parallel::Tags::Section<ParallelComponent, Tags::IsFinestGrid>>(
     136              :         [&grid_index_section, &finest_grid_section](
     137              :             const auto stored_grid_index_section,
     138              :             const auto stored_finest_grid_section) {
     139              :           // Only update the grid index section if we don't have one already
     140              :           // because the elements in the old grid didn't change. This avoids a
     141              :           // bug(?) with Charm++ where section reductions don't work with the
     142              :           // new section. It's possible that this issue is with (not) updating
     143              :           // the section cookie, but it's not clear how to do that because a
     144              :           // multicast message is needed for that and we can't even do a
     145              :           // broadcast to the section without a segfault.
     146              :           if (not stored_grid_index_section->has_value()) {
     147              :             *stored_grid_index_section = std::move(grid_index_section);
     148              :           }
     149              :           *stored_finest_grid_section = std::move(finest_grid_section);
     150              :         },
     151              :         make_not_null(&box));
     152              :   }
     153              : };
     154              : 
     155            0 : struct DestroyGrid {
     156              :   template <typename ParallelComponent, typename DbTagsList,
     157              :             typename Metavariables, size_t Dim>
     158            0 :   static void apply(db::DataBox<DbTagsList>& box,
     159              :                     Parallel::GlobalCache<Metavariables>& cache,
     160              :                     const ElementId<Dim>& element_id, const size_t grid_index) {
     161              :     if (grid_index == element_id.grid_index()) {
     162              :       // Destroy the element
     163              :       Parallel::deregister_element<ParallelComponent>(box, cache, element_id);
     164              :       auto& array_proxy =
     165              :           Parallel::get_parallel_component<ParallelComponent>(cache);
     166              :       array_proxy[element_id].ckDestroy();
     167              :       return;
     168              :     }
     169              :     // Unregister the parent ID if it was destroyed
     170              :     const auto& parent_id = db::get<amr::Tags::ParentId<Dim>>(box);
     171              :     if (parent_id.has_value() and parent_id->grid_index() == grid_index) {
     172              :       db::mutate<amr::Tags::ParentId<Dim>, amr::Tags::ParentMesh<Dim>>(
     173              :           [](const gsl::not_null<std::optional<ElementId<Dim>>*>
     174              :                  stored_parent_id,
     175              :              const gsl::not_null<std::optional<Mesh<Dim>>*>
     176              :                  stored_parent_mesh) {
     177              :             *stored_parent_id = std::nullopt;
     178              :             *stored_parent_mesh = std::nullopt;
     179              :           },
     180              :           make_not_null(&box));
     181              :     }
     182              :   }
     183              : };
     184              : 
     185              : template <typename ElementArray>
     186            0 : struct UpdateSections {
     187            0 :   using const_global_cache_tags = tmpl::list<amr::Tags::MaxCoarseLevels>;
     188              : 
     189              :   template <typename DbTagList, typename... InboxTags, typename Metavariables,
     190              :             typename ArrayIndex, typename ActionList,
     191              :             typename ParallelComponent>
     192            0 :   static Parallel::iterable_action_return_t apply(
     193              :       db::DataBox<DbTagList>& box,
     194              :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     195              :       Parallel::GlobalCache<Metavariables>& cache,
     196              :       const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
     197              :       const ParallelComponent* const /*meta*/) {
     198              :     static constexpr size_t Dim = Metavariables::volume_dim;
     199              :     const auto& all_element_ids = db::get<Tags::AllElementIds<Dim>>(box);
     200              :     auto& element_array = Parallel::get_parallel_component<ElementArray>(cache);
     201              :     const size_t finest_grid_index = std::prev(all_element_ids.end())->first;
     202              :     const std::optional<size_t> max_coarse_levels =
     203              :         db::get<amr::Tags::MaxCoarseLevels>(box);
     204              :     for (const auto& [grid_index, element_ids] : all_element_ids) {
     205              :       if (max_coarse_levels.has_value() and
     206              :           finest_grid_index - grid_index > max_coarse_levels.value()) {
     207              :         // Delete grids that are coarser than the maximum allowed level
     208              :         Parallel::simple_action<DestroyGrid>(element_array, grid_index);
     209              :         continue;
     210              :       }
     211              :       std::vector<CkArrayIndex> array_indices(element_ids.size());
     212              :       std::transform(
     213              :           element_ids.begin(), element_ids.end(), array_indices.begin(),
     214              :           [](const ElementId<Dim>& local_element_id) {
     215              :             return Parallel::ArrayIndex<ElementId<Dim>>(local_element_id);
     216              :           });
     217              :       using GridIndexSection = Parallel::Section<ElementArray, Tags::GridIndex>;
     218              :       GridIndexSection grid_index_section{
     219              :           grid_index, GridIndexSection::cproxy_section::ckNew(
     220              :                           element_array.ckGetArrayID(), array_indices.data(),
     221              :                           array_indices.size())};
     222              :       using FinestGridSection =
     223              :           Parallel::Section<ElementArray, Tags::IsFinestGrid>;
     224              :       const std::optional<FinestGridSection> finest_grid_section =
     225              :           grid_index == finest_grid_index
     226              :               ? std::make_optional(FinestGridSection{
     227              :                     true, FinestGridSection::cproxy_section::ckNew(
     228              :                               element_array.ckGetArrayID(),
     229              :                               array_indices.data(), array_indices.size())})
     230              :               : std::nullopt;
     231              :       // Send new sections to all elements. Broadcasting to the section fails
     232              :       // with a segfault for some reason.
     233              :       Parallel::simple_action<UpdateSectionsOnElement>(
     234              :           element_array, grid_index, grid_index_section, finest_grid_section);
     235              :     }
     236              :     return {Parallel::AlgorithmExecution::Pause, std::nullopt};
     237              :   }
     238              : };
     239              : 
     240              : }  // namespace amr::Actions
        

Generated by: LCOV version 2.0-1