Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <optional> 7 : #include <string> 8 : #include <type_traits> 9 : #include <vector> 10 : 11 : #include "DataStructures/DataBox/DataBox.hpp" 12 : #include "Domain/Tags.hpp" 13 : #include "IO/H5/TensorData.hpp" 14 : #include "IO/Observer/Actions/ObserverRegistration.hpp" 15 : #include "IO/Observer/ObservationId.hpp" 16 : #include "IO/Observer/ObserverComponent.hpp" 17 : #include "IO/Observer/Tags.hpp" 18 : #include "IO/Observer/VolumeActions.hpp" 19 : #include "NumericalAlgorithms/Spectral/Mesh.hpp" 20 : #include "Parallel/AlgorithmExecution.hpp" 21 : #include "Parallel/ArrayComponentId.hpp" 22 : #include "Parallel/GlobalCache.hpp" 23 : #include "Parallel/Info.hpp" 24 : #include "Parallel/Invoke.hpp" 25 : #include "Parallel/Local.hpp" 26 : #include "ParallelAlgorithms/Interpolation/InterpolationTargetDetail.hpp" 27 : #include "ParallelAlgorithms/Interpolation/Tags.hpp" 28 : #include "Utilities/GetOutput.hpp" 29 : #include "Utilities/MakeString.hpp" 30 : #include "Utilities/TMPL.hpp" 31 : #include "Utilities/TaggedTuple.hpp" 32 : 33 : namespace intrp::Actions { 34 : namespace detail { 35 : // This requires there to be a type alias named `interpolator_source_vars` in 36 : // the metavariables 37 : template <typename TemporalIdTag, typename Metavariables> 38 : ElementVolumeData construct_element_volume_data( 39 : const ElementId<Metavariables::volume_dim>& element_id, 40 : const typename intrp::Tags::VolumeVarsInfo<Metavariables, 41 : TemporalIdTag>::Info& info) { 42 : std::vector<TensorComponent> components{}; 43 : 44 : const auto& all_source_vars = info.source_vars_from_element; 45 : tmpl::for_each<typename Metavariables::interpolator_source_vars>( 46 : [&components, &all_source_vars](auto source_var_tag_v) { 47 : using source_var_tag = 48 : tmpl::type_from<std::decay_t<decltype(source_var_tag_v)>>; 49 : const auto& tensor = get<source_var_tag>(all_source_vars); 50 : for (size_t i = 0; i < tensor.size(); i++) { 51 : const auto& tensor_component = tensor[i]; 52 : components.emplace_back( 53 : db::tag_name<source_var_tag>() + tensor.component_suffix(i), 54 : tensor_component); 55 : } 56 : }); 57 : 58 : return ElementVolumeData{element_id, std::move(components), info.mesh}; 59 : } 60 : } // namespace detail 61 : 62 : /*! 63 : * \brief Dump all volume data at all temporal IDs stored in the interpolator. 64 : * 65 : * All dumped data will be in the usual volume files, but under different 66 : * subfiles. There will be one subfile for every temporal ID type (as the 67 : * interpolator can have multiple different temporal ID types from different 68 : * interpolation targets). The tensors that are dumped are the ones defined in 69 : * the `interpolator_source_vars` type alias in the Metavariables. 70 : */ 71 : template <typename AllTemporalIds> 72 1 : struct DumpInterpolatorVolumeData { 73 0 : using const_global_cache_tags = 74 : tmpl::list<intrp::Tags::DumpVolumeDataOnFailure>; 75 : 76 : template <typename DbTagList, typename... InboxTags, typename Metavariables, 77 : typename ArrayIndex, typename ActionList, 78 : typename ParallelComponent> 79 0 : static Parallel::iterable_action_return_t apply( 80 : db::DataBox<DbTagList>& box, 81 : const tuples::TaggedTuple<InboxTags...>& /*inboxes*/, 82 : Parallel::GlobalCache<Metavariables>& cache, 83 : const ArrayIndex& array_index, const ActionList /*meta*/, 84 : const ParallelComponent* const /*meta*/) { 85 : if (not Parallel::get<intrp::Tags::DumpVolumeDataOnFailure>(cache)) { 86 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 87 : } 88 : 89 : auto& observer_writer = *Parallel::local_branch( 90 : Parallel::get_parallel_component< 91 : observers::ObserverWriter<Metavariables>>(cache)); 92 : 93 : const Parallel::ArrayComponentId array_component_id = 94 : Parallel::make_array_component_id<ParallelComponent>(array_index); 95 : 96 : tmpl::for_each<AllTemporalIds>([&box, &observer_writer, 97 : &array_component_id](auto temporal_id_v) { 98 : using temporal_id_t = 99 : tmpl::type_from<std::decay_t<decltype(temporal_id_v)>>; 100 : const auto& volume_vars_info = 101 : db::get<intrp::Tags::VolumeVarsInfo<Metavariables, temporal_id_t>>( 102 : box); 103 : const std::string subfile_name{"/InterpolatorVolumeData_"s + 104 : db::tag_name<temporal_id_t>()}; 105 : 106 : for (const auto& [temporal_id, info_map] : volume_vars_info) { 107 : std::vector<ElementVolumeData> element_volume_data{}; 108 : for (const auto& [element_id, info] : info_map) { 109 : element_volume_data.emplace_back( 110 : detail::construct_element_volume_data<temporal_id_t, 111 : Metavariables>(element_id, 112 : info)); 113 : } 114 : 115 : Parallel::threaded_action< 116 : observers::ThreadedActions::ContributeVolumeDataToWriter>( 117 : observer_writer, 118 : observers::ObservationId{ 119 : InterpolationTarget_detail::get_temporal_id_value(temporal_id), 120 : subfile_name}, 121 : array_component_id, subfile_name, 122 : std::unordered_map<Parallel::ArrayComponentId, 123 : std::vector<ElementVolumeData>>{ 124 : {array_component_id, std::move(element_volume_data)}}); 125 : } 126 : }); 127 : 128 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 129 : } 130 : }; 131 : } // namespace intrp::Actions