RunEventsAndDenseTriggers.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <tuple>
8 
10 #include "Evolution/EventsAndDenseTriggers/EventsAndDenseTriggers.hpp"
11 #include "Evolution/EventsAndDenseTriggers/Tags.hpp"
12 #include "Parallel/AlgorithmMetafunctions.hpp"
13 #include "Time/EvolutionOrdering.hpp"
14 #include "Time/Tags.hpp"
15 #include "Time/TimeSteppers/TimeStepper.hpp"
16 #include "Utilities/Gsl.hpp"
17 #include "Utilities/TMPL.hpp"
18 #include "Utilities/TaggedTuple.hpp"
19 
20 /// \cond
21 namespace Parallel {
22 template <typename Metavariables>
23 class GlobalCache;
24 } // namespace Parallel
25 namespace Tags {
26 struct TimeStep;
27 } // namespace Tags
28 /// \endcond
29 
30 namespace evolution::Actions {
31 /// \ingroup ActionsGroup
32 /// \ingroup EventsAndTriggersGroup
33 /// \brief Run the events and dense triggers
34 ///
35 /// Uses:
36 /// - DataBox: EventsAndDenseTriggers, as required by events and triggers
37 ///
38 /// DataBox changes:
39 /// - Adds: nothing
40 /// - Removes: nothing
41 /// - Modifies: nothing
42 template <typename PrimFromCon = void>
44  template <typename DbTags, typename... InboxTags, typename Metavariables,
45  typename ArrayIndex, typename ActionList,
46  typename ParallelComponent>
48  db::DataBox<DbTags>& box,
51  const ArrayIndex& array_index, const ActionList /*meta*/,
52  const ParallelComponent* const component) noexcept {
53  const auto& time_step_id = db::get<::Tags::TimeStepId>(box);
54  if (time_step_id.slab_number() < 0) {
55  // Skip dense output during self-start
56  return {std::move(box), Parallel::AlgorithmExecution::Continue};
57  }
58 
59  auto& events_and_dense_triggers =
60  db::get_mutable_reference<::evolution::Tags::EventsAndDenseTriggers>(
61  make_not_null(&box));
62 
63  const auto step_end =
64  time_step_id.step_time() + db::get<::Tags::TimeStep>(box);
65  const evolution_less<double> before{time_step_id.time_runs_forward()};
66 
67  for (;;) {
68  const double next_trigger = events_and_dense_triggers.next_trigger(box);
69  if (before(step_end.value(), next_trigger)) {
70  return {std::move(box), Parallel::AlgorithmExecution::Continue};
71  }
72 
73  if (db::get<::Tags::Time>(box) != next_trigger) {
74  db::mutate<::Tags::Time>(
75  make_not_null(&box),
76  [&next_trigger](const gsl::not_null<double*> time) noexcept {
77  *time = next_trigger;
78  });
79  }
80 
81  const auto triggered = events_and_dense_triggers.is_ready(
82  box, cache, array_index, component);
83  using TriggeringState = std::decay_t<decltype(triggered)>;
84  switch (triggered) {
85  case TriggeringState::NotReady:
86  return {std::move(box), Parallel::AlgorithmExecution::Retry};
87  case TriggeringState::NeedsEvolvedVariables:
88  {
89  using variables_tag = typename Metavariables::system::variables_tag;
91  bool dense_output_succeeded = false;
92  db::mutate<variables_tag>(
93  make_not_null(&box),
94  [&dense_output_succeeded, &next_trigger](
96  const TimeStepper& stepper,
97  const typename history_tag::type& history) noexcept {
98  dense_output_succeeded =
99  stepper.dense_update_u(vars, history, next_trigger);
100  },
101  db::get<::Tags::TimeStepper<>>(box), db::get<history_tag>(box));
102  if (not dense_output_succeeded) {
103  // With LTS, we may need to wait for neighbor data
104  // rather than take another step.
105  static_assert(not Metavariables::local_time_stepping,
106  "LTS support for RunDenseEventsAndTriggers is not "
107  "implemented.");
108 
109  // Need to take another time step
110  return {std::move(box), Parallel::AlgorithmExecution::Continue};
111  }
112 
113  static_assert(
114  Metavariables::system::has_primitive_and_conservative_vars !=
115  std::is_same_v<PrimFromCon, void>,
116  "Primitive update scheme not provided.");
117  if constexpr (
118  Metavariables::system::has_primitive_and_conservative_vars) {
119  db::mutate_apply<PrimFromCon>(make_not_null(&box));
120  }
121  }
122  [[fallthrough]];
123  default:
124  break;
125  }
126 
127  events_and_dense_triggers.run_events(box, cache, array_index, component);
128  }
129  }
130 };
131 
133  using initialization_tags =
134  tmpl::list<evolution::Tags::EventsAndDenseTriggers>;
135  using initialization_tags_to_keep = initialization_tags;
136 
137  template <typename DbTags, typename... InboxTags, typename Metavariables,
138  typename ArrayIndex, typename ActionList,
139  typename ParallelComponent>
140  static auto apply(db::DataBox<DbTags>& box,
143  const ArrayIndex& /*array_index*/,
144  const ActionList /*meta*/,
145  const ParallelComponent* const /*component*/) noexcept {
146  return std::forward_as_tuple(std::move(box));
147  }
148 };
149 } // namespace evolution::Actions
Parallel::AlgorithmExecution::Retry
@ Retry
Temporarily stop executing iterable actions, but try the same action again after receiving data from ...
evolution::Actions::RunEventsAndDenseTriggers
Run the events and dense triggers.
Definition: RunEventsAndDenseTriggers.hpp:43
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:15
evolution_comparator
Definition: EvolutionOrdering.hpp:20
tuple
Parallel::AlgorithmExecution::Continue
@ Continue
Leave the algorithm termination flag in its current state.
DataBox.hpp
cstddef
TimeStepper
Definition: TimeStepper.hpp:47
evolution::Actions::InitializeRunEventsAndDenseTriggers
Definition: RunEventsAndDenseTriggers.hpp:132
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
Parallel::AlgorithmExecution
AlgorithmExecution
The possible options for altering the current execution of the algorithm, used in the return type of ...
Definition: AlgorithmMetafunctions.hpp:31
std::decay_t
TimeStepper::dense_update_u
bool dense_update_u(const gsl::not_null< Vars * > u, const TimeSteppers::History< Vars, DerivVars > &history, const double time) const noexcept
Compute the solution value at a time between steps. To evaluate at a time within a given step,...
Definition: TimeStepper.hpp:91
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
Gsl.hpp
make_not_null
gsl::not_null< T * > make_not_null(T *ptr) noexcept
Construct a not_null from a pointer. Often this will be done as an implicit conversion,...
Definition: Gsl.hpp:880
Tags::HistoryEvolvedVariables
Definition: Tags.hpp:85
Parallel
Functionality for parallelization.
Definition: ElementReceiveInterpPoints.hpp:13
TMPL.hpp
gsl::not_null
Require a pointer to not be a nullptr
Definition: ReadSpecPiecewisePolynomial.hpp:13