Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <initializer_list> 7 : #include <memory> 8 : #include <type_traits> 9 : #include <typeinfo> 10 : 11 : #include "DataStructures/DataBox/Tag.hpp" 12 : #include "Time/LtsMode.hpp" 13 : #include "Time/OptionTags/TimeStepper.hpp" 14 : #include "Time/TimeSteppers/LtsTimeStepper.hpp" 15 : #include "Time/TimeSteppers/TimeStepper.hpp" 16 : #include "Utilities/Serialization/Serialize.hpp" 17 : #include "Utilities/TMPL.hpp" 18 : 19 : namespace Tags { 20 : /// \ingroup DataBoxTagsGroup 21 : /// \ingroup TimeGroup 22 : /// The evolution TimeStepper. 23 : /// 24 : /// The \p StepperType template parameter should be one of the time 25 : /// stepper base classes, such as `TimeStepper` or `LtsTimeStepper`. 26 : /// 27 : /// If the \p MonotonicLts parameter is true, the chosen stepper will 28 : /// be required to be monotonic when parsed from options in local 29 : /// time-stepping mode. This is generally required for evolutions 30 : /// with control systems. 31 : /// 32 : /// For the contained object to be used, the reference tags listed in 33 : /// `time_stepper_ref_tags<StepperType>` will also need to be added to 34 : /// the DataBox. 35 : template <typename StepperType, bool MonotonicLts = false> 36 1 : struct ConcreteTimeStepper : db::SimpleTag { 37 0 : using type = std::unique_ptr<StepperType>; 38 : template <typename Metavars> 39 0 : using option_tags = tmpl::list<::OptionTags::TimeStepper<StepperType>>; 40 : 41 0 : static constexpr bool pass_metavariables = true; 42 : template <typename Metavars> 43 0 : static std::unique_ptr<StepperType> create_from_options( 44 : const std::unique_ptr<StepperType>& time_stepper) { 45 : const ::LtsMode lts_mode = Metavars::local_time_stepping 46 : ? ::LtsMode::Conservative 47 : : ::LtsMode::Off; 48 : using factory_types = 49 : tmpl::at<typename Metavars::factory_creation::factory_classes, 50 : StepperType>; 51 : [&]<typename... Derived>(tmpl::list<Derived...> /*meta*/) { 52 : validate_time_stepper(*time_stepper, lts_mode, {&typeid(Derived)...}); 53 : }(factory_types{}); 54 : return serialize_and_deserialize<type>(time_stepper); 55 : } 56 : 57 : private: 58 0 : static void validate_time_stepper( 59 : const StepperType& time_stepper, ::LtsMode lts_mode, 60 : std::initializer_list<const std::type_info*> factory_types); 61 : }; 62 : 63 : /// \ingroup DataBoxTagsGroup 64 : /// \ingroup TimeGroup 65 : /// Access to a time stepper through the `StepperInterface` interface 66 : /// (such as `TimeStepper` or `LtsTimeStepper`). 67 : /// 68 : /// \details This tag cannot be added directly to the DataBox of 69 : /// GlobalCache because it contains an abstract type, but can only be 70 : /// used for retrieving the time stepper. Instead, the 71 : /// `ConcreteTimeStepper` tag should be added, along with the 72 : /// reference tags given by `time_stepper_ref_tags`. 73 : template <typename StepperInterface> 74 1 : struct TimeStepper : db::SimpleTag { 75 0 : using type = StepperInterface; 76 : }; 77 : 78 : /// \ingroup DataBoxTagsGroup 79 : /// \ingroup TimeGroup 80 : /// Reference tag to provide access to the time stepper through its 81 : /// provided interfaces, such as `Tags::TimeStepper<TimeStepper>` and 82 : /// `Tags::TimeStepper<LtsTimeStepper>`. Usually added through the 83 : /// `time_stepper_ref_tags` alias. 84 : template <typename StepperInterface, typename StepperType, 85 : typename MonotonicLts> 86 1 : struct TimeStepperRef : TimeStepper<StepperInterface>, db::ReferenceTag { 87 0 : using base = TimeStepper<StepperInterface>; 88 0 : using argument_tags = 89 : tmpl::list<ConcreteTimeStepper<StepperType, MonotonicLts::value>>; 90 0 : static const StepperInterface& get(const StepperType& stepper) { 91 : return stepper; 92 : } 93 : }; 94 : 95 : /// \ingroup DataBoxTagsGroup 96 : /// \ingroup TimeGroup 97 : /// Compute tag to allow LTS code to compile in GTS executables. 98 1 : struct LtsOrError : TimeStepper<LtsTimeStepper>, db::ReferenceTag { 99 0 : using base = TimeStepper<LtsTimeStepper>; 100 0 : using argument_tags = tmpl::list<TimeStepper<::TimeStepper>>; 101 0 : static const LtsTimeStepper& get(const ::TimeStepper& stepper); 102 : }; 103 : } // namespace Tags 104 : 105 : /// \ingroup TimeGroup 106 : /// List of immutable tags needed when adding a Tags::ConcreteTimeStepper. 107 : template <typename StepperType, bool MonotonicLts = false> 108 1 : using time_stepper_ref_tags = tmpl::append< 109 : tmpl::transform< 110 : typename StepperType::provided_time_stepper_interfaces, 111 : tmpl::bind<::Tags::TimeStepperRef, tmpl::_1, tmpl::pin<StepperType>, 112 : std::bool_constant<MonotonicLts>>>, 113 : tmpl::conditional_t< 114 : tmpl::list_contains_v< 115 : typename StepperType::provided_time_stepper_interfaces, 116 : LtsTimeStepper>, 117 : tmpl::list<>, tmpl::list<Tags::LtsOrError>>>;