SpECTRE Documentation Coverage Report
Current view: top level - ControlSystem/Actions - InitializeMeasurements.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 14.3 % 7 1
Test Date: 2026-10-22 17:29:42
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 <algorithm>
       7              : #include <cstddef>
       8              : #include <limits>
       9              : #include <memory>
      10              : #include <optional>
      11              : #include <tuple>
      12              : #include <utility>
      13              : 
      14              : #include "ControlSystem/CombinedName.hpp"
      15              : #include "ControlSystem/FutureMeasurements.hpp"
      16              : #include "ControlSystem/Metafunctions.hpp"
      17              : #include "ControlSystem/Tags/FutureMeasurements.hpp"
      18              : #include "ControlSystem/Tags/MeasurementTimescales.hpp"
      19              : #include "ControlSystem/Tags/SystemTags.hpp"
      20              : #include "ControlSystem/Trigger.hpp"
      21              : #include "DataStructures/DataBox/DataBox.hpp"
      22              : #include "Parallel/AlgorithmExecution.hpp"
      23              : #include "Parallel/GlobalCache.hpp"
      24              : #include "ParallelAlgorithms/EventsAndDenseTriggers/DenseTrigger.hpp"
      25              : #include "ParallelAlgorithms/EventsAndDenseTriggers/EventsAndDenseTriggers.hpp"
      26              : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
      27              : #include "Time/ChooseLtsStepSize.hpp"
      28              : #include "Time/LtsMode.hpp"
      29              : #include "Time/Slab.hpp"
      30              : #include "Time/Time.hpp"
      31              : #include "Utilities/ErrorHandling/Error.hpp"
      32              : #include "Utilities/Gsl.hpp"
      33              : #include "Utilities/MakeVector.hpp"
      34              : #include "Utilities/TMPL.hpp"
      35              : 
      36              : /// \cond
      37              : class TimeStepper;
      38              : namespace Tags {
      39              : struct EventsAndDenseTriggers;
      40              : struct LtsMode;
      41              : struct TimeStep;
      42              : template <typename StepperInterface>
      43              : struct TimeStepper;
      44              : }  // namespace Tags
      45              : namespace domain::Tags {
      46              : struct FunctionsOfTime;
      47              : }  // namespace domain::Tags
      48              : namespace tuples {
      49              : template <typename... Tags>
      50              : class TaggedTuple;
      51              : }  // namespace tuples
      52              : /// \endcond
      53              : 
      54              : namespace control_system::Actions {
      55              : /// \ingroup ControlSystemGroup
      56              : /// \brief Set up the element component for control-system measurements.
      57              : template <typename ControlSystems>
      58            1 : struct InitializeMeasurements {
      59            0 :   using control_system_groups =
      60              :       tmpl::transform<metafunctions::measurements_t<ControlSystems>,
      61              :                       metafunctions::control_systems_with_measurement<
      62              :                           tmpl::pin<ControlSystems>, tmpl::_1>>;
      63              : 
      64            0 :   using simple_tags =
      65              :       tmpl::transform<control_system_groups,
      66              :                       tmpl::bind<Tags::FutureMeasurements, tmpl::_1>>;
      67            0 :   using const_global_cache_tags =
      68              :       tmpl::list<Tags::MeasurementsPerUpdate, Tags::DelayUpdate>;
      69            0 :   using mutable_global_cache_tags =
      70              :       tmpl::list<control_system::Tags::MeasurementTimescales>;
      71              : 
      72              :   template <typename DbTagsList, typename... InboxTags, typename Metavariables,
      73              :             typename ArrayIndex, typename ActionList,
      74              :             typename ParallelComponent>
      75            0 :   static Parallel::iterable_action_return_t apply(
      76              :       db::DataBox<DbTagsList>& box,
      77              :       const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
      78              :       const Parallel::GlobalCache<Metavariables>& cache,
      79              :       const ArrayIndex& /*array_index*/, ActionList /*meta*/,
      80              :       const ParallelComponent* const /*meta*/) {
      81              :     if (not db::get<Tags::DelayUpdate>(box) and
      82              :         not db::get<::Tags::TimeStepper<TimeStepper>>(box).monotonic()) {
      83              :       ERROR_NO_TRACE(
      84              :           "Chosen TimeStepper requires DelayUpdate: true to avoid deadlocks");
      85              :     }
      86              : 
      87              :     const double initial_time = db::get<::Tags::Time>(box);
      88              :     const int measurements_per_update =
      89              :         db::get<Tags::MeasurementsPerUpdate>(box);
      90              :     const auto& timescales = Parallel::get<Tags::MeasurementTimescales>(cache);
      91              :     tmpl::for_each<control_system_groups>([&](auto group_v) {
      92              :       using group = tmpl::type_from<decltype(group_v)>;
      93              :       const bool active =
      94              :           timescales.at(combined_name<group>())->func(initial_time)[0][0] !=
      95              :           std::numeric_limits<double>::infinity();
      96              :       db::mutate<Tags::FutureMeasurements<group>>(
      97              :           [&](const gsl::not_null<FutureMeasurements*> measurements) {
      98              :             if (active) {
      99              :               *measurements = FutureMeasurements(
     100              :                   static_cast<size_t>(measurements_per_update), initial_time);
     101              :             } else {
     102              :               *measurements = FutureMeasurements(
     103              :                   1, std::numeric_limits<double>::infinity());
     104              :             }
     105              :           },
     106              :           make_not_null(&box));
     107              :     });
     108              : 
     109              :     db::mutate<::Tags::EventsAndDenseTriggers>(
     110              :         [](const gsl::not_null<EventsAndDenseTriggers*>
     111              :                events_and_dense_triggers) {
     112              :           tmpl::for_each<metafunctions::measurements_t<ControlSystems>>(
     113              :               [&events_and_dense_triggers](auto measurement_v) {
     114              :                 using measurement = tmpl::type_from<decltype(measurement_v)>;
     115              :                 using control_system_group =
     116              :                     metafunctions::control_systems_with_measurement_t<
     117              :                         ControlSystems, measurement>;
     118              :                 using events = tmpl::transform<
     119              :                     typename measurement::submeasurements,
     120              :                     metafunctions::event_from_submeasurement<
     121              :                         tmpl::pin<control_system_group>, tmpl::_1>>;
     122              :                 std::vector<std::unique_ptr<::Event>> vector_of_events =
     123              :                     tmpl::as_pack<events>([](auto... events_v) {
     124              :                       return make_vector<std::unique_ptr<::Event>>(
     125              :                           std::make_unique<
     126              :                               tmpl::type_from<decltype(events_v)>>()...);
     127              :                     });
     128              :                 events_and_dense_triggers->add_trigger_and_events(
     129              :                     std::make_unique<
     130              :                         control_system::Trigger<control_system_group>>(),
     131              :                     std::move(vector_of_events));
     132              :               });
     133              :         },
     134              :         make_not_null(&box));
     135              : 
     136              :     // Ensure that the initial time step is small enough that we don't
     137              :     // need to perform any measurements to complete it.  This is only
     138              :     // necessary for TimeSteppers that use the self-start procedure,
     139              :     // because they cannot adjust their step size on the first step
     140              :     // after self-start, but it isn't harmful to do it in other cases.
     141              :     //
     142              :     // Unlike in the steady-state step-limiting code, we don't do
     143              :     // anything clever looking at measurement times or planning ahead
     144              :     // for future steps.  Avoiding a single non-ideal step isn't worth
     145              :     // the added complexity.
     146              :     const auto lts_mode = db::get<::Tags::LtsMode>(box);
     147              :     double earliest_expiration = std::numeric_limits<double>::infinity();
     148              :     for (const auto& fot :
     149              :          Parallel::get<domain::Tags::FunctionsOfTime>(cache)) {
     150              :       earliest_expiration =
     151              :           std::min(earliest_expiration, fot.second->time_bounds()[1]);
     152              :     }
     153              :     const auto& time_step = db::get<::Tags::TimeStep>(box);
     154              :     const auto start_time = time_step.slab().start();
     155              :     if ((start_time + time_step).value() > earliest_expiration) {
     156              :       db::mutate<::Tags::TimeStep>(
     157              :           [&](const gsl::not_null<TimeDelta*> step) {
     158              :             if (lts_mode != LtsMode::Off) {
     159              :               *step = choose_lts_step_size(
     160              :                   start_time,
     161              :                   0.99 * (earliest_expiration - start_time.value()));
     162              :             } else {
     163              :               *step = Slab(start_time.value(), earliest_expiration).duration();
     164              :             }
     165              :           },
     166              :           make_not_null(&box));
     167              :     }
     168              : 
     169              :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     170              :   }
     171              : };
     172              : }  // namespace control_system::Actions
        

Generated by: LCOV version 2.0-1