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

Generated by: LCOV version 1.14