@@ -155,13 +155,6 @@ void apply_coefficients(const gsl::not_null<T*> result,
155155 }
156156}
157157
158- bool operator ==(const AdamsScheme& a, const AdamsScheme& b) {
159- return a.type == b.type and a.order == b.order ;
160- }
161- bool operator !=(const AdamsScheme& a, const AdamsScheme& b) {
162- return not (a == b);
163- }
164-
165158namespace {
166159// Collect the ids used for interpolating during a step to `end_time`
167160// from `times`.
@@ -171,29 +164,33 @@ namespace {
171164template <typename TimeType>
172165OrderVector<TimeStepId> find_relevant_ids (
173166 const ConstBoundaryHistoryTimes& times, const TimeType& end_time,
174- const AdamsScheme& scheme ) {
167+ const SchemeType scheme_type, const int order_offset ) {
175168 OrderVector<TimeStepId> ids{};
176169 using difference_type = std::iterator_traits<
177170 ConstBoundaryHistoryTimes::const_iterator>::difference_type;
178171 const evolution_less<> less{times.front ().time_runs_forward ()};
179172 // Can't do a binary search because times are not sorted during self-start.
180173 auto used_range_end = times.end ();
181- while (used_range_end != times.begin ()) {
174+ for (;;) {
175+ ASSERT (used_range_end != times.begin (),
176+ " All times in history were after " << end_time);
182177 if (less ((used_range_end - 1 )->step_time (), end_time)) {
183178 break ;
184179 }
185180 --used_range_end;
186181 }
182+ const auto last_step =
183+ static_cast <size_t >(used_range_end - times.begin () - 1 );
184+ const auto order =
185+ static_cast <difference_type>(times.integration_order (last_step)) +
186+ order_offset;
187187 const auto number_of_past_steps =
188- static_cast <difference_type>(scheme.order ) -
189- (scheme.type == SchemeType::Implicit ? 1 : 0 );
188+ order - (scheme_type == SchemeType::Implicit ? 1 : 0 );
190189 ASSERT (used_range_end - times.begin () >= number_of_past_steps,
191190 " Insufficient past data." );
192191 std::copy (used_range_end - number_of_past_steps, used_range_end,
193192 std::back_inserter (ids));
194- if (scheme.type == SchemeType::Implicit) {
195- const auto last_step =
196- static_cast <size_t >(used_range_end - times.begin () - 1 );
193+ if (scheme_type == SchemeType::Implicit) {
197194 ASSERT (times.number_of_substeps (last_step) == 2 ,
198195 " Must have substep data for implicit stepping." );
199196 ids.push_back (times[{last_step, 1 }]);
@@ -202,52 +199,42 @@ OrderVector<TimeStepId> find_relevant_ids(
202199}
203200
204201// Choose the relevant times from `local` and `remote` for defining
205- // small steps for `small_step_scheme` , using the specified schemes
206- // for interpolation on the local and remote sides.
202+ // the small steps, using the specified schemes for interpolation on
203+ // the local and remote sides.
207204//
208- // This is the most recent values from the union of the `local` and
209- // `remote` times with any values that should only be used for
210- // interpolation removed .
205+ // This is the `num_steps` most recent values from the union of the
206+ // `local` and ` remote` times, excluding any values that should only
207+ // be used for interpolation .
211208OrderVector<Time> merge_to_small_steps (const OrderVector<Time>& local,
212209 const OrderVector<Time>& remote,
213210 const evolution_less<Time>& less,
214- const AdamsScheme& local_scheme,
215- const AdamsScheme& remote_scheme,
216- const AdamsScheme& small_step_scheme ) {
217- OrderVector<Time> small_steps (small_step_scheme. order );
211+ const SchemeType local_scheme,
212+ const SchemeType remote_scheme,
213+ const size_t num_steps ) {
214+ OrderVector<Time> small_steps (num_steps );
218215 auto local_it = local.rbegin ();
219216 auto remote_it = remote.rbegin ();
220217
221- ASSERT (not (local_scheme. type == SchemeType::Implicit and
222- remote_scheme. type == SchemeType::Explicit and
218+ ASSERT (not (local_scheme == SchemeType::Implicit and
219+ remote_scheme == SchemeType::Explicit and
223220 less (*local_it, *remote_it)),
224221 " Explicit time " << *remote_it << " after implicit " << *local_it);
225- ASSERT (not (remote_scheme. type == SchemeType::Implicit and
226- local_scheme. type == SchemeType::Explicit and
222+ ASSERT (not (remote_scheme == SchemeType::Implicit and
223+ local_scheme == SchemeType::Explicit and
227224 less (*remote_it, *local_it)),
228225 " Explicit time " << *local_it << " after implicit " << *remote_it);
229226
230- if (small_step_scheme.type == SchemeType::Explicit) {
231- // Don't use implicit interpolation points for an explicit step
232- if (local_scheme.type == SchemeType::Implicit) {
233- ++local_it;
234- }
235- if (remote_scheme.type == SchemeType::Implicit) {
227+ if (local_scheme == SchemeType::Implicit and
228+ remote_scheme == SchemeType::Implicit) {
229+ // If both the interpolation schemes are implicit, we will get
230+ // two times after the small step we are working on, one from
231+ // each. One of them (if they are different) belongs to a later
232+ // small step, and we should ignore it. If they are the same,
233+ // ignoring one of them is harmless.
234+ if (less (*local_it, *remote_it)) {
236235 ++remote_it;
237- }
238- } else {
239- if (local_scheme.type == SchemeType::Implicit and
240- remote_scheme.type == SchemeType::Implicit) {
241- // If both the interpolation schemes are implicit, we will get
242- // two times after the small step we are working on, one from
243- // each. One of them (if they are different) belongs to a later
244- // small step, and we should ignore it. If they are the same,
245- // ignoring one of them is harmless.
246- if (less (*local_it, *remote_it)) {
247- ++remote_it;
248- } else {
249- ++local_it;
250- }
236+ } else {
237+ ++local_it;
251238 }
252239 }
253240
@@ -327,44 +314,61 @@ LtsCoefficients lts_coefficients(const ConstBoundaryHistoryTimes& local_times,
327314 const ConstBoundaryHistoryTimes& remote_times,
328315 const Time& start_time,
329316 const TimeType& end_time,
330- const AdamsScheme& local_scheme,
331- const AdamsScheme& remote_scheme,
332- const AdamsScheme& small_step_scheme) {
317+ const SchemeType local_scheme,
318+ const SchemeType remote_scheme,
319+ const int local_order_offset,
320+ const int remote_order_offset) {
321+ ASSERT (local_order_offset == 0 or local_order_offset == -1 ,
322+ " Must be 0 or -1, not " << local_order_offset);
323+ ASSERT (remote_order_offset == 0 or remote_order_offset == -1 ,
324+ " Must be 0 or -1, not " << remote_order_offset);
333325 if (start_time == end_time) {
334326 return {};
335327 }
328+ const int integration_order_offset =
329+ std::max (local_order_offset, remote_order_offset);
336330 const evolution_less<Time> time_less{local_times.front ().time_runs_forward ()};
337331
338332 LtsCoefficients step_coefficients{};
339333
340334 TimeType small_step_end = end_time;
341335 for (;;) {
342- const OrderVector<TimeStepId> local_ids =
343- find_relevant_ids ( local_times, small_step_end, local_scheme);
344- const OrderVector<TimeStepId> remote_ids =
345- find_relevant_ids ( remote_times, small_step_end, remote_scheme);
336+ const OrderVector<TimeStepId> local_ids = find_relevant_ids (
337+ local_times, small_step_end, local_scheme, local_order_offset );
338+ const OrderVector<TimeStepId> remote_ids = find_relevant_ids (
339+ remote_times, small_step_end, remote_scheme, remote_order_offset );
346340
347341 // Check is the there is actually local time-stepping happening at
348342 // this boundary. Only check for the latest small step, before we
349343 // have generated any coefficients.
350- if (step_coefficients.empty () and small_step_scheme == local_scheme and
351- small_step_scheme == remote_scheme and local_ids == remote_ids) {
344+ if (step_coefficients.empty () and local_scheme == remote_scheme and
345+ local_ids == remote_ids) {
352346 return lts_coefficients_for_gts (local_ids, start_time, end_time);
353347 }
354348
355- OrderVector<Time> local_control_times (local_scheme. order );
349+ OrderVector<Time> local_control_times (local_ids. size () );
356350 alg::transform (local_ids, local_control_times.begin (), exact_substep_time);
357- OrderVector<Time> remote_control_times (remote_scheme. order );
351+ OrderVector<Time> remote_control_times (remote_ids. size () );
358352 alg::transform (remote_ids, remote_control_times.begin (),
359353 exact_substep_time);
360354
355+ const size_t local_order =
356+ local_ids.size () - static_cast <size_t >(local_order_offset);
357+ const size_t remote_order =
358+ remote_ids.size () - static_cast <size_t >(remote_order_offset);
359+ const size_t integration_order =
360+ std::max (local_order, remote_order) +
361+ static_cast <size_t >(integration_order_offset);
362+
361363 const OrderVector<Time> small_step_times = merge_to_small_steps (
362364 local_control_times, remote_control_times, time_less, local_scheme,
363- remote_scheme, small_step_scheme );
365+ remote_scheme, integration_order );
364366 const Time current_small_step =
365367 small_step_times[small_step_times.size () -
366- (small_step_scheme.type == SchemeType::Implicit ? 2
367- : 1 )];
368+ (local_scheme == SchemeType::Implicit or
369+ remote_scheme == SchemeType::Implicit
370+ ? 2
371+ : 1 )];
368372 ASSERT (not time_less (current_small_step, start_time),
369373 " Reached time " << current_small_step
370374 << " without hitting start time " << start_time
@@ -459,8 +463,9 @@ GENERATE_INSTANTIATIONS(INSTANTIATE, (MATH_WRAPPER_TYPES))
459463 template LtsCoefficients lts_coefficients ( \
460464 const ConstBoundaryHistoryTimes& local_times, \
461465 const ConstBoundaryHistoryTimes& remote_times, const Time& start_time, \
462- const TIME_TYPE (data) & end_time, const AdamsScheme& local_scheme, \
463- const AdamsScheme& remote_scheme, const AdamsScheme& small_step_scheme);
466+ const TIME_TYPE (data) & end_time, SchemeType local_scheme, \
467+ SchemeType remote_scheme, int local_order_offset, \
468+ int remote_order_offset);
464469
465470GENERATE_INSTANTIATIONS (INSTANTIATE , (Time, ApproximateTime))
466471#undef INSTANTIATE
0 commit comments