Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <algorithm> 7 : #include <cstddef> 8 : #include <deque> 9 : #include <sstream> 10 : #include <string> 11 : 12 : #include "DataStructures/DataBox/DataBox.hpp" 13 : #include "DataStructures/Variables.hpp" 14 : #include "IO/Logging/Verbosity.hpp" 15 : #include "Parallel/Printf/Printf.hpp" 16 : #include "ParallelAlgorithms/Interpolation/Actions/InterpolatorReceiveVolumeData.hpp" 17 : #include "ParallelAlgorithms/Interpolation/Tags.hpp" 18 : #include "Utilities/Algorithm.hpp" 19 : #include "Utilities/Gsl.hpp" 20 : #include "Utilities/PrettyType.hpp" 21 : #include "Utilities/Requires.hpp" 22 : #include "Utilities/TMPL.hpp" 23 : #include "Utilities/TaggedTuple.hpp" 24 : 25 : /// \cond 26 : 27 : namespace Parallel { 28 : template <typename Metavariables> 29 : class GlobalCache; 30 : } // namespace Parallel 31 : namespace intrp { 32 : namespace Tags { 33 : template <size_t Dim> 34 : struct NumberOfElements; 35 : template <typename Metavariables> 36 : struct InterpolatedVarsHolders; 37 : template <typename Metavariables, typename TemporalId> 38 : struct VolumeVarsInfo; 39 : } // namespace Tags 40 : namespace Vars { 41 : template <typename InterpolationTargetTag, typename Metavariables> 42 : struct HolderTag; 43 : } // namespace Vars 44 : } // namespace intrp 45 : /// \endcond 46 : 47 : namespace intrp { 48 : namespace Actions { 49 : 50 : /// \ingroup ActionsGroup 51 : /// \brief Cleans up stored volume data that is no longer needed. 52 : /// 53 : /// Called by InterpolationTargetReceiveVars. 54 : /// 55 : /// Uses: 56 : /// - Databox: 57 : /// - `Tags::InterpolatedVarsHolders<Metavariables>` 58 : /// - `Tags::VolumeVarsInfo<Metavariables>` 59 : /// 60 : /// DataBox changes: 61 : /// - Adds: nothing 62 : /// - Removes: nothing 63 : /// - Modifies: 64 : /// - `Tags::InterpolatedVarsHolders<Metavariables>` 65 : /// - `Tags::VolumeVarsInfo<Metavariables>` 66 : /// 67 : /// For requirements on InterpolationTargetTag, see InterpolationTarget 68 : template <typename InterpolationTargetTag> 69 1 : struct CleanUpInterpolator { 70 : template <typename ParallelComponent, typename DbTags, typename Metavariables, 71 : typename ArrayIndex> 72 0 : static void apply( 73 : db::DataBox<DbTags>& box, // HorizonManager's box 74 : const Parallel::GlobalCache<Metavariables>& cache, 75 : const ArrayIndex& /*array_index*/, 76 : const typename InterpolationTargetTag::temporal_id::type& temporal_id) { 77 : std::stringstream ss{}; 78 : const ::Verbosity& verbosity = Parallel::get<intrp::Tags::Verbosity>(cache); 79 : const bool debug_print = verbosity >= ::Verbosity::Debug; 80 : if (debug_print) { 81 : ss << InterpolationTarget_detail::interpolator_output_prefix< 82 : InterpolationTargetTag>(temporal_id) 83 : << ", "; 84 : } 85 : 86 : // Signal that this InterpolationTarget is done at this time. 87 : db::mutate<Tags::InterpolatedVarsHolders<Metavariables>>( 88 : [&temporal_id]( 89 : const gsl::not_null< 90 : typename Tags::InterpolatedVarsHolders<Metavariables>::type*> 91 : holders) { 92 : get<Vars::HolderTag<InterpolationTargetTag, Metavariables>>(*holders) 93 : .temporal_ids_when_data_has_been_interpolated.push_back( 94 : temporal_id); 95 : }, 96 : make_not_null(&box)); 97 : 98 : // If we don't need any of the volume data anymore for this 99 : // temporal_id, we will remove them. 100 : bool this_temporal_id_is_done = true; 101 : const auto& holders = 102 : db::get<Tags::InterpolatedVarsHolders<Metavariables>>(box); 103 : tmpl::for_each<typename Metavariables::interpolation_target_tags>( 104 : [&holders, &this_temporal_id_is_done, &temporal_id, &ss, 105 : &debug_print](auto tag) { 106 : using Tag = typename decltype(tag)::type; 107 : // Here we decide whether this interpolation target is "done" (i.e. it 108 : // does not need to interpolate) at this temporal_id. If it is "done", 109 : // then we don't need to store the volume data. Usually "done" means 110 : // that it has already done its interpolation at this temporal_id. But 111 : // note that if an interpolation target is not using the Interpolator 112 : // at all, it is considered "done", because we don't need any volume 113 : // data for it and should not store it. Similarly, interpolation 114 : // targets whose temporal_id has a different type than TemporalId are 115 : // considered "done" because they too do not use the Interpolator and 116 : // don't need volume data to be saved. 117 : if constexpr (detail::using_interpolator_component_v<Metavariables, 118 : Tag> and 119 : std::is_same_v< 120 : typename InterpolationTargetTag::temporal_id, 121 : typename Tag::temporal_id>) { 122 : const auto& finished_temporal_ids = 123 : get<Vars::HolderTag<Tag, Metavariables>>(holders) 124 : .temporal_ids_when_data_has_been_interpolated; 125 : if (not alg::found(finished_temporal_ids, temporal_id)) { 126 : this_temporal_id_is_done = false; 127 : if (debug_print) { 128 : ss << "not finished for " << pretty_type::name<Tag>() << ", "; 129 : } 130 : } 131 : } 132 : }); 133 : 134 : // We don't need any more volume data for this temporal_id, so 135 : // remove it. Note that the removal (and the computation of 136 : // this_temporal_id_is_done above) loop over only those 137 : // InterpolationTargets whose temporal_id type matches 138 : // InterpolationTargetTag::temporal_id. 139 : if (this_temporal_id_is_done) { 140 : db::mutate<Tags::VolumeVarsInfo< 141 : Metavariables, typename InterpolationTargetTag::temporal_id>>( 142 : [&temporal_id]( 143 : const gsl::not_null<typename Tags::VolumeVarsInfo< 144 : Metavariables, 145 : typename InterpolationTargetTag::temporal_id>::type*> 146 : volume_vars_info) { volume_vars_info->erase(temporal_id); }, 147 : make_not_null(&box)); 148 : 149 : // Clean up temporal_ids_when_data_has_been_interpolated, if 150 : // it is too large. 151 : [[maybe_unused]] constexpr size_t finished_temporal_ids_max_size = 1000; 152 : 153 : db::mutate<Tags::InterpolatedVarsHolders<Metavariables>>( 154 : [](const gsl::not_null< 155 : typename Tags::InterpolatedVarsHolders<Metavariables>::type*> 156 : holders_l) { 157 : tmpl::for_each<typename Metavariables::interpolation_target_tags>( 158 : [&](auto tag) { 159 : using Tag = typename decltype(tag)::type; 160 : if constexpr (std::is_same_v<typename InterpolationTargetTag:: 161 : temporal_id, 162 : typename Tag::temporal_id>) { 163 : auto& finished_temporal_ids = 164 : get<Vars::HolderTag<Tag, Metavariables>>(*holders_l) 165 : .temporal_ids_when_data_has_been_interpolated; 166 : if (finished_temporal_ids.size() > 167 : finished_temporal_ids_max_size) { 168 : const size_t num_to_remove = 169 : finished_temporal_ids.size() - 170 : finished_temporal_ids_max_size; 171 : for (size_t i = 0; i < num_to_remove; ++i) { 172 : // All the new temporal_ids are added with push_back, 173 : // so we remove the oldest ones by using pop_front. 174 : finished_temporal_ids.pop_front(); 175 : } 176 : } 177 : } 178 : }); 179 : }, 180 : make_not_null(&box)); 181 : 182 : if (debug_print) { 183 : ss << "finished interpolating and cleaned up interpolator."; 184 : } 185 : } 186 : 187 : if (debug_print) { 188 : Parallel::printf("%s\n", ss.str()); 189 : } 190 : } 191 : }; 192 : } // namespace Actions 193 : } // namespace intrp