SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/EventsAndDenseTriggers - DenseTrigger.hpp Hit Total Coverage
Commit: 965048f86d23c819715b3af1ca3f880c8145d4bb Lines: 4 10 40.0 %
Date: 2024-05-16 17:00:40
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 <optional>
       8             : #include <pup.h>
       9             : #include <type_traits>
      10             : 
      11             : #include "DataStructures/DataBox/DataBox.hpp"
      12             : #include "Parallel/Tags/Metavariables.hpp"
      13             : #include "Utilities/CallWithDynamicType.hpp"
      14             : #include "Utilities/Gsl.hpp"
      15             : #include "Utilities/Serialization/CharmPupable.hpp"
      16             : #include "Utilities/Serialization/PupStlCpp17.hpp"
      17             : 
      18             : /// \cond
      19             : namespace Parallel {
      20             : template <typename Metavariables>
      21             : class GlobalCache;
      22             : }  // namespace Parallel
      23             : namespace Tags {
      24             : struct Time;
      25             : }  // namespace Tags
      26             : /// \endcond
      27             : 
      28             : /// \ingroup EventsAndTriggersGroup
      29           0 : namespace DenseTriggers {}
      30             : 
      31             : /// \ingroup EventsAndTriggersGroup
      32             : /// Base class for checking whether to run an Event at arbitrary times.
      33             : ///
      34             : /// The DataBox passed to the member functions will have
      35             : /// `::Tags::Time`, and therefore any compute tags depending on that
      36             : /// value, set to the time to be tested.  Any discrete properties of
      37             : /// steps or slabs, such as the step size, may have the values from
      38             : /// times off by one step.  The evolved variables will be in an
      39             : /// unspecified state.
      40           1 : class DenseTrigger : public PUP::able {
      41             :  protected:
      42             :   /// \cond
      43             :   DenseTrigger() = default;
      44             :   DenseTrigger(const DenseTrigger&) = default;
      45             :   DenseTrigger(DenseTrigger&&) = default;
      46             :   DenseTrigger& operator=(const DenseTrigger&) = default;
      47             :   DenseTrigger& operator=(DenseTrigger&&) = default;
      48             :   /// \endcond
      49             : 
      50             :  public:
      51           0 :   ~DenseTrigger() override = default;
      52             : 
      53             :   /// \cond
      54             :   explicit DenseTrigger(CkMigrateMessage* const msg) : PUP::able(msg) {}
      55             :   WRAPPED_PUPable_abstract(DenseTrigger);  // NOLINT
      56             :   /// \endcond
      57             : 
      58             :   /// Check whether the trigger fires.  Returns std::nullopt if
      59             :   /// insufficient data is available to make the decision.  The
      60             :   /// trigger is not responsible for checking whether dense output of
      61             :   /// the evolved variables is possible, but may need to check things
      62             :   /// such as the availability of FunctionOfTime data.
      63             :   template <typename DbTags, typename Metavariables, typename ArrayIndex,
      64             :             typename Component>
      65           1 :   std::optional<bool> is_triggered(
      66             :       const gsl::not_null<db::DataBox<DbTags>*> box,
      67             :       Parallel::GlobalCache<Metavariables>& cache,
      68             :       const ArrayIndex& array_index, const Component* const component) {
      69             :     using factory_classes =
      70             :         typename std::decay_t<decltype(db::get<Parallel::Tags::Metavariables>(
      71             :             *box))>::factory_creation::factory_classes;
      72             :     previous_trigger_time_ = next_previous_trigger_time_;
      73             :     return call_with_dynamic_type<std::optional<bool>,
      74             :                                   tmpl::at<factory_classes, DenseTrigger>>(
      75             :         this,
      76             :         [this, &array_index, &box, &cache, &component](auto* const trigger) {
      77             :           using TriggerType = std::decay_t<decltype(*trigger)>;
      78             :           const auto result = db::mutate_apply<
      79             :               typename TriggerType::is_triggered_return_tags,
      80             :               typename TriggerType::is_triggered_argument_tags>(
      81             :               [&array_index, &cache, &component,
      82             :                &trigger](const auto&... args) {
      83             :                 return trigger->is_triggered(cache, array_index, component,
      84             :                                              args...);
      85             :               },
      86             :               box);
      87             :           if (result == std::optional{true}) {
      88             :             next_previous_trigger_time_ = db::get<::Tags::Time>(*box);
      89             :           }
      90             :           return result;
      91             :         });
      92             :   }
      93             : 
      94             :   /// Obtain the next time to check the trigger, or std::nullopt if the
      95             :   /// trigger is not ready to report yet.
      96             :   template <typename DbTags, typename Metavariables, typename ArrayIndex,
      97             :             typename Component>
      98           1 :   std::optional<double> next_check_time(
      99             :       const gsl::not_null<db::DataBox<DbTags>*> box,
     100             :       Parallel::GlobalCache<Metavariables>& cache,
     101             :       const ArrayIndex& array_index, const Component* component) {
     102             :     using factory_classes =
     103             :         typename std::decay_t<decltype(db::get<Parallel::Tags::Metavariables>(
     104             :             *box))>::factory_creation::factory_classes;
     105             :     return call_with_dynamic_type<std::optional<double>,
     106             :                                   tmpl::at<factory_classes, DenseTrigger>>(
     107             :         this, [&array_index, &box, &cache, &component](auto* const trigger) {
     108             :           using TriggerType = std::decay_t<decltype(*trigger)>;
     109             :           return db::mutate_apply<
     110             :               typename TriggerType::next_check_time_return_tags,
     111             :               typename TriggerType::next_check_time_argument_tags>(
     112             :               [&array_index, &cache, &component,
     113             :                &trigger](const auto&... args) {
     114             :                 return trigger->next_check_time(cache, array_index, component,
     115             :                                                 args...);
     116             :               },
     117             :               box);
     118             :         });
     119             :   }
     120             : 
     121             :   /// \brief Reports the value of `::Tags::Time` when the trigger most recently
     122             :   /// fired, except for the most recent call of `is_triggered`.
     123             :   ///
     124             :   /// \details The most recent call of `is_triggered` is not used for reporting
     125             :   /// the previous trigger so that the time reported to the event is actually
     126             :   /// the previous time value on which the trigger fired and activated the
     127             :   /// event. Without ignoring the most recent call of `is_triggered`, we'd just
     128             :   /// always be reporting the current time to the event, because events always
     129             :   /// run after their associated triggers fire via a call to `is_triggered`.
     130           1 :   std::optional<double> previous_trigger_time() const {
     131             :     return previous_trigger_time_;
     132             :   }
     133             : 
     134           0 :   void pup(PUP::er& p) override {
     135             :     p | next_previous_trigger_time_;
     136             :     p | previous_trigger_time_;
     137             :   }
     138             : 
     139             :  private:
     140           0 :   std::optional<double> next_previous_trigger_time_ = std::nullopt;
     141           0 :   std::optional<double> previous_trigger_time_ = std::nullopt;
     142             : };

Generated by: LCOV version 1.14