LCOV - code coverage report
Current view: top level - src/timesteppers - TimeStepper.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 26ef6a Lines: 104 115 90.4 %
Date: 2026-06-24 21:19:51 Functions: 13 16 81.2 %
Legend: Lines: hit not hit

          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      110515 : TimeStepper::validParams()
      17             : {
      18      110515 :   InputParameters params = MooseObject::validParams();
      19      331545 :   params.addParam<bool>(
      20      221030 :       "reset_dt", false, "Use when restarting a calculation to force a change in dt.");
      21      552575 :   params.addRangeCheckedParam<Real>(
      22             :       "cutback_factor_at_failure",
      23      221030 :       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      331545 :   params.addParam<bool>("enable", true, "whether or not to enable the time stepper");
      27      331545 :   params.declareControllable("enable");
      28             : 
      29      221030 :   params.registerBase("TimeStepper");
      30      110515 :   params.registerSystemAttributeName("TimeStepper");
      31             : 
      32      110515 :   return params;
      33           0 : }
      34             : 
      35       30780 : TimeStepper::TimeStepper(const InputParameters & parameters)
      36             :   : MooseObject(parameters),
      37             :     Restartable(this, "TimeSteppers"),
      38             :     ScalarCoupleable(this),
      39       30780 :     _fe_problem(parameters.have_parameter<FEProblemBase *>("_fe_problem_base")
      40       92340 :                     ? *getParam<FEProblemBase *>("_fe_problem_base")
      41       30780 :                     : *getParam<FEProblem *>("_fe_problem")),
      42      123120 :     _executioner(*getCheckedPointerParam<TransientBase *>("_executioner")),
      43       30780 :     _time(_fe_problem.time()),
      44       30780 :     _time_old(_fe_problem.timeOld()),
      45       30780 :     _t_step(_fe_problem.timeStep()),
      46       30780 :     _dt(_fe_problem.dt()),
      47       30780 :     _dt_min(_executioner.dtMin()),
      48       30780 :     _dt_max(_executioner.dtMax()),
      49       30780 :     _end_time(_executioner.endTime()),
      50       30780 :     _sync_times(_app.getOutputWarehouse().getSyncTimes()),
      51       30780 :     _timestep_tolerance(_executioner.timestepTol()),
      52       30780 :     _verbose(_executioner.verbose()),
      53       30780 :     _converged(true),
      54       61560 :     _cutback_factor_at_failure(getParam<Real>("cutback_factor_at_failure")),
      55       61560 :     _reset_dt(getParam<bool>("reset_dt")),
      56       30780 :     _has_reset_dt(false),
      57       30780 :     _currently_restepping(false),
      58       30780 :     _failure_count(0),
      59      153900 :     _current_dt(declareRestartableData<Real>("current_dt", 1.0))
      60             : {
      61       30780 : }
      62             : 
      63       29475 : TimeStepper::~TimeStepper() {}
      64             : 
      65             : void
      66       28988 : TimeStepper::init()
      67             : {
      68       28988 : }
      69             : 
      70             : void
      71       30640 : TimeStepper::preExecute()
      72             : {
      73             :   // Delete all sync times that are at or before the begin time
      74       30670 :   while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin())
      75          30 :     _sync_times.erase(_sync_times.begin());
      76       30640 : }
      77             : 
      78             : void
      79      227305 : TimeStepper::computeStep()
      80             : {
      81      227305 :   if (_t_step < 2 || (_reset_dt && !_has_reset_dt))
      82             :   {
      83       57281 :     _has_reset_dt = true;
      84             : 
      85      114551 :     if (converged())
      86       56434 :       _current_dt = computeInitialDT();
      87             :     else
      88         847 :       _current_dt = computeFailedDT();
      89             :   }
      90             :   else
      91             :   {
      92      170024 :     if (converged())
      93      168744 :       _current_dt = computeDT();
      94             :     else
      95        1280 :       _current_dt = computeFailedDT();
      96             :   }
      97      227246 :   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      227243 : }
     101             : 
     102             : bool
     103      177024 : TimeStepper::constrainStep(Real & dt)
     104             : {
     105      177024 :   bool at_sync_point = false;
     106             : 
     107      177024 :   std::ostringstream diag;
     108             : 
     109             :   // Don't let the time step size exceed maximum time step size
     110      177024 :   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      177024 :   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      177024 :   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      177024 :   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      177024 :   if (_verbose)
     159             :   {
     160        5158 :     _console << diag.str();
     161             :   }
     162             : 
     163      177024 :   return at_sync_point;
     164      177024 : }
     165             : 
     166             : void
     167      239409 : TimeStepper::step()
     168             : {
     169      239409 :   _converged = _executioner.timeStepSolveObject()->solve();
     170             : 
     171      239289 :   if (!_converged)
     172        2157 :     _failure_count++;
     173      239289 : }
     174             : 
     175             : void
     176      238739 : TimeStepper::acceptStep()
     177             : {
     178             :   // If there are sync times at or before the current time, delete them
     179      239015 :   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      238739 :   _currently_restepping = false;
     185      238739 : }
     186             : 
     187             : void
     188        3334 : TimeStepper::rejectStep()
     189             : {
     190        3334 :   _currently_restepping = true;
     191        3334 :   _fe_problem.restoreSolutions();
     192        3334 : }
     193             : 
     194             : unsigned int
     195         180 : TimeStepper::numFailures() const
     196             : {
     197         180 :   return _failure_count;
     198             : }
     199             : 
     200             : bool
     201      467483 : TimeStepper::converged() const
     202             : {
     203      467483 :   return _converged;
     204             : }
     205             : 
     206             : Real
     207        2045 : TimeStepper::computeFailedDT()
     208             : {
     209        2045 :   if (_dt <= _dt_min)
     210          56 :     mooseError("Solve failed and timestep already at or below dtmin, cannot continue!");
     211             : 
     212             :   // cut the time step
     213        1989 :   if (_cutback_factor_at_failure * _dt >= _dt_min)
     214        1961 :     return _cutback_factor_at_failure * _dt;
     215             :   else // (_cutback_factor_at_failure * _current_dt < _dt_min)
     216          28 :     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 : }

Generated by: LCOV version 1.14