InterpolationTargetReceiveVars.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <memory>
8 #include <unordered_set>
9 #include <utility>
10 #include <vector>
11 
15 #include "Parallel/Invoke.hpp"
16 #include "Utilities/Gsl.hpp"
17 #include "Utilities/Requires.hpp"
18 #include "Utilities/TMPL.hpp"
20 
21 /// \cond
22 // IWYU pragma: no_forward_declare db::DataBox
23 namespace intrp {
24 template <class Metavariables>
25 struct Interpolator;
26 template <typename Metavariables, typename InterpolationTargetTag>
27 class InterpolationTarget;
28 namespace Actions {
29 template <typename InterpolationTargetTag>
30 struct CleanUpInterpolator;
31 } // namespace Actions
32 namespace Tags {
33 struct IndicesOfFilledInterpPoints;
34 template <typename Metavariables>
35 struct TemporalIds;
36 } // namespace Tags
37 } // namespace intrp
38 namespace Tags {
39 template <typename TagsList>
40 struct Variables;
41 } // namespace Tags
42 /// \endcond
43 
44 namespace intrp {
45 
46 namespace InterpolationTarget_detail {
47 
48 // apply_callback accomplishes the overload for the
49 // two signatures of callback functions.
50 // Uses SFINAE on return type.
51 template <typename T, typename DbTags, typename Metavariables>
52 auto apply_callback(
55  const typename Metavariables::temporal_id::type& temporal_id) noexcept
56  -> decltype(T::post_interpolation_callback::apply(box, cache, temporal_id),
57  bool()) {
58  return T::post_interpolation_callback::apply(box, cache, temporal_id);
59 }
60 
61 template <typename T, typename DbTags, typename Metavariables>
62 auto apply_callback(
65  const typename Metavariables::temporal_id::type& temporal_id) noexcept
66  -> decltype(T::post_interpolation_callback::apply(*box, *cache,
67  temporal_id),
68  bool()) {
69  T::post_interpolation_callback::apply(*box, *cache, temporal_id);
70  // For the simpler callback function, we will always clean up volume data, so
71  // we return true here.
72  return true;
73 }
74 
75 /// Calls the callback function, tells interpolators to clean up the current
76 /// temporal_id, and then if there are more temporal_ids to be interpolated,
77 /// starts the next one.
78 template <typename InterpolationTargetTag, typename DbTags,
79  typename Metavariables>
80 void callback_and_cleanup(
83  cache) noexcept {
84  const auto temporal_id =
85  db::get<Tags::TemporalIds<Metavariables>>(*box).front();
86 
87  // Add compute_items_on_target to the box.
88  auto box_with_more_items = db::create_from<
91  typename InterpolationTargetTag::compute_items_on_target>>(
92  std::move(*box));
93 
94  // apply_callback should return true if we are done with this
95  // temporal_id. It should return false only if the callback
96  // calls another `intrp::Action` that needs the volume data at this
97  // same temporal_id. If it returns false, we exit here and do not
98  // clean up.
99  const bool done_with_temporal_id = apply_callback<InterpolationTargetTag>(
100  make_not_null(&box_with_more_items), cache, temporal_id);
101 
102  // Remove compute_items_on_target from the box.
103  *box = db::create_from<
105  db::AddSimpleTags<>, db::AddComputeTags<>>(
106  std::move(box_with_more_items));
107 
108  if (not done_with_temporal_id) {
109  return;
110  }
111 
112  // We are now done with this temporal_id, so we can pop it and
113  // clean up volume data associated with it.
114 
115  db::mutate<Tags::TemporalIds<Metavariables>>(
116  box, [](const gsl::not_null<
118  ids) noexcept { ids->pop_front(); });
119 
120  // Tell interpolators to clean up at this temporal_id for this
121  // InterpolationTargetTag.
122  auto& interpolator_proxy =
123  Parallel::get_parallel_component<Interpolator<Metavariables>>(*cache);
124  Parallel::simple_action<Actions::CleanUpInterpolator<InterpolationTargetTag>>(
125  interpolator_proxy, temporal_id);
126 
127  // If there are further temporal_ids, begin interpolation for
128  // the next one.
129  const auto& temporal_ids = db::get<Tags::TemporalIds<Metavariables>>(*box);
130  if (not temporal_ids.empty()) {
131  auto& my_proxy = Parallel::get_parallel_component<
132  InterpolationTarget<Metavariables, InterpolationTargetTag>>(*cache);
134  typename InterpolationTargetTag::compute_target_points>(
135  my_proxy, temporal_ids.front());
136  }
137 }
138 
139 } // namespace InterpolationTarget_detail
140 
141 namespace Actions {
142 /// \ingroup ActionsGroup
143 /// \brief Receives interpolated variables from an `Interpolator` on a subset
144 /// of the target points.
145 ///
146 /// If interpolated variables for all target points have been received, then
147 /// - Calls `InterpolationTargetTag::post_interpolation_callback`
148 /// - Tells `Interpolator`s that the interpolation is complete
149 /// (by calling
150 /// `Actions::CleanUpInterpolator<InterpolationTargetTag>`)
151 /// - Removes the first `temporal_id` from `Tags::TemporalIds<Metavariables>`
152 /// - If there are more `temporal_id`s, begins interpolation at the next
153 /// `temporal_id` (by calling `InterpolationTargetTag::compute_target_points`)
154 ///
155 /// Uses:
156 /// - DataBox:
157 /// - `Tags::TemporalIds<Metavariables>`
158 /// - `Tags::IndicesOfFilledInterpPoints`
159 /// - `::Tags::Variables<typename
160 /// InterpolationTargetTag::vars_to_interpolate_to_target>`
161 ///
162 /// DataBox changes:
163 /// - Adds: nothing
164 /// - Removes: nothing
165 /// - Modifies:
166 /// - `Tags::TemporalIds<Metavariables>`
167 /// - `Tags::IndicesOfFilledInterpPoints`
168 /// - `::Tags::Variables<typename
169 /// InterpolationTargetTag::vars_to_interpolate_to_target>`
170 ///
171 /// For requirements on InterpolationTargetTag, see InterpolationTarget
172 template <typename InterpolationTargetTag>
174  /// For requirements on Metavariables, see InterpolationTarget
175  template <typename DbTags, typename... InboxTags, typename Metavariables,
176  typename ArrayIndex, typename ActionList,
177  typename ParallelComponent,
178  Requires<tmpl::list_contains_v<
179  DbTags, typename Tags::TemporalIds<Metavariables>>> = nullptr>
180  static void apply(
181  db::DataBox<DbTags>& box,
182  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
184  const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
185  const ParallelComponent* const /*meta*/,
187  typename InterpolationTargetTag::vars_to_interpolate_to_target>>>&
188  vars_src,
189  const std::vector<std::vector<size_t>>& global_offsets) noexcept {
190  db::mutate<
193  typename InterpolationTargetTag::vars_to_interpolate_to_target>>(
194  make_not_null(&box),
195  [
196  &vars_src, &global_offsets
198  indices_of_filled,
200  typename InterpolationTargetTag::vars_to_interpolate_to_target>>*>
201  vars_dest) noexcept {
202  const size_t npts_dest = vars_dest->number_of_grid_points();
203  const size_t nvars = vars_dest->number_of_independent_components;
204  for (size_t j = 0; j < global_offsets.size(); ++j) {
205  const size_t npts_src = global_offsets[j].size();
206  for (size_t i = 0; i < npts_src; ++i) {
207  // If a point is on the boundary of two (or more)
208  // elements, it is possible that we have received data
209  // for this point from more than one Interpolator.
210  // This will rarely occur, but it does occur, e.g. when
211  // a point is exactly on some symmetry
212  // boundary (such as the x-y plane) and this symmetry
213  // boundary is exactly the boundary between two
214  // elements. If this happens, we accept the first
215  // duplicated point, and we ignore subsequent
216  // duplicated points. The points are easy to keep track
217  // of because global_offsets uniquely identifies them.
218  if (indices_of_filled->insert(global_offsets[j][i]).second) {
219  for (size_t v = 0; v < nvars; ++v) {
220  // clang-tidy: no pointer arithmetic
221  vars_dest->data()[global_offsets[j][i] + // NOLINT
222  v * npts_dest] = // NOLINT
223  vars_src[j].data()[i + v * npts_src]; // NOLINT
224  }
225  }
226  }
227  }
228  });
229 
230  if (db::get<Tags::IndicesOfFilledInterpPoints>(box).size() ==
232  typename InterpolationTargetTag::vars_to_interpolate_to_target>>(
233  box)
234  .number_of_grid_points()) {
235  // All the points have been interpolated.
236  InterpolationTarget_detail::callback_and_cleanup<InterpolationTargetTag>(
237  make_not_null(&box), make_not_null(&cache));
238  }
239  }
240 };
241 } // namespace Actions
242 } // namespace intrp
Definition: Variables.hpp:46
Defines class tuples::TaggedTuple.
void mutate(const gsl::not_null< DataBox< TagList > *> box, Invokable &&invokable, Args &&... args) noexcept
Allows changing the state of one or more non-computed elements in the DataBox.
Definition: DataBox.hpp:1099
Definition: AddTemporalIdsToInterpolationTarget.hpp:17
Keeps track of which points have been filled with interpolated data.
Definition: Tags.hpp:31
tmpl::flatten< tmpl::list< Tags... > > RemoveTags
List of Tags to remove from the DataBox.
Definition: DataBox.hpp:1220
Defines the type alias Requires.
constexpr auto apply(F &&f, const DataBox< BoxTags > &box, Args &&... args)
Apply the function f with argument Tags TagsList from DataBox box
Definition: DataBox.hpp:1595
temporal_ids on which to interpolate.
Definition: InterpolationTargetWedgeSectionTorus.hpp:29
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:272
Defines classes and functions used for manipulating DataBox&#39;s.
constexpr auto create_from(db::DataBox< TagsList > &&box, Args &&... args) noexcept
Create a new DataBox from an existing one adding or removing items and compute items.
Definition: DataBox.hpp:1414
tmpl::flatten< tmpl::list< Tags... > > AddSimpleTags
List of Tags to add to the DataBox.
Definition: DataBox.hpp:1227
Definition: InterpolationTargetWedgeSectionTorus.hpp:24
static void apply(db::DataBox< DbTags > &box, const tuples::TaggedTuple< InboxTags... > &, Parallel::ConstGlobalCache< Metavariables > &cache, const ArrayIndex &, const ActionList, const ParallelComponent *const, const std::vector< db::item_type<::Tags::Variables< typename InterpolationTargetTag::vars_to_interpolate_to_target >>> &vars_src, const std::vector< std::vector< size_t >> &global_offsets) noexcept
For requirements on Metavariables, see InterpolationTarget.
Definition: InterpolationTargetReceiveVars.hpp:180
Definition: DataBoxTag.hpp:29
Receives interpolated variables from an Interpolator on a subset of the target points.
Definition: InterpolationTargetReceiveVars.hpp:173
A Charm++ chare that caches constant data once per Charm++ node.
Definition: ConstGlobalCache.hpp:76
const auto & get(const DataBox< TagList > &box) noexcept
Retrieve the item with tag Tag from the DataBox.
Definition: DataBox.hpp:1211
Wraps the template metaprogramming library used (brigand)
auto get_parallel_component(ConstGlobalCache< Metavariables > &cache) noexcept -> Parallel::proxy_from_parallel_component< ConstGlobalCache_detail::get_component_if_mocked< typename Metavariables::component_list, ParallelComponentTag >> &
Access the Charm++ proxy associated with a ParallelComponent.
Definition: ConstGlobalCache.hpp:163
typename DataBox_detail::item_type_impl< TagList, Tag >::type item_type
Get the type that is returned by the Tag. If it is a base tag then a TagList must be passed as a seco...
Definition: DataBoxTag.hpp:410
Defines functions and classes from the GSL.
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, but it may be necessary to perform the conversion explicitly when type deduction is desired.
Definition: Gsl.hpp:863
void simple_action(Proxy &&proxy) noexcept
Invoke a simple action on proxy
Definition: Invoke.hpp:112
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t ...
Definition: Requires.hpp:67
Identifies a step in the linear solver algorithm.
Definition: IterationId.hpp:25
Definition: SolvePoissonProblem.hpp:38
Defines classes SimpleTag, PrefixTag, ComputeTag and several functions for retrieving tag info...
Defines class template ConstGlobalCache.
Definition: ComputeTimeDerivative.hpp:28
Require a pointer to not be a nullptr
Definition: ConservativeFromPrimitive.hpp:12
tmpl::flatten< tmpl::list< Tags... > > AddComputeTags
List of Compute Item Tags to add to the DataBox.
Definition: DataBox.hpp:1234