55
66#include < algorithm>
77#include < cmath>
8- #include < cstdint>
98#include < limits>
10- #include < memory>
11- #include < optional>
129#include < pup.h>
1310#include < string>
1411#include < type_traits>
15- #include < vector>
12+ #include < typeindex>
13+ #include < typeinfo>
14+ #include < unordered_map>
1615
17- #include " DataStructures/DataBox/DataBoxTag.hpp"
18- #include " DataStructures/TaggedVariant.hpp"
1916#include " Options/String.hpp"
20- #include " ParallelAlgorithms/EventsAndTriggers/EventsAndTriggers.hpp"
21- #include " ParallelAlgorithms/EventsAndTriggers/WhenToCheck.hpp"
22- #include " Time/ChangeSlabSize/Event.hpp"
17+ #include " Time/RequestsStepperErrorTolerances.hpp"
2318#include " Time/StepChoosers/StepChooser.hpp"
2419#include " Time/StepperErrorTolerances.hpp"
25- #include " Time/Tags/IsUsingTimeSteppingErrorControl.hpp"
26- #include " Time/Tags/StepperErrorTolerances.hpp"
20+ #include " Time/Tags/StepperErrorTolerancesCompute.hpp"
2721#include " Time/Tags/StepperErrors.hpp"
2822#include " Time/TimeStepRequest.hpp"
29- #include " Time/TimeSteppers/TimeStepper.hpp"
30- #include " Time/VariableOrderAlgorithm.hpp"
31- #include " Utilities/ErrorHandling/Assert.hpp"
32- #include " Utilities/ErrorHandling/Error.hpp"
33- #include " Utilities/Gsl.hpp"
3423#include " Utilities/Serialization/CharmPupable.hpp"
3524#include " Utilities/TMPL.hpp"
3625
3726// / \cond
38- namespace Tags {
39- template <Triggers::WhenToCheck WhenToCheck>
40- struct EventsAndTriggers ;
41- template <bool LocalTimeStepping>
42- struct IsUsingTimeSteppingErrorControlCompute ;
43- struct StepChoosers ;
44- template <typename EvolvedVariableTag, bool LocalTimeStepping>
45- struct StepperErrorTolerancesCompute ;
46- template <typename StepperInterface>
47- struct TimeStepper ;
48- struct VariableOrderAlgorithm ;
49- } // namespace Tags
27+ struct NoSuchType ;
5028// / \endcond
5129
5230namespace StepChoosers {
53- namespace ErrorControl_detail {
54- struct IsAnErrorControl {};
55- template <typename EvolvedVariableTag>
56- struct ErrorControlBase : IsAnErrorControl {
57- public:
58- virtual StepperErrorTolerances tolerances () const = 0;
59-
60- protected:
61- ErrorControlBase () = default ;
62- ~ErrorControlBase () = default ;
63- };
64- } // namespace ErrorControl_detail
65-
6631/* !
6732 * \brief Sets a goal based on time-stepper truncation error.
6833 *
@@ -133,9 +98,8 @@ struct ErrorControlBase : IsAnErrorControl {
13398 */
13499template <typename StepChooserUse, typename EvolvedVariableTag,
135100 typename ErrorControlSelector = NoSuchType>
136- class ErrorControl
137- : public StepChooser<StepChooserUse>,
138- public ErrorControl_detail::ErrorControlBase<EvolvedVariableTag> {
101+ class ErrorControl : public StepChooser <StepChooserUse>,
102+ public RequestsStepperErrorTolerances {
139103 public:
140104 // / \cond
141105 ErrorControl () = default ;
@@ -204,7 +168,7 @@ class ErrorControl
204168 using simple_tags = tmpl::list<::Tags::StepperErrors<EvolvedVariableTag>>;
205169
206170 using compute_tags = tmpl::list<
207- Tags::IsUsingTimeSteppingErrorControlCompute <
171+ Tags::StepperErrorEstimatesEnabledCompute <
208172 std::is_same_v<StepChooserUse, ::StepChooserUse::LtsStep>>,
209173 Tags::StepperErrorTolerancesCompute<
210174 EvolvedVariableTag,
@@ -249,10 +213,12 @@ class ErrorControl
249213 bool uses_local_data () const override { return true ; }
250214 bool can_be_delayed () const override { return true ; }
251215
252- StepperErrorTolerances tolerances () const override {
253- return {.estimates = StepperErrorTolerances::Estimates::StepperOrder,
254- .absolute = absolute_tolerance_,
255- .relative = relative_tolerance_};
216+ std::unordered_map<std::type_index, StepperErrorTolerances> tolerances ()
217+ const override {
218+ return {{typeid (EvolvedVariableTag),
219+ {.estimates = StepperErrorTolerances::Estimates::StepperOrder,
220+ .absolute = absolute_tolerance_,
221+ .relative = relative_tolerance_}}};
256222 }
257223
258224 void pup (PUP::er& p) override { // NOLINT
@@ -278,146 +244,3 @@ PUP::able::PUP_ID ErrorControl<StepChooserUse, EvolvedVariableTag,
278244 ErrorControlSelector>::my_PUP_ID = 0 ; // NOLINT
279245// / \endcond
280246} // namespace StepChoosers
281-
282- namespace Tags {
283- // / \ingroup TimeGroup
284- // / \brief A tag that is true if the `ErrorControl` step chooser is one of the
285- // / option-created `Event`s.
286- template <bool LocalTimeStepping>
287- struct IsUsingTimeSteppingErrorControlCompute
288- : db::ComputeTag,
289- IsUsingTimeSteppingErrorControl {
290- using base = IsUsingTimeSteppingErrorControl;
291- using return_type = type;
292- using argument_tags = tmpl::conditional_t <
293- LocalTimeStepping, tmpl::list<::Tags::StepChoosers>,
294- tmpl::list<::Tags::EventsAndTriggers<Triggers::WhenToCheck::AtSlabs>>>;
295-
296- // local time stepping
297- static void function (
298- const gsl::not_null<bool *> is_using_error_control,
299- const std::vector<
300- std::unique_ptr<::StepChooser<StepChooserUse::LtsStep>>>&
301- step_choosers) {
302- *is_using_error_control = false ;
303- for (const auto & step_chooser : step_choosers) {
304- if (dynamic_cast <
305- const ::StepChoosers::ErrorControl_detail::IsAnErrorControl*>(
306- &*step_chooser) != nullptr ) {
307- *is_using_error_control = true ;
308- return ;
309- }
310- }
311- }
312-
313- // global time stepping
314- static void function (const gsl::not_null<bool *> is_using_error_control,
315- const ::EventsAndTriggers& events_and_triggers) {
316- // In principle the slab size could be changed based on a dense
317- // trigger, but it's not clear that there is ever a good reason to
318- // do so, and it wouldn't make sense to use error control in that
319- // context in any case.
320- *is_using_error_control = false ;
321- events_and_triggers.for_each_event ([&](const auto & event) {
322- if (*is_using_error_control) {
323- return ;
324- }
325- if (const auto * const change_slab_size =
326- dynamic_cast <const ::Events::ChangeSlabSize*>(&event)) {
327- change_slab_size->for_each_step_chooser (
328- [&](const StepChooser<StepChooserUse::Slab>& step_chooser) {
329- if (*is_using_error_control) {
330- return ;
331- }
332- if (dynamic_cast <const ::StepChoosers::ErrorControl_detail::
333- IsAnErrorControl*>(&step_chooser) !=
334- nullptr ) {
335- *is_using_error_control = true ;
336- }
337- });
338- }
339- });
340- }
341- };
342-
343- // / \ingroup TimeGroup
344- // / \brief A tag that contains the error tolerances if the
345- // / `ErrorControl` step chooser is one of the option-created `Event`s.
346- template <typename EvolvedVariableTag, bool LocalTimeStepping>
347- struct StepperErrorTolerancesCompute
348- : db::ComputeTag,
349- StepperErrorTolerances<EvolvedVariableTag> {
350- using base = StepperErrorTolerances<EvolvedVariableTag>;
351- using return_type = typename base::type;
352- using argument_tags = tmpl::conditional_t <
353- LocalTimeStepping,
354- tmpl::list<::Tags::StepChoosers, ::Tags::TimeStepper<::TimeStepper>,
355- ::Tags::VariableOrderAlgorithm>,
356- tmpl::list<::Tags::EventsAndTriggers<Triggers::WhenToCheck::AtSlabs>>>;
357-
358- // local time stepping
359- static void function (
360- const gsl::not_null<::StepperErrorTolerances*> tolerances,
361- const std::vector<
362- std::unique_ptr<::StepChooser<StepChooserUse::LtsStep>>>&
363- step_choosers,
364- const ::TimeStepper& time_stepper,
365- const ::VariableOrderAlgorithm& variable_order_algorithm) {
366- *tolerances = ::StepperErrorTolerances{};
367- for (const auto & step_chooser : step_choosers) {
368- set_tolerances_if_error_control (tolerances, *step_chooser);
369- }
370- // Error-based variable-order requires some variable to be
371- // controlled using error control, but in a split-variable system
372- // a different variable might be controlled, so no control on this
373- // variable is not an error.
374- if (tolerances->estimates != ::StepperErrorTolerances::Estimates::None and
375- variants::holds_alternative<TimeSteppers::Tags::VariableOrder>(
376- time_stepper.order ())) {
377- tolerances->estimates = std::max (
378- tolerances->estimates , variable_order_algorithm.required_estimates ());
379- }
380- }
381-
382- // global time stepping
383- static void function (
384- const gsl::not_null<::StepperErrorTolerances*> tolerances,
385- const ::EventsAndTriggers& events_and_triggers) {
386- *tolerances = ::StepperErrorTolerances{};
387- // In principle the slab size could be changed based on a dense
388- // trigger, but it's not clear that there is ever a good reason to
389- // do so, and it wouldn't make sense to use error control in that
390- // context in any case.
391- events_and_triggers.for_each_event ([&](const auto & event) {
392- if (const auto * const change_slab_size =
393- dynamic_cast <const ::Events::ChangeSlabSize*>(&event)) {
394- change_slab_size->for_each_step_chooser (
395- [&](const StepChooser<StepChooserUse::Slab>& step_chooser) {
396- set_tolerances_if_error_control (tolerances, step_chooser);
397- });
398- }
399- });
400- }
401-
402- private:
403- template <typename StepChooserUse>
404- static void set_tolerances_if_error_control (
405- const gsl::not_null<::StepperErrorTolerances*> tolerances,
406- const StepChooser<StepChooserUse>& step_chooser) {
407- if (const auto * const error_control =
408- dynamic_cast <const ::StepChoosers::ErrorControl_detail::
409- ErrorControlBase<EvolvedVariableTag>*>(
410- &step_chooser);
411- error_control != nullptr ) {
412- const auto this_tolerances = error_control->tolerances ();
413- if (tolerances->estimates != ::StepperErrorTolerances::Estimates::None and
414- *tolerances != this_tolerances) {
415- ERROR_NO_TRACE (" All ErrorControl events for "
416- << db::tag_name<EvolvedVariableTag>()
417- << " must use the same tolerances." );
418- }
419- *tolerances = this_tolerances;
420- }
421- }
422- };
423- } // namespace Tags
0 commit comments