SpECTRE Documentation Coverage Report
Current view: top level - Time/StepChoosers - StepToTimes.hpp Hit Total Coverage
Commit: 52f20d7d69c179a8fabd675cc9d8c5355c7d621c Lines: 2 13 15.4 %
Date: 2024-04-17 15:32:38
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : #pragma once
       5             : 
       6             : #include <limits>
       7             : #include <memory>
       8             : #include <pup.h>
       9             : #include <pup_stl.h>
      10             : #include <utility>
      11             : 
      12             : #include "Options/String.hpp"
      13             : #include "Time/StepChoosers/StepChooser.hpp"
      14             : #include "Time/TimeSequence.hpp"
      15             : #include "Time/TimeStepId.hpp"
      16             : #include "Time/Utilities.hpp"
      17             : #include "Utilities/Serialization/CharmPupable.hpp"
      18             : #include "Utilities/TMPL.hpp"
      19             : 
      20             : /// \cond
      21             : namespace Tags {
      22             : struct TimeStepId;
      23             : }  // namespace Tags
      24             : /// \endcond
      25             : 
      26             : namespace StepChoosers {
      27             : /// Suggests step sizes to place steps at specific times.
      28             : ///
      29             : /// The suggestion provided depends on the current time, so it should
      30             : /// be applied immediately, rather than delayed several slabs.
      31           1 : class StepToTimes : public StepChooser<StepChooserUse::Slab> {
      32             :  public:
      33             :   /// \cond
      34             :   StepToTimes() = default;
      35             :   explicit StepToTimes(CkMigrateMessage* /*unused*/) {}
      36             :   using PUP::able::register_constructor;
      37             :   WRAPPED_PUPable_decl_template(StepToTimes);  // NOLINT
      38             :   /// \endcond
      39             : 
      40           0 :   struct Times {
      41           0 :     using type = std::unique_ptr<TimeSequence<double>>;
      42           0 :     static constexpr Options::String help{"Times to force steps at"};
      43             :   };
      44             : 
      45           0 :   static constexpr Options::String help =
      46             :       "Suggests step sizes to place steps at specific times.\n"
      47             :       "\n"
      48             :       "The suggestion provided depends on the current time, so it should\n"
      49             :       "be applied immediately, rather than delayed several slabs.";
      50           0 :   using options = tmpl::list<Times>;
      51             : 
      52           0 :   explicit StepToTimes(std::unique_ptr<TimeSequence<double>> times)
      53             :       : times_(std::move(times)) {}
      54             : 
      55           0 :   using argument_tags = tmpl::list<::Tags::TimeStepId>;
      56             : 
      57           0 :   std::pair<double, bool> operator()(const TimeStepId& time_step_id,
      58             :                                      const double last_step_magnitude) const {
      59             :     const double now = time_step_id.substep_time();
      60             :     // Trying to step to a given time might not get us exactly there
      61             :     // because of rounding errors.  Avoid taking an extra tiny step if
      62             :     // we undershoot.
      63             :     const double sloppiness = slab_rounding_error(time_step_id.step_time());
      64             : 
      65             :     const auto goal_times = times_->times_near(now);
      66             :     if (not goal_times[1]) {
      67             :       // No times requested.
      68             :       return std::make_pair(std::numeric_limits<double>::infinity(), true);
      69             :     }
      70             : 
      71             :     double distance_to_next_goal = std::numeric_limits<double>::signaling_NaN();
      72             :     if (time_step_id.time_runs_forward()) {
      73             :       const auto next_time =
      74             :           *goal_times[1] > now + sloppiness ? goal_times[1] : goal_times[2];
      75             :       if (not next_time) {
      76             :         // We've passed all the times.  No restriction.
      77             :         return std::make_pair(std::numeric_limits<double>::infinity(), true);
      78             :       }
      79             :       distance_to_next_goal = *next_time - now;
      80             :     } else {
      81             :       const auto next_time =
      82             :           *goal_times[1] < now - sloppiness ? goal_times[1] : goal_times[0];
      83             :       if (not next_time) {
      84             :         // We've passed all the times.  No restriction.
      85             :         return std::make_pair(std::numeric_limits<double>::infinity(), true);
      86             :       }
      87             :       distance_to_next_goal = now - *next_time;
      88             :     }
      89             : 
      90             :     if (distance_to_next_goal < 2.0 / 3.0 * last_step_magnitude) {
      91             :       // Our goal is well within range of the expected allowed step
      92             :       // size.
      93             :       return std::make_pair(distance_to_next_goal, true);
      94             :     } else {
      95             :       // We can't reach our goal in one step, or at least might not be
      96             :       // able to if the step adjusts a relatively small amount for
      97             :       // other reasons.  Prevent the step from bringing us too close
      98             :       // to the goal so that the step following this one will not be
      99             :       // too small.
     100             :       return std::make_pair(2.0 / 3.0 * distance_to_next_goal, true);
     101             :     }
     102             :   }
     103             : 
     104           1 :   bool uses_local_data() const override;
     105             : 
     106             :   // NOLINTNEXTLINE(google-runtime-references)
     107           0 :   void pup(PUP::er& p) override { p | times_; }
     108             : 
     109             :  private:
     110           0 :   std::unique_ptr<TimeSequence<double>> times_;
     111             : };
     112             : }  // namespace StepChoosers

Generated by: LCOV version 1.14