SpECTRE Documentation Coverage Report
Current view: top level - ControlSystem - Trigger.hpp Hit Total Coverage
Commit: 3c2e9d3ed337bca2146eee9de07432e292a38c3a Lines: 2 12 16.7 %
Date: 2024-06-11 22:56:19
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 <memory>
       7             : #include <optional>
       8             : #include <pup.h>
       9             : #include <string>
      10             : #include <type_traits>
      11             : 
      12             : #include "ControlSystem/CombinedName.hpp"
      13             : #include "ControlSystem/FutureMeasurements.hpp"
      14             : #include "ControlSystem/Metafunctions.hpp"
      15             : #include "IO/Logging/Verbosity.hpp"
      16             : #include "Parallel/ArrayComponentId.hpp"
      17             : #include "Parallel/Callback.hpp"
      18             : #include "Parallel/GlobalCache.hpp"
      19             : #include "Parallel/Printf/Printf.hpp"
      20             : #include "ParallelAlgorithms/EventsAndDenseTriggers/DenseTrigger.hpp"
      21             : #include "Utilities/ErrorHandling/Assert.hpp"
      22             : #include "Utilities/GetOutput.hpp"
      23             : #include "Utilities/Gsl.hpp"
      24             : #include "Utilities/PrettyType.hpp"
      25             : #include "Utilities/Serialization/CharmPupable.hpp"
      26             : #include "Utilities/TMPL.hpp"
      27             : 
      28             : /// \cond
      29             : namespace Tags {
      30             : struct Time;
      31             : }  // namespace Tags
      32             : namespace control_system::Tags {
      33             : template <typename ControlSystems>
      34             : struct FutureMeasurements;
      35             : struct MeasurementTimescales;
      36             : struct Verbosity;
      37             : }  // namespace control_system::Tags
      38             : /// \endcond
      39             : 
      40             : namespace control_system {
      41             : /// \ingroup ControlSystemsGroup
      42             : /// \ingroup EventsAndTriggersGroup
      43             : /// Trigger for control system measurements.
      44             : ///
      45             : /// This trigger is only intended to be used with the
      46             : /// `control_system::Event` event.  A specialization of this trigger
      47             : /// will be created during control system initialization for each
      48             : /// unique \ref control_system::protocols::Measurement "measurement".
      49             : ///
      50             : /// These triggers must be added to the \ref
      51             : /// Options::protocols::FactoryCreation "factory_creation" struct in
      52             : /// the metavariables, even though they cannot be created from the
      53             : /// input file.  The `control_system::control_system_triggers`
      54             : /// metafunction provides the list of triggers to include.
      55             : template <typename ControlSystems>
      56           1 : class Trigger : public DenseTrigger {
      57             :   static_assert(tmpl::size<ControlSystems>::value > 0);
      58           0 :   using measurement = typename tmpl::front<ControlSystems>::measurement;
      59             :   static_assert(tmpl::all<ControlSystems,
      60             :                           std::is_same<metafunctions::measurement<tmpl::_1>,
      61             :                                        tmpl::pin<measurement>>>::value);
      62             : 
      63             :  public:
      64             :   /// \cond
      65             :   // LCOV_EXCL_START
      66             :   explicit Trigger(CkMigrateMessage* const msg) : DenseTrigger(msg) {}
      67             :   using PUP::able::register_constructor;
      68             :   WRAPPED_PUPable_decl_template(Trigger);  // NOLINT
      69             :   // LCOV_EXCL_STOP
      70             :   /// \endcond
      71             : 
      72             :   // This trigger is created during control system initialization, not
      73             :   // from the input file.
      74           0 :   static constexpr bool factory_creatable = false;
      75           0 :   Trigger() = default;
      76             : 
      77           0 :   using is_triggered_return_tags = tmpl::list<>;
      78           0 :   using is_triggered_argument_tags =
      79             :       tmpl::list<::Tags::Time,
      80             :                  control_system::Tags::FutureMeasurements<ControlSystems>>;
      81             : 
      82             :   template <typename Metavariables, typename ArrayIndex, typename Component>
      83           0 :   std::optional<bool> is_triggered(
      84             :       Parallel::GlobalCache<Metavariables>& cache,
      85             :       const ArrayIndex& array_index, const Component* /*component*/,
      86             :       const double time,
      87             :       const control_system::FutureMeasurements& measurement_times) {
      88             :     const auto next_measurement = measurement_times.next_measurement();
      89             :     ASSERT(next_measurement.has_value(),
      90             :            "Checking trigger without knowing next time.");
      91             :     const bool triggered = time == *next_measurement;
      92             : 
      93             :     if (Parallel::get<Tags::Verbosity>(cache) >= ::Verbosity::Debug) {
      94             :       Parallel::printf(
      95             :           "%s, time = %.16f: Trigger for control systems (%s) is%s "
      96             :           "triggered.\n",
      97             :           get_output(array_index), time,
      98             :           pretty_type::list_of_names<ControlSystems>(),
      99             :           (triggered ? "" : " not"));
     100             :     }
     101             : 
     102             :     return triggered;
     103             :   }
     104             : 
     105           0 :   using next_check_time_return_tags =
     106             :       tmpl::list<control_system::Tags::FutureMeasurements<ControlSystems>>;
     107           0 :   using next_check_time_argument_tags = tmpl::list<::Tags::Time>;
     108             : 
     109             :   template <typename Metavariables, typename ArrayIndex, typename Component>
     110           0 :   std::optional<double> next_check_time(
     111             :       Parallel::GlobalCache<Metavariables>& cache,
     112             :       const ArrayIndex& array_index, const Component* /*component*/,
     113             :       const gsl::not_null<control_system::FutureMeasurements*>
     114             :           measurement_times,
     115             :       const double time) {
     116             :     if (measurement_times->next_measurement() == std::optional(time)) {
     117             :       measurement_times->pop_front();
     118             :     }
     119             : 
     120             :     if (not measurement_times->next_measurement().has_value()) {
     121             :       const auto& proxy =
     122             :           ::Parallel::get_parallel_component<Component>(cache)[array_index];
     123             :       const bool is_ready = Parallel::mutable_cache_item_is_ready<
     124             :           control_system::Tags::MeasurementTimescales>(
     125             :           cache, Parallel::make_array_component_id<Component>(array_index),
     126             :           [&](const auto& measurement_timescales) {
     127             :             const std::string& measurement_name =
     128             :                 control_system::combined_name<ControlSystems>();
     129             :             ASSERT(measurement_timescales.count(measurement_name) == 1,
     130             :                    "Control system trigger expects a measurement timescale "
     131             :                    "with the name '"
     132             :                        << measurement_name
     133             :                        << "' but could not find one. Available names are: "
     134             :                        << keys_of(measurement_timescales));
     135             :             measurement_times->update(
     136             :                 *measurement_timescales.at(measurement_name));
     137             :             if (not measurement_times->next_measurement().has_value()) {
     138             :               return std::unique_ptr<Parallel::Callback>(
     139             :                   new Parallel::PerformAlgorithmCallback(proxy));
     140             :             }
     141             :             return std::unique_ptr<Parallel::Callback>{};
     142             :           });
     143             : 
     144             :       if (not is_ready) {
     145             :         if (Parallel::get<Tags::Verbosity>(cache) >= ::Verbosity::Debug) {
     146             :           Parallel::printf(
     147             :               "%s, time = %.16f: Trigger for control systems (%s) - Cannot "
     148             :               "calculate next_check_time\n",
     149             :               get_output(array_index), time,
     150             :               pretty_type::list_of_names<ControlSystems>());
     151             :         }
     152             :         return std::nullopt;
     153             :       }
     154             :     }
     155             : 
     156             :     const double next_trigger = *measurement_times->next_measurement();
     157             :     ASSERT(next_trigger > time,
     158             :            "Next trigger is in the past: " << next_trigger << " > " << time);
     159             : 
     160             :     if (Parallel::get<Tags::Verbosity>(cache) >= ::Verbosity::Debug) {
     161             :       Parallel::printf(
     162             :           "%s, time = %.16f: Trigger for control systems (%s) - next check "
     163             :           "time is %.16f\n",
     164             :           get_output(array_index), time,
     165             :           pretty_type::list_of_names<ControlSystems>(), next_trigger);
     166             :     }
     167             : 
     168             :     return {next_trigger};
     169             :   }
     170             : };
     171             : 
     172             : /// \cond
     173             : template <typename ControlSystems>
     174             : PUP::able::PUP_ID Trigger<ControlSystems>::my_PUP_ID = 0;  // NOLINT
     175             : /// \endcond
     176             : 
     177             : // This metafunction is tested in Test_EventTriggerMetafunctions.cpp
     178             : 
     179             : /// \ingroup ControlSystemGroup
     180             : /// The list of triggers needed for measurements for a list of control
     181             : /// systems.
     182             : template <typename ControlSystems>
     183           1 : using control_system_triggers = tmpl::transform<
     184             :     metafunctions::measurements_t<ControlSystems>,
     185             :     tmpl::bind<Trigger, metafunctions::control_systems_with_measurement<
     186             :                             tmpl::pin<ControlSystems>, tmpl::_1>>>;
     187             : }  // namespace control_system

Generated by: LCOV version 1.14