Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <algorithm>
7 : #include <deque>
8 : #include <type_traits>
9 : #include <unordered_map>
10 : #include <utility>
11 :
12 : #include "DataStructures/DataBox/DataBox.hpp"
13 : #include "DataStructures/Variables.hpp"
14 : #include "Domain/Tags.hpp"
15 : #include "NumericalAlgorithms/Spectral/Mesh.hpp"
16 : #include "Parallel/GlobalCache.hpp"
17 : #include "ParallelAlgorithms/Interpolation/Actions/TryToInterpolate.hpp"
18 : #include "ParallelAlgorithms/Interpolation/Tags.hpp"
19 : #include "Utilities/Algorithm.hpp"
20 : #include "Utilities/Gsl.hpp"
21 : #include "Utilities/TMPL.hpp"
22 : #include "Utilities/TaggedTuple.hpp"
23 :
24 : namespace intrp {
25 : namespace Actions {
26 : namespace detail {
27 : template <typename Metavariables, typename Tag, typename = std::void_t<>>
28 : struct get_interpolating_component_or_interpolator {
29 : using type = Interpolator<Metavariables>;
30 : };
31 : template <typename Metavariables, typename Tag>
32 : struct get_interpolating_component_or_interpolator<
33 : Metavariables, Tag,
34 : std::void_t<
35 : typename Tag::template interpolating_component<Metavariables>>> {
36 : using type = typename Tag::template interpolating_component<Metavariables>;
37 : };
38 : template <typename Metavariables, typename Tag>
39 : using get_interpolating_component_or_interpolator_t =
40 : typename get_interpolating_component_or_interpolator<Metavariables,
41 : Tag>::type;
42 :
43 : template <typename Metavariables, typename Tag>
44 : constexpr bool using_interpolator_component_v = std::is_same_v<
45 : get_interpolating_component_or_interpolator_t<Metavariables, Tag>,
46 : Interpolator<Metavariables>>;
47 : } // namespace detail
48 :
49 : /// \ingroup ActionsGroup
50 : /// \brief Adds volume data from an `Element`.
51 : ///
52 : /// Attempts to interpolate if it already has received target points from
53 : /// any InterpolationTargets.
54 : ///
55 : /// Uses:
56 : /// - DataBox:
57 : /// - `Tags::NumberOfElements`
58 : ///
59 : /// DataBox changes:
60 : /// - Adds: nothing
61 : /// - Removes: nothing
62 : /// - Modifies:
63 : /// - `Tags::VolumeVarsInfo<Metavariables>`
64 : /// - `Tags::InterpolatedVarsHolders<Metavariables>`
65 : template <typename TemporalId>
66 1 : struct InterpolatorReceiveVolumeData {
67 : template <typename ParallelComponent, typename DbTags, typename Metavariables,
68 : typename ArrayIndex, size_t VolumeDim>
69 0 : static void apply(
70 : db::DataBox<DbTags>& box, Parallel::GlobalCache<Metavariables>& cache,
71 : const ArrayIndex& /*array_index*/,
72 : const typename TemporalId::type& temporal_id,
73 : const ElementId<VolumeDim>& element_id, const ::Mesh<VolumeDim>& mesh,
74 : Variables<typename Metavariables::interpolator_source_vars>&&
75 : interpolator_source_vars) {
76 : // Determine if we have already finished interpolating on this
77 : // temporal_id. If so, then we simply return, ignore the incoming
78 : // data, and do not interpolate.
79 : //
80 : // This scenario can happen if there is an element that is not
81 : // used or needed for any InterpolationTarget, and if that element
82 : // calls InterpolatorReceiveVolumeData so late that all the
83 : // InterpolationTargets for the current temporal_id have already
84 : // finished.
85 : bool this_temporal_id_is_done = true;
86 : const auto& holders =
87 : db::get<Tags::InterpolatedVarsHolders<Metavariables>>(box);
88 : tmpl::for_each<typename Metavariables::interpolation_target_tags>(
89 : [&holders, &this_temporal_id_is_done, &temporal_id](auto tag_v) {
90 : using tag = typename decltype(tag_v)::type;
91 : // Here we decide whether this interpolation target is "done" (i.e. it
92 : // does not need to interpolate) at this temporal_id. If it is "done",
93 : // then we don't need to store the volume data. Usually "done" means
94 : // that it has already done its interpolation at this temporal_id. But
95 : // note that if an interpolation target is not using the Interpolator
96 : // at all, it is considered "done", because we don't need any volume
97 : // data for it and should not store it. Similarly, interpolation
98 : // targets whose temporal_id has a different type than TemporalId are
99 : // considered "done" because they too do not use the Interpolator and
100 : // don't need volume data to be saved.
101 : if constexpr (detail::using_interpolator_component_v<Metavariables,
102 : tag> and
103 : std::is_same_v<TemporalId, typename tag::temporal_id>) {
104 : const auto& finished_temporal_ids =
105 : get<Vars::HolderTag<tag, Metavariables>>(holders)
106 : .temporal_ids_when_data_has_been_interpolated;
107 : if (not alg::found(finished_temporal_ids, temporal_id)) {
108 : this_temporal_id_is_done = false;
109 : }
110 : }
111 : });
112 :
113 : if (this_temporal_id_is_done) {
114 : return;
115 : }
116 :
117 : // Add to the VolumeVarsInfo for this TemporalId type. (Note that
118 : // multiple VolumeVarsInfos, each with a different TemporalId
119 : // type, can be in the databox. Note also that the above check
120 : // for this_temporal_id_is_done and the interpolation below are
121 : // done only for this TemporalId type and not for any other
122 : // VolumeVarsInfos that might be in the DataBox.)
123 : db::mutate<Tags::VolumeVarsInfo<Metavariables, TemporalId>>(
124 : [&temporal_id, &element_id, &mesh, &interpolator_source_vars](
125 : const gsl::not_null<
126 : typename Tags::VolumeVarsInfo<Metavariables, TemporalId>::type*>
127 : container) {
128 : if (container->find(temporal_id) == container->end()) {
129 : container->emplace(
130 : temporal_id,
131 : std::unordered_map<ElementId<VolumeDim>,
132 : typename Tags::VolumeVarsInfo<
133 : Metavariables, TemporalId>::Info>{});
134 : }
135 : container->at(temporal_id)
136 : .emplace(std::make_pair(
137 : element_id,
138 : typename Tags::VolumeVarsInfo<Metavariables,
139 : TemporalId>::Info{
140 : mesh, std::move(interpolator_source_vars), {}}));
141 : },
142 : make_not_null(&box));
143 :
144 : // Try to interpolate data for all InterpolationTargets for this
145 : // temporal_id. Also make sure this target is using the interpolator. No
146 : // sense in calling this for targets that don't use it.
147 : tmpl::for_each<typename Metavariables::interpolation_target_tags>(
148 : [&box, &cache, &temporal_id](auto tag_v) {
149 : using tag = typename decltype(tag_v)::type;
150 : if constexpr (detail::using_interpolator_component_v<Metavariables,
151 : tag> and
152 : std::is_same_v<typename tag::temporal_id, TemporalId>) {
153 : try_to_interpolate<tag>(make_not_null(&box), make_not_null(&cache),
154 : temporal_id);
155 : }
156 : });
157 : }
158 : };
159 :
160 : } // namespace Actions
161 : } // namespace intrp
|