Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include "DataStructures/DataBox/DataBox.hpp" 7 : #include "Time/AdaptiveSteppingDiagnostics.hpp" 8 : #include "Time/Slab.hpp" 9 : #include "Time/Tags/HistoryEvolvedVariables.hpp" 10 : #include "Time/Time.hpp" 11 : #include "Time/TimeStepId.hpp" 12 : #include "Utilities/ErrorHandling/Assert.hpp" 13 : #include "Utilities/Gsl.hpp" 14 : #include "Utilities/TMPL.hpp" 15 : 16 : /// \cond 17 : namespace Tags { 18 : struct AdaptiveSteppingDiagnostics; 19 : struct MinimumTimeStep; 20 : template <typename Tag> 21 : struct Next; 22 : struct TimeStep; 23 : struct TimeStepId; 24 : template <typename StepperInterface> 25 : struct TimeStepper; 26 : } // namespace Tags 27 : class TimeStepper; 28 : /// \endcond 29 : 30 : /// \ingroup TimeGroup 31 : /// Change the slab size, updating all quantities in the DataBox 32 : /// depending on it. 33 : /// 34 : /// The end of the slab (in the appropriate direction for the 35 : /// evolution's flow of time) will be set to \p new_slab_end. The 36 : /// time step is set to the same fraction of the new slab as it was of 37 : /// the old. 38 : template <typename DbTags> 39 1 : void change_slab_size(const gsl::not_null<db::DataBox<DbTags>*> box, 40 : const double new_slab_end) { 41 : const TimeStepId& old_time_step_id = db::get<Tags::TimeStepId>(*box); 42 : 43 : ASSERT(old_time_step_id.is_at_slab_boundary(), 44 : "Cannot change slab size in middle of slab: " << old_time_step_id); 45 : 46 : const Slab old_slab = old_time_step_id.step_time().slab(); 47 : const double old_slab_end = old_time_step_id.time_runs_forward() 48 : ? old_slab.end().value() 49 : : old_slab.start().value(); 50 : 51 : if (new_slab_end == old_slab_end) { 52 : return; 53 : } 54 : 55 : const TimeDelta& old_time_step = db::get<Tags::TimeStep>(*box); 56 : 57 : const Slab new_slab = old_time_step_id.time_runs_forward() 58 : ? Slab(old_slab.start().value(), new_slab_end) 59 : : Slab(new_slab_end, old_slab.end().value()); 60 : // We are at a slab boundary, so the substep is 0. 61 : const TimeStepId new_time_step_id( 62 : old_time_step_id.time_runs_forward(), old_time_step_id.slab_number(), 63 : old_time_step_id.step_time().with_slab(new_slab)); 64 : const auto new_time_step = old_time_step.with_slab(new_slab); 65 : 66 : if (std::abs(new_time_step.value()) < 67 : db::get<::Tags::MinimumTimeStep>(*box)) { 68 : ERROR_NO_TRACE( 69 : "Chosen step size " 70 : << new_time_step.value() << " is smaller than the MinimumTimeStep of " 71 : << db::get<::Tags::MinimumTimeStep>(*box) 72 : << " while changing the slab size to " << new_slab.duration().value() 73 : << ".\n" 74 : "\n" 75 : "This can indicate a flaw in the step chooser, the grid, or a " 76 : "simulation instability that an error-based stepper is naively " 77 : "attempting to resolve. A possible issue is an aliasing-driven " 78 : "instability that could be cured by more aggressive filtering if " 79 : "you are using DG."); 80 : } 81 : 82 : const auto new_next_time_step_id = 83 : db::get<Tags::TimeStepper<TimeStepper>>(*box).next_time_id( 84 : new_time_step_id, new_time_step); 85 : 86 : db::mutate_apply< 87 : tmpl::push_front<Tags::get_all_history_tags<DbTags>, 88 : ::Tags::Next<::Tags::TimeStepId>, ::Tags::TimeStep, 89 : ::Tags::TimeStepId, ::Tags::AdaptiveSteppingDiagnostics>, 90 : tmpl::list<>>( 91 : [&new_next_time_step_id, &new_time_step, &new_time_step_id]( 92 : const gsl::not_null<TimeStepId*> next_time_step_id, 93 : const gsl::not_null<TimeDelta*> time_step, 94 : const gsl::not_null<TimeStepId*> local_time_step_id, 95 : const gsl::not_null<AdaptiveSteppingDiagnostics*> diags, 96 : const auto... histories) { 97 : const auto update_history = [&](const auto history) { 98 : if (not history->empty() and 99 : history->back().time_step_id == *local_time_step_id) { 100 : ASSERT(history->at_step_start(), 101 : "Cannot change step size with substep data."); 102 : history->back().time_step_id = new_time_step_id; 103 : } 104 : return 0; 105 : }; 106 : expand_pack(update_history(histories)...); 107 : 108 : *next_time_step_id = new_next_time_step_id; 109 : *time_step = new_time_step; 110 : *local_time_step_id = new_time_step_id; 111 : ++diags->number_of_slab_size_changes; 112 : }, 113 : box); 114 : }