ObserveTimeStep.hpp
1 // 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 <string>
11 #include <type_traits>
12 #include <utility>
13 #include <vector>
14 
15 #include "IO/Observer/ArrayComponentId.hpp"
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/ReductionActions.hpp" // IWYU pragma: keep
20 #include "IO/Observer/TypeOfObservation.hpp"
21 #include "Options/Options.hpp"
22 #include "Parallel/ArrayIndex.hpp"
24 #include "Parallel/GlobalCache.hpp"
25 #include "Parallel/Invoke.hpp"
26 #include "Parallel/Reduction.hpp"
27 #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
28 #include "Time/Slab.hpp"
29 #include "Time/Time.hpp"
30 #include "Utilities/Functional.hpp"
31 #include "Utilities/Registration.hpp"
32 #include "Utilities/TMPL.hpp"
33 
34 /// \cond
35 namespace Tags {
36 struct Time;
37 struct TimeStep;
38 } // namespace Tags
39 /// \endcond
40 
41 namespace Events {
42 /// \cond
43 template <typename Metavariables, typename EventRegistrars>
44 class ObserveTimeStep;
45 /// \endcond
46 
47 namespace Registrars {
48 template <typename Metavariables>
49 using ObserveTimeStep =
51 } // namespace Registrars
52 
53 /*!
54  * \brief %Observe the size of the time steps.
55  *
56  * Writes reduction quantities:
57  * - `%Time`
58  * - `NumberOfPoints`
59  * - `%Slab size`
60  * - `Minimum time step`
61  * - `Maximum time step`
62  * - `Effective time step`
63  *
64  * The effective time step is the step size of a global-time-stepping
65  * method that would perform a similar amount of work. This is the
66  * harmonic mean of the step size over all grid points:
67  *
68  * \f{equation}
69  * (\Delta t)_{\text{eff}}^{-1} =
70  * \frac{\sum_{i \in \text{points}} (\Delta t)_i^{-1}}{N_{\text{points}}}.
71  * \f}
72  *
73  * This corresponds to averaging the number of steps per unit time
74  * taken by all points.
75  *
76  * All values are reported as positive numbers, even for backwards
77  * evolutions.
78  */
79 template <typename Metavariables,
80  typename EventRegistrars =
81  tmpl::list<Registrars::ObserveTimeStep<Metavariables>>>
82 class ObserveTimeStep : public Event<EventRegistrars> {
83  private:
84  using ReductionData = Parallel::ReductionData<
91  double, funcl::Plus<>,
94 
95  public:
96  /// The name of the subfile inside the HDF5 file
97  struct SubfileName {
98  using type = std::string;
99  static constexpr Options::String help = {
100  "The name of the subfile inside the HDF5 file without an extension and "
101  "without a preceding '/'."};
102  };
103 
104  /// \cond
105  explicit ObserveTimeStep(CkMigrateMessage* /*unused*/) noexcept {}
106  using PUP::able::register_constructor;
108  /// \endcond
109 
110  using options = tmpl::list<SubfileName>;
111  static constexpr Options::String help =
112  "Observe the size of the time steps.\n"
113  "\n"
114  "Writes reduction quantities:\n"
115  "- Time\n"
116  "- NumberOfPoints\n"
117  "- Slab size\n"
118  "- Minimum time step\n"
119  "- Maximum time step\n"
120  "- Effective time step\n"
121  "\n"
122  "The effective time step is the step size of a global-time-stepping\n"
123  "method that would perform a similar amount of work.\n"
124  "\n"
125  "All values are reported as positive numbers, even for backwards\n"
126  "evolutions.";
127 
128  ObserveTimeStep() = default;
129  explicit ObserveTimeStep(const std::string& subfile_name) noexcept;
130 
131  using observed_reduction_data_tags =
132  observers::make_reduction_data_tags<tmpl::list<ReductionData>>;
133 
134  // We obtain the grid size from the variables, rather than the mesh,
135  // so that this observer is not DG-specific.
136  using argument_tags =
137  tmpl::list<Tags::Time, Tags::TimeStep,
138  typename Metavariables::system::variables_tag>;
139 
140  template <typename ArrayIndex, typename ParallelComponent>
141  void operator()(
142  const double& time, const TimeDelta& time_step,
143  const typename Metavariables::system::variables_tag::type& variables,
145  const ArrayIndex& array_index,
146  const ParallelComponent* const /*meta*/) const noexcept {
147  const size_t number_of_grid_points = variables.number_of_grid_points();
148  const double slab_size = time_step.slab().duration().value();
149  const double step_size = abs(time_step.value());
150 
151  auto& local_observer =
152  *Parallel::get_parallel_component<observers::Observer<Metavariables>>(
153  cache)
154  .ckLocalBranch();
155  Parallel::simple_action<observers::Actions::ContributeReductionData>(
156  local_observer, observers::ObservationId(time, subfile_path_ + ".dat"),
159  Parallel::ArrayIndex<ArrayIndex>(array_index)},
160  subfile_path_,
161  std::vector<std::string>{"Time", "NumberOfPoints", "Slab size",
162  "Minimum time step", "Maximum time step",
163  "Effective time step"},
164  ReductionData{time, number_of_grid_points, slab_size, step_size,
165  step_size, number_of_grid_points / step_size});
166  }
167 
168  using observation_registration_tags = tmpl::list<>;
170  get_observation_type_and_key_for_registration() const noexcept {
172  observers::ObservationKey(subfile_path_ + ".dat")};
173  }
174 
175  // NOLINTNEXTLINE(google-runtime-references)
176  void pup(PUP::er& p) override {
178  p | subfile_path_;
179  }
180 
181  private:
182  std::string subfile_path_;
183 };
184 
185 template <typename Metavariables, typename EventRegistrars>
186 ObserveTimeStep<Metavariables, EventRegistrars>::ObserveTimeStep(
187  const std::string& subfile_name) noexcept
188  : subfile_path_("/" + subfile_name) {}
189 
190 /// \cond
191 template <typename Metavariables, typename EventRegistrars>
192 PUP::able::PUP_ID ObserveTimeStep<Metavariables, EventRegistrars>::my_PUP_ID =
193  0; // NOLINT
194 /// \endcond
195 } // namespace Events
observers::ObservationId
A unique identifier for an observation representing the type of observation and the instance (e....
Definition: ObservationId.hpp:71
funcl::Divides
Functional for computing / of two objects.
Definition: Functional.hpp:235
std::string
CharmPupable.hpp
utility
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:15
Parallel::ReductionDatum
The data to be reduced, and invokables to be called whenever two reduction messages are combined and ...
Definition: Reduction.hpp:63
std::pair
GlobalCache.hpp
std::index_sequence
Options.hpp
vector
Tags::TimeStep
Tag for step size.
Definition: Tags.hpp:42
observers::ObservationKey
Used as a key in maps to keep track of how many elements have registered.
Definition: ObservationId.hpp:28
Events::ObserveTimeStep::SubfileName
The name of the subfile inside the HDF5 file.
Definition: ObserveTimeStep.hpp:97
cmath
Registration::Registrar
A template for defining a registrar.
Definition: Registration.hpp:42
std::add_pointer_t
WRAPPED_PUPable_decl_template
#define WRAPPED_PUPable_decl_template(className)
Mark derived classes as serializable.
Definition: CharmPupable.hpp:22
Event
Definition: Event.hpp:30
cstddef
funcl::Plus
Functional for computing + of two objects.
Definition: Functional.hpp:238
TimeDelta
Definition: Time.hpp:88
Tags::Time
Tag for the current time as a double.
Definition: Tags.hpp:73
Time.hpp
Time
Definition: Time.hpp:29
Options::String
const char *const String
The string used in option structs.
Definition: Options.hpp:32
observers::TypeOfObservation::Reduction
@ Reduction
The sender will only perform reduction observations.
Slab.hpp
observers::ArrayComponentId
An ID type that identifies both the parallel component and the index in the parallel component.
Definition: ArrayComponentId.hpp:27
Events::ObserveTimeStep
Observe the size of the time steps.
Definition: ObserveTimeStep.hpp:82
std::time
T time(T... args)
Parallel::ArrayIndex
The array index used for indexing Chare Arrays, mostly an implementation detail.
Definition: ArrayIndex.hpp:27
type_traits
TMPL.hpp
string