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>>>;
|