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 "ParallelAlgorithms/Interpolation/InterpolationTargetDetail.hpp" 28 : #include "ParallelAlgorithms/Interpolation/Protocols/PostInterpolationCallback.hpp" 29 : #include "Utilities/Functional.hpp" 30 : #include "Utilities/Gsl.hpp" 31 : #include "Utilities/PrettyType.hpp" 32 : #include "Utilities/ProtocolHelpers.hpp" 33 : #include "Utilities/TMPL.hpp" 34 : 35 : namespace ah::callbacks { 36 : namespace detail { 37 : template <typename T> 38 : struct is_array_of_double : std::false_type {}; 39 : 40 : template <std::size_t N> 41 : struct is_array_of_double<std::array<double, N>> : std::true_type {}; 42 : 43 : template <typename... Ts> 44 : auto make_legend(tmpl::list<Ts...> /* meta */) { 45 : std::vector<std::string> legend = {"Time"}; 46 : 47 : [[maybe_unused]] auto append_tags = [&legend](auto tag) { 48 : using TagType = decltype(tag); 49 : using ReturnType = typename TagType::type; 50 : 51 : if constexpr (is_array_of_double<ReturnType>::value) { 52 : constexpr std::array<const char*, 3> suffix = {"_x", "_y", "_z"}; 53 : for (size_t i = 0; i < std::tuple_size<ReturnType>::value; ++i) { 54 : legend.push_back(db::tag_name<TagType>() + gsl::at(suffix, i)); 55 : } 56 : } else { 57 : legend.push_back(db::tag_name<TagType>()); 58 : } 59 : }; 60 : 61 : (append_tags(Ts{}), ...); 62 : 63 : return legend; 64 : } 65 : 66 : template <typename DbTags, typename... Ts> 67 : auto make_reduction_data(const db::DataBox<DbTags>& box, double time, 68 : tmpl::list<Ts...> /* meta */) { 69 : return std::make_tuple(time, get<Ts>(box)...); 70 : } 71 : 72 : } // namespace detail 73 : 74 : /*! 75 : * \brief A `ah::protocol::Callback` that outputs a `double` or 76 : * `std::array<double, N>` quantity on a surface as a time series in the 77 : * reductions file. 78 : */ 79 : template <typename TagsToObserve, typename HorizonMetavars> 80 1 : struct ObserveTimeSeriesOnHorizon : tt::ConformsTo<ah::protocols::Callback> { 81 : template <typename DbTags, typename Metavariables> 82 0 : static void apply(const db::DataBox<DbTags>& box, 83 : Parallel::GlobalCache<Metavariables>& cache, 84 : const FastFlow::Status /*status*/) { 85 : const auto& time = db::get<ah::Tags::CurrentTime>(box).value(); 86 : auto& proxy = Parallel::get_parallel_component< 87 : observers::ObserverWriter<Metavariables>>(cache); 88 : 89 : // We call this on proxy[0] because the 0th element of a NodeGroup is 90 : // always guaranteed to be present. 91 : Parallel::threaded_action< 92 : observers::ThreadedActions::WriteReductionDataRow>( 93 : proxy[0], std::string{"/" + pretty_type::name<HorizonMetavars>()}, 94 : detail::make_legend(TagsToObserve{}), 95 : detail::make_reduction_data(box, time.id, TagsToObserve{})); 96 : } 97 : }; 98 : } // namespace ah::callbacks