SpECTRE Documentation Coverage Report
Current view: top level - ControlSystem/Tags - MeasurementTimescales.hpp Hit Total Coverage
Commit: 37c384043430860f87787999aa7399d01bb3d213 Lines: 1 7 14.3 %
Date: 2024-04-20 02:24:02
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 <array>
       7             : #include <limits>
       8             : #include <memory>
       9             : #include <optional>
      10             : #include <string>
      11             : #include <unordered_map>
      12             : 
      13             : #include "ControlSystem/CalculateMeasurementTimescales.hpp"
      14             : #include "ControlSystem/CombinedName.hpp"
      15             : #include "ControlSystem/Controller.hpp"
      16             : #include "ControlSystem/ExpirationTimes.hpp"
      17             : #include "ControlSystem/Metafunctions.hpp"
      18             : #include "ControlSystem/Tags/OptionTags.hpp"
      19             : #include "ControlSystem/Tags/SystemTags.hpp"
      20             : #include "ControlSystem/TimescaleTuner.hpp"
      21             : #include "DataStructures/DataBox/Tag.hpp"
      22             : #include "DataStructures/DataVector.hpp"
      23             : #include "Domain/Creators/OptionTags.hpp"
      24             : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp"
      25             : #include "Domain/FunctionsOfTime/PiecewisePolynomial.hpp"
      26             : #include "Time/OptionTags/InitialTime.hpp"
      27             : #include "Time/OptionTags/InitialTimeStep.hpp"
      28             : #include "Utilities/ErrorHandling/Error.hpp"
      29             : #include "Utilities/TMPL.hpp"
      30             : #include "Utilities/TypeTraits/IsA.hpp"
      31             : 
      32             : /// \cond
      33             : template <class Metavariables, typename ControlSystem>
      34             : struct ControlComponent;
      35             : /// \endcond
      36             : 
      37             : namespace control_system::Tags {
      38             : /*!
      39             :  * \ingroup DataBoxTagsGroup
      40             :  * \ingroup ControlSystemGroup
      41             :  * \brief The measurement timescales associated with
      42             :  * domain::Tags::FunctionsOfTime.
      43             :  *
      44             :  * We group measurement timescales by
      45             :  * the `control_system::protocols::Measurement` that their corresponding control
      46             :  * systems use. This is because one measurement may be used to update many
      47             :  * functions of time. Each group of functions of time associated with a
      48             :  * particular measurement has a corresponding timescale here, represented as
      49             :  * `PiecewisePolynomial<0>` with a single entry. That single entry is the
      50             :  * minimum of all `control_system::calculate_measurement_timescales` for every
      51             :  * control system in that group.
      52             :  *
      53             :  * The name of a measurement timescale is calculated using
      54             :  * `control_system::system_to_combined_names` for every group of control systems
      55             :  * with the same measurement.
      56             :  *
      57             :  * If all control systems that use the same measurement aren't active, then the
      58             :  * measurement timescale and expiration time are
      59             :  * `std::numeric_limits<double>::infinity()`.
      60             :  */
      61           1 : struct MeasurementTimescales : db::SimpleTag {
      62           0 :   using type = std::unordered_map<
      63             :       std::string, std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>;
      64             : 
      65             :   template <typename Metavariables>
      66           0 :   using option_holders = control_system::inputs<
      67             :       tmpl::transform<tmpl::filter<typename Metavariables::component_list,
      68             :                                    tt::is_a<ControlComponent, tmpl::_1>>,
      69             :                       tmpl::bind<tmpl::back, tmpl::_1>>>;
      70             : 
      71           0 :   static constexpr bool pass_metavariables = true;
      72             : 
      73             :   template <typename Metavariables>
      74           0 :   using option_tags = tmpl::push_front<
      75             :       option_holders<Metavariables>,
      76             :       control_system::OptionTags::MeasurementsPerUpdate,
      77             :       domain::OptionTags::DomainCreator<Metavariables::volume_dim>,
      78             :       ::OptionTags::InitialTime, ::OptionTags::InitialTimeStep>;
      79             : 
      80             :   template <typename Metavariables, typename... OptionHolders>
      81           0 :   static type create_from_options(
      82             :       const int measurements_per_update,
      83             :       const std::unique_ptr<::DomainCreator<Metavariables::volume_dim>>&
      84             :           domain_creator,
      85             :       const double initial_time, const double initial_time_step,
      86             :       const OptionHolders&... option_holders) {
      87             :     std::unordered_map<std::string,
      88             :                        std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>
      89             :         timescales{};
      90             : 
      91             :     using control_systems =
      92             :         tmpl::list<typename OptionHolders::control_system...>;
      93             : 
      94             :     // First string is name of each control system. Second string is combination
      95             :     // of control systems with same measurement
      96             :     std::unordered_map<std::string, std::string> map_of_names =
      97             :         system_to_combined_names<control_systems>();
      98             : 
      99             :     // Initialize all measurements to infinity so we can take the min later
     100             :     std::unordered_map<std::string, double> min_measurement_timescales{};
     101             :     std::unordered_map<std::string, double> expiration_times{};
     102             :     for (const auto& [control_system_name, combined_name] : map_of_names) {
     103             :       (void)control_system_name;
     104             :       if (min_measurement_timescales.count(combined_name) != 1) {
     105             :         min_measurement_timescales[combined_name] =
     106             :             std::numeric_limits<double>::infinity();
     107             :         expiration_times[combined_name] =
     108             :             std::numeric_limits<double>::infinity();
     109             :       }
     110             :     }
     111             : 
     112             :     [[maybe_unused]] const auto combine_measurement_timescales =
     113             :         [&initial_time, &initial_time_step, &domain_creator,
     114             :          &measurements_per_update, &map_of_names, &min_measurement_timescales,
     115             :          &expiration_times](const auto& option_holder) {
     116             :           // This check is intentionally inside the lambda so that it will not
     117             :           // trigger for domains without control systems.
     118             :           if (initial_time_step <= 0.0) {
     119             :             ERROR(
     120             :                 "Control systems can only be used in forward-in-time "
     121             :                 "evolutions.");
     122             :           }
     123             : 
     124             :           const std::string& control_system_name =
     125             :               std::decay_t<decltype(option_holder)>::control_system::name();
     126             :           const std::string& combined_name = map_of_names[control_system_name];
     127             : 
     128             :           auto tuner = option_holder.tuner;
     129             :           ::control_system::Tags::detail::initialize_tuner(
     130             :               make_not_null(&tuner), domain_creator, initial_time,
     131             :               control_system_name);
     132             : 
     133             :           const auto& controller = option_holder.controller;
     134             :           DataVector measurement_timescales = calculate_measurement_timescales(
     135             :               controller, tuner, measurements_per_update);
     136             : 
     137             :           double min_measurement_timescale = min(measurement_timescales);
     138             : 
     139             :           // If the control system isn't active, set measurement timescale and
     140             :           // expiration time to be infinity.
     141             :           if (not option_holder.is_active) {
     142             :             min_measurement_timescale = std::numeric_limits<double>::infinity();
     143             :           }
     144             : 
     145             :           min_measurement_timescales[combined_name] =
     146             :               std::min(min_measurement_timescales[combined_name],
     147             :                        min_measurement_timescale);
     148             : 
     149             :           if (min_measurement_timescales[combined_name] !=
     150             :               std::numeric_limits<double>::infinity()) {
     151             :             const double expiration_time = measurement_expiration_time(
     152             :                 initial_time, DataVector{1_st, 0.0},
     153             :                 DataVector{1_st, min_measurement_timescales[combined_name]},
     154             :                 measurements_per_update);
     155             :             expiration_times[combined_name] =
     156             :                 std::min(expiration_times[combined_name], expiration_time);
     157             :           }
     158             :         };
     159             : 
     160             :     EXPAND_PACK_LEFT_TO_RIGHT(combine_measurement_timescales(option_holders));
     161             : 
     162             :     for (const auto& [combined_name, min_measurement_timescale] :
     163             :          min_measurement_timescales) {
     164             :       double expiration_time = expiration_times[combined_name];
     165             :       timescales.emplace(
     166             :           combined_name,
     167             :           std::make_unique<domain::FunctionsOfTime::PiecewisePolynomial<0>>(
     168             :               initial_time,
     169             :               std::array{DataVector{1, min_measurement_timescale}},
     170             :               expiration_time));
     171             :     }
     172             : 
     173             :     return timescales;
     174             :   }
     175             : };
     176             : }  // namespace control_system::Tags

Generated by: LCOV version 1.14