https://mooseframework.inl.gov
Loading...
Searching...
No Matches
TimeSequenceStepperBase.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
11#include "FEProblem.h"
12#include "Transient.h"
13
14#include <algorithm>
15#include <functional>
16
19{
21 params.addParam<bool>(
22 "use_last_dt_after_last_t",
23 false,
24 "If true, uses the final time step size for times after the last time in the sequence, "
25 "instead of taking a single step directly to the simulation end time");
26 params.addParam<bool>(
27 "use_last_t_for_end_time", false, "Use last time in sequence as 'end_time' in Executioner.");
28 return params;
29}
30
32 : TimeStepper(parameters),
33 _use_last_dt_after_last_t(getParam<bool>("use_last_dt_after_last_t")),
34 _current_step(declareRestartableData<unsigned int>("current_step", 0)),
35 _time_sequence(declareRestartableData<std::vector<Real>>("time_sequence")),
36 _set_end_time(getParam<bool>("use_last_t_for_end_time"))
37{
38}
39
40void
41TimeSequenceStepperBase::setupSequence(const std::vector<Real> & times)
42{
43 // In case of half transient, transient's end time needs to be reset to
44 // be able to imprint TimeSequenceStepperBase's end time
47
48 // When restarting or recovering, we reload _time_sequence as restartable data
49 if (_time_sequence.empty() || (!_app.isRestarting() && !_app.isRecovering()))
50 updateSequence(times);
51 else if (_app.isRecovering())
52 mooseAssert(_current_step < _time_sequence.size() &&
54 (_current_step + 1 == _time_sequence.size() ||
56 "The recovered current step must identify the last reached sequence time");
57 else
58 {
59 if (!MooseUtils::absoluteFuzzyEqual(_executioner.getStartTime(), _time_sequence[0]))
60 mooseError("Timesequencestepper does not allow the start time to be modified.");
61
62 auto current_input_sequence = buildSequence(times);
63 // Count the leading sequence entries already reached at the current time. Entries no greater
64 // than _time + _timestep_tolerance are complete, so this count is also the index of the first
65 // future entry, or sequence.size() if every entry is complete.
66 const auto completed_prefix_size = [this](const auto & sequence)
67 {
68 return std::distance(sequence.begin(),
69 std::find_if(sequence.begin(),
70 sequence.end(),
71 [this](const auto sequence_time)
72 { return sequence_time - _time > _timestep_tolerance; }));
73 };
74
75 const auto saved_prefix_size = completed_prefix_size(_time_sequence);
76 const auto current_prefix_size = completed_prefix_size(current_input_sequence);
77 if (current_prefix_size != saved_prefix_size)
78 mooseError("The timesequence provided in the restart file must be identical to "
79 "the one in the old file through the restart time, but it contains ",
80 current_prefix_size,
81 " completed value(s) instead of ",
82 saved_prefix_size,
83 ".");
84
85 for (const auto j : make_range(saved_prefix_size))
86 if (!MooseUtils::absoluteFuzzyEqual(current_input_sequence[j], _time_sequence[j]))
87 mooseError("The timesequence provided in the restart file must be identical to "
88 "the one in the old file through the restart time, but entry ",
89 j + 1,
90 " is ",
91 current_input_sequence[j],
92 " in the restart input and ",
94 " in the restarted input.");
95
96 _time_sequence = std::move(current_input_sequence);
98 }
99
100 // Set end time to last time in sequence if requested
101 if (_set_end_time)
102 {
103 auto & end_time = _executioner.endTime();
104 end_time = _time_sequence.back();
105 }
106
108 {
109 unsigned int half = (_time_sequence.size() - 1) / 2;
111 }
112}
113
114std::vector<Real>
115TimeSequenceStepperBase::buildSequence(const std::vector<Real> & times) const
116{
117 const Real start_time = _executioner.getStartTime();
118 const Real end_time = _executioner.endTime();
119
120 // make sure time sequence is in strictly ascending order
121 if (!std::is_sorted(times.begin(), times.end(), std::less_equal<Real>()))
122 paramError("time_sequence", "Time points must be in strictly ascending order.");
123
124 std::vector<Real> sequence{start_time};
125 for (const auto time : times)
126 if (time > start_time && time <= end_time)
127 sequence.push_back(time);
128
129 // Always append end_time as a sentinel, even when it duplicates the last supplied time.
130 if (!_set_end_time)
131 sequence.push_back(end_time);
132
133 return sequence;
134}
135
136void
142
143void
148
149bool
150TimeSequenceStepperBase::advanceToFutureTime(Real time, Real tolerance, Real & next_time)
151{
153 const auto first_future = findFirstFutureTime(time, tolerance);
154 if (first_future == _time_sequence.cend())
155 return false;
156
157 next_time = *first_future;
158 return true;
159}
160
161std::vector<Real>::const_iterator
162TimeSequenceStepperBase::findFirstFutureTime(Real time, Real tolerance) const
163{
164 return std::partition_point(_time_sequence.begin(),
165 _time_sequence.end(),
166 [time, tolerance](const auto sequence_time)
167 { return sequence_time - time <= tolerance; });
168}
169
170void
172{
173 const auto first_future = findFirstFutureTime(time, tolerance);
175 first_future == _time_sequence.cbegin()
176 ? 0
177 : static_cast<unsigned int>(std::distance(_time_sequence.cbegin(), first_future) - 1);
178}
179
180Real
182{
184 mooseAssert(_current_step + 1 < _time_sequence.size(),
185 "The time sequence must contain a future time");
186 return _time_sequence[_current_step + 1];
187}
188
189void
198
199Real
204
205Real
207{
209 mooseAssert(_current_step + 1 < _time_sequence.size(),
210 "The time sequence must contain a future time");
211 const auto next_time = _time_sequence[_current_step + 1];
212
214 {
215 // last *provided* time value index; actual last index corresponds to end time
216 const auto last_t_index = _time_sequence.size() - 2;
217 if (_current_step + 1 > last_t_index)
218 return _time_sequence[last_t_index] - _time_sequence[last_t_index - 1];
219 }
220
221 return next_time - _time;
222}
void ErrorVector unsigned int
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
bool isRestarting() const
Whether or not this is a "restart" calculation.
Definition MooseApp.C:1675
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition MooseApp.C:1669
bool testCheckpointHalfTransient() const
Whether or not this simulation should only run half its transient (useful for testing recovery)
Definition MooseApp.h:524
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
TimeSequenceStepperBase(const InputParameters &parameters)
bool advanceToFutureTime(Real time, Real tolerance, Real &next_time)
Return the first sequence time that has not yet been reached, if any.
std::vector< Real >::const_iterator findFirstFutureTime(Real time, Real tolerance) const
Find the first sequence time greater than time by more than tolerance.
void updateSequence(const std::vector< Real > &times)
virtual void acceptStep() override
This gets called when time step is accepted.
virtual void refreshSequence()
Re-read a time sequence source that can change during the simulation.
void setupSequence(const std::vector< Real > &times)
virtual Real computeInitialDT() override
Computes time step size for the initial time step.
const bool _set_end_time
Whether to use the last t in sequence as Executioner end_time.
unsigned int & _current_step
the step that the time stepper is currently at
virtual Real computeDT() override
Computes time step size after the initial time step.
static InputParameters validParams()
void synchronizeCurrentStep(Real time, Real tolerance)
Set the current sequence position from time.
std::vector< Real > & _time_sequence
stores the sequence of time points
const bool _use_last_dt_after_last_t
Whether to use the final dt past the last t in sequence.
std::vector< Real > buildSequence(const std::vector< Real > &times) const
Build the canonical time sequence for the current start and end times.
virtual Real getNextTimeInSequence()
Get the next time in the input time sequence.
Base class for time stepping.
Definition TimeStepper.h:23
static InputParameters validParams()
Definition TimeStepper.C:16
virtual void acceptStep()
This gets called when time step is accepted.
TransientBase & _executioner
Reference to transient executioner.
Real & _timestep_tolerance
Real & _time
Values from executioner.
Real getStartTime() const
Return the start time.
Real & endTime()
Get a modifiable reference to the end time.