Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : // Tests for this file are combined with the ones for
5 : // ObserveFieldsOnHorizon.hpp in
6 : // Test_ObserveFieldsAndTimeSeriesOnHorizon.cpp since they are so similar.
7 :
8 : #pragma once
9 :
10 : #include <array>
11 : #include <cstddef>
12 : #include <string>
13 : #include <utility>
14 : #include <vector>
15 :
16 : #include "DataStructures/DataBox/DataBox.hpp"
17 : #include "DataStructures/LinkedMessageId.hpp"
18 : #include "IO/Observer/ObserverComponent.hpp"
19 : #include "IO/Observer/ReductionActions.hpp"
20 : #include "Parallel/GlobalCache.hpp"
21 : #include "Parallel/Invoke.hpp"
22 : #include "Parallel/Local.hpp"
23 : #include "Parallel/Reduction.hpp"
24 : #include "ParallelAlgorithms/ApparentHorizonFinder/FastFlow.hpp"
25 : #include "ParallelAlgorithms/ApparentHorizonFinder/Protocols/Callback.hpp"
26 : #include "ParallelAlgorithms/ApparentHorizonFinder/Tags.hpp"
27 : #include "Utilities/Functional.hpp"
28 : #include "Utilities/Gsl.hpp"
29 : #include "Utilities/PrettyType.hpp"
30 : #include "Utilities/ProtocolHelpers.hpp"
31 : #include "Utilities/TMPL.hpp"
32 :
33 : namespace ah::callbacks {
34 : namespace detail {
35 : template <typename T>
36 : struct is_array_of_double : std::false_type {};
37 :
38 : template <std::size_t N>
39 : struct is_array_of_double<std::array<double, N>> : std::true_type {};
40 :
41 : template <typename... Ts>
42 : auto make_legend(tmpl::list<Ts...> /* meta */) {
43 : std::vector<std::string> legend = {"Time"};
44 :
45 : [[maybe_unused]] auto append_tags = [&legend](auto tag) {
46 : using TagType = decltype(tag);
47 : using ReturnType = typename TagType::type;
48 :
49 : if constexpr (is_array_of_double<ReturnType>::value) {
50 : constexpr std::array<const char*, 3> suffix = {"_x", "_y", "_z"};
51 : for (size_t i = 0; i < std::tuple_size<ReturnType>::value; ++i) {
52 : legend.push_back(db::tag_name<TagType>() + gsl::at(suffix, i));
53 : }
54 : } else {
55 : legend.push_back(db::tag_name<TagType>());
56 : }
57 : };
58 :
59 : (append_tags(Ts{}), ...);
60 :
61 : return legend;
62 : }
63 :
64 : template <typename DbTags, typename... Ts>
65 : auto make_reduction_data(const db::DataBox<DbTags>& box, double time,
66 : tmpl::list<Ts...> /* meta */) {
67 : return std::make_tuple(time, get<Ts>(box)...);
68 : }
69 :
70 : } // namespace detail
71 :
72 : /*!
73 : * \brief A `ah::protocol::Callback` that outputs a `double` or
74 : * `std::array<double, N>` quantity on a surface as a time series in the
75 : * reductions file.
76 : */
77 : template <typename TagsToObserve, typename HorizonMetavars>
78 1 : struct ObserveTimeSeriesOnHorizon : tt::ConformsTo<ah::protocols::Callback> {
79 : template <typename DbTags, typename Metavariables>
80 0 : static void apply(const db::DataBox<DbTags>& box,
81 : Parallel::GlobalCache<Metavariables>& cache,
82 : const FastFlow::Status /*status*/) {
83 : const auto& time = db::get<ah::Tags::CurrentTime>(box).value();
84 : auto& proxy = Parallel::get_parallel_component<
85 : observers::ObserverWriter<Metavariables>>(cache);
86 :
87 : // We call this on proxy[0] because the 0th element of a NodeGroup is
88 : // always guaranteed to be present.
89 : Parallel::threaded_action<
90 : observers::ThreadedActions::WriteReductionDataRow>(
91 : proxy[0], std::string{"/" + pretty_type::name<HorizonMetavars>()},
92 : detail::make_legend(TagsToObserve{}),
93 : detail::make_reduction_data(box, time.id, TagsToObserve{}));
94 : }
95 : };
96 : } // namespace ah::callbacks
|