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