Line data Source code
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 : 10 : #include "TimeStepper.h" 11 : #include "FEProblem.h" 12 : #include "TransientBase.h" 13 : #include "MooseApp.h" 14 : 15 : InputParameters 16 291348 : TimeStepper::validParams() 17 : { 18 291348 : InputParameters params = MooseObject::validParams(); 19 874044 : params.addParam<bool>( 20 582696 : "reset_dt", false, "Use when restarting a calculation to force a change in dt."); 21 1456740 : params.addRangeCheckedParam<Real>( 22 : "cutback_factor_at_failure", 23 582696 : 0.5, 24 : "cutback_factor_at_failure>0 & cutback_factor_at_failure<1", 25 : "Factor to apply to timestep if a time step fails to converge."); 26 874044 : params.addParam<bool>("enable", true, "whether or not to enable the time stepper"); 27 874044 : params.declareControllable("enable"); 28 : 29 582696 : params.registerBase("TimeStepper"); 30 291348 : params.registerSystemAttributeName("TimeStepper"); 31 : 32 291348 : return params; 33 0 : } 34 : 35 31563 : TimeStepper::TimeStepper(const InputParameters & parameters) 36 : : MooseObject(parameters), 37 : Restartable(this, "TimeSteppers"), 38 : ScalarCoupleable(this), 39 31563 : _fe_problem(parameters.have_parameter<FEProblemBase *>("_fe_problem_base") 40 94689 : ? *getParam<FEProblemBase *>("_fe_problem_base") 41 31563 : : *getParam<FEProblem *>("_fe_problem")), 42 126252 : _executioner(*getCheckedPointerParam<TransientBase *>("_executioner")), 43 31563 : _time(_fe_problem.time()), 44 31563 : _time_old(_fe_problem.timeOld()), 45 31563 : _t_step(_fe_problem.timeStep()), 46 31563 : _dt(_fe_problem.dt()), 47 31563 : _dt_min(_executioner.dtMin()), 48 31563 : _dt_max(_executioner.dtMax()), 49 31563 : _end_time(_executioner.endTime()), 50 31563 : _sync_times(_app.getOutputWarehouse().getSyncTimes()), 51 31563 : _timestep_tolerance(_executioner.timestepTol()), 52 31563 : _verbose(_executioner.verbose()), 53 31563 : _converged(true), 54 63126 : _cutback_factor_at_failure(getParam<Real>("cutback_factor_at_failure")), 55 63126 : _reset_dt(getParam<bool>("reset_dt")), 56 31563 : _has_reset_dt(false), 57 31563 : _failure_count(0), 58 157815 : _current_dt(declareRestartableData<Real>("current_dt", 1.0)) 59 : { 60 31563 : } 61 : 62 29485 : TimeStepper::~TimeStepper() {} 63 : 64 : void 65 29576 : TimeStepper::init() 66 : { 67 29576 : } 68 : 69 : void 70 30868 : TimeStepper::preExecute() 71 : { 72 : // Delete all sync times that are at or before the begin time 73 30899 : while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin()) 74 31 : _sync_times.erase(_sync_times.begin()); 75 30868 : } 76 : 77 : void 78 240446 : TimeStepper::computeStep() 79 : { 80 240446 : if (_t_step < 2 || (_reset_dt && !_has_reset_dt)) 81 : { 82 57654 : _has_reset_dt = true; 83 : 84 115292 : if (converged()) 85 56750 : _current_dt = computeInitialDT(); 86 : else 87 904 : _current_dt = computeFailedDT(); 88 : } 89 : else 90 : { 91 182792 : if (converged()) 92 179497 : _current_dt = computeDT(); 93 : else 94 3295 : _current_dt = computeFailedDT(); 95 : } 96 240325 : if (_current_dt < -TOLERANCE) 97 4 : mooseError("Negative time step detected :" + std::to_string(_current_dt) + 98 : " Investigate the TimeStepper to resolve this error"); 99 240321 : } 100 : 101 : bool 102 188140 : TimeStepper::constrainStep(Real & dt) 103 : { 104 188140 : bool at_sync_point = false; 105 : 106 188140 : std::ostringstream diag; 107 : 108 : // Don't let the time step size exceed maximum time step size 109 188140 : if (dt > _dt_max) 110 : { 111 216 : dt = _dt_max; 112 216 : diag << "Limiting dt to dtmax: " << std::setw(9) << std::setprecision(6) << std::setfill('0') 113 216 : << std::showpoint << std::left << _dt_max << std::endl; 114 : } 115 : 116 : // Don't allow time step size to be smaller than minimum time step size 117 188140 : if (dt < _dt_min) 118 : { 119 172 : dt = _dt_min; 120 172 : diag << "Increasing dt to dtmin: " << std::setw(9) << std::setprecision(6) << std::setfill('0') 121 172 : << std::showpoint << std::left << _dt_min << std::endl; 122 : } 123 : 124 : // Don't let time go beyond simulation end time (unless we're doing a half transient) 125 188140 : if (_time + dt > _end_time && !_app.testCheckpointHalfTransient()) 126 : { 127 1336 : dt = _end_time - _time; 128 : diag << "Limiting dt for end_time: " << std::setw(9) << std::setprecision(6) 129 1336 : << std::setfill('0') << std::showpoint << std::left << _end_time << " dt: " << std::setw(9) 130 1336 : << std::setprecision(6) << std::setfill('0') << std::showpoint << std::left << dt 131 1336 : << std::endl; 132 : } 133 : 134 : // Adjust to a sync time if supplied 135 188140 : if (!_sync_times.empty() && _time + dt + _timestep_tolerance >= (*_sync_times.begin())) 136 : { 137 315 : dt = *_sync_times.begin() - _time; 138 : diag << "Limiting dt for sync_time: " << std::setw(9) << std::setprecision(6) 139 315 : << std::setfill('0') << std::showpoint << std::left << *_sync_times.begin() 140 315 : << " dt: " << std::setw(9) << std::setprecision(6) << std::setfill('0') << std::showpoint 141 315 : << std::left << dt << std::endl; 142 : 143 315 : if (dt <= 0.0) 144 : { 145 0 : _console << diag.str(); 146 0 : mooseError("Adjusting to sync_time resulted in a non-positive time step. dt: ", 147 : dt, 148 : " sync_time: ", 149 0 : *_sync_times.begin(), 150 : " time: ", 151 0 : _time); 152 : } 153 : 154 315 : at_sync_point = true; 155 : } 156 : 157 188140 : if (_verbose) 158 : { 159 5804 : _console << diag.str(); 160 : } 161 : 162 188140 : return at_sync_point; 163 188140 : } 164 : 165 : void 166 255215 : TimeStepper::step() 167 : { 168 255215 : _converged = _executioner.timeStepSolveObject()->solve(); 169 : 170 255072 : if (!_converged) 171 4227 : _failure_count++; 172 255072 : } 173 : 174 : void 175 252221 : TimeStepper::acceptStep() 176 : { 177 : // If there are sync times at or before the current time, delete them 178 252536 : while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin()) 179 : { 180 315 : _sync_times.erase(_sync_times.begin()); 181 : } 182 252221 : } 183 : 184 : void 185 5325 : TimeStepper::rejectStep() 186 : { 187 5325 : _fe_problem.restoreSolutions(); 188 5325 : } 189 : 190 : unsigned int 191 200 : TimeStepper::numFailures() const 192 : { 193 200 : return _failure_count; 194 : } 195 : 196 : bool 197 496379 : TimeStepper::converged() const 198 : { 199 496379 : return _converged; 200 : } 201 : 202 : Real 203 4106 : TimeStepper::computeFailedDT() 204 : { 205 4106 : if (_dt <= _dt_min) 206 117 : mooseError("Solve failed and timestep already at or below dtmin, cannot continue!"); 207 : 208 : // cut the time step 209 3989 : if (_cutback_factor_at_failure * _dt >= _dt_min) 210 3913 : return _cutback_factor_at_failure * _dt; 211 : else // (_cutback_factor_at_failure * _current_dt < _dt_min) 212 76 : return _dt_min; 213 : } 214 : 215 : void 216 0 : TimeStepper::forceTimeStep(Real dt) 217 : { 218 0 : _current_dt = dt; 219 0 : } 220 : 221 : void 222 0 : TimeStepper::forceNumSteps(const unsigned int num_steps) 223 : { 224 0 : _executioner.forceNumSteps(num_steps); 225 0 : }