Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <array>
7 : #include <charm++.h>
8 : #include <cstddef>
9 : #include <optional>
10 : #include <utility>
11 : #include <vector>
12 :
13 : #include "DataStructures/DataBox/DataBox.hpp"
14 : #include "Evolution/DiscontinuousGalerkin/EqualRateLts/Tags/EqualRateRegionId.hpp"
15 : #include "Evolution/DiscontinuousGalerkin/EqualRateLts/Tags/EqualRateRegions.hpp"
16 : #include "Parallel/AlgorithmExecution.hpp"
17 : #include "Parallel/GlobalCache.hpp"
18 : #include "Parallel/Invoke.hpp"
19 : #include "Parallel/Section.hpp"
20 : #include "Parallel/Tags/Section.hpp"
21 : #include "Parallel/TypeTraits.hpp"
22 : #include "Time/LtsMode.hpp"
23 : #include "Time/Tags/FixedLtsRatio.hpp"
24 : #include "Utilities/ErrorHandling/Assert.hpp"
25 : #include "Utilities/Gsl.hpp"
26 : #include "Utilities/TMPL.hpp"
27 :
28 : /// \cond
29 : template <size_t Dim, typename T>
30 : class DirectionalIdMap;
31 : template <size_t VolumeDim>
32 : class Element;
33 : class TimeDelta;
34 : namespace Tags {
35 : struct LtsMode;
36 : struct TimeStep;
37 : } // namespace Tags
38 : namespace domain::Tags {
39 : template <size_t VolumeDim>
40 : struct Element;
41 : template <size_t Dim>
42 : struct InitialRefinementLevels;
43 : } // namespace domain::Tags
44 : namespace evolution::dg {
45 : template <size_t Dim>
46 : class EqualRateRegionsBase;
47 : template <size_t VolumeDim>
48 : class MortarInfo;
49 : } // namespace evolution::dg
50 : namespace evolution::dg::Tags {
51 : template <size_t Dim>
52 : struct MortarInfo;
53 : } // namespace evolution::dg::Tags
54 : namespace tuples {
55 : template <class... Tags>
56 : class TaggedTuple;
57 : } // namespace tuples
58 : /// \endcond
59 :
60 : namespace evolution::dg::Initialization {
61 : /// Set up `FixedLtsRatio` and mortar time-stepping policies to
62 : /// disable local time-stepping in equal rate regions.
63 : template <size_t Dim>
64 1 : struct SetupLocalEqualRateRegion {
65 0 : using return_tags =
66 : tmpl::list<::Tags::FixedLtsRatio, evolution::dg::Tags::MortarInfo<Dim>>;
67 0 : using argument_tags =
68 : tmpl::list<domain::Tags::Element<Dim>,
69 : evolution::dg::Tags::EqualRateRegions<Dim>, ::Tags::TimeStep>;
70 :
71 0 : static void apply(
72 : gsl::not_null<std::optional<size_t>*> fixed_lts_ratio,
73 : gsl::not_null<DirectionalIdMap<Dim, ::evolution::dg::MortarInfo<Dim>>*>
74 : mortar_infos,
75 : const Element<Dim>& element,
76 : const EqualRateRegionsBase<Dim>& equal_rate_regions,
77 : const TimeDelta& time_step);
78 : };
79 :
80 0 : namespace Actions {
81 : template <size_t Dim>
82 0 : struct SetEqualRateSection {
83 : template <typename ParallelComponent, typename DbTags, typename Metavariables,
84 : typename ArrayIndex>
85 0 : static void apply(
86 : db::DataBox<DbTags>& box, Parallel::GlobalCache<Metavariables>& /*cache*/,
87 : const ArrayIndex& /*array_index*/,
88 : Parallel::Section<ParallelComponent, Tags::EqualRateRegionId> section) {
89 : const auto& equal_rate_regions =
90 : db::get<evolution::dg::Tags::EqualRateRegions<Dim>>(box);
91 : const auto& element = db::get<domain::Tags::Element<Dim>>(box);
92 : if (equal_rate_regions.is_in_region(section.id(), element.id())) {
93 : db::mutate<
94 : Parallel::Tags::Section<ParallelComponent, Tags::EqualRateRegionId>>(
95 : [&](const gsl::not_null<std::optional<Parallel::Section<
96 : ParallelComponent, Tags::EqualRateRegionId>>*>
97 : box_section) {
98 : ASSERT(not box_section->has_value(),
99 : "Already have an equal-rate section");
100 : box_section->emplace(std::move(section));
101 : },
102 : make_not_null(&box));
103 : }
104 : }
105 : };
106 :
107 : namespace SetupEqualRateRegions_detail {
108 : template <size_t Dim>
109 : struct SectionsToCreate {
110 : using argument_tags = tmpl::list<domain::Tags::Element<Dim>,
111 : evolution::dg::Tags::EqualRateRegions<Dim>,
112 : domain::Tags::InitialRefinementLevels<Dim>>;
113 :
114 : static std::vector<std::pair<EqualRateRegionId, std::vector<CkArrayIndex>>>
115 : apply(const Element<Dim>& element,
116 : const EqualRateRegionsBase<Dim>& equal_rate_regions,
117 : const std::vector<std::array<size_t, Dim>>& initial_refinement_levels);
118 : };
119 : } // namespace SetupEqualRateRegions_detail
120 :
121 : /// Set up `FixedLtsRatio` and mortar time-stepping policies to
122 : /// disable local time-stepping in equal rate regions.
123 : template <typename Metavariables, size_t Dim, typename RegionGenerators>
124 1 : struct SetupEqualRateRegions {
125 : private:
126 0 : using array_components = tmpl::filter<typename Metavariables::component_list,
127 : Parallel::is_array<tmpl::_1>>;
128 : static_assert(tmpl::size<array_components>::value == 1,
129 : "Cannot identify element array.");
130 :
131 : public:
132 0 : using ParallelComponent = tmpl::front<array_components>;
133 :
134 0 : using const_global_cache_tags = tmpl::list<
135 : evolution::dg::Tags::ConcreteEqualRateRegions<Dim, RegionGenerators>>;
136 0 : using simple_tags = tmpl::list<
137 : ::Tags::FixedLtsRatio,
138 : Parallel::Tags::Section<ParallelComponent, Tags::EqualRateRegionId>>;
139 0 : using compute_tags = tmpl::list<
140 : evolution::dg::Tags::EqualRateRegionsRef<Dim, RegionGenerators>>;
141 :
142 : template <typename DbTags, typename... InboxTags, typename ArrayIndex,
143 : typename ActionList>
144 0 : static Parallel::iterable_action_return_t apply(
145 : db::DataBox<DbTags>& box,
146 : const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
147 : Parallel::GlobalCache<Metavariables>& cache,
148 : const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
149 : const ParallelComponent* const /*meta*/) {
150 : if (db::get<::Tags::LtsMode>(box) == LtsMode::Off) {
151 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
152 : }
153 :
154 : db::mutate_apply<SetupLocalEqualRateRegion<Dim>>(make_not_null(&box));
155 :
156 : // Set up sections. This will be empty everywhere except element 0.
157 : const auto sections_to_create =
158 : db::apply<SetupEqualRateRegions_detail::SectionsToCreate<Dim>>(box);
159 : for (const auto& [region_id, section_elements] : sections_to_create) {
160 : auto& component =
161 : Parallel::get_parallel_component<ParallelComponent>(cache);
162 : using Section =
163 : Parallel::Section<ParallelComponent, Tags::EqualRateRegionId>;
164 : const Section section{
165 : region_id, Section::cproxy_section::ckNew(component.ckGetArrayID(),
166 : section_elements)};
167 :
168 : // Charm sections are buggy. Most of their features only work
169 : // when manually sending charm messages. The higher-level
170 : // interfaces exist, but fail to actually transmit data to the
171 : // receiving end and pass in garbage instead. This is mentioned
172 : // in an offhand remark in a section of the charm documentation
173 : // on "optimized multicast". As a result we avoid doing
174 : // anything other than reductions (which seem to work) on
175 : // sections. Here we use an array broadcast and ignore the
176 : // message on most of the elements because section broadcasts
177 : // don't work.
178 : Parallel::simple_action<SetEqualRateSection<Dim>>(component, section);
179 : }
180 :
181 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
182 : }
183 : };
184 : } // namespace Actions
185 : } // namespace evolution::dg::Initialization
|