Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <deque> 7 : #include <optional> 8 : #include <set> 9 : #include <string> 10 : #include <unordered_map> 11 : 12 : #include "DataStructures/DataBox/Tag.hpp" 13 : #include "DataStructures/LinkedMessageId.hpp" 14 : #include "Domain/Creators/OptionTags.hpp" 15 : #include "Domain/Structure/BlockGroups.hpp" 16 : #include "Domain/Structure/ElementId.hpp" 17 : #include "IO/Logging/Verbosity.hpp" 18 : #include "NumericalAlgorithms/SphericalHarmonics/StrahlkorperFunctions.hpp" 19 : #include "ParallelAlgorithms/ApparentHorizonFinder/OptionTags.hpp" 20 : #include "ParallelAlgorithms/ApparentHorizonFinder/Storage.hpp" 21 : #include "Utilities/GetOutput.hpp" 22 : #include "Utilities/Gsl.hpp" 23 : #include "Utilities/Serialization/Serialize.hpp" 24 : #include "Utilities/TMPL.hpp" 25 : #include "Utilities/TypeTraits/CreateGetTypeAliasOrDefault.hpp" 26 : 27 : /// \cond 28 : namespace control_system::OptionTags { 29 : struct WriteDataToDisk; 30 : } // namespace control_system::OptionTags 31 : class FastFlow; 32 : namespace ylm { 33 : template <typename Frame> 34 : class Strahlkorper; 35 : } // namespace ylm 36 : namespace ah { 37 : template <class Metavariables, typename HorizonMetavars> 38 : struct Component; 39 : } // namespace ah 40 : namespace Tags { 41 : struct Time; 42 : } // namespace Tags 43 : /// \endcond 44 : 45 : /*! 46 : * \brief Tags for the apparent horizon finder. 47 : */ 48 : namespace ah::Tags { 49 : /*! 50 : * \brief Verbosity of horizon finder 51 : */ 52 1 : struct Verbosity : db::SimpleTag { 53 0 : using type = ::Verbosity; 54 : }; 55 : 56 : /*! 57 : * \brief Holds a `::FastFlow` object. Needs to be reset after each horizon 58 : * find. 59 : */ 60 1 : struct FastFlow : db::SimpleTag { 61 0 : using type = ::FastFlow; 62 : }; 63 : 64 : /*! 65 : * \brief Tag that holds the current time. 66 : * 67 : * \details The value of this tag is `std::nullopt` if the current time isn't 68 : * set. 69 : */ 70 1 : struct CurrentTime : db::SimpleTag { 71 0 : using type = std::optional<LinkedMessageId<double>>; 72 : }; 73 : 74 : /*! 75 : * \brief List of times waiting for previous horizon finds to finish 76 : * before they can be started. 77 : */ 78 1 : struct PendingTimes : db::SimpleTag { 79 0 : using type = std::set<LinkedMessageId<double>>; 80 : }; 81 : 82 : /*! 83 : * \brief Tag that holds all completed times 84 : */ 85 1 : struct CompletedTimes : db::SimpleTag { 86 0 : using type = std::set<LinkedMessageId<double>>; 87 : }; 88 : 89 : /*! 90 : * \brief Holds potential dependency for apparent horizon callbacks. 91 : */ 92 1 : struct Dependency : db::SimpleTag { 93 0 : using type = std::optional<std::string>; 94 : }; 95 : 96 : /*! 97 : * \brief Tag that holds the current resolution L. 98 : * 99 : * \details The value of this tag is `std::nullopt` if the current resolution L 100 : * isn't set. 101 : */ 102 1 : struct CurrentResolutionL : db::SimpleTag { 103 0 : using type = std::optional<size_t>; 104 : }; 105 : 106 : /*! 107 : * \brief Storage of all variables (volume or interpolated) for all times of the 108 : * horizon finder. 109 : */ 110 : template <typename Fr> 111 1 : struct Storage : db::SimpleTag { 112 0 : using type = std::unordered_map<LinkedMessageId<double>, 113 : ah::Storage::SingleTimeStorage<Fr>>; 114 : }; 115 : 116 : /*! 117 : * \brief Order in which blocks are searched for horizon finding. See 118 : * `::block_logical_coordinates` for details. 119 : */ 120 1 : struct BlockSearchOrder : db::SimpleTag { 121 0 : using type = std::vector<size_t>; 122 : }; 123 : 124 : /*! 125 : * \brief Deque of `ah::Storage::PreviousSurface`s. 126 : */ 127 : template <typename Fr> 128 1 : struct PreviousSurfaces : db::SimpleTag { 129 0 : using type = std::deque<ah::Storage::PreviousSurface<Fr>>; 130 : }; 131 : 132 : /*! 133 : * \brief Holds the previous surface. Used to determine which elements will send 134 : * data for the next horizon find. 135 : */ 136 : template <typename HorizonMetavars> 137 1 : struct PreviousSurface : db::SimpleTag { 138 0 : using type = 139 : ah::Storage::LockedPreviousSurface<typename HorizonMetavars::frame>; 140 0 : using option_tags = tmpl::list<>; 141 0 : static constexpr bool pass_metavariables = false; 142 0 : static type create_from_options() { return {}; } 143 : }; 144 : 145 : /*! 146 : * \brief Global cache tag that holds horizon finder options 147 : */ 148 : template <typename HorizonMetavars> 149 1 : struct ApparentHorizonOptions : db::SimpleTag { 150 0 : using type = HorizonOptions<typename HorizonMetavars::frame>; 151 0 : using option_tags = 152 : tmpl::list<OptionTags::ApparentHorizonOptions<HorizonMetavars>>; 153 : 154 0 : static constexpr bool pass_metavariables = false; 155 0 : static type create_from_options(const type& option) { 156 : return {deserialize<type>(serialize<type>(option).data())}; 157 : } 158 : }; 159 : 160 : namespace tags_detail { 161 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(component_being_mocked) 162 : 163 : template <typename HorizonComponent> 164 : struct get_horizon_metavars_from_component { 165 : using type = typename HorizonComponent::horizon_metavars; 166 : }; 167 : 168 : template <typename Metavariables> 169 : using get_horizon_metavars = tmpl::transform< 170 : tmpl::filter<tmpl::transform< 171 : typename Metavariables::component_list, 172 : get_component_being_mocked_or_default<tmpl::_1, tmpl::_1>>, 173 : tt::is_a<ah::Component, tmpl::_1>>, 174 : get_horizon_metavars_from_component<tmpl::_1>>; 175 : 176 : template <typename HorizonMetavars> 177 : struct get_horizon_options; 178 : 179 : template <typename... HorizonMetavars> 180 : struct get_horizon_options<tmpl::list<HorizonMetavars...>> { 181 : using type = 182 : tmpl::list<OptionTags::ApparentHorizonOptions<HorizonMetavars>...>; 183 : }; 184 : 185 : } // namespace tags_detail 186 : 187 : /*! 188 : * \brief Holds a map between horizon name and a set of block names that should 189 : * be used for interpolation for that horizon. 190 : */ 191 1 : struct BlocksForHorizonFind : db::SimpleTag { 192 0 : using type = std::unordered_map<std::string, std::unordered_set<std::string>>; 193 : template <typename Metavariables> 194 0 : using option_tags = tmpl::push_front< 195 : typename tags_detail::get_horizon_options< 196 : tags_detail::get_horizon_metavars<Metavariables>>::type, 197 : ::domain::OptionTags::DomainCreator<Metavariables::volume_dim>>; 198 : 199 0 : static constexpr bool pass_metavariables = true; 200 : template <typename Metavariables, typename... HorizonOptionClasses> 201 0 : static type create_from_options( 202 : const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>& 203 : domain_creator, 204 : const HorizonOptionClasses&... all_horizon_options) { 205 : return create_from_options_impl<Metavariables>( 206 : domain_creator, std::forward_as_tuple(all_horizon_options...), 207 : std::make_index_sequence<sizeof...(HorizonOptionClasses)>{}); 208 : } 209 : 210 : private: 211 : // Need the names of the target tags which are in the option tags, but not the 212 : // horizon options themselves. This just expands a tuple to be able to index 213 : // the `option_tags` type alias so we can get the name of the target horizon 214 : template <typename Metavariables, typename HorizonOptionsTuple, size_t... Is> 215 0 : static type create_from_options_impl( 216 : const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>& 217 : domain_creator, 218 : const HorizonOptionsTuple& all_horizon_options, 219 : const std::index_sequence<Is...>& /*index_sequence*/ 220 : ) { 221 : std::unordered_map<std::string, std::unordered_set<std::string>> result{}; 222 : 223 : const auto block_names = domain_creator->block_names(); 224 : const auto block_groups = domain_creator->block_groups(); 225 : 226 : const auto append_to_result = [&](const std::string& name, 227 : const auto& horizon_options) { 228 : if (horizon_options.blocks_for_horizon_find.has_value()) { 229 : result[name] = domain::expand_block_groups_to_block_names( 230 : horizon_options.blocks_for_horizon_find.value(), block_names, 231 : block_groups); 232 : } else { 233 : // Insert all blocks 234 : result[name].insert(block_names.begin(), block_names.end()); 235 : } 236 : 237 : // Needed for the expand_pack below 238 : return 0; 239 : }; 240 : 241 : expand_pack( 242 : append_to_result(tmpl::at_c<option_tags<Metavariables>, Is + 1>::name(), 243 : std::get<Is>(all_horizon_options))...); 244 : 245 : return result; 246 : } 247 : }; 248 : 249 : /// @{ 250 : /*! 251 : * \brief Tag to be used for the `time_tag` alias of a `HorizonMetavars` for an 252 : * observation horizon find. 253 : * 254 : * \details We need separate time tags for all horizon finders because of the 255 : * current design of the horizon finder. So we just make a simple compute tag 256 : * that takes the actual time out of the box since we still want the actual time 257 : * to be the same, just a different tag. 258 : * 259 : */ 260 : template <size_t Index> 261 1 : struct ObservationTime : db::SimpleTag { 262 0 : static std::string name() { return "AhObservationTime" + get_output(Index); } 263 0 : using type = LinkedMessageId<double>; 264 : }; 265 : 266 : template <size_t Index> 267 0 : struct ObservationTimeCompute : ObservationTime<Index>, db::ComputeTag { 268 0 : using argument_tags = tmpl::list<::Tags::Time>; 269 0 : using base = ObservationTime<Index>; 270 0 : using return_type = LinkedMessageId<double>; 271 : 272 0 : static void function(const gsl::not_null<LinkedMessageId<double>*> ah_time, 273 : const double time) { 274 : // The horizon finder knows how to handle the nullopt 275 : *ah_time = LinkedMessageId<double>{time, std::nullopt}; 276 : } 277 : }; 278 : /// @} 279 : 280 : /*! 281 : * \brief Tag that holds the strahlkorper of the previous FastFlow iteration 282 : * (not the strahlkorper of the entire previous horizon find.) 283 : */ 284 : template <typename Frame> 285 1 : struct PreviousIterationStrahlkorper : db::SimpleTag { 286 0 : using type = ylm::Strahlkorper<Frame>; 287 : }; 288 : 289 : /*! 290 : * \brief Tag to hold the number of failed interpolations to a surface during 291 : * iterations of the FastFlow algorithm. 292 : */ 293 1 : struct FailedInterpolationIterations : db::SimpleTag { 294 0 : using type = size_t; 295 : }; 296 : 297 : /// Simple tag for whether to write the centers of the horizons to disk. 298 1 : struct ObserveCenters : db::SimpleTag { 299 0 : using type = bool; 300 0 : using option_tags = tmpl::list<control_system::OptionTags::WriteDataToDisk>; 301 : 302 0 : static constexpr bool pass_metavariables = false; 303 0 : static type create_from_options(const type& option) { return option; } 304 : }; 305 : 306 : /// \ingroup DataBoxTagsGroup 307 : /// DataBox tag that holds the maximum L for horizon resolution and output. 308 1 : struct LMax : db::SimpleTag { 309 0 : using type = size_t; 310 : 311 0 : using option_tags = tmpl::list<OptionTags::LMax>; 312 0 : static constexpr bool pass_metavariables = false; 313 0 : static type create_from_options(const size_t max_l) { return max_l; } 314 : }; 315 : } // namespace ah::Tags