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 : template <typename Tag> 20 : struct Next; 21 : struct TimeStep; 22 : struct TimeStepId; 23 : template <typename StepperInterface> 24 : struct TimeStepper; 25 : } // namespace Tags 26 : class TimeStepper; 27 : /// \endcond 28 : 29 : /// \ingroup TimeGroup 30 : /// Change the slab size, updating all quantities in the DataBox 31 : /// depending on it. 32 : /// 33 : /// The end of the slab (in the appropriate direction for the 34 : /// evolution's flow of time) will be set to \p new_slab_end. The 35 : /// time step is set to the same fraction of the new slab as it was of 36 : /// the old. 37 : template <typename DbTags> 38 1 : void change_slab_size(const gsl::not_null<db::DataBox<DbTags>*> box, 39 : const double new_slab_end) { 40 : const TimeStepId& old_time_step_id = db::get<Tags::TimeStepId>(*box); 41 : 42 : ASSERT(old_time_step_id.is_at_slab_boundary(), 43 : "Cannot change slab size in middle of slab: " << old_time_step_id); 44 : 45 : const Slab old_slab = old_time_step_id.step_time().slab(); 46 : const double old_slab_end = old_time_step_id.time_runs_forward() 47 : ? old_slab.end().value() 48 : : old_slab.start().value(); 49 : 50 : if (new_slab_end == old_slab_end) { 51 : return; 52 : } 53 : 54 : const TimeDelta& old_time_step = db::get<Tags::TimeStep>(*box); 55 : 56 : const Slab new_slab = old_time_step_id.time_runs_forward() 57 : ? Slab(old_slab.start().value(), new_slab_end) 58 : : Slab(new_slab_end, old_slab.end().value()); 59 : // We are at a slab boundary, so the substep is 0. 60 : const TimeStepId new_time_step_id( 61 : old_time_step_id.time_runs_forward(), old_time_step_id.slab_number(), 62 : old_time_step_id.step_time().with_slab(new_slab)); 63 : const auto new_time_step = old_time_step.with_slab(new_slab); 64 : 65 : const auto new_next_time_step_id = 66 : db::get<Tags::TimeStepper<TimeStepper>>(*box).next_time_id( 67 : new_time_step_id, new_time_step); 68 : 69 : db::mutate_apply< 70 : tmpl::push_front<Tags::get_all_history_tags<DbTags>, 71 : ::Tags::Next<::Tags::TimeStepId>, ::Tags::TimeStep, 72 : ::Tags::Next<::Tags::TimeStep>, ::Tags::TimeStepId, 73 : ::Tags::AdaptiveSteppingDiagnostics>, 74 : tmpl::list<>>( 75 : [&new_next_time_step_id, &new_time_step, &new_time_step_id]( 76 : const gsl::not_null<TimeStepId*> next_time_step_id, 77 : const gsl::not_null<TimeDelta*> time_step, 78 : const gsl::not_null<TimeDelta*> next_time_step, 79 : const gsl::not_null<TimeStepId*> local_time_step_id, 80 : const gsl::not_null<AdaptiveSteppingDiagnostics*> diags, 81 : const auto... histories) { 82 : const auto update_history = [&](const auto history) { 83 : if (not history->empty() and 84 : history->back().time_step_id == *local_time_step_id) { 85 : ASSERT(history->at_step_start(), 86 : "Cannot change step size with substep data."); 87 : history->back().time_step_id = new_time_step_id; 88 : } 89 : return 0; 90 : }; 91 : expand_pack(update_history(histories)...); 92 : 93 : *next_time_step_id = new_next_time_step_id; 94 : *time_step = new_time_step; 95 : *next_time_step = new_time_step; 96 : *local_time_step_id = new_time_step_id; 97 : ++diags->number_of_slab_size_changes; 98 : }, 99 : box); 100 : }