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 "NumericalAlgorithms/Spectral/Mesh.hpp" 19 : #include "Options/Auto.hpp" 20 : #include "Options/String.hpp" 21 : #include "Parallel/ArrayComponentId.hpp" 22 : #include "Parallel/InboxInserters.hpp" 23 : #include "Utilities/PrettyType.hpp" 24 : #include "Utilities/TaggedTuple.hpp" 25 : 26 : /// Items related to loading data from files 27 : namespace importers { 28 : 29 : /// The input file options associated with the data importer 30 1 : namespace OptionTags { 31 : 32 : /*! 33 : * \brief The file to read data from. 34 : */ 35 1 : struct FileGlob { 36 0 : using type = std::string; 37 0 : static constexpr Options::String help = "Path to the data file"; 38 : }; 39 : 40 : /*! 41 : * \brief The subgroup within the file to read data from. 42 : * 43 : * This subgroup should conform to the `h5::VolumeData` format. 44 : */ 45 1 : struct Subgroup { 46 0 : using type = std::string; 47 0 : static constexpr Options::String help = 48 : "The subgroup within the file, excluding extensions"; 49 : }; 50 : 51 : /*! 52 : * \brief The observation value at which to read data from the file. 53 : */ 54 1 : struct ObservationValue { 55 0 : using type = std::variant<double, ObservationSelector>; 56 0 : static constexpr Options::String help = 57 : "The observation value at which to read data"; 58 : }; 59 : 60 0 : struct ObservationValueEpsilon { 61 0 : using type = Options::Auto<double>; 62 0 : static constexpr Options::String help = 63 : "Look for observations in the data within this epsilon of the " 64 : "'ObservationValue'. Set to 'Auto' to use default of 1e-12. This option " 65 : "is ignored if the 'ObservationValue' is a selector like 'First' or " 66 : "'Last'."; 67 : }; 68 : 69 : /*! 70 : * \brief Toggle interpolation of numeric data to the target domain 71 : */ 72 1 : struct ElementsAreIdentical { 73 0 : using type = bool; 74 0 : static constexpr Options::String help = 75 : "Indicate that the elements of the source and target domain are the " 76 : "same, meaning that the domains are the same and their h-refinement is " 77 : "the same. In this case, data can be transferred between the source and " 78 : "target elements one-to-one, and interpolations only happen if the " 79 : "elements have different meshes (p-refinement). " 80 : "For example, you can enable this option if you have generated data " 81 : "on the target points, or if you have already interpolated your data, " 82 : "or if you import data from a simulation that differs only by " 83 : "p-refinement. " 84 : "When this option is enabled, datasets " 85 : "'InertialCoordinates(_x,_y,_z)' must exist in the files. They are used " 86 : "to verify that the target points indeed match the source data."; 87 : }; 88 : } // namespace OptionTags 89 : 90 : /// Options that specify the volume data to load. See the option tags for 91 : /// details. 92 1 : struct ImporterOptions 93 : : tuples::TaggedTuple<OptionTags::FileGlob, OptionTags::Subgroup, 94 : OptionTags::ObservationValue, 95 : OptionTags::ObservationValueEpsilon, 96 : OptionTags::ElementsAreIdentical> { 97 0 : using options = tags_list; 98 0 : static constexpr Options::String help = "The volume data to load."; 99 : using TaggedTuple::TaggedTuple; 100 : }; 101 : 102 : /// The \ref DataBoxGroup tags associated with the data importer 103 : namespace Tags { 104 : 105 : /// Options that specify the volume data to load. See the option tags for 106 : /// details. 107 : template <typename OptionsGroup> 108 1 : struct ImporterOptions : db::SimpleTag { 109 0 : static std::string name() { return "VolumeData"; } 110 0 : using type = importers::ImporterOptions; 111 0 : static constexpr Options::String help = importers::ImporterOptions::help; 112 0 : using group = OptionsGroup; 113 0 : using option_tags = tmpl::list<ImporterOptions>; 114 0 : static constexpr bool pass_metavariables = false; 115 0 : static type create_from_options(type value) { return value; } 116 : }; 117 : 118 : /*! 119 : * \brief The elements that will receive data from the importer. 120 : * 121 : * \details Identifiers for elements from multiple parallel components can be 122 : * stored. Each element is identified by an `Parallel::ArrayComponentId` and 123 : * also needs to provide the inertial coordinates of its grid points. The 124 : * imported data will be interpolated to these grid points. 125 : */ 126 : template <size_t Dim> 127 1 : struct RegisteredElements : db::SimpleTag { 128 0 : using type = std::unordered_map< 129 : Parallel::ArrayComponentId, 130 : std::pair<tnsr::I<DataVector, Dim, Frame::Inertial>, ::Mesh<Dim>>>; 131 : }; 132 : 133 : /// Indicates which volume data files have already been read. 134 1 : struct ElementDataAlreadyRead : db::SimpleTag { 135 0 : using type = std::unordered_set<size_t>; 136 : }; 137 : 138 : /*! 139 : * \brief Inbox tag that carries the data read from a volume data file. 140 : * 141 : * Since we read a volume data file only once, this tag's map will only ever 142 : * hold data at the index (i.e. the temporal ID) with value `0`. 143 : */ 144 : template <typename FieldTagsList> 145 1 : struct VolumeData : Parallel::InboxInserters::Value<VolumeData<FieldTagsList>> { 146 0 : using temporal_id = size_t; 147 0 : using type = 148 : std::map<temporal_id, tuples::tagged_tuple_from_typelist<FieldTagsList>>; 149 : 150 0 : static std::string output_inbox(const type& inbox, 151 : const size_t padding_size) { 152 : std::stringstream ss{}; 153 : const std::string pad(padding_size, ' '); 154 : 155 : ss << std::scientific << std::setprecision(16); 156 : ss << pad << "VolumeDataInbox:\n"; 157 : // We don't really care about the variables, just the times 158 : for (const auto& [index, variables] : inbox) { 159 : (void)variables; 160 : ss << pad << " Index: " << index << "\n"; 161 : } 162 : 163 : return ss.str(); 164 : } 165 : }; 166 : } // namespace Tags 167 : 168 : } // namespace importers