LCOV - code coverage report
Current view: top level - src/timesteppers - TimeStepper.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 101 112 90.2 %
Date: 2025-08-08 20:01:16 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      275671 : TimeStepper::validParams()
      17             : {
      18      275671 :   InputParameters params = MooseObject::validParams();
      19      827013 :   params.addParam<bool>(
      20      551342 :       "reset_dt", false, "Use when restarting a calculation to force a change in dt.");
      21      827013 :   params.addRangeCheckedParam<Real>(
      22             :       "cutback_factor_at_failure",
      23      551342 :       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      275671 :   params.addParam<bool>("enable", true, "whether or not to enable the time stepper");
      27      275671 :   params.declareControllable("enable");
      28             : 
      29      275671 :   params.registerBase("TimeStepper");
      30      275671 :   params.registerSystemAttributeName("TimeStepper");
      31             : 
      32      275671 :   return params;
      33           0 : }
      34             : 
      35       30856 : TimeStepper::TimeStepper(const InputParameters & parameters)
      36             :   : MooseObject(parameters),
      37             :     Restartable(this, "TimeSteppers"),
      38             :     ScalarCoupleable(this),
      39       30856 :     _fe_problem(parameters.have_parameter<FEProblemBase *>("_fe_problem_base")
      40       61712 :                     ? *getParam<FEProblemBase *>("_fe_problem_base")
      41       30856 :                     : *getParam<FEProblem *>("_fe_problem")),
      42       30856 :     _executioner(*getCheckedPointerParam<TransientBase *>("_executioner")),
      43       30856 :     _time(_fe_problem.time()),
      44       30856 :     _time_old(_fe_problem.timeOld()),
      45       30856 :     _t_step(_fe_problem.timeStep()),
      46       30856 :     _dt(_fe_problem.dt()),
      47       30856 :     _dt_min(_executioner.dtMin()),
      48       30856 :     _dt_max(_executioner.dtMax()),
      49       30856 :     _end_time(_executioner.endTime()),
      50       30856 :     _sync_times(_app.getOutputWarehouse().getSyncTimes()),
      51       30856 :     _timestep_tolerance(_executioner.timestepTol()),
      52       30856 :     _verbose(_executioner.verbose()),
      53       30856 :     _converged(true),
      54       30856 :     _cutback_factor_at_failure(getParam<Real>("cutback_factor_at_failure")),
      55       30856 :     _reset_dt(getParam<bool>("reset_dt")),
      56       30856 :     _has_reset_dt(false),
      57       30856 :     _failure_count(0),
      58       61712 :     _current_dt(declareRestartableData<Real>("current_dt", 1.0))
      59             : {
      60       30856 : }
      61             : 
      62       28807 : TimeStepper::~TimeStepper() {}
      63             : 
      64             : void
      65       29042 : TimeStepper::init()
      66             : {
      67       29042 : }
      68             : 
      69             : void
      70       30222 : TimeStepper::preExecute()
      71             : {
      72             :   // Delete all sync times that are at or before the begin time
      73       30253 :   while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin())
      74          31 :     _sync_times.erase(_sync_times.begin());
      75       30222 : }
      76             : 
      77             : void
      78      237374 : TimeStepper::computeStep()
      79             : {
      80      237374 :   if (_t_step < 2 || (_reset_dt && !_has_reset_dt))
      81             :   {
      82       56446 :     _has_reset_dt = true;
      83             : 
      84       56446 :     if (converged())
      85       55542 :       _current_dt = computeInitialDT();
      86             :     else
      87         904 :       _current_dt = computeFailedDT();
      88             :   }
      89             :   else
      90             :   {
      91      180928 :     if (converged())
      92      177633 :       _current_dt = computeDT();
      93             :     else
      94        3295 :       _current_dt = computeFailedDT();
      95             :   }
      96      237253 :   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      237249 : }
     100             : 
     101             : bool
     102      185314 : TimeStepper::constrainStep(Real & dt)
     103             : {
     104      185314 :   bool at_sync_point = false;
     105             : 
     106      185314 :   std::ostringstream diag;
     107             : 
     108             :   // Don't let the time step size exceed maximum time step size
     109      185314 :   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      185314 :   if (dt < _dt_min)
     118             :   {
     119         168 :     dt = _dt_min;
     120         168 :     diag << "Increasing dt to dtmin: " << std::setw(9) << std::setprecision(6) << std::setfill('0')
     121         168 :          << 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      185314 :   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      185314 :   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      185314 :   if (_verbose)
     158             :   {
     159        5684 :     _console << diag.str();
     160             :   }
     161             : 
     162      185314 :   return at_sync_point;
     163      185314 : }
     164             : 
     165             : void
     166      253335 : TimeStepper::step()
     167             : {
     168      253335 :   _converged = _executioner.timeStepSolveObject()->solve();
     169             : 
     170      253193 :   if (!_converged)
     171        4227 :     _failure_count++;
     172      253193 : }
     173             : 
     174             : void
     175      249597 : TimeStepper::acceptStep()
     176             : {
     177             :   // If there are sync times at or before the current time, delete them
     178      249912 :   while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin())
     179             :   {
     180         315 :     _sync_times.erase(_sync_times.begin());
     181             :   }
     182      249597 : }
     183             : 
     184             : void
     185        5304 : TimeStepper::rejectStep()
     186             : {
     187        5304 :   _fe_problem.restoreSolutions();
     188        5304 : }
     189             : 
     190             : unsigned int
     191         200 : TimeStepper::numFailures() const
     192             : {
     193         200 :   return _failure_count;
     194             : }
     195             : 
     196             : bool
     197      491165 : TimeStepper::converged() const
     198             : {
     199      491165 :   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 : }

Generated by: LCOV version 1.14