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 271193 : TimeStepper::validParams() 17 : { 18 271193 : InputParameters params = MooseObject::validParams(); 19 813579 : params.addParam<bool>( 20 542386 : "reset_dt", false, "Use when restarting a calculation to force a change in dt."); 21 813579 : params.addRangeCheckedParam<Real>( 22 : "cutback_factor_at_failure", 23 542386 : 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 271193 : params.addParam<bool>("enable", true, "whether or not to enable the time stepper"); 27 271193 : params.declareControllable("enable"); 28 : 29 271193 : params.registerBase("TimeStepper"); 30 271193 : params.registerSystemAttributeName("TimeStepper"); 31 : 32 271193 : return params; 33 0 : } 34 : 35 28617 : TimeStepper::TimeStepper(const InputParameters & parameters) 36 : : MooseObject(parameters), 37 : Restartable(this, "TimeSteppers"), 38 : ScalarCoupleable(this), 39 28617 : _fe_problem(parameters.have_parameter<FEProblemBase *>("_fe_problem_base") 40 57234 : ? *getParam<FEProblemBase *>("_fe_problem_base") 41 28617 : : *getParam<FEProblem *>("_fe_problem")), 42 28617 : _executioner(*getCheckedPointerParam<TransientBase *>("_executioner")), 43 28617 : _time(_fe_problem.time()), 44 28617 : _time_old(_fe_problem.timeOld()), 45 28617 : _t_step(_fe_problem.timeStep()), 46 28617 : _dt(_fe_problem.dt()), 47 28617 : _dt_min(_executioner.dtMin()), 48 28617 : _dt_max(_executioner.dtMax()), 49 28617 : _end_time(_executioner.endTime()), 50 28617 : _sync_times(_app.getOutputWarehouse().getSyncTimes()), 51 28617 : _timestep_tolerance(_executioner.timestepTol()), 52 28617 : _verbose(_executioner.verbose()), 53 28617 : _converged(true), 54 28617 : _cutback_factor_at_failure(getParam<Real>("cutback_factor_at_failure")), 55 28617 : _reset_dt(getParam<bool>("reset_dt")), 56 28617 : _has_reset_dt(false), 57 28617 : _failure_count(0), 58 57234 : _current_dt(declareRestartableData<Real>("current_dt", 1.0)) 59 : { 60 28617 : } 61 : 62 26584 : TimeStepper::~TimeStepper() {} 63 : 64 : void 65 26874 : TimeStepper::init() 66 : { 67 26874 : } 68 : 69 : void 70 27917 : TimeStepper::preExecute() 71 : { 72 : // Delete all sync times that are at or before the begin time 73 27947 : while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin()) 74 30 : _sync_times.erase(_sync_times.begin()); 75 27917 : } 76 : 77 : void 78 218484 : TimeStepper::computeStep() 79 : { 80 218484 : if (_t_step < 2 || (_reset_dt && !_has_reset_dt)) 81 : { 82 51870 : _has_reset_dt = true; 83 : 84 51870 : if (converged()) 85 50974 : _current_dt = computeInitialDT(); 86 : else 87 896 : _current_dt = computeFailedDT(); 88 : } 89 : else 90 : { 91 166614 : if (converged()) 92 163263 : _current_dt = computeDT(); 93 : else 94 3351 : _current_dt = computeFailedDT(); 95 : } 96 218363 : 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 218359 : } 100 : 101 : bool 102 170500 : TimeStepper::constrainStep(Real & dt) 103 : { 104 170500 : bool at_sync_point = false; 105 : 106 170500 : std::ostringstream diag; 107 : 108 : // Don't let the time step size exceed maximum time step size 109 170500 : if (dt > _dt_max) 110 : { 111 198 : dt = _dt_max; 112 198 : diag << "Limiting dt to dtmax: " << std::setw(9) << std::setprecision(6) << std::setfill('0') 113 198 : << 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 170500 : if (dt < _dt_min) 118 : { 119 154 : dt = _dt_min; 120 154 : diag << "Increasing dt to dtmin: " << std::setw(9) << std::setprecision(6) << std::setfill('0') 121 154 : << 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 170500 : if (_time + dt > _end_time && !_app.testCheckpointHalfTransient()) 126 : { 127 1225 : dt = _end_time - _time; 128 : diag << "Limiting dt for end_time: " << std::setw(9) << std::setprecision(6) 129 1225 : << std::setfill('0') << std::showpoint << std::left << _end_time << " dt: " << std::setw(9) 130 1225 : << std::setprecision(6) << std::setfill('0') << std::showpoint << std::left << dt 131 1225 : << std::endl; 132 : } 133 : 134 : // Adjust to a sync time if supplied 135 170500 : if (!_sync_times.empty() && _time + dt + _timestep_tolerance >= (*_sync_times.begin())) 136 : { 137 288 : dt = *_sync_times.begin() - _time; 138 : diag << "Limiting dt for sync_time: " << std::setw(9) << std::setprecision(6) 139 288 : << std::setfill('0') << std::showpoint << std::left << *_sync_times.begin() 140 288 : << " dt: " << std::setw(9) << std::setprecision(6) << std::setfill('0') << std::showpoint 141 288 : << std::left << dt << std::endl; 142 : 143 288 : 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 288 : at_sync_point = true; 155 : } 156 : 157 170500 : if (_verbose) 158 : { 159 5258 : _console << diag.str(); 160 : } 161 : 162 170500 : return at_sync_point; 163 170500 : } 164 : 165 : void 166 231888 : TimeStepper::step() 167 : { 168 231888 : _converged = _executioner.timeStepSolveObject()->solve(); 169 : 170 231746 : if (!_converged) 171 4273 : _failure_count++; 172 231746 : } 173 : 174 : void 175 229094 : TimeStepper::acceptStep() 176 : { 177 : // If there are sync times at or before the current time, delete them 178 229382 : while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin()) 179 : { 180 288 : _sync_times.erase(_sync_times.begin()); 181 : } 182 229094 : } 183 : 184 : void 185 4214 : TimeStepper::rejectStep() 186 : { 187 4214 : _fe_problem.restoreSolutions(); 188 4214 : } 189 : 190 : unsigned int 191 200 : TimeStepper::numFailures() const 192 : { 193 200 : return _failure_count; 194 : } 195 : 196 : bool 197 451621 : TimeStepper::converged() const 198 : { 199 451621 : return _converged; 200 : } 201 : 202 : Real 203 4162 : TimeStepper::computeFailedDT() 204 : { 205 4162 : 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 4045 : if (_cutback_factor_at_failure * _dt >= _dt_min) 210 3969 : 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 : }