LCOV - code coverage report
Current view: top level - src/timesteppers - TimeStepper.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 104 115 90.4 %
Date: 2026-05-29 20:35:17 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      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 : }

Generated by: LCOV version 1.14