Skip to content

Commit 550b360

Browse files
committed
Merge branch 'IterationNumberBasedTimeStepping' into 'master'
Fix bugs and add tests for IterationNumberBasedTimeStepping See merge request ogs/ogs!5383
2 parents f9d83ca + 5f2338e commit 550b360

File tree

11 files changed

+330
-109
lines changed

11 files changed

+330
-109
lines changed

NumLib/TimeStepping/Algorithms/IterationNumberBasedTimeStepping.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ std::tuple<bool, double> IterationNumberBasedTimeStepping::next(
9595
ts_previous = // essentially equal to ts_previous.dt = _ts_current.dt.
9696
TimeStep{ts_previous.previous(), ts_previous.previous() + dt,
9797
ts_previous.timeStepNumber()};
98+
ts_current = TimeStep{ts_current.previous(), ts_current.previous() + dt,
99+
ts_current.timeStepNumber()};
98100

99101
_previous_time_step_accepted = false;
100102
return std::make_tuple(_previous_time_step_accepted, dt);
@@ -165,6 +167,9 @@ double IterationNumberBasedTimeStepping::getNextTimeStepSize(
165167
return std::clamp(dt, _min_dt, _max_dt);
166168
}
167169

170+
// restrict dt to _max_dt before taking fixed times for output into account
171+
dt = std::min(dt, _max_dt);
172+
168173
// find first fixed timestep for output larger than the current time, i.e.,
169174
// current time < fixed output time
170175
auto fixed_output_time_it = std::find_if(

NumLib/TimeStepping/TimeStep.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
#pragma once
1414

15+
#include <spdlog/fmt/bundled/ostream.h>
16+
1517
#include <cstddef>
1618
#include <limits>
1719

@@ -84,6 +86,14 @@ class TimeStep final
8486
void setAccepted(bool const accepted) { _is_accepted = accepted; }
8587
bool isAccepted() const { return _is_accepted; }
8688

89+
friend inline std::ostream& operator<<(std::ostream& os, TimeStep const& ts)
90+
{
91+
return os << "previous: " << ts.previous()
92+
<< " | current: " << ts.current() << " | dt: " << ts.dt()
93+
<< " | timestep number: " << ts.timeStepNumber()
94+
<< " | is_accepted: " << ts.isAccepted();
95+
}
96+
8797
private:
8898
/// previous time step
8999
Time _previous;
@@ -105,3 +115,8 @@ inline void updateTimeSteps(double const dt, TimeStep& previous_timestep,
105115
}
106116

107117
} // namespace NumLib
118+
119+
template <>
120+
struct fmt::formatter<NumLib::TimeStep> : fmt::ostream_formatter
121+
{
122+
};

ProcessLib/SmallDeformation/Tests.cmake

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,7 @@ AddTest(
363363
REQUIREMENTS NOT OGS_USE_MPI
364364
RUNTIME 1
365365
PROPERTIES
366-
# Time step size of 0.125 means the time step has been halved twice from its initial size.
367-
# That proves that OGS gracefully handles such conditions
368-
PASS_REGULAR_EXPRESSION "The new step size of 0[.]125 is the same as that of the previous rejected time step[.]"
366+
PASS_REGULAR_EXPRESSION "Time stepper cannot reduce the time step size further[.]"
369367
)
370368

371369
if(NOT OGS_USE_PETSC)

Tests/Data/TH2M/H2M/EmbeddedFracturePermeability/IfG_t_0.vtu

Lines changed: 17 additions & 17 deletions
Large diffs are not rendered by default.

Tests/Data/TH2M/H2M/EmbeddedFracturePermeability/IfG_t_100.vtu

Lines changed: 17 additions & 17 deletions
Large diffs are not rendered by default.

Tests/Data/TH2M/H2M/EmbeddedFracturePermeability/IfG_t_10000.vtu

Lines changed: 17 additions & 17 deletions
Large diffs are not rendered by default.

Tests/Data/TH2M/H2M/EmbeddedFracturePermeability/IfG_t_5000.vtu

Lines changed: 16 additions & 16 deletions
Large diffs are not rendered by default.

Tests/Data/TH2M/H2M/EmbeddedFracturePermeability/IfG_t_5100.vtu

Lines changed: 17 additions & 17 deletions
Large diffs are not rendered by default.

Tests/NumLib/TestTimeSteppingFixed.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class NumLibTimeSteppingFixed_TimeSteps : public ::testing::Test
8383
std::vector<double> const expected_times) const
8484
{
8585
std::vector<double> times =
86-
timeStepping(algorithm, dummy_number_iterations, {});
86+
timeStepping(algorithm, dummy_number_iterations, {}, {});
8787

8888
ASSERT_EQ(expected_times.size(), times.size());
8989
ASSERT_ARRAY_NEAR(expected_times, times, expected_times.size(),

Tests/NumLib/TestTimeSteppingIterationNumber.cpp

Lines changed: 196 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@
1212

1313
#include <gtest/gtest.h>
1414

15-
#include <ranges>
15+
#include <algorithm>
16+
#include <range/v3/range/conversion.hpp>
17+
#include <range/v3/view/iota.hpp>
18+
#include <range/v3/view/transform.hpp>
19+
#include <range/v3/view/zip.hpp>
1620
#include <tuple>
1721
#include <utility>
1822
#include <vector>
@@ -71,7 +75,7 @@ TEST(NumLib, findMultiplierTimestepAcceptedPiecewiseConstant)
7175

7276
bool const current_time_step_is_accepted = true;
7377
for (auto const [n, m] :
74-
std::views::zip(nonlinear_iteration_numbers, multipliers))
78+
ranges::views::zip(nonlinear_iteration_numbers, multipliers))
7579
{
7680
auto const multiplier = NumLib::findMultiplier(
7781
n, current_time_step_is_accepted, nonlinear_iteration_numbers,
@@ -91,7 +95,7 @@ TEST(
9195

9296
bool const current_time_step_is_accepted = true;
9397
for (auto const [n, m] :
94-
std::views::zip(nonlinear_iteration_numbers, multipliers))
98+
ranges::views::zip(nonlinear_iteration_numbers, multipliers))
9599
{
96100
auto const multiplier = NumLib::findMultiplier(
97101
n, current_time_step_is_accepted, nonlinear_iteration_numbers,
@@ -187,7 +191,7 @@ TEST(NumLib, findMultiplierTimestepRejected)
187191

188192
bool const current_time_step_is_accepted = false;
189193
for (auto const [n, m] :
190-
std::views::zip(nonlinear_iteration_numbers, multipliers))
194+
ranges::views::zip(nonlinear_iteration_numbers, multipliers))
191195
{
192196
auto const multiplier = NumLib::findMultiplier(
193197
n, current_time_step_is_accepted, nonlinear_iteration_numbers,
@@ -328,11 +332,11 @@ TEST(NumLib, TimeSteppingIterationNumberBased2)
328332
1, 31, 1, 10, 1, multiplier_interpolation_type,
329333
std::move(iter_times_vector), std::move(multiplier_vector), {});
330334

331-
std::vector<int> nr_iterations = {0, 2, 2, 2, 4, 6, 8, 4, 1};
332-
const std::vector<double> expected_vec_t = {1, 2, 4, 8, 16,
335+
std::vector<int> const nr_iterations = {0, 2, 2, 2, 4, 6, 8, 4, 1};
336+
std::vector<double> const expected_vec_t = {1, 2, 4, 8, 16,
333337
24, 28, 29, 30, 31};
334338

335-
std::vector<double> vec_t = timeStepping(alg, nr_iterations, {});
339+
std::vector<double> vec_t = timeStepping(alg, nr_iterations, {}, {});
336340

337341
ASSERT_EQ(expected_vec_t.size(), vec_t.size());
338342
ASSERT_ARRAY_NEAR(expected_vec_t, vec_t, expected_vec_t.size(),
@@ -350,14 +354,196 @@ TEST(NumLib, TimeSteppingIterationNumberBased2FixedOutputTimes)
350354
1, 31, 1, 10, 1, multiplier_interpolation_type,
351355
std::move(iter_times_vector), std::move(multiplier_vector), {});
352356

353-
std::vector<int> nr_iterations = {0, 2, 2, 2, 4, 6, 8, 4, 1, 1, 1, 1, 1};
354-
const std::vector<double> expected_vec_t = {1, 2, 4, 5, 7, 9, 10,
357+
std::vector<int> const nr_iterations = {0, 2, 2, 2, 4, 6, 8,
358+
4, 1, 1, 1, 1, 1};
359+
std::vector<double> const expected_vec_t = {1, 2, 4, 5, 7, 9, 10,
355360
11, 12, 14, 18, 20, 24, 31};
356361

357362
std::vector<double> vec_t =
358-
timeStepping(alg, nr_iterations, fixed_output_times);
363+
timeStepping(alg, nr_iterations, fixed_output_times, {});
359364

360365
EXPECT_EQ(expected_vec_t.size(), vec_t.size());
361366
ASSERT_ARRAY_NEAR(expected_vec_t, vec_t, expected_vec_t.size(),
362367
std::numeric_limits<double>::epsilon());
363368
}
369+
370+
TEST(NumLib, TimeSteppingIterationNumberBased_simple)
371+
{
372+
// *** initialization of IterationNumberBaseTimeStepping object
373+
constexpr int number_of_multipliers = 20;
374+
std::vector multiplier_vector(number_of_multipliers, 1.0);
375+
376+
auto iter_times_vector =
377+
ranges::views::iota(1, static_cast<int>(multiplier_vector.size() + 1)) |
378+
ranges::to<std::vector>;
379+
380+
std::vector<double> const fixed_output_times = {};
381+
382+
NumLib::MultiplyerInterpolationType const multiplier_interpolation_type =
383+
NumLib::MultiplyerInterpolationType::PiecewiseConstant;
384+
385+
double const t_initial = 0.0;
386+
double const t_end = 8000.0;
387+
double const min_dt = 0.001;
388+
double const max_dt = 2100;
389+
double const initial_dt = 100;
390+
391+
NumLib::IterationNumberBasedTimeStepping alg(
392+
t_initial, t_end, min_dt, max_dt, initial_dt,
393+
multiplier_interpolation_type, std::move(iter_times_vector),
394+
std::move(multiplier_vector), std::move(fixed_output_times));
395+
// *** end initialization of IterationNumberBaseTimeStepping object
396+
397+
std::vector<int> const rejected_steps = {};
398+
std::vector<int> const nr_iterations = {
399+
0, 4, 3, 9, 3, 5, 4, 3, 3, 7, 10, 4, 3, 3, 3, 5, 3, 4, 7, 15,
400+
3, 7, 15, 3, 11, 8, 4, 5, 5, 4, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3,
401+
3, 3, 3, 3, 7, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4,
402+
4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3};
403+
404+
auto const expected_vec_t =
405+
ranges::views::iota(0, static_cast<int>(nr_iterations.size()) + 1) |
406+
ranges::views::transform([](int i) { return (i * 100.0); }) |
407+
ranges::to<std::vector>;
408+
409+
std::vector<double> const vec_t =
410+
timeStepping(alg, nr_iterations, fixed_output_times, rejected_steps);
411+
412+
EXPECT_EQ(expected_vec_t.size(), vec_t.size());
413+
ASSERT_ARRAY_NEAR(expected_vec_t, vec_t, expected_vec_t.size(),
414+
std::numeric_limits<double>::epsilon());
415+
}
416+
417+
TEST(NumLib, TimeSteppingIterationNumberBased_simple2)
418+
{
419+
// *** initialization of IterationNumberBaseTimeStepping object
420+
constexpr int number_of_multipliers = 20;
421+
std::vector multiplier_vector(number_of_multipliers - 1, 1.0);
422+
multiplier_vector.emplace_back(0.1); // multiplier for rejected step
423+
424+
auto iter_times_vector =
425+
ranges::views::iota(1, static_cast<int>(multiplier_vector.size() + 1)) |
426+
ranges::to<std::vector>;
427+
428+
std::vector<double> fixed_output_times = {};
429+
430+
NumLib::MultiplyerInterpolationType const multiplier_interpolation_type =
431+
NumLib::MultiplyerInterpolationType::PiecewiseConstant;
432+
double const t_initial = 0.0;
433+
double const t_end = 200.0;
434+
double const min_dt = 10;
435+
double const max_dt = 200;
436+
double const initial_dt = 100;
437+
NumLib::IterationNumberBasedTimeStepping alg(
438+
t_initial, t_end, min_dt, max_dt, initial_dt,
439+
multiplier_interpolation_type, std::move(iter_times_vector),
440+
std::move(multiplier_vector), std::move(fixed_output_times));
441+
// *** end initialization of IterationNumberBaseTimeStepping object
442+
443+
std::vector<int> const rejected_steps = {2};
444+
std::vector<int> const nr_iterations = {0, 4, 3, 3, 3, 3,
445+
3, 3, 9, 10, 19, 1};
446+
// current time step size:
447+
std::vector<double> const expected_vec_t = {
448+
0, 100, 200, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200};
449+
450+
std::vector<double> const vec_t =
451+
timeStepping(alg, nr_iterations, fixed_output_times, rejected_steps);
452+
453+
EXPECT_EQ(expected_vec_t.size(), vec_t.size());
454+
ASSERT_ARRAY_NEAR(expected_vec_t, vec_t, expected_vec_t.size(),
455+
std::numeric_limits<double>::epsilon());
456+
}
457+
458+
// extracted from Sandwich-0c-Aqeel-R5DeCoT68
459+
TEST(NumLib, TimeSteppingIterationNumberBasedSandwich_0c)
460+
{
461+
// *** initialization of IterationNumberBaseTimeStepping object
462+
std::vector<double> multiplier_vector = {
463+
5, 4.25, 3.5, 2.75, 2, 1.6333, 1.2667,
464+
0.9, 0.8333, 0.7667, 0.7, 0.6333, 0.5667, 0.5,
465+
0.4333, 0.3667, 0.3, 0.2333, 0.1667, 0.1};
466+
467+
auto iter_times_vector =
468+
ranges::views::iota(1, static_cast<int>(multiplier_vector.size() + 1)) |
469+
ranges::to<std::vector>;
470+
471+
std::vector<double> fixed_output_times = {
472+
0, 432000, 440640, 950400, 959040, 3024000, 3032640,
473+
5961600, 6480000, 7689600, 7776000, 7819200, 12528000};
474+
475+
NumLib::MultiplyerInterpolationType const multiplier_interpolation_type =
476+
NumLib::MultiplyerInterpolationType::PiecewiseConstant;
477+
// *** original data
478+
double const t_initial = 0.0;
479+
double const t_end = 12528000.0;
480+
double const min_dt = 0.001;
481+
double const max_dt = 432000;
482+
double const initial_dt = 120;
483+
NumLib::IterationNumberBasedTimeStepping alg(
484+
t_initial, t_end, min_dt, max_dt, initial_dt,
485+
multiplier_interpolation_type, std::move(iter_times_vector),
486+
std::move(multiplier_vector), std::move(fixed_output_times));
487+
// *** end initialization of IterationNumberBaseTimeStepping object
488+
489+
std::vector<int> const rejected_steps = {6, 8, 10, 12, 14, 14, 24};
490+
491+
std::vector<int> const nr_iterations = {
492+
0, 4, 3, 9, 3, 5, 5, // <- time step 6 rejected
493+
3, // <- time step 6 repeated
494+
3, 8, // <- time step 8 rejected
495+
10, // <- time step 8 repeated
496+
4, 4, // <- time step 10 rejected
497+
3, // <- time step 10 repeated
498+
3, 6, // <- time step 12 rejected
499+
3, // <- time step 12 repeated
500+
4, 8, // <- time step 14 rejected
501+
17, // <- time step 14 rejected again
502+
3, // <- time step 14 repeated (and accepted)
503+
9, 4, 5, 5, 4, 3, 3, 3, 3, 11, // <- time step 24 rejected
504+
3 // <- time step 24 repeated
505+
};
506+
507+
// current timestep sizes:
508+
std::vector<double> const expected_vec_t = {
509+
0,
510+
120,
511+
450,
512+
1605,
513+
2567.4614999999999,
514+
5936.0767500000002,
515+
12673.30725, // ts 6 rejected
516+
6609.7998000000007, // ts 6 repeated
517+
8967.8304749999988,
518+
17220.937837499994, // ts 8 rejected
519+
16395.627101249993, // ts 8 repeated
520+
22090.518774595865,
521+
37751.470876297011, // ts 10 rejected
522+
23656.61398476598, // ts 10 repeated
523+
29137.947220361384,
524+
48322.613544945292, // ts 12 rejected
525+
31056.413852819776, // ts 12 repeated
526+
37771.047066424137,
527+
56236.288403836123, // ts 14 rejected
528+
54389.764270094922, // ts 14 rejected
529+
42756.662227525369, // ts 14 repeated
530+
60206.315291379709,
531+
74747.111189489529,
532+
114734.29990929153,
533+
194708.67734889555,
534+
354657.43222810357,
535+
432000,
536+
440640,
537+
470880,
538+
576720,
539+
947160, // ts 24 rejected
540+
579960, // ts 24 repeated
541+
591300};
542+
543+
std::vector<double> const vec_t =
544+
timeStepping(alg, nr_iterations, fixed_output_times, rejected_steps);
545+
546+
EXPECT_EQ(expected_vec_t.size(), vec_t.size());
547+
ASSERT_ARRAY_NEAR(expected_vec_t, vec_t, expected_vec_t.size(),
548+
5e4 * std::numeric_limits<double>::epsilon());
549+
}

0 commit comments

Comments
 (0)