Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <cstddef> 8 : #include <optional> 9 : #include <string> 10 : #include <variant> 11 : #include <vector> 12 : 13 : #include "DataStructures/DataBox/TagName.hpp" 14 : #include "DataStructures/Tensor/Tensor.hpp" 15 : #include "IO/Exporter/Exporter.hpp" 16 : #include "Utilities/TaggedTuple.hpp" 17 : 18 : namespace spectre::Exporter { 19 : 20 : /*! 21 : * \brief Interpolates data in volume files to target points 22 : * 23 : * This is an overload of the `interpolate_to_points` function that works with 24 : * Tensor types and tags, rather than the raw C++ types that are used in the 25 : * other overload so it can be used by external programs. 26 : * 27 : * The `Tags` template parameter is a typelist of tags that should be read from 28 : * the volume files. The dataset names to read are constructed from the tag 29 : * names. Here is an example of how to use this function: 30 : * 31 : * \snippet Test_Exporter.cpp interpolate_tensors_to_points_example 32 : */ 33 : template <typename Tags, typename DataType, size_t Dim> 34 1 : tuples::tagged_tuple_from_typelist<Tags> interpolate_to_points( 35 : const std::variant<std::vector<std::string>, std::string>& 36 : volume_files_or_glob, 37 : const std::string& subfile_name, 38 : const std::variant<ObservationId, ObservationStep>& observation, 39 : const tnsr::I<DataType, Dim>& target_points, 40 : bool extrapolate_into_excisions = false, 41 : std::optional<size_t> num_threads = std::nullopt) { 42 : // Convert target_points to an array of vectors 43 : // Possible performance optimization: avoid copying the data by allowing 44 : // interpolate_to_points to accept pointers or spans. 45 : const size_t num_points = target_points.begin()->size(); 46 : std::array<std::vector<double>, Dim> target_points_array{}; 47 : for (size_t d = 0; d < Dim; ++d) { 48 : gsl::at(target_points_array, d).resize(num_points); 49 : for (size_t i = 0; i < num_points; ++i) { 50 : gsl::at(target_points_array, d)[i] = target_points.get(d)[i]; 51 : } 52 : } 53 : // Collect tensor component names 54 : std::vector<std::string> tensor_components{}; 55 : tmpl::for_each<Tags>([&tensor_components](auto tag_v) { 56 : using tensor_tag = tmpl::type_from<decltype(tag_v)>; 57 : using TensorType = typename tensor_tag::type; 58 : const std::string tag_name = db::tag_name<tensor_tag>(); 59 : for (size_t i = 0; i < TensorType::size(); ++i) { 60 : const std::string component_name = 61 : tag_name + TensorType::component_suffix(i); 62 : tensor_components.push_back(component_name); 63 : } 64 : }); 65 : // Interpolate! 66 : const auto interpolated_data = interpolate_to_points( 67 : volume_files_or_glob, subfile_name, observation, tensor_components, 68 : target_points_array, extrapolate_into_excisions, num_threads); 69 : // Convert the interpolated data to a tagged_tuple 70 : tuples::tagged_tuple_from_typelist<Tags> result{}; 71 : size_t component_index = 0; 72 : tmpl::for_each<Tags>( 73 : [&component_index, &interpolated_data, &result](auto tag_v) { 74 : using tensor_tag = tmpl::type_from<decltype(tag_v)>; 75 : using TensorType = typename tensor_tag::type; 76 : for (size_t i = 0; i < TensorType::size(); ++i) { 77 : const auto& component_data = interpolated_data[component_index]; 78 : get<tensor_tag>(result)[i] = DataVector(component_data); 79 : ++component_index; 80 : } 81 : }); 82 : return result; 83 : } 84 : 85 : } // namespace spectre::Exporter