Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <cstddef> 7 : #include <iomanip> 8 : #include <map> 9 : #include <sstream> 10 : #include <string> 11 : #include <unordered_map> 12 : #include <unordered_set> 13 : #include <variant> 14 : 15 : #include "DataStructures/DataBox/Tag.hpp" 16 : #include "DataStructures/Tensor/TypeAliases.hpp" 17 : #include "IO/Importers/ObservationSelector.hpp" 18 : #include "Options/String.hpp" 19 : #include "Parallel/ArrayComponentId.hpp" 20 : #include "Parallel/InboxInserters.hpp" 21 : #include "Utilities/PrettyType.hpp" 22 : #include "Utilities/TaggedTuple.hpp" 23 : 24 : /// Items related to loading data from files 25 : namespace importers { 26 : 27 : /// The input file options associated with the data importer 28 1 : namespace OptionTags { 29 : 30 : /*! 31 : * \brief The file to read data from. 32 : */ 33 1 : struct FileGlob { 34 0 : using type = std::string; 35 0 : static constexpr Options::String help = "Path to the data file"; 36 : }; 37 : 38 : /*! 39 : * \brief The subgroup within the file to read data from. 40 : * 41 : * This subgroup should conform to the `h5::VolumeData` format. 42 : */ 43 1 : struct Subgroup { 44 0 : using type = std::string; 45 0 : static constexpr Options::String help = 46 : "The subgroup within the file, excluding extensions"; 47 : }; 48 : 49 : /*! 50 : * \brief The observation value at which to read data from the file. 51 : */ 52 1 : struct ObservationValue { 53 0 : using type = std::variant<double, ObservationSelector>; 54 0 : static constexpr Options::String help = 55 : "The observation value at which to read data"; 56 : }; 57 : 58 : /*! 59 : * \brief Toggle interpolation of numeric data to the target domain 60 : */ 61 1 : struct EnableInterpolation { 62 0 : static std::string name() { return "Interpolate"; } 63 0 : using type = bool; 64 0 : static constexpr Options::String help = 65 : "Enable to interpolate the volume data to the target domain. Disable to " 66 : "load volume data directly into elements with the same name. " 67 : "For example, you can disable interpolation if you have generated data " 68 : "on the target points, or if you have already interpolated your data. " 69 : "When interpolation is disabled, datasets " 70 : "'InertialCoordinates(_x,_y,_z)' must exist in the files. They are used " 71 : "to verify that the target points indeed match the source data."; 72 : }; 73 : } // namespace OptionTags 74 : 75 : /// Options that specify the volume data to load. See the option tags for 76 : /// details. 77 1 : struct ImporterOptions 78 : : tuples::TaggedTuple<OptionTags::FileGlob, OptionTags::Subgroup, 79 : OptionTags::ObservationValue, 80 : OptionTags::EnableInterpolation> { 81 0 : using options = tags_list; 82 0 : static constexpr Options::String help = "The volume data to load."; 83 : using TaggedTuple::TaggedTuple; 84 : }; 85 : 86 : /// The \ref DataBoxGroup tags associated with the data importer 87 : namespace Tags { 88 : 89 : /// Options that specify the volume data to load. See the option tags for 90 : /// details. 91 : template <typename OptionsGroup> 92 1 : struct ImporterOptions : db::SimpleTag { 93 0 : static std::string name() { return "VolumeData"; } 94 0 : using type = importers::ImporterOptions; 95 0 : static constexpr Options::String help = importers::ImporterOptions::help; 96 0 : using group = OptionsGroup; 97 0 : using option_tags = tmpl::list<ImporterOptions>; 98 0 : static constexpr bool pass_metavariables = false; 99 0 : static type create_from_options(type value) { return value; } 100 : }; 101 : 102 : /*! 103 : * \brief The elements that will receive data from the importer. 104 : * 105 : * \details Identifiers for elements from multiple parallel components can be 106 : * stored. Each element is identified by an `Parallel::ArrayComponentId` and 107 : * also needs to provide the inertial coordinates of its grid points. The 108 : * imported data will be interpolated to these grid points. 109 : */ 110 : template <size_t Dim> 111 1 : struct RegisteredElements : db::SimpleTag { 112 0 : using type = std::unordered_map<Parallel::ArrayComponentId, 113 : tnsr::I<DataVector, Dim, Frame::Inertial>>; 114 : }; 115 : 116 : /// Indicates which volume data files have already been read. 117 1 : struct ElementDataAlreadyRead : db::SimpleTag { 118 0 : using type = std::unordered_set<size_t>; 119 : }; 120 : 121 : /*! 122 : * \brief Inbox tag that carries the data read from a volume data file. 123 : * 124 : * Since we read a volume data file only once, this tag's map will only ever 125 : * hold data at the index (i.e. the temporal ID) with value `0`. 126 : */ 127 : template <typename FieldTagsList> 128 1 : struct VolumeData : Parallel::InboxInserters::Value<VolumeData<FieldTagsList>> { 129 0 : using temporal_id = size_t; 130 0 : using type = 131 : std::map<temporal_id, tuples::tagged_tuple_from_typelist<FieldTagsList>>; 132 : 133 0 : static std::string output_inbox(const type& inbox, 134 : const size_t padding_size) { 135 : std::stringstream ss{}; 136 : const std::string pad(padding_size, ' '); 137 : 138 : ss << std::scientific << std::setprecision(16); 139 : ss << pad << "VolumeDataInbox:\n"; 140 : // We don't really care about the variables, just the times 141 : for (const auto& [index, variables] : inbox) { 142 : (void)variables; 143 : ss << pad << " Index: " << index << "\n"; 144 : } 145 : 146 : return ss.str(); 147 : } 148 : }; 149 : } // namespace Tags 150 : 151 : } // namespace importers