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 300078 : TimeStepper::validParams() 17 : { 18 300078 : InputParameters params = MooseObject::validParams(); 19 900234 : params.addParam<bool>( 20 600156 : "reset_dt", false, "Use when restarting a calculation to force a change in dt."); 21 1500390 : params.addRangeCheckedParam<Real>( 22 : "cutback_factor_at_failure", 23 600156 : 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 900234 : params.addParam<bool>("enable", true, "whether or not to enable the time stepper"); 27 900234 : params.declareControllable("enable"); 28 : 29 600156 : params.registerBase("TimeStepper"); 30 300078 : params.registerSystemAttributeName("TimeStepper"); 31 : 32 300078 : return params; 33 0 : } 34 : 35 32088 : TimeStepper::TimeStepper(const InputParameters & parameters) 36 : : MooseObject(parameters), 37 : Restartable(this, "TimeSteppers"), 38 : ScalarCoupleable(this), 39 32088 : _fe_problem(parameters.have_parameter<FEProblemBase *>("_fe_problem_base") 40 96264 : ? *getParam<FEProblemBase *>("_fe_problem_base") 41 32088 : : *getParam<FEProblem *>("_fe_problem")), 42 128352 : _executioner(*getCheckedPointerParam<TransientBase *>("_executioner")), 43 32088 : _time(_fe_problem.time()), 44 32088 : _time_old(_fe_problem.timeOld()), 45 32088 : _t_step(_fe_problem.timeStep()), 46 32088 : _dt(_fe_problem.dt()), 47 32088 : _dt_min(_executioner.dtMin()), 48 32088 : _dt_max(_executioner.dtMax()), 49 32088 : _end_time(_executioner.endTime()), 50 32088 : _sync_times(_app.getOutputWarehouse().getSyncTimes()), 51 32088 : _timestep_tolerance(_executioner.timestepTol()), 52 32088 : _verbose(_executioner.verbose()), 53 32088 : _converged(true), 54 64176 : _cutback_factor_at_failure(getParam<Real>("cutback_factor_at_failure")), 55 64176 : _reset_dt(getParam<bool>("reset_dt")), 56 32088 : _has_reset_dt(false), 57 32088 : _failure_count(0), 58 160440 : _current_dt(declareRestartableData<Real>("current_dt", 1.0)) 59 : { 60 32088 : } 61 : 62 29950 : TimeStepper::~TimeStepper() {} 63 : 64 : void 65 30077 : TimeStepper::init() 66 : { 67 30077 : } 68 : 69 : void 70 31334 : TimeStepper::preExecute() 71 : { 72 : // Delete all sync times that are at or before the begin time 73 31365 : while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin()) 74 31 : _sync_times.erase(_sync_times.begin()); 75 31334 : } 76 : 77 : void 78 242904 : TimeStepper::computeStep() 79 : { 80 242904 : if (_t_step < 2 || (_reset_dt && !_has_reset_dt)) 81 : { 82 58474 : _has_reset_dt = true; 83 : 84 116932 : if (converged()) 85 57570 : _current_dt = computeInitialDT(); 86 : else 87 904 : _current_dt = computeFailedDT(); 88 : } 89 : else 90 : { 91 184430 : if (converged()) 92 181133 : _current_dt = computeDT(); 93 : else 94 3297 : _current_dt = computeFailedDT(); 95 : } 96 242781 : 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 242777 : } 100 : 101 : bool 102 190186 : TimeStepper::constrainStep(Real & dt) 103 : { 104 190186 : bool at_sync_point = false; 105 : 106 190186 : std::ostringstream diag; 107 : 108 : // Don't let the time step size exceed maximum time step size 109 190186 : 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 190186 : 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 190186 : 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 190186 : 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 190186 : if (_verbose) 158 : { 159 5804 : _console << diag.str(); 160 : } 161 : 162 190186 : return at_sync_point; 163 190186 : } 164 : 165 : void 166 257290 : TimeStepper::step() 167 : { 168 257290 : _converged = _executioner.timeStepSolveObject()->solve(); 169 : 170 257147 : if (!_converged) 171 4229 : _failure_count++; 172 257147 : } 173 : 174 : void 175 254265 : TimeStepper::acceptStep() 176 : { 177 : // If there are sync times at or before the current time, delete them 178 254580 : while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin()) 179 : { 180 315 : _sync_times.erase(_sync_times.begin()); 181 : } 182 254265 : } 183 : 184 : void 185 5356 : TimeStepper::rejectStep() 186 : { 187 5356 : _fe_problem.restoreSolutions(); 188 5356 : } 189 : 190 : unsigned int 191 200 : TimeStepper::numFailures() const 192 : { 193 200 : return _failure_count; 194 : } 195 : 196 : bool 197 500912 : TimeStepper::converged() const 198 : { 199 500912 : return _converged; 200 : } 201 : 202 : Real 203 4108 : TimeStepper::computeFailedDT() 204 : { 205 4108 : if (_dt <= _dt_min) 206 119 : 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 : }