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