SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/Events - ObserveTimeStep.hpp Hit Total Coverage
Commit: 1f2210958b4f38fdc0400907ee7c6d5af5111418 Lines: 3 31 9.7 %
Date: 2025-12-05 05:03:31
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 <cstddef>
       7             : #include <optional>
       8             : #include <string>
       9             : #include <tuple>
      10             : #include <type_traits>
      11             : #include <utility>
      12             : #include <vector>
      13             : 
      14             : #include "IO/Observer/Helpers.hpp"
      15             : #include "IO/Observer/ObservationId.hpp"
      16             : #include "IO/Observer/ObserverComponent.hpp"
      17             : #include "IO/Observer/Protocols/ReductionDataFormatter.hpp"
      18             : #include "IO/Observer/ReductionActions.hpp"
      19             : #include "IO/Observer/TypeOfObservation.hpp"
      20             : #include "Options/String.hpp"
      21             : #include "Parallel/ArrayComponentId.hpp"
      22             : #include "Parallel/ArrayIndex.hpp"
      23             : #include "Parallel/GlobalCache.hpp"
      24             : #include "Parallel/Info.hpp"
      25             : #include "Parallel/Invoke.hpp"
      26             : #include "Parallel/Local.hpp"
      27             : #include "Parallel/Reduction.hpp"
      28             : #include "Parallel/TypeTraits.hpp"
      29             : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
      30             : #include "Utilities/Functional.hpp"
      31             : #include "Utilities/ProtocolHelpers.hpp"
      32             : #include "Utilities/Serialization/CharmPupable.hpp"
      33             : #include "Utilities/TMPL.hpp"
      34             : 
      35             : /// \cond
      36             : class TimeDelta;
      37             : namespace PUP {
      38             : class er;
      39             : }  // namespace PUP
      40             : namespace Tags {
      41             : struct TimeStep;
      42             : }  // namespace Tags
      43             : /// \endcond
      44             : 
      45             : namespace Events {
      46             : namespace detail {
      47             : using ObserveTimeStepReductionData = Parallel::ReductionData<
      48             :     Parallel::ReductionDatum<double, funcl::AssertEqual<>>,
      49             :     Parallel::ReductionDatum<size_t, funcl::Plus<>>,
      50             :     Parallel::ReductionDatum<double, funcl::AssertEqual<>>,
      51             :     Parallel::ReductionDatum<double, funcl::Min<>>,
      52             :     Parallel::ReductionDatum<double, funcl::Max<>>,
      53             :     Parallel::ReductionDatum<
      54             :         double, funcl::Plus<>,
      55             :         funcl::Divides<funcl::Literal<1, double>, funcl::Divides<>>,
      56             :         std::index_sequence<1>>,
      57             :     Parallel::ReductionDatum<double, funcl::Min<>>,
      58             :     Parallel::ReductionDatum<double, funcl::Max<>>>;
      59             : 
      60             : struct FormatTimeOutput
      61             :     : tt::ConformsTo<observers::protocols::ReductionDataFormatter> {
      62             :   using reduction_data = ObserveTimeStepReductionData;
      63             :   std::string operator()(double time, size_t num_points, double slab_size,
      64             :                          double min_time_step, double max_time_step,
      65             :                          double effective_time_step, double min_wall_time,
      66             :                          double max_wall_time) const;
      67             :   // NOLINTNEXTLINE
      68             :   void pup(PUP::er& p);
      69             : };
      70             : }  // namespace detail
      71             : 
      72             : /*!
      73             :  * \brief %Observe the size of the time steps.
      74             :  *
      75             :  * Writes reduction quantities:
      76             :  * - `%Time`
      77             :  * - `NumberOfPoints`
      78             :  * - `%Slab size`
      79             :  * - `Minimum time step`
      80             :  * - `Maximum time step`
      81             :  * - `Effective time step`
      82             :  *
      83             :  * The effective time step is the step size of a global-time-stepping
      84             :  * method that would perform a similar amount of work.  This is the
      85             :  * harmonic mean of the step size over all grid points:
      86             :  *
      87             :  * \f{equation}
      88             :  * (\Delta t)_{\text{eff}}^{-1} =
      89             :  * \frac{\sum_{i \in \text{points}} (\Delta t)_i^{-1}}{N_{\text{points}}}.
      90             :  * \f}
      91             :  *
      92             :  * This corresponds to averaging the number of steps per unit time
      93             :  * taken by all points.
      94             :  *
      95             :  * All values are reported as positive numbers, even for backwards
      96             :  * evolutions.
      97             :  */
      98             : template <typename System>
      99           1 : class ObserveTimeStep : public Event {
     100             :  private:
     101           0 :   using ReductionData = Events::detail::ObserveTimeStepReductionData;
     102             : 
     103             :  public:
     104             :   /// The name of the subfile inside the HDF5 file
     105           1 :   struct SubfileName {
     106           0 :     using type = std::string;
     107           0 :     static constexpr Options::String help = {
     108             :         "The name of the subfile inside the HDF5 file without an extension and "
     109             :         "without a preceding '/'."};
     110             :   };
     111             : 
     112           0 :   struct PrintTimeToTerminal {
     113           0 :     using type = bool;
     114           0 :     static constexpr Options::String help = {
     115             :         "Whether to print the time to screen."};
     116             :   };
     117             : 
     118           0 :   struct ObservePerCore {
     119           0 :     using type = bool;
     120           0 :     static constexpr Options::String help = {
     121             :         "Also write the data per-core in a file per-node."};
     122             :   };
     123             : 
     124             :   /// \cond
     125             :   explicit ObserveTimeStep(CkMigrateMessage* /*m*/);
     126             :   using PUP::able::register_constructor;
     127             :   WRAPPED_PUPable_decl_template(ObserveTimeStep);  // NOLINT
     128             :   /// \endcond
     129             : 
     130           0 :   using options = tmpl::list<SubfileName, PrintTimeToTerminal, ObservePerCore>;
     131           0 :   static constexpr Options::String help =
     132             :       "Observe the size of the time steps.\n"
     133             :       "\n"
     134             :       "Writes reduction quantities:\n"
     135             :       "- Time\n"
     136             :       "- NumberOfPoints\n"
     137             :       "- Slab size\n"
     138             :       "- Minimum time step\n"
     139             :       "- Maximum time step\n"
     140             :       "- Effective time step\n"
     141             :       "\n"
     142             :       "The effective time step is the step size of a global-time-stepping\n"
     143             :       "method that would perform a similar amount of work.\n"
     144             :       "\n"
     145             :       "All values are reported as positive numbers, even for backwards\n"
     146             :       "evolutions.";
     147             : 
     148           0 :   ObserveTimeStep();
     149           0 :   ObserveTimeStep(const std::string& subfile_name, bool output_time,
     150             :                   bool observe_per_core);
     151             : 
     152           0 :   using observed_reduction_data_tags =
     153             :       observers::make_reduction_data_tags<tmpl::list<ReductionData>>;
     154             : 
     155           0 :   using compute_tags_for_observation_box = tmpl::list<>;
     156             : 
     157           0 :   using return_tags = tmpl::list<>;
     158             :   // We obtain the grid size from the variables, rather than the mesh,
     159             :   // so that this observer is not DG-specific.
     160           0 :   using argument_tags =
     161             :       tmpl::list<::Tags::TimeStep, typename System::variables_tag>;
     162             : 
     163             :   template <typename ArrayIndex, typename ParallelComponent,
     164             :             typename Metavariables>
     165           0 :   void operator()(const TimeDelta& time_step,
     166             :                   const typename System::variables_tag::type& variables,
     167             :                   Parallel::GlobalCache<Metavariables>& cache,
     168             :                   const ArrayIndex& array_index,
     169             :                   const ParallelComponent* const /*meta*/,
     170             :                   const ObservationValue& observation_value) const {
     171             :     auto [observation_id, legend, reduction_data, formatter] =
     172             :         assemble_data(time_step, variables, observation_value);
     173             : 
     174             :     auto& local_observer = *Parallel::local_branch(
     175             :         Parallel::get_parallel_component<
     176             :             tmpl::conditional_t<Parallel::is_nodegroup_v<ParallelComponent>,
     177             :                                 observers::ObserverWriter<Metavariables>,
     178             :                                 observers::Observer<Metavariables>>>(cache));
     179             : 
     180             :     Parallel::ArrayComponentId array_component_id{
     181             :         std::add_pointer_t<ParallelComponent>{nullptr},
     182             :         Parallel::ArrayIndex<ArrayIndex>(array_index)};
     183             : 
     184             :     if constexpr (Parallel::is_nodegroup_v<ParallelComponent>) {
     185             :       const std::optional<int> observe_with_core_id =
     186             :           observe_per_core_
     187             :               ? std::make_optional(Parallel::my_node<int>(local_observer))
     188             :               : std::nullopt;
     189             :       Parallel::threaded_action<
     190             :           observers::ThreadedActions::CollectReductionDataOnNode>(
     191             :           local_observer, std::move(observation_id),
     192             :           std::move(array_component_id), subfile_path_, std::move(legend),
     193             :           std::move(reduction_data), std::move(formatter),
     194             :           observe_with_core_id);
     195             :     } else {
     196             :       Parallel::simple_action<observers::Actions::ContributeReductionData>(
     197             :           local_observer, std::move(observation_id),
     198             :           std::move(array_component_id), subfile_path_, std::move(legend),
     199             :           std::move(reduction_data), std::move(formatter), observe_per_core_);
     200             :     }
     201             :   }
     202             : 
     203           0 :   using observation_registration_tags = tmpl::list<>;
     204             :   std::pair<observers::TypeOfObservation, observers::ObservationKey>
     205           0 :   get_observation_type_and_key_for_registration() const;
     206             : 
     207           0 :   using is_ready_argument_tags = tmpl::list<>;
     208             : 
     209             :   template <typename Metavariables, typename ArrayIndex, typename Component>
     210           0 :   bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/,
     211             :                 const ArrayIndex& /*array_index*/,
     212             :                 const Component* const /*meta*/) const {
     213             :     return true;
     214             :   }
     215             : 
     216           1 :   bool needs_evolved_variables() const override;
     217             : 
     218             :   // NOLINTNEXTLINE(google-runtime-references)
     219           0 :   void pup(PUP::er& p) override;
     220             : 
     221             :  private:
     222           0 :   auto assemble_data(const TimeDelta& time_step,
     223             :                      const typename System::variables_tag::type& variables,
     224             :                      const ObservationValue& observation_value) const
     225             :       -> std::tuple<observers::ObservationId, std::vector<std::string>,
     226             :                     ReductionData,
     227             :                     std::optional<Events::detail::FormatTimeOutput>>;
     228             : 
     229           0 :   std::string subfile_path_;
     230           0 :   bool output_time_;
     231           0 :   bool observe_per_core_;
     232             : };
     233             : }  // namespace Events

Generated by: LCOV version 1.14