12 #include "DataStructures/ComplexDataVector.hpp"
14 #include "DataStructures/SpinWeighted.hpp"
15 #include "Evolution/Systems/Cce/OptionTags.hpp"
16 #include "Evolution/Systems/Cce/ScriPlusInterpolationManager.hpp"
17 #include "Evolution/Systems/Cce/Tags.hpp"
18 #include "IO/Observer/WriteSimpleData.hpp"
19 #include "NumericalAlgorithms/Spectral/SwshCoefficients.hpp"
20 #include "NumericalAlgorithms/Spectral/SwshTransform.hpp"
22 #include "Parallel/Invoke.hpp"
23 #include "Time/Tags.hpp"
25 #include "Utilities/MakeString.hpp"
31 template <
typename Metavariables>
32 struct AnalyticWorldtubeBoundary;
38 template <
typename Tag>
40 static std::string name() noexcept {
return db::tag_name<Tag>(); }
42 template <
typename Tag>
43 struct ScriOutput<Tags::ScriPlus<Tag>> {
44 static std::string name() noexcept {
return pretty_type::short_name<Tag>(); }
47 struct ScriOutput<Tags::Du<Tags::TimeIntegral<Tags::ScriPlus<Tags::Psi4>>>> {
48 static std::string name() noexcept {
return "Psi4"; }
51 using weyl_correction_list =
52 tmpl::list<Tags::Du<Tags::TimeIntegral<Tags::ScriPlus<Tags::Psi4>>>,
53 Tags::ScriPlus<Tags::Psi3>, Tags::ScriPlus<Tags::Psi2>,
54 Tags::ScriPlus<Tags::Psi1>, Tags::ScriPlus<Tags::Psi0>,
55 Tags::EthInertialRetardedTime>;
57 void correct_weyl_scalars_for_inertial_time(
59 weyl_correction_variables) noexcept;
108 template <
typename ObserverWriterComponent,
typename BoundaryComponent>
110 using const_global_cache_tags = tmpl::flatten<
113 tt::is_a_v<AnalyticWorldtubeBoundary, BoundaryComponent>,
114 tmpl::list<Tags::OutputNoninertialNews>, tmpl::list<>>>>;
115 template <
typename DbTags,
typename... InboxTags,
typename Metavariables,
116 typename ArrayIndex,
typename ActionList,
117 typename ParallelComponent>
119 db::DataBox<DbTags>& box,
122 const ArrayIndex& ,
const ActionList ,
123 const ParallelComponent*
const ) noexcept {
124 const size_t observation_l_max = db::get<Tags::ObservationLMax>(box);
125 const size_t l_max = db::get<Tags::LMax>(box);
129 file_legend.reserve(2 *
square(observation_l_max + 1) + 1);
130 file_legend.emplace_back(
"time");
131 for (
int i = 0; i <= static_cast<int>(observation_l_max); ++i) {
132 for (
int j = -i; j <= i; ++j) {
133 file_legend.push_back(
MakeString{} <<
"Real Y_" << i <<
"," << j);
134 file_legend.push_back(
MakeString{} <<
"Imag Y_" << i <<
"," << j);
144 Variables<detail::weyl_correction_list> corrected_scri_plus_weyl{
150 tmpl::front<typename Metavariables::scri_values_to_observe>>>(box)
151 .first_time_is_ready_to_interpolate()) {
153 double interpolation_time = 0.0;
154 tmpl::for_each<detail::weyl_correction_list>([&interpolation_time,
155 &corrected_scri_plus_weyl,
156 &box](
auto tag_v) noexcept {
157 using tag =
typename decltype(tag_v)::type;
159 db::mutate<Tags::InterpolationManager<ComplexDataVector, tag>>(
164 interpolation_manager) {
166 interpolation_manager->interpolate_and_pop_first_time();
168 interpolation_time = interpolation.first;
169 get(get<tag>(corrected_scri_plus_weyl)).data() = interpolation.second;
172 detail::correct_weyl_scalars_for_inertial_time(
176 tmpl::for_each<detail::weyl_correction_list>(
177 [&data_to_write, &corrected_scri_plus_weyl, &interpolation_time,
178 &file_legend, &observation_l_max, &l_max, &
cache,
179 &goldberg_modes](
auto tag_v) noexcept {
180 using tag =
typename decltype(tag_v)::type;
181 if constexpr (tmpl::list_contains_v<
182 typename Metavariables::scri_values_to_observe,
184 ScriObserveInterpolated::transform_and_write<
185 tag, tag::type::type::spin, ParallelComponent>(
186 get(get<tag>(corrected_scri_plus_weyl)).data(),
189 observation_l_max,
cache);
196 detail::weyl_correction_list>>(
197 [&box, &data_to_write, &file_legend, &observation_l_max, &l_max,
198 &
cache, &goldberg_modes](
auto tag_v) noexcept {
199 using tag =
typename decltype(tag_v)::type;
201 db::mutate<Tags::InterpolationManager<ComplexDataVector, tag>>(
206 interpolation_manager) {
208 interpolation_manager->interpolate_and_pop_first_time();
210 ScriObserveInterpolated::transform_and_write<
211 tag, tag::type::type::spin, ParallelComponent>(
212 interpolation.second, interpolation.first,
214 file_legend, l_max, observation_l_max,
cache);
218 if constexpr (tmpl::list_contains_v<DbTags,
220 if (not db::get<Tags::OutputNoninertialNews>(box)) {
221 db::get<Tags::AnalyticBoundaryDataManager>(box)
222 .template write_news<ParallelComponent>(
cache,
227 return std::forward_as_tuple(std::move(box));
231 template <
typename Tag,
int Spin,
typename ParallelComponent,
232 typename Metavariables>
233 static void transform_and_write(
238 const size_t observation_l_max,
243 goldberg_modes.set_data_ref(goldberg_mode_buffer);
248 (*data_to_write_buffer)[0] = time;
249 for (
size_t i = 0; i <
square(observation_l_max + 1); ++i) {
250 (*data_to_write_buffer)[2 * i + 1] = real(goldberg_modes.data()[i]);
251 (*data_to_write_buffer)[2 * i + 2] = imag(goldberg_modes.data()[i]);
254 Parallel::get_parallel_component<ParallelComponent>(
cache);
255 auto observer_proxy =
256 Parallel::get_parallel_component<ObserverWriterComponent>(
257 cache)[
static_cast<size_t>(
259 Parallel::threaded_action<observers::ThreadedActions::WriteSimpleData>(
260 observer_proxy, legend, *data_to_write_buffer,
261 "/" + detail::ScriOutput<Tag>::name());