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/LocalTimeStepping.hpp" 14 : #include "Time/OptionTags/TimeStepper.hpp" 15 : #include "Time/TimeSteppers/LtsTimeStepper.hpp" 16 : #include "Time/TimeSteppers/TimeStepper.hpp" 17 : #include "Utilities/Serialization/Serialize.hpp" 18 : #include "Utilities/TMPL.hpp" 19 : 20 : namespace Tags { 21 : /// \ingroup DataBoxTagsGroup 22 : /// \ingroup TimeGroup 23 : /// The evolution TimeStepper. 24 : /// 25 : /// The \p StepperType template parameter should be one of the time 26 : /// stepper base classes, such as `TimeStepper` or `LtsTimeStepper`. 27 : /// 28 : /// If the \p MonotonicLts parameter is true, the chosen stepper will 29 : /// be required to be monotonic when parsed from options in local 30 : /// time-stepping mode. This is generally required for evolutions 31 : /// with control systems. 32 : /// 33 : /// For the contained object to be used, the reference tags listed in 34 : /// `time_stepper_ref_tags<StepperType>` will also need to be added to 35 : /// the DataBox. 36 : template <typename StepperType, bool MonotonicLts = false> 37 1 : struct ConcreteTimeStepper : db::SimpleTag { 38 0 : using type = std::unique_ptr<StepperType>; 39 : template <typename Metavars> 40 0 : using option_tags = tmpl::list<::OptionTags::TimeStepper<StepperType>, 41 : ::OptionTags::LocalTimeStepping>; 42 : 43 0 : static constexpr bool pass_metavariables = true; 44 : template <typename Metavars> 45 0 : static std::unique_ptr<StepperType> create_from_options( 46 : const std::unique_ptr<StepperType>& time_stepper, 47 : const ::LtsMode lts_mode) { 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>>>;