Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <algorithm>
7 : #include <cmath>
8 : #include <limits>
9 : #include <pup.h>
10 : #include <pup_stl.h>
11 : #include <string>
12 : #include <utility>
13 :
14 : #include "Options/Context.hpp"
15 : #include "Options/Options.hpp"
16 : #include "Options/ParseError.hpp"
17 : #include "Options/String.hpp"
18 : #include "ParallelAlgorithms/EventsAndTriggers/Trigger.hpp"
19 : #include "Time/Time.hpp"
20 : #include "Time/TimeSequence.hpp"
21 : #include "Utilities/Serialization/CharmPupable.hpp"
22 : #include "Utilities/TMPL.hpp"
23 :
24 : /// \cond
25 : namespace Tags {
26 : struct Time;
27 : struct TimeStep;
28 : } // namespace Tags
29 : /// \endcond
30 :
31 : namespace Triggers {
32 0 : namespace NearTimes_enums {
33 0 : enum class Unit { Time, Slab, Step };
34 0 : enum class Direction { Before, After, Both };
35 : } // namespace NearTimes_enums
36 :
37 : /// \ingroup EventsAndTriggersGroup
38 : /// \ingroup TimeGroup
39 : /// Trigger in intervals surrounding particular times.
40 : ///
41 : /// When using adaptive time stepping, intervals specified in terms of
42 : /// slabs or steps are approximate.
43 : ///
44 : /// \see Times
45 1 : class NearTimes : public Trigger {
46 : public:
47 : /// \cond
48 : NearTimes() = default;
49 : explicit NearTimes(CkMigrateMessage* /*unused*/) {}
50 : using PUP::able::register_constructor;
51 : WRAPPED_PUPable_decl_template(NearTimes); // NOLINT
52 : /// \endcond
53 :
54 0 : using Unit = NearTimes_enums::Unit;
55 0 : using Direction = NearTimes_enums::Direction;
56 :
57 0 : struct OptionTags {
58 0 : struct Times {
59 0 : using type = std::unique_ptr<TimeSequence<double>>;
60 0 : static constexpr Options::String help = "Times to trigger at";
61 : };
62 :
63 0 : struct Range {
64 0 : using type = double;
65 0 : static type lower_bound() { return 0.0; }
66 0 : static constexpr Options::String help =
67 : "Maximum time difference to trigger at";
68 : };
69 :
70 0 : struct Unit {
71 0 : using type = NearTimes::Unit;
72 0 : static constexpr Options::String help =
73 : "Interpret Range as 'Time', 'Step's, or 'Slab's";
74 : };
75 :
76 0 : struct Direction {
77 0 : using type = NearTimes::Direction;
78 0 : static constexpr Options::String help =
79 : "Trigger 'Before', 'After', or 'Both' from the times";
80 : };
81 : };
82 :
83 0 : static constexpr Options::String help =
84 : "Trigger in intervals surrounding particular times.";
85 0 : using options =
86 : tmpl::list<typename OptionTags::Times, typename OptionTags::Range,
87 : typename OptionTags::Unit, typename OptionTags::Direction>;
88 :
89 0 : NearTimes(std::unique_ptr<TimeSequence<double>> times, const double range,
90 : const Unit unit, const Direction direction)
91 : : times_(std::move(times)),
92 : range_(range),
93 : unit_(unit),
94 : direction_(direction) {}
95 :
96 0 : using argument_tags = tmpl::list<Tags::Time, Tags::TimeStep>;
97 :
98 0 : bool operator()(const double now, const TimeDelta& time_step) const;
99 :
100 : // NOLINTNEXTLINE(google-runtime-references)
101 0 : void pup(PUP::er& p) override;
102 :
103 : private:
104 0 : std::unique_ptr<TimeSequence<double>> times_{};
105 0 : double range_ = std::numeric_limits<double>::signaling_NaN();
106 0 : Unit unit_{};
107 0 : Direction direction_{};
108 : };
109 : } // namespace Triggers
110 :
111 : template <>
112 0 : struct Options::create_from_yaml<Triggers::NearTimes_enums::Unit> {
113 0 : using type = Triggers::NearTimes_enums::Unit;
114 : template <typename Metavariables>
115 0 : static type create(const Options::Option& options) {
116 : const auto unit = options.parse_as<std::string>();
117 : if (unit == "Time") {
118 : return type::Time;
119 : } else if (unit == "Step") {
120 : return type::Step;
121 : } else if (unit == "Slab") {
122 : return type::Slab;
123 : } else {
124 : PARSE_ERROR(options.context(), "Unit must be 'Time', 'Step', or 'Slab'");
125 : }
126 : }
127 : };
128 :
129 : template <>
130 0 : struct Options::create_from_yaml<
131 : typename Triggers::NearTimes_enums::Direction> {
132 0 : using type = Triggers::NearTimes_enums::Direction;
133 : template <typename Metavariables>
134 0 : static type create(const Options::Option& options) {
135 : const auto unit = options.parse_as<std::string>();
136 : if (unit == "Before") {
137 : return type::Before;
138 : } else if (unit == "After") {
139 : return type::After;
140 : } else if (unit == "Both") {
141 : return type::Both;
142 : } else {
143 : PARSE_ERROR(options.context(),
144 : "Direction must be 'Before', 'After', or 'Both'");
145 : }
146 : }
147 : };
|