Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <optional>
7 : #include <tuple>
8 :
9 : #include "DataStructures/DataBox/DataBox.hpp"
10 : #include "Evolution/Systems/Cce/OptionTags.hpp"
11 : #include "Evolution/Systems/Cce/Tags.hpp"
12 : #include "IO/Observer/ReductionActions.hpp"
13 : #include "Parallel/AlgorithmExecution.hpp"
14 : #include "Parallel/GlobalCache.hpp"
15 : #include "Parallel/Local.hpp"
16 : #include "Time/TimeStepId.hpp"
17 :
18 : /// \cond
19 : namespace Tags {
20 : struct TimeStep;
21 : struct TimeStepId;
22 : } // namespace Tags
23 : /// \endcond
24 :
25 : namespace Cce {
26 : namespace Actions {
27 :
28 : namespace detail {
29 : template <typename Tag>
30 : struct get_interpolator_argument_tag {
31 : using type = Tag;
32 : };
33 :
34 : template <typename Tag>
35 : struct get_interpolator_argument_tag<Tags::Du<Tag>> {
36 : using type = Tag;
37 : };
38 :
39 : template <typename Tag>
40 : struct InsertIntoInterpolationManagerImpl {
41 : using return_tags =
42 : tmpl::list<Tags::InterpolationManager<ComplexDataVector, Tag>>;
43 : using argument_tags =
44 : tmpl::list<typename get_interpolator_argument_tag<Tag>::type,
45 : Tags::InertialRetardedTime>;
46 : static void apply(
47 : const gsl::not_null<ScriPlusInterpolationManager<ComplexDataVector, Tag>*>
48 : interpolation_manager,
49 : const typename Tag::type& scri_data,
50 : const Scalar<DataVector>& inertial_retarded_time) {
51 : interpolation_manager->insert_data(get(inertial_retarded_time),
52 : get(scri_data).data());
53 : }
54 : };
55 :
56 : template <typename LhsTag, typename RhsTag>
57 : struct InsertIntoInterpolationManagerImpl<::Tags::Multiplies<LhsTag, RhsTag>> {
58 : using return_tags = tmpl::list<Tags::InterpolationManager<
59 : ComplexDataVector, ::Tags::Multiplies<LhsTag, RhsTag>>>;
60 : using argument_tags =
61 : tmpl::list<typename get_interpolator_argument_tag<LhsTag>::type, RhsTag,
62 : Tags::InertialRetardedTime>;
63 : static void apply(const gsl::not_null<ScriPlusInterpolationManager<
64 : ComplexDataVector, ::Tags::Multiplies<LhsTag, RhsTag>>*>
65 : interpolation_manager,
66 : const typename LhsTag::type& lhs_data,
67 : const typename RhsTag::type& rhs_data,
68 : const Scalar<DataVector>& inertial_retarded_time) {
69 : interpolation_manager->insert_data(get(inertial_retarded_time),
70 : get(lhs_data).data(),
71 : get(rhs_data).data());
72 : }
73 : };
74 :
75 : template <typename Tag, typename ParallelComponent, typename Metavariables>
76 : void output_impl(const size_t observation_l_max, const size_t l_max,
77 : const TimeStepId& time_id, const typename Tag::type& tag_data,
78 : Parallel::GlobalCache<Metavariables>& cache) {
79 : std::vector<double> data_to_write(2 * square(observation_l_max + 1) + 1);
80 : std::vector<std::string> file_legend;
81 : file_legend.reserve(2 * square(observation_l_max + 1) + 1);
82 : file_legend.emplace_back("time");
83 : for (int l = 0; l <= static_cast<int>(observation_l_max); ++l) {
84 : for (int m = -l; m <= l; ++m) {
85 : file_legend.push_back(MakeString{} << "Real Y_" << l << "," << m);
86 : file_legend.push_back(MakeString{} << "Imag Y_" << l << "," << m);
87 : }
88 : }
89 : auto observer_proxy = Parallel::get_parallel_component<
90 : observers::ObserverWriter<Metavariables>>(cache)[0];
91 : // swsh transform
92 : const ComplexModalVector goldberg_modes =
93 : Spectral::Swsh::libsharp_to_goldberg_modes(
94 : Spectral::Swsh::swsh_transform(l_max, 1, get(tag_data)), l_max)
95 : .data();
96 :
97 : data_to_write[0] = time_id.substep_time();
98 : for (size_t i = 0; i < square(observation_l_max + 1); ++i) {
99 : data_to_write[2 * i + 1] = real(goldberg_modes[i]);
100 : data_to_write[2 * i + 2] = imag(goldberg_modes[i]);
101 : }
102 : Parallel::threaded_action<observers::ThreadedActions::WriteReductionDataRow>(
103 : observer_proxy, "/Cce/" + db::tag_name<Tag>() + "_Noninertial",
104 : file_legend, std::make_tuple(data_to_write));
105 : }
106 : } // namespace detail
107 :
108 : /*!
109 : * \ingroup ActionsGroup
110 : * \brief Places the data from the current hypersurface necessary to compute
111 : * `Tag` in the `ScriPlusInterpolationManager` associated with the `Tag`.
112 : *
113 : * \details Adds both the appropriate scri+ value(s) and a number of target
114 : * inertial times to interpolate of quantity equal to the
115 : * `InitializationTags::ScriOutputDensity` determined from options, equally
116 : * spaced between the current time and the next time in the algorithm.
117 : *
118 : * Uses:
119 : * - `::Tags::TimeStepId`
120 : * - `::Tags::Next<::Tags::TimeStepId>`
121 : * - `Cce::InitializationTags::ScriOutputDensity`
122 : * - if `Tag` is `::Tags::Multiplies<Lhs, Rhs>`:
123 : * - `Lhs` and `Rhs`
124 : * - if `Tag` has `Cce::Tags::Du<Argument>`:
125 : * - `Argument`
126 : * - otherwise uses `Tag`
127 : *
128 : * \ref DataBoxGroup changes:
129 : * - Modifies:
130 : * - `Tags::InterpolationManager<ComplexDataVector, Tag>`
131 : * - Adds: nothing
132 : * - Removes: nothing
133 : */
134 : template <typename Tag, typename BoundaryComponent>
135 1 : struct InsertInterpolationScriData {
136 0 : using const_global_cache_tags = tmpl::flatten<
137 : tmpl::list<InitializationTags::ScriOutputDensity,
138 : std::conditional_t<
139 : tt::is_a_v<AnalyticWorldtubeBoundary, BoundaryComponent>,
140 : tmpl::list<Tags::OutputNoninertialNews>, tmpl::list<>>>>;
141 : template <typename DbTags, typename... InboxTags, typename Metavariables,
142 : typename ArrayIndex, typename ActionList,
143 : typename ParallelComponent>
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 constexpr(tt::is_a_v<AnalyticWorldtubeBoundary, BoundaryComponent>) {
151 : if (db::get<Tags::OutputNoninertialNews>(box) and
152 : db::get<::Tags::TimeStepId>(box).substep() == 0 and
153 : std::is_same_v<Tag, Tags::News>) {
154 : detail::output_impl<Tags::News, ParallelComponent>(
155 : db::get<Tags::ObservationLMax>(box), db::get<Tags::LMax>(box),
156 : db::get<::Tags::TimeStepId>(box), db::get<Tags::News>(box), cache);
157 : db::get<Tags::AnalyticBoundaryDataManager>(box)
158 : .template write_news<ParallelComponent>(
159 : cache, db::get<::Tags::TimeStepId>(box).substep_time());
160 : }
161 : }
162 : if (db::get<::Tags::TimeStepId>(box).substep() == 0) {
163 : // insert the data points into the interpolator.
164 : db::mutate_apply<detail::InsertIntoInterpolationManagerImpl<Tag>>(
165 : make_not_null(&box));
166 :
167 : const auto& time_span_deque =
168 : db::get<Tags::InterpolationManager<ComplexDataVector, Tag>>(box)
169 : .get_u_bondi_ranges();
170 :
171 : const double this_time = time_span_deque.back().first;
172 : double time_delta_estimate = db::get<::Tags::TimeStep>(box).value();
173 : if (time_span_deque.size() > 1) {
174 : time_delta_estimate =
175 : this_time - time_span_deque[time_span_deque.size() - 2].first;
176 : }
177 :
178 : // insert the target times into the interpolator.
179 : db::mutate<Tags::InterpolationManager<ComplexDataVector, Tag>>(
180 : [&this_time, &time_delta_estimate](
181 : const gsl::not_null<
182 : ScriPlusInterpolationManager<ComplexDataVector, Tag>*>
183 : interpolation_manager,
184 : const size_t number_of_interpolated_times) {
185 : for (size_t i = 0; i < number_of_interpolated_times; ++i) {
186 : interpolation_manager->insert_target_time(
187 : this_time +
188 : time_delta_estimate * static_cast<double>(i) /
189 : static_cast<double>(number_of_interpolated_times));
190 : }
191 : },
192 : make_not_null(&box),
193 : db::get<InitializationTags::ScriOutputDensity>(box));
194 : }
195 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
196 : }
197 : };
198 : } // namespace Actions
199 : } // namespace Cce
|