www.mooseframework.org
IterationAdaptiveDT.C
Go to the documentation of this file.
1 /****************************************************************/
2 /* DO NOT MODIFY THIS HEADER */
3 /* MOOSE - Multiphysics Object Oriented Simulation Environment */
4 /* */
5 /* (c) 2010 Battelle Energy Alliance, LLC */
6 /* ALL RIGHTS RESERVED */
7 /* */
8 /* Prepared by Battelle Energy Alliance, LLC */
9 /* Under Contract No. DE-AC07-05ID14517 */
10 /* With the U. S. Department of Energy */
11 /* */
12 /* See COPYRIGHT for full restrictions */
13 /****************************************************************/
14 
15 // MOOSE includes
16 #include "IterationAdaptiveDT.h"
17 #include "Function.h"
18 #include "Piecewise.h"
19 #include "Transient.h"
20 #include "NonlinearSystem.h"
21 
22 template <>
25 {
27  params.addClassDescription("Adjust the timestep based on the number of iterations");
28  params.addParam<int>("optimal_iterations",
29  "The target number of nonlinear iterations for adaptive timestepping");
30  params.addParam<int>("iteration_window",
31  "Attempt to grow/shrink timestep if the iteration count "
32  "is below/above 'optimal_iterations plus/minus "
33  "iteration_window' (default = optimal_iterations/5).");
34  params.addParam<unsigned>("linear_iteration_ratio",
35  "The ratio of linear to nonlinear iterations "
36  "to determine target linear iterations and "
37  "window for adaptive timestepping (default = "
38  "25)");
39  params.addParam<PostprocessorName>("postprocessor_dtlim",
40  "If specified, the postprocessor value "
41  "is used as an upper limit for the "
42  "current time step length");
43  params.addParam<FunctionName>("timestep_limiting_function",
44  "A 'Piecewise' type function used to control the timestep by "
45  "limiting the change in the function over a timestep");
46  params.addParam<Real>(
47  "max_function_change",
48  "The absolute value of the maximum change in timestep_limiting_function over a timestep");
49  params.addParam<bool>("force_step_every_function_point",
50  false,
51  "Forces the timestepper to take "
52  "a step that is consistent with "
53  "points defined in the function");
54  params.addRequiredParam<Real>("dt", "The default timestep size between solves");
55  params.addParam<std::vector<Real>>("time_t", "The values of t");
56  params.addParam<std::vector<Real>>("time_dt", "The values of dt");
57  params.addParam<Real>("growth_factor",
58  2.0,
59  "Factor to apply to timestep if easy convergence (if "
60  "'optimal_iterations' is specified) or if recovering "
61  "from failed solve");
62  params.addParam<Real>("cutback_factor",
63  0.5,
64  "Factor to apply to timestep if difficult "
65  "convergence (if 'optimal_iterations' is specified) "
66  "or if solution failed");
67  return params;
68 }
69 
71  : TimeStepper(parameters),
73  _dt_old(declareRestartableData<Real>("dt_old", 0.0)),
74  _input_dt(getParam<Real>("dt")),
75  _tfunc_last_step(declareRestartableData<bool>("tfunc_last_step", false)),
76  _sync_last_step(declareRestartableData<bool>("sync_last_step", false)),
77  _linear_iteration_ratio(isParamValid("linear_iteration_ratio")
78  ? getParam<unsigned>("linear_iteration_ratio")
79  : 25), // Default to 25
80  _adaptive_timestepping(false),
81  _pps_value(isParamValid("postprocessor_dtlim") ? &getPostprocessorValue("postprocessor_dtlim")
82  : NULL),
83  _timestep_limiting_function(NULL),
84  _piecewise_timestep_limiting_function(NULL),
85  _times(0),
86  _max_function_change(-1),
87  _force_step_every_function_point(getParam<bool>("force_step_every_function_point")),
88  _tfunc_times(getParam<std::vector<Real>>("time_t").begin(),
89  getParam<std::vector<Real>>("time_t").end()),
90  _time_ipol(getParam<std::vector<Real>>("time_t"), getParam<std::vector<Real>>("time_dt")),
91  _use_time_ipol(_time_ipol.getSampleSize() > 0),
92  _growth_factor(getParam<Real>("growth_factor")),
93  _cutback_factor(getParam<Real>("cutback_factor")),
94  _nl_its(declareRestartableData<unsigned int>("nl_its", 0)),
95  _l_its(declareRestartableData<unsigned int>("l_its", 0)),
96  _cutback_occurred(declareRestartableData<bool>("cutback_occurred", false)),
97  _at_function_point(false)
98 {
99  if (isParamValid("optimal_iterations"))
100  {
101  _adaptive_timestepping = true;
102  _optimal_iterations = getParam<int>("optimal_iterations");
103 
104  if (isParamValid("iteration_window"))
105  _iteration_window = getParam<int>("iteration_window");
106  else
108  }
109  else
110  {
111  if (isParamValid("iteration_window"))
112  mooseError("'optimal_iterations' must be used for 'iteration_window' to be used");
113  if (isParamValid("linear_iteration_ratio"))
114  mooseError("'optimal_iterations' must be used for 'linear_iteration_ratio' to be used");
115  }
116 
117  if (isParamValid("timestep_limiting_function"))
119  isParamValid("max_function_change") ? getParam<Real>("max_function_change") : -1;
120  else if (isParamValid("max_function_change"))
121  mooseError("'timestep_limiting_function' must be used for 'max_function_change' to be used");
122 }
123 
124 void
126 {
127  if (isParamValid("timestep_limiting_function"))
128  {
130  &_fe_problem.getFunction(getParam<FunctionName>("timestep_limiting_function"),
131  isParamValid("_tid") ? getParam<THREAD_ID>("_tid") : 0);
133 
135  {
136  unsigned int time_size = _piecewise_timestep_limiting_function->functionSize();
137  _times.resize(time_size);
138 
139  for (unsigned int i = 0; i < time_size; ++i)
141  }
142  else
143  mooseError("timestep_limiting_function must be a Piecewise function");
144  }
145 }
146 
147 void
149 {
151 
152  // Delete all tfunc times that are at or before the begin time
153  while (!_tfunc_times.empty() && _time + _timestep_tolerance >= *_tfunc_times.begin())
154  _tfunc_times.erase(_tfunc_times.begin());
155 }
156 
157 Real
159 {
160  return _input_dt;
161 }
162 
163 Real
165 {
166  Real dt = _dt_old;
167 
168  if (_cutback_occurred)
169  {
170  _cutback_occurred = false;
172  {
173  // Don't allow it to grow this step, but shrink if needed
174  bool allowToGrow = false;
175  computeAdaptiveDT(dt, allowToGrow);
176  }
177  }
178  else if (_tfunc_last_step)
179  {
180  _tfunc_last_step = false;
181  _sync_last_step = false;
183 
184  if (_verbose)
185  {
186  _console << "Setting dt to value specified by dt function: " << std::setw(9) << dt << '\n';
187  }
188  }
189  else if (_sync_last_step)
190  {
191  _sync_last_step = false;
192  dt = _dt_old;
193 
194  if (_verbose)
195  {
196  _console << "Setting dt to value used before sync: " << std::setw(9) << dt << '\n';
197  }
198  }
199  else if (_adaptive_timestepping)
200  computeAdaptiveDT(dt);
201  else if (_use_time_ipol)
202  dt = computeInterpolationDT();
203  else
204  {
205  dt *= _growth_factor;
206  if (dt > _dt_old * _growth_factor)
207  dt = _dt_old * _growth_factor;
208  }
209 
210  return dt;
211 }
212 
213 bool
215 {
216  bool at_sync_point = TimeStepper::constrainStep(dt);
217 
218  // Limit the timestep to postprocessor value
219 
221 
222  // Limit the timestep to limit change in the function
223  limitDTByFunction(dt);
224 
225  // Adjust to the next tfunc time if needed
226  if (!_tfunc_times.empty() && _time + dt + _timestep_tolerance >= *_tfunc_times.begin())
227  {
228  dt = *_tfunc_times.begin() - _time;
229 
230  if (_verbose)
231  {
232  _console << "Limiting dt to sync with dt function time: " << std::setw(9)
233  << *_tfunc_times.begin() << " dt: " << std::setw(9) << dt << '\n';
234  }
235  }
236 
237  return at_sync_point;
238 }
239 
240 Real
242 {
243  _cutback_occurred = true;
244 
245  // Can't cut back any more
246  if (_dt <= _dt_min)
247  mooseError("Solve failed and timestep already at dtmin, cannot continue!");
248 
249  if (_verbose)
250  {
251  _console << "\nSolve failed with dt: " << std::setw(9) << _dt
252  << "\nRetrying with reduced dt: " << std::setw(9) << _dt * _cutback_factor << '\n';
253  }
254  else
255  _console << "\nSolve failed, cutting timestep.\n";
256 
257  return _dt * _cutback_factor;
258 }
259 
260 void
262 {
263  if (_pps_value)
264  {
265  if (*_pps_value > _dt_min && limitedDT > *_pps_value)
266  {
267  limitedDT = *_pps_value;
268 
269  if (_verbose)
270  _console << "Limiting dt to postprocessor value. dt = " << limitedDT << '\n';
271  }
272  }
273 }
274 
275 void
277 {
278  Real orig_dt = limitedDT;
279 
281  {
282  Point dummyPoint;
283  Real oldValue = _timestep_limiting_function->value(_time_old, dummyPoint);
284  Real newValue = _timestep_limiting_function->value(_time_old + limitedDT, dummyPoint);
285  Real change = std::abs(newValue - oldValue);
286 
287  if (_max_function_change > 0.0 && change > _max_function_change)
288  {
289  do
290  {
291  limitedDT /= 2.0;
292  newValue = _timestep_limiting_function->value(_time_old + limitedDT, dummyPoint);
293  change = std::abs(newValue - oldValue);
294  } while (change > _max_function_change);
295  }
296  }
297 
298  _at_function_point = false;
300  {
301  for (unsigned int i = 0; i + 1 < _times.size(); ++i)
302  {
303  if (_time >= _times[i] && _time < _times[i + 1])
304  {
305  if (limitedDT > _times[i + 1] - _time - _timestep_tolerance)
306  {
307  limitedDT = _times[i + 1] - _time;
308  _at_function_point = true;
309  }
310  break;
311  }
312  }
313  }
314 
315  if (_verbose && limitedDT != orig_dt)
316  {
317  if (_at_function_point)
318  _console << "Limiting dt to match function point. dt = ";
319  else
320  _console << "Limiting dt to limit change in function. dt = ";
321 
322  _console << limitedDT << '\n';
323  }
324 }
325 
326 void
327 IterationAdaptiveDT::computeAdaptiveDT(Real & dt, bool allowToGrow, bool allowToShrink)
328 {
329  const unsigned int growth_nl_its(
331  const unsigned int shrink_nl_its(_optimal_iterations + _iteration_window);
332  const unsigned int growth_l_its(_optimal_iterations > _iteration_window
335  : 0);
336  const unsigned int shrink_l_its(_linear_iteration_ratio *
338 
339  if (allowToGrow && (_nl_its < growth_nl_its && _l_its < growth_l_its))
340  {
341  // Grow the timestep
342  dt *= _growth_factor;
343 
344  if (_verbose)
345  {
346  _console << "Growing dt: nl its = " << _nl_its << " < " << growth_nl_its
347  << " && lin its = " << _l_its << " < " << growth_l_its << " old dt: " << std::setw(9)
348  << _dt_old << " new dt: " << std::setw(9) << dt << '\n';
349  }
350  }
351  else if (allowToShrink && (_nl_its > shrink_nl_its || _l_its > shrink_l_its))
352  {
353  // Shrink the timestep
354  dt *= _cutback_factor;
355 
356  if (_verbose)
357  {
358  _console << "Shrinking dt: nl its = " << _nl_its << " > " << shrink_nl_its
359  << " || lin its = " << _l_its << " > " << shrink_l_its << " old dt: " << std::setw(9)
360  << _dt_old << " new dt: " << std::setw(9) << dt << '\n';
361  }
362  }
363 }
364 
365 Real
367 {
368  Real dt = _time_ipol.sample(_time_old);
369 
370  if (dt > _dt_old * _growth_factor)
371  {
372  dt = _dt_old * _growth_factor;
373 
374  if (_verbose)
375  {
376  _console << "Growing dt to recover from cutback. "
377  << " old dt: " << std::setw(9) << _dt_old << " new dt: " << std::setw(9) << dt
378  << '\n';
379  }
380  }
381 
382  return dt;
383 }
384 
385 void
387 {
389 }
390 
391 void
393 {
395 
396  while (!_tfunc_times.empty() && _time + _timestep_tolerance >= *_tfunc_times.begin())
397  {
398  if (std::abs(_time - *_tfunc_times.begin()) <= _timestep_tolerance)
399  _tfunc_last_step = true;
400 
401  _tfunc_times.erase(_tfunc_times.begin());
402  }
403 
406 
408  _dt + _timestep_tolerance < _executioner.unconstrainedDT())
409  {
411  _sync_last_step = true;
412 
413  if (_verbose)
414  {
415  _console << "Sync point hit in current step, using previous dt for old dt: " << std::setw(9)
416  << _dt_old << '\n';
417  }
418  }
419  else
420  _dt_old = _dt;
421 }
Real & _timestep_tolerance
Definition: TimeStepper.h:138
virtual Real value(Real t, const Point &p)
Override this to evaluate the scalar function at point (t,x,y,z), by default this returns zero...
Definition: Function.C:43
unsigned int nLinearIterations()
Return the number of linear iterations.
bool atSyncPoint()
Is the current step at a sync point (sync times, time interval, target time, etc)?
Definition: Transient.h:190
unsigned int nNonlinearIterations()
Return the number of non-linear iterations.
NonlinearSystemBase & getNonlinearSystemBase()
unsigned int & _nl_its
Number of nonlinear iterations in previous solve.
Piecewise * _piecewise_timestep_limiting_function
Real & _time_old
Definition: TimeStepper.h:130
virtual Real computeDT() override
Called to compute _current_dt for a normal step.
Base class for time stepping.
Definition: TimeStepper.h:31
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
const Real _input_dt
The dt from the input file.
virtual Real computeInitialDT() override
Called to compute _current_dt for the first timestep.
Transient & _executioner
Reference to transient executioner.
Definition: TimeStepper.h:126
IterationAdaptiveDT(const InputParameters &parameters)
Real sample(Real x) const
This function will take an independent variable input and will return the dependent variable based on...
virtual bool constrainStep(Real &dt)
Called after computeStep() is called.
Definition: TimeStepper.C:94
void limitDTByFunction(Real &limitedDT)
virtual bool constrainStep(Real &dt) override
Called after computeStep() is called.
int _optimal_iterations
Adapt the timestep to maintain this non-linear iteration count...
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
virtual Real computeFailedDT() override
Called to compute _current_dt after a solve has failed.
FEProblemBase & _fe_problem
Definition: TimeStepper.h:124
Real unconstrainedDT()
Get the unconstrained dt.
Definition: Transient.h:196
const bool _use_time_ipol
true if we want to use piecewise-defined time stepping
unsigned int & _l_its
Number of linear iterations in previous solve.
virtual void preExecute() override
virtual Function & getFunction(const std::string &name, THREAD_ID tid=0)
Function * _timestep_limiting_function
virtual void acceptStep()
This gets called when time step is accepted.
Definition: TimeStepper.C:165
LinearInterpolation _time_ipol
Piecewise linear definition of time stepping.
const PostprocessorValue * _pps_value
if specified, the postprocessor value is an upper limit for the time step length
virtual Real domain(int i)
Definition: Piecewise.C:114
virtual void rejectStep() override
This gets called when time step is rejected.
std::set< Real > _tfunc_times
bool _adaptive_timestepping
adaptive timestepping is active if the optimal_iterations input parameter is specified ...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition: MooseObject.h:67
virtual void init() override
Initialize the time stepper.
void computeAdaptiveDT(Real &dt, bool allowToGrow=true, bool allowToShrink=true)
const int _linear_iteration_ratio
use _optimal_iterations and _iteration_window multiplied with this factor for linear iterations ...
const Real _growth_factor
grow the timestep by this factor
InputParameters validParams< TimeStepper >()
Definition: TimeStepper.C:22
bool _force_step_every_function_point
insert sync points at the time nodes of the _piecewise_timestep_limiting_function ...
std::vector< Real > _times
time point defined in the piecewise function
virtual Real & dtOld() const
const Real _cutback_factor
cut the timestep by by this factor
int _iteration_window
...plus/minus this value.
virtual void preExecute()
Definition: TimeStepper.C:65
virtual void rejectStep()
This gets called when time step is rejected.
Definition: TimeStepper.C:175
Real & _dt_min
Definition: TimeStepper.h:133
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an option parameter and a documentation string to the InputParameters object...
void mooseError(Args &&...args) const
Definition: MooseObject.h:80
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
bool & _verbose
should detailed diagnostic output be printed
Definition: TimeStepper.h:141
Real & _dt
Definition: TimeStepper.h:132
Function which provides a piecewise approximation to a provided (x,y) point data set.
Definition: Piecewise.h:31
InputParameters validParams< IterationAdaptiveDT >()
Real & _time
Values from executioner.
Definition: TimeStepper.h:129
Interface class for classes which interact with Postprocessors.
void limitDTToPostprocessorValue(Real &limitedDT)
virtual Real functionSize()
Definition: Piecewise.C:108
virtual void acceptStep() override
This gets called when time step is accepted.