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