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 109781 : TimeStepper::validParams() 17 : { 18 109781 : InputParameters params = MooseObject::validParams(); 19 329343 : params.addParam<bool>( 20 219562 : "reset_dt", false, "Use when restarting a calculation to force a change in dt."); 21 548905 : params.addRangeCheckedParam<Real>( 22 : "cutback_factor_at_failure", 23 219562 : 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 329343 : params.addParam<bool>("enable", true, "whether or not to enable the time stepper"); 27 329343 : params.declareControllable("enable"); 28 : 29 219562 : params.registerBase("TimeStepper"); 30 109781 : params.registerSystemAttributeName("TimeStepper"); 31 : 32 109781 : return params; 33 0 : } 34 : 35 30413 : TimeStepper::TimeStepper(const InputParameters & parameters) 36 : : MooseObject(parameters), 37 : Restartable(this, "TimeSteppers"), 38 : ScalarCoupleable(this), 39 30413 : _fe_problem(parameters.have_parameter<FEProblemBase *>("_fe_problem_base") 40 91239 : ? *getParam<FEProblemBase *>("_fe_problem_base") 41 30413 : : *getParam<FEProblem *>("_fe_problem")), 42 121652 : _executioner(*getCheckedPointerParam<TransientBase *>("_executioner")), 43 30413 : _time(_fe_problem.time()), 44 30413 : _time_old(_fe_problem.timeOld()), 45 30413 : _t_step(_fe_problem.timeStep()), 46 30413 : _dt(_fe_problem.dt()), 47 30413 : _dt_min(_executioner.dtMin()), 48 30413 : _dt_max(_executioner.dtMax()), 49 30413 : _end_time(_executioner.endTime()), 50 30413 : _sync_times(_app.getOutputWarehouse().getSyncTimes()), 51 30413 : _timestep_tolerance(_executioner.timestepTol()), 52 30413 : _verbose(_executioner.verbose()), 53 30413 : _converged(true), 54 60826 : _cutback_factor_at_failure(getParam<Real>("cutback_factor_at_failure")), 55 60826 : _reset_dt(getParam<bool>("reset_dt")), 56 30413 : _has_reset_dt(false), 57 30413 : _currently_restepping(false), 58 30413 : _failure_count(0), 59 152065 : _current_dt(declareRestartableData<Real>("current_dt", 1.0)) 60 : { 61 30413 : } 62 : 63 29109 : TimeStepper::~TimeStepper() {} 64 : 65 : void 66 28621 : TimeStepper::init() 67 : { 68 28621 : } 69 : 70 : void 71 29832 : TimeStepper::preExecute() 72 : { 73 : // Delete all sync times that are at or before the begin time 74 29862 : while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin()) 75 30 : _sync_times.erase(_sync_times.begin()); 76 29832 : } 77 : 78 : void 79 222581 : TimeStepper::computeStep() 80 : { 81 222581 : if (_t_step < 2 || (_reset_dt && !_has_reset_dt)) 82 : { 83 55626 : _has_reset_dt = true; 84 : 85 111242 : if (converged()) 86 54806 : _current_dt = computeInitialDT(); 87 : else 88 820 : _current_dt = computeFailedDT(); 89 : } 90 : else 91 : { 92 166955 : if (converged()) 93 165687 : _current_dt = computeDT(); 94 : else 95 1268 : _current_dt = computeFailedDT(); 96 : } 97 222523 : if (_current_dt < -TOLERANCE) 98 3 : mooseError("Negative time step detected :" + std::to_string(_current_dt) + 99 : " Investigate the TimeStepper to resolve this error"); 100 222520 : } 101 : 102 : bool 103 173513 : TimeStepper::constrainStep(Real & dt) 104 : { 105 173513 : bool at_sync_point = false; 106 : 107 173513 : std::ostringstream diag; 108 : 109 : // Don't let the time step size exceed maximum time step size 110 173513 : if (dt > _dt_max) 111 : { 112 197 : dt = _dt_max; 113 197 : diag << "Limiting dt to dtmax: " << std::setw(9) << std::setprecision(6) << std::setfill('0') 114 197 : << std::showpoint << std::left << _dt_max << std::endl; 115 : } 116 : 117 : // Don't allow time step size to be smaller than minimum time step size 118 173513 : if (dt < _dt_min) 119 : { 120 157 : dt = _dt_min; 121 157 : diag << "Increasing dt to dtmin: " << std::setw(9) << std::setprecision(6) << std::setfill('0') 122 157 : << std::showpoint << std::left << _dt_min << std::endl; 123 : } 124 : 125 : // Don't let time go beyond simulation end time (unless we're doing a half transient) 126 173513 : if (_time + dt > _end_time && !_app.testCheckpointHalfTransient()) 127 : { 128 1203 : dt = _end_time - _time; 129 : diag << "Limiting dt for end_time: " << std::setw(9) << std::setprecision(6) 130 1203 : << std::setfill('0') << std::showpoint << std::left << _end_time << " dt: " << std::setw(9) 131 1203 : << std::setprecision(6) << std::setfill('0') << std::showpoint << std::left << dt 132 1203 : << std::endl; 133 : } 134 : 135 : // Adjust to a sync time if supplied 136 173513 : if (!_sync_times.empty() && _time + dt + _timestep_tolerance >= (*_sync_times.begin())) 137 : { 138 276 : dt = *_sync_times.begin() - _time; 139 : diag << "Limiting dt for sync_time: " << std::setw(9) << std::setprecision(6) 140 276 : << std::setfill('0') << std::showpoint << std::left << *_sync_times.begin() 141 276 : << " dt: " << std::setw(9) << std::setprecision(6) << std::setfill('0') << std::showpoint 142 276 : << std::left << dt << std::endl; 143 : 144 276 : if (dt <= 0.0) 145 : { 146 0 : _console << diag.str(); 147 0 : mooseError("Adjusting to sync_time resulted in a non-positive time step. dt: ", 148 : dt, 149 : " sync_time: ", 150 0 : *_sync_times.begin(), 151 : " time: ", 152 0 : _time); 153 : } 154 : 155 276 : at_sync_point = true; 156 : } 157 : 158 173513 : if (_verbose) 159 : { 160 5142 : _console << diag.str(); 161 : } 162 : 163 173513 : return at_sync_point; 164 173513 : } 165 : 166 : void 167 235725 : TimeStepper::step() 168 : { 169 235725 : _converged = _executioner.timeStepSolveObject()->solve(); 170 : 171 235605 : if (!_converged) 172 2118 : _failure_count++; 173 235605 : } 174 : 175 : void 176 235094 : TimeStepper::acceptStep() 177 : { 178 : // If there are sync times at or before the current time, delete them 179 235370 : while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin()) 180 : { 181 276 : _sync_times.erase(_sync_times.begin()); 182 : } 183 : // If we accept a step, we are no longer taking a failed step again 184 235094 : _currently_restepping = false; 185 235094 : } 186 : 187 : void 188 3295 : TimeStepper::rejectStep() 189 : { 190 3295 : _currently_restepping = true; 191 3295 : _fe_problem.restoreSolutions(); 192 3295 : } 193 : 194 : unsigned int 195 180 : TimeStepper::numFailures() const 196 : { 197 180 : return _failure_count; 198 : } 199 : 200 : bool 201 459075 : TimeStepper::converged() const 202 : { 203 459075 : return _converged; 204 : } 205 : 206 : Real 207 2006 : TimeStepper::computeFailedDT() 208 : { 209 2006 : if (_dt <= _dt_min) 210 55 : mooseError("Solve failed and timestep already at or below dtmin, cannot continue!"); 211 : 212 : // cut the time step 213 1951 : if (_cutback_factor_at_failure * _dt >= _dt_min) 214 1924 : return _cutback_factor_at_failure * _dt; 215 : else // (_cutback_factor_at_failure * _current_dt < _dt_min) 216 27 : return _dt_min; 217 : } 218 : 219 : void 220 0 : TimeStepper::forceTimeStep(Real dt) 221 : { 222 0 : _current_dt = dt; 223 0 : } 224 : 225 : void 226 0 : TimeStepper::forceNumSteps(const unsigned int num_steps) 227 : { 228 0 : _executioner.forceNumSteps(num_steps); 229 0 : }