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