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 <sstream>
12 #include <type_traits>
13 #include <utility>
14 #include <vector>
15 
16 #include "IO/Observer/ArrayComponentId.hpp"
17 #include "IO/Observer/Helpers.hpp"
18 #include "IO/Observer/ObservationId.hpp"
19 #include "IO/Observer/ObserverComponent.hpp" // IWYU pragma: keep
20 #include "IO/Observer/Protocols/ReductionDataFormatter.hpp"
21 #include "IO/Observer/ReductionActions.hpp" // IWYU pragma: keep
22 #include "IO/Observer/TypeOfObservation.hpp"
23 #include "Options/Options.hpp"
24 #include "Parallel/ArrayIndex.hpp"
26 #include "Parallel/GlobalCache.hpp"
27 #include "Parallel/Invoke.hpp"
28 #include "Parallel/Reduction.hpp"
29 #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
30 #include "Time/Slab.hpp"
31 #include "Time/Time.hpp"
32 #include "Utilities/Functional.hpp"
33 #include "Utilities/ProtocolHelpers.hpp"
34 #include "Utilities/TMPL.hpp"
35 
36 /// \cond
37 namespace Tags {
38 struct Time;
39 struct TimeStep;
40 } // namespace Tags
41 /// \endcond
42 
43 namespace Events {
44 namespace detail {
45 using ObserveTimeStepReductionData = Parallel::ReductionData<
52  double, funcl::Plus<>,
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  noexcept {
70  ss << "Simulation time: " << std::to_string(time)
71  << "\n Wall time: " << std::to_string(min_wall_time)
72  << "s (min) - "
73  << std::to_string(max_wall_time) << "s (max)";
74  return ss.str();
75  }
76  // NOLINTNEXTLINE
77  void pup(PUP::er& /*p*/) noexcept {}
78 };
79 } // namespace detail
80 
81 /*!
82  * \brief %Observe the size of the time steps.
83  *
84  * Writes reduction quantities:
85  * - `%Time`
86  * - `NumberOfPoints`
87  * - `%Slab size`
88  * - `Minimum time step`
89  * - `Maximum time step`
90  * - `Effective time step`
91  *
92  * The effective time step is the step size of a global-time-stepping
93  * method that would perform a similar amount of work. This is the
94  * harmonic mean of the step size over all grid points:
95  *
96  * \f{equation}
97  * (\Delta t)_{\text{eff}}^{-1} =
98  * \frac{\sum_{i \in \text{points}} (\Delta t)_i^{-1}}{N_{\text{points}}}.
99  * \f}
100  *
101  * This corresponds to averaging the number of steps per unit time
102  * taken by all points.
103  *
104  * All values are reported as positive numbers, even for backwards
105  * evolutions.
106  */
107 template <typename System>
108 class ObserveTimeStep : public Event {
109  private:
110  using ReductionData = Events::detail::ObserveTimeStepReductionData;
111 
112  public:
113  /// The name of the subfile inside the HDF5 file
114  struct SubfileName {
115  using type = std::string;
116  static constexpr Options::String help = {
117  "The name of the subfile inside the HDF5 file without an extension and "
118  "without a preceding '/'."};
119  };
120 
122  using type = bool;
123  static constexpr Options::String help = {
124  "Whether to print the time to screen."};
125  };
126 
127  /// \cond
128  explicit ObserveTimeStep(CkMigrateMessage* /*unused*/) noexcept {}
129  using PUP::able::register_constructor;
131  /// \endcond
132 
133  using options = tmpl::list<SubfileName, PrintTimeToTerminal>;
134  static constexpr Options::String help =
135  "Observe the size of the time steps.\n"
136  "\n"
137  "Writes reduction quantities:\n"
138  "- Time\n"
139  "- NumberOfPoints\n"
140  "- Slab size\n"
141  "- Minimum time step\n"
142  "- Maximum time step\n"
143  "- Effective time step\n"
144  "\n"
145  "The effective time step is the step size of a global-time-stepping\n"
146  "method that would perform a similar amount of work.\n"
147  "\n"
148  "All values are reported as positive numbers, even for backwards\n"
149  "evolutions.";
150 
151  ObserveTimeStep() = default;
152  explicit ObserveTimeStep(const std::string& subfile_name,
153  const bool output_time) noexcept;
154 
155  using observed_reduction_data_tags =
156  observers::make_reduction_data_tags<tmpl::list<ReductionData>>;
157 
158  // We obtain the grid size from the variables, rather than the mesh,
159  // so that this observer is not DG-specific.
160  using argument_tags =
161  tmpl::list<Tags::Time, Tags::TimeStep, typename System::variables_tag>;
162 
163  template <typename ArrayIndex, typename ParallelComponent,
164  typename Metavariables>
165  void operator()(const double& time, const TimeDelta& time_step,
166  const typename System::variables_tag::type& variables,
168  const ArrayIndex& array_index,
169  const ParallelComponent* const /*meta*/) const noexcept {
170  const size_t number_of_grid_points = variables.number_of_grid_points();
171  const double slab_size = time_step.slab().duration().value();
172  const double step_size = abs(time_step.value());
173  const double wall_time = sys::wall_time();
174 
175  auto& local_observer =
176  *Parallel::get_parallel_component<observers::Observer<Metavariables>>(
177  cache)
178  .ckLocalBranch();
179  auto formatter =
180  output_time_ ? std::make_optional(Events::detail::FormatTimeOutput{})
181  : std::nullopt;
182  Parallel::simple_action<observers::Actions::ContributeReductionData>(
183  local_observer, observers::ObservationId(time, subfile_path_ + ".dat"),
186  Parallel::ArrayIndex<ArrayIndex>(array_index)},
187  subfile_path_,
188  std::vector<std::string>{"Time", "NumberOfPoints", "Slab size",
189  "Minimum time step", "Maximum time step",
190  "Effective time step", "Minimum Walltime",
191  "Maximum Walltime"},
192  ReductionData{time, number_of_grid_points, slab_size, step_size,
193  step_size, number_of_grid_points / step_size, wall_time,
194  wall_time},
195  std::move(formatter));
196  }
197 
198  using observation_registration_tags = tmpl::list<>;
200  get_observation_type_and_key_for_registration() const noexcept {
202  observers::ObservationKey(subfile_path_ + ".dat")};
203  }
204 
205  using is_ready_argument_tags = tmpl::list<>;
206 
207  template <typename Metavariables, typename ArrayIndex, typename Component>
208  bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/,
209  const ArrayIndex& /*array_index*/,
210  const Component* const /*meta*/) const noexcept {
211  return true;
212  }
213 
214  bool needs_evolved_variables() const noexcept override { return false; }
215 
216  // NOLINTNEXTLINE(google-runtime-references)
217  void pup(PUP::er& p) override {
218  Event::pup(p);
219  p | subfile_path_;
220  p | output_time_;
221  }
222 
223  private:
224  std::string subfile_path_;
225  bool output_time_;
226 };
227 
228 template <typename System>
229 ObserveTimeStep<System>::ObserveTimeStep(const std::string& subfile_name,
230  const bool output_time) noexcept
231  : subfile_path_("/" + subfile_name), output_time_(output_time) {}
232 
233 /// \cond
234 template <typename System>
235 PUP::able::PUP_ID ObserveTimeStep<System>::my_PUP_ID = 0; // NOLINT
236 /// \endcond
237 } // namespace Events
observers::ObservationId
A unique identifier for an observation representing the type of observation and the instance (e....
Definition: ObservationId.hpp:71
sstream
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:65
std::pair
GlobalCache.hpp
std::index_sequence
Options.hpp
vector
observers::ObservationKey
Used as a key in maps to keep track of how many elements have registered.
Definition: ObservationId.hpp:28
std::stringstream
Events::ObserveTimeStep::SubfileName
The name of the subfile inside the HDF5 file.
Definition: ObserveTimeStep.hpp:114
cmath
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:19
cstddef
funcl::Plus
Functional for computing + of two objects.
Definition: Functional.hpp:238
TimeDelta
Definition: Time.hpp:88
Time.hpp
sys::wall_time
double wall_time()
The elapsed wall time in seconds.
Definition: ParallelInfo.hpp:94
ActionTesting::cache
Parallel::GlobalCache< Metavariables > & cache(MockRuntimeSystem< Metavariables > &runner, const ArrayIndex &array_index) noexcept
Returns the GlobalCache of Component with index array_index.
Definition: MockRuntimeSystemFreeFunctions.hpp:382
PhaseControl::reduction_data
Parallel::ReductionData< Parallel::ReductionDatum< tuples::tagged_tuple_from_typelist< TagsAndCombinesPresent >, TaggedTupleCombine > > reduction_data
A Parallel::ReductionData with a single Parallel::ReductionDatum for a given tagged tuple type determ...
Definition: PhaseControlReductionHelpers.hpp:83
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
Events::ObserveTimeStep::PrintTimeToTerminal
Definition: ObserveTimeStep.hpp:121
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:108
std::time
T time(T... args)
Parallel::ArrayIndex
The array index used for indexing Chare Arrays, mostly an implementation detail.
Definition: ArrayIndex.hpp:28
Events::ObserveTimeStep::needs_evolved_variables
bool needs_evolved_variables() const noexcept override
Whether the event uses anything depending on the evolved_variables. If this returns false,...
Definition: ObserveTimeStep.hpp:214
tt::ConformsTo
Indicate a class conforms to the Protocol.
Definition: ProtocolHelpers.hpp:22
type_traits
TMPL.hpp
string