Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <memory> 7 : #include <type_traits> 8 : 9 : #include "DataStructures/DataBox/Tag.hpp" 10 : #include "DataStructures/TaggedVariant.hpp" 11 : #include "Time/OptionTags/TimeStepper.hpp" 12 : #include "Time/TimeSteppers/TimeStepper.hpp" 13 : #include "Utilities/ErrorHandling/Error.hpp" 14 : #include "Utilities/Serialization/Serialize.hpp" 15 : #include "Utilities/TMPL.hpp" 16 : 17 : /// \cond 18 : class LtsTimeStepper; 19 : /// \endcond 20 : 21 : namespace Tags { 22 : /// \ingroup DataBoxTagsGroup 23 : /// \ingroup TimeGroup 24 : /// The evolution TimeStepper. The template parameter should be one 25 : /// of the time stepper base classes, such as `TimeStepper` or 26 : /// `LtsTimeStepper`. 27 : /// 28 : /// For the contained object to be used, the reference tags listed in 29 : /// `time_stepper_ref_tags<StepperType>` will also need to be added to 30 : /// the DataBox. 31 : template <typename StepperType> 32 1 : struct ConcreteTimeStepper : db::SimpleTag { 33 0 : using type = std::unique_ptr<StepperType>; 34 0 : using option_tags = tmpl::list<::OptionTags::TimeStepper<StepperType>>; 35 : 36 0 : static constexpr bool pass_metavariables = false; 37 0 : static std::unique_ptr<StepperType> create_from_options( 38 : const std::unique_ptr<StepperType>& time_stepper) { 39 : if (not std::is_same_v<StepperType, LtsTimeStepper> and 40 : variants::holds_alternative<TimeSteppers::Tags::VariableOrder>( 41 : time_stepper->order())) { 42 : ERROR_NO_TRACE( 43 : "Variable-order TimeSteppers are only supported in evolutions with " 44 : "local time-stepping."); 45 : } 46 : return deserialize<type>(serialize<type>(time_stepper).data()); 47 : } 48 : }; 49 : 50 : /// \ingroup DataBoxTagsGroup 51 : /// \ingroup TimeGroup 52 : /// Access to a time stepper through the `StepperInterface` interface 53 : /// (such as `TimeStepper` or `LtsTimeStepper`). 54 : /// 55 : /// \details This tag cannot be added directly to the DataBox of 56 : /// GlobalCache because it contains an abstract type, but can only be 57 : /// used for retrieving the time stepper. Instead, the 58 : /// `ConcreteTimeStepper` tag should be added, along with the 59 : /// reference tags given by `time_stepper_ref_tags`. 60 : template <typename StepperInterface> 61 1 : struct TimeStepper : db::SimpleTag { 62 0 : using type = StepperInterface; 63 : }; 64 : 65 : /// \ingroup DataBoxTagsGroup 66 : /// \ingroup TimeGroup 67 : /// Reference tag to provide access to the time stepper through its 68 : /// provided interfaces, such as `Tags::TimeStepper<TimeStepper>` and 69 : /// `Tags::TimeStepper<LtsTimeStepper>`. Usually added through the 70 : /// `time_stepper_ref_tags` alias. 71 : template <typename StepperInterface, typename StepperType> 72 1 : struct TimeStepperRef : TimeStepper<StepperInterface>, db::ReferenceTag { 73 0 : using base = TimeStepper<StepperInterface>; 74 0 : using argument_tags = tmpl::list<ConcreteTimeStepper<StepperType>>; 75 0 : static const StepperInterface& get(const StepperType& stepper) { 76 : return stepper; 77 : } 78 : }; 79 : } // namespace Tags 80 : 81 : /// \ingroup TimeGroup 82 : /// List of Tags::TimeStepperRef specializations needed when adding a 83 : /// Tags::ConcreteTimeStepper. 84 : template <typename StepperType> 85 1 : using time_stepper_ref_tags = tmpl::transform< 86 : typename StepperType::provided_time_stepper_interfaces, 87 : tmpl::bind<::Tags::TimeStepperRef, tmpl::_1, tmpl::pin<StepperType>>>;