TimeStepper.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <cstdint>
8 #include <pup.h>
9 #include <type_traits>
10 
12 #include "Time/TimeId.hpp"
13 #include "Utilities/FakeVirtual.hpp"
14 #include "Utilities/Gsl.hpp"
15 #include "Utilities/TMPL.hpp"
16 
17 /// \cond
18 class TimeDelta;
19 namespace TimeSteppers {
20 class AdamsBashforthN; // IWYU pragma: keep
21 template <typename LocalVars, typename RemoteVars, typename CouplingResult>
22 class BoundaryHistory;
23 template <typename Vars, typename DerivVars>
24 class History;
25 } // namespace TimeSteppers
26 /// \endcond
27 
28 /// \ingroup TimeSteppersGroup
29 ///
30 /// Holds classes that take time steps.
31 namespace TimeSteppers {
32 class AdamsBashforthN; // IWYU pragma: keep
33 class RungeKutta3; // IWYU pragma: keep
34 } // namespace TimeSteppers
35 
36 namespace TimeStepper_detail {
37 DEFINE_FAKE_VIRTUAL(dense_update_u)
38 DEFINE_FAKE_VIRTUAL(update_u)
39 } // namespace TimeStepper_detail
40 
41 /// \ingroup TimeSteppersGroup
42 ///
43 /// Abstract base class for TimeSteppers.
44 class TimeStepper : public PUP::able {
45  public:
46  using Inherit = TimeStepper_detail::FakeVirtualInherit_dense_update_u<
47  TimeStepper_detail::FakeVirtualInherit_update_u<TimeStepper>>;
48  using creatable_classes =
49  tmpl::list<TimeSteppers::AdamsBashforthN, TimeSteppers::RungeKutta3>;
50 
52 
53  /// Add the change for the current substep to u.
54  template <typename Vars, typename DerivVars>
55  void update_u(
56  const gsl::not_null<Vars*> u,
58  const TimeDelta& time_step) const noexcept {
59  return TimeStepper_detail::fake_virtual_update_u<creatable_classes>(
60  this, u, history, time_step);
61  }
62 
63  /// Compute the solution value at a time between steps. To evaluate
64  /// at a time within a given step, this must be called before the
65  /// step is completed but after any intermediate substeps have been
66  /// taken. The value of `*u` before this function is called should
67  /// be the value at the last substep.
68  template <typename Vars, typename DerivVars>
71  const double time) const noexcept {
72  return TimeStepper_detail::fake_virtual_dense_update_u<creatable_classes>(
73  this, u, history, time);
74  }
75 
76  /// Number of substeps in this TimeStepper
77  virtual uint64_t number_of_substeps() const noexcept = 0;
78 
79  /// Number of past time steps needed for multi-step method
80  virtual size_t number_of_past_steps() const noexcept = 0;
81 
82  /// Rough estimate of the maximum step size this method can take
83  /// stably as a multiple of the step for Euler's method.
84  virtual double stable_step() const noexcept = 0;
85 
86  /// The TimeId after the current substep
87  virtual TimeId next_time_id(const TimeId& current_id,
88  const TimeDelta& time_step) const noexcept = 0;
89 };
90 
91 // LtsTimeStepper cannot be split out into its own file because the
92 // LtsTimeStepper -> TimeStepper -> AdamsBashforthN -> LtsTimeStepper
93 // include loop causes AdamsBashforthN to be defined before its base
94 // class if LtsTimeStepper is included first.
95 namespace LtsTimeStepper_detail {
96 DEFINE_FAKE_VIRTUAL(boundary_dense_output)
97 DEFINE_FAKE_VIRTUAL(can_change_step_size)
98 DEFINE_FAKE_VIRTUAL(compute_boundary_delta)
99 } // namespace LtsTimeStepper_detail
100 
101 /// \ingroup TimeSteppersGroup
102 ///
103 /// Base class for TimeSteppers with local time-stepping support,
104 /// derived from TimeStepper.
105 class LtsTimeStepper : public TimeStepper::Inherit {
106  public:
107  using Inherit =
108  LtsTimeStepper_detail::FakeVirtualInherit_boundary_dense_output<
109  LtsTimeStepper_detail::FakeVirtualInherit_can_change_step_size<
110  LtsTimeStepper_detail::FakeVirtualInherit_compute_boundary_delta<
111  LtsTimeStepper>>>;
112  // When you add a class here, remember to add it to TimeStepper as well.
113  using creatable_classes = tmpl::list<TimeSteppers::AdamsBashforthN>;
114 
115  WRAPPED_PUPable_abstract(LtsTimeStepper); // NOLINT
116 
117  /// \brief Compute the change in a boundary quantity due to the
118  /// coupling on the interface.
119  ///
120  /// The coupling function `coupling` should take the local and
121  /// remote flux data and compute the derivative of the boundary
122  /// quantity. These values may be used to form a linear combination
123  /// internally, so the result should have appropriate mathematical
124  /// operators defined to allow that.
125  template <typename LocalVars, typename RemoteVars, typename Coupling>
128  const Coupling& coupling,
130  LocalVars, RemoteVars,
131  std::result_of_t<const Coupling&(LocalVars, RemoteVars)>>*>
132  history,
133  const TimeDelta& time_step) const noexcept {
134  return LtsTimeStepper_detail::fake_virtual_compute_boundary_delta<
135  creatable_classes>(this, coupling, history, time_step);
136  }
137 
138  template <typename LocalVars, typename RemoteVars, typename Coupling>
140  boundary_dense_output(
141  const Coupling& coupling,
143  LocalVars, RemoteVars,
144  std::result_of_t<const Coupling&(LocalVars, RemoteVars)>>& history,
145  const double time) const noexcept {
146  return LtsTimeStepper_detail::fake_virtual_boundary_dense_output<
147  creatable_classes>(this, coupling, history, time);
148  }
149 
150  /// Substep LTS integrators are not supported, so this is always 1.
151  uint64_t number_of_substeps() const noexcept final { return 1; }
152 
153  /// Whether a local change in the step size is allowed before taking
154  /// a step. This should be called after the history has been
155  /// updated with the current time derivative. This does not control
156  /// global step size changes, which are always allowed at slab
157  /// boundaries.
158  template <typename Vars, typename DerivVars>
160  const TimeId& time_id,
161  const TimeSteppers::History<Vars, DerivVars>& history) const noexcept {
162  return LtsTimeStepper_detail::fake_virtual_can_change_step_size<
163  creatable_classes>(this, time_id, history);
164  }
165 
166  /// \cond
167  // FakeVirtual forces derived classes to override the fake virtual
168  // methods. Here the base class method is actually what we want
169  // because we are not a most-derived class, so we forward to the
170  // TimeStepper version.
171  template <typename Vars, typename DerivVars>
172  void update_u(
173  const gsl::not_null<Vars*> u,
175  const TimeDelta& time_step) const noexcept {
176  return TimeStepper::update_u(u, history, time_step);
177  }
178  /// \endcond
179 };
180 
181 
182 #include "Time/TimeSteppers/AdamsBashforthN.hpp" // IWYU pragma: keep
183 #include "Time/TimeSteppers/RungeKutta3.hpp" // IWYU pragma: keep
std::result_of_t< const Coupling &(LocalVars, RemoteVars)> compute_boundary_delta(const Coupling &coupling, const gsl::not_null< TimeSteppers::BoundaryHistory< LocalVars, RemoteVars, std::result_of_t< const Coupling &(LocalVars, RemoteVars)>> *> history, const TimeDelta &time_step) const noexcept
Compute the change in a boundary quantity due to the coupling on the interface.
Definition: TimeStepper.hpp:127
Abstract base class for TimeSteppers.
Definition: TimeStepper.hpp:44
A unique identifier for the temporal state of an integrated system.
Definition: TimeId.hpp:25
Defines macros to allow serialization of abstract template base classes.
Defines class TimeId.
uint64_t number_of_substeps() const noexcept final
Substep LTS integrators are not supported, so this is always 1.
Definition: TimeStepper.hpp:151
Base class for TimeSteppers with local time-stepping support, derived from TimeStepper.
Definition: TimeStepper.hpp:105
Definition: TimeStepper.hpp:95
History data used by a TimeStepper.
Definition: History.hpp:25
History data used by a TimeStepper for boundary integration.
Definition: BoundaryHistory.hpp:31
Defines class RungeKutta3.
Represents an interval of time within a single slab.
Definition: Time.hpp:108
void 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:69
bool can_change_step_size(const TimeId &time_id, const TimeSteppers::History< Vars, DerivVars > &history) const noexcept
Whether a local change in the step size is allowed before taking a step. This should be called after ...
Definition: TimeStepper.hpp:159
Defines class AdamsBashforthN.
#define WRAPPED_PUPable_abstract(className)
Wraps the Charm++ macro, see the Charm++ documentation.
Definition: CharmPupable.hpp:39
Wraps the template metaprogramming library used (brigand)
Defines functions and classes from the GSL.
void update_u(const gsl::not_null< Vars *> u, const gsl::not_null< TimeSteppers::History< Vars, DerivVars > *> history, const TimeDelta &time_step) const noexcept
Add the change for the current substep to u.
Definition: TimeStepper.hpp:55
Holds classes that take time steps.
Definition: BoundaryHistory.hpp:23
Definition: TimeStepper.hpp:36
#define DEFINE_FAKE_VIRTUAL(function)
Define a function that acts similarly to a virtual function, but can take template parameters...
Definition: FakeVirtual.hpp:50
Require a pointer to not be a nullptr
Definition: ConservativeFromPrimitive.hpp:12