LCOV - code coverage report
Current view: top level - src/timesteppers - TimeSequenceStepperBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 1f9d31 Lines: 84 91 92.3 %
Date: 2025-09-02 20:01:20 Functions: 9 9 100.0 %
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 "TimeSequenceStepperBase.h"
      11             : #include "FEProblem.h"
      12             : #include "Transient.h"
      13             : 
      14             : #include <algorithm>
      15             : #include <functional>
      16             : 
      17             : InputParameters
      18       71995 : TimeSequenceStepperBase::validParams()
      19             : {
      20       71995 :   InputParameters params = TimeStepper::validParams();
      21      215985 :   params.addParam<bool>(
      22             :       "use_last_dt_after_last_t",
      23      143990 :       false,
      24             :       "If true, uses the final time step size for times after the last time in the sequence, "
      25             :       "instead of taking a single step directly to the simulation end time");
      26      143990 :   params.addParam<bool>(
      27      143990 :       "use_last_t_for_end_time", false, "Use last time in sequence as 'end_time' in Executioner.");
      28       71995 :   return params;
      29           0 : }
      30             : 
      31         336 : TimeSequenceStepperBase::TimeSequenceStepperBase(const InputParameters & parameters)
      32             :   : TimeStepper(parameters),
      33         336 :     _use_last_dt_after_last_t(getParam<bool>("use_last_dt_after_last_t")),
      34         672 :     _current_step(declareRestartableData<unsigned int>("current_step", 0)),
      35         672 :     _time_sequence(declareRestartableData<std::vector<Real>>("time_sequence")),
      36        1008 :     _set_end_time(getParam<bool>("use_last_t_for_end_time"))
      37             : {
      38         336 : }
      39             : 
      40             : void
      41         336 : TimeSequenceStepperBase::setupSequence(const std::vector<Real> & times)
      42             : {
      43             :   // In case of half transient, transient's end time needs to be reset to
      44             :   // be able to imprint TimeSequenceStepperBase's end time
      45         336 :   if (_app.testCheckpointHalfTransient())
      46          14 :     _executioner.endTime() = _executioner.endTime() * 2.0 - _executioner.getStartTime();
      47             : 
      48             :   // only set up _time_sequence if the app is _not_ recovering
      49         336 :   if (!_app.isRecovering())
      50             :   {
      51             :     // also we need to do something different when restarting
      52         322 :     if (!_app.isRestarting() || _time_sequence.empty())
      53         275 :       updateSequence(times);
      54             :     else
      55             :     {
      56             :       // in case of restart it should be allowed to modify _time_sequence if it follows the
      57             :       // following rule:
      58             :       // all times up to _current_step are identical
      59             :       // 1. start time cannot be modified
      60             :       // 2. the entries in _time_sequence and times must be equal up to entry with index
      61             :       // _current_step
      62             : 
      63          47 :       if (!MooseUtils::absoluteFuzzyEqual(_executioner.getStartTime(), _time_sequence[0]))
      64           0 :         mooseError("Timesequencestepper does not allow the start time to be modified.");
      65             : 
      66             :       // sync _executioner.endTime with _time_sequence
      67          47 :       Real end_time = _executioner.endTime();
      68             : 
      69             :       // make sure time sequence is in ascending order
      70         243 :       for (unsigned int j = 0; j < times.size() - 1; ++j)
      71         196 :         if (times[j + 1] <= times[j])
      72           0 :           mooseError("time_sequence must be in ascending order.");
      73             : 
      74          47 :       if (times.size() < _current_step + 1)
      75          14 :         mooseError("The timesequence provided in the restart file must be identical to "
      76             :                    "the one in the old file up to entry number ",
      77           0 :                    _current_step + 1,
      78             :                    " but there are only ",
      79           7 :                    times.size(),
      80             :                    " value(s) provided for the timesequence in the restart input.");
      81             : 
      82             :       // save the restarted time_sequence
      83          40 :       std::vector<Real> saved_time_sequence = _time_sequence;
      84             : 
      85          40 :       _time_sequence.clear();
      86             : 
      87             :       // step 1: fill in the entries up to _current_step
      88         153 :       for (unsigned int j = 0; j <= _current_step; ++j)
      89             :       {
      90         120 :         if (!MooseUtils::absoluteFuzzyEqual(times[j], saved_time_sequence[j]))
      91          14 :           mooseError("The timesequence provided in the restart file must be identical to "
      92             :                      "the one in the old file up to entry number ",
      93           0 :                      _current_step + 1,
      94             :                      " but entry ",
      95           7 :                      j + 1,
      96             :                      " is ",
      97           7 :                      times[j],
      98             :                      " in the restart input but ",
      99           7 :                      saved_time_sequence[j],
     100             :                      " in the restarted input.");
     101             : 
     102         113 :         _time_sequence.push_back(saved_time_sequence[j]);
     103             :       }
     104             : 
     105             :       // step 2: fill in the entries up after _current_step
     106         121 :       for (unsigned int j = _current_step + 1; j < times.size(); ++j)
     107             :       {
     108          88 :         if (times[j] < end_time)
     109          66 :           _time_sequence.push_back(times[j]);
     110             :       }
     111             : 
     112          33 :       if (!_set_end_time)
     113          33 :         _time_sequence.push_back(end_time);
     114          33 :     }
     115             :   }
     116             : 
     117             :   // Set end time to last time in sequence if requested
     118         314 :   if (_set_end_time)
     119             :   {
     120          13 :     auto & end_time = _executioner.endTime();
     121          13 :     end_time = _time_sequence.back();
     122             :   }
     123             : 
     124         314 :   if (_app.testCheckpointHalfTransient())
     125             :   {
     126          14 :     unsigned int half = (_time_sequence.size() - 1) / 2;
     127          14 :     _executioner.endTime() = _time_sequence[half];
     128             :   }
     129         314 : }
     130             : 
     131             : void
     132         563 : TimeSequenceStepperBase::updateSequence(const std::vector<Real> & times)
     133             : {
     134         563 :   Real start_time = _executioner.getStartTime();
     135         563 :   Real end_time = _executioner.endTime();
     136             : 
     137             :   // make sure time sequence is in strictly ascending order
     138         563 :   if (!std::is_sorted(times.begin(), times.end(), std::less_equal<Real>()))
     139          16 :     paramError("time_sequence", "Time points must be in strictly ascending order.");
     140             : 
     141         555 :   _time_sequence.push_back(start_time);
     142        3002 :   for (unsigned int j = 0; j < times.size(); ++j)
     143             :   {
     144        2447 :     if (times[j] > start_time && times[j] < end_time)
     145        2038 :       _time_sequence.push_back(times[j]);
     146             :   }
     147             : 
     148         555 :   if (!_set_end_time)
     149         543 :     _time_sequence.push_back(end_time);
     150         555 : }
     151             : 
     152             : void
     153         288 : TimeSequenceStepperBase::resetSequence()
     154             : {
     155         288 :   _time_sequence.clear();
     156         288 : }
     157             : 
     158             : void
     159        1849 : TimeSequenceStepperBase::acceptStep()
     160             : {
     161        1849 :   TimeStepper::acceptStep();
     162        1849 :   if (MooseUtils::absoluteFuzzyGreaterEqual(_time, getNextTimeInSequence()))
     163        1226 :     increaseCurrentStep();
     164        1849 : }
     165             : 
     166             : Real
     167         362 : TimeSequenceStepperBase::computeInitialDT()
     168             : {
     169         362 :   return computeDT();
     170             : }
     171             : 
     172             : Real
     173         972 : TimeSequenceStepperBase::computeDT()
     174             : {
     175         972 :   if (_use_last_dt_after_last_t)
     176             :   {
     177             :     // last *provided* time value index; actual last index corresponds to end time
     178          84 :     const auto last_t_index = _time_sequence.size() - 2;
     179          84 :     if (_current_step + 1 > last_t_index)
     180          24 :       return _time_sequence[last_t_index] - _time_sequence[last_t_index - 1];
     181             :     else
     182          60 :       return _time_sequence[_current_step + 1] - _time_sequence[_current_step];
     183             :   }
     184             :   else
     185         888 :     return _time_sequence[_current_step + 1] - _time_sequence[_current_step];
     186             : }
     187             : 
     188             : Real
     189           9 : TimeSequenceStepperBase::computeFailedDT()
     190             : {
     191           9 :   if (computeDT() <= _dt_min)
     192           0 :     mooseError("Solve failed and timestep already at or below dtmin, cannot continue!");
     193             : 
     194             :   // cut the time step in a half if possible
     195           9 :   Real dt = _cutback_factor_at_failure * computeDT();
     196           9 :   if (dt < _dt_min)
     197           0 :     dt = _dt_min;
     198           9 :   _time_sequence.insert(_time_sequence.begin() + _current_step + 1,
     199           9 :                         _time_sequence[_current_step] + dt);
     200           9 :   return computeDT();
     201             : }

Generated by: LCOV version 1.14