LCOV - code coverage report
Current view: top level - src/timesteppers - TimeStepper.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 101 112 90.2 %
Date: 2025-07-17 01:28:37 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      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 : }

Generated by: LCOV version 1.14