LCOV - code coverage report
Current view: top level - src/timesteppers - TimeSequenceStepperBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 66 71 93.0 %
Date: 2025-08-08 20:01:16 Functions: 7 7 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       71799 : TimeSequenceStepperBase::validParams()
      19             : {
      20       71799 :   InputParameters params = TimeStepper::validParams();
      21      215397 :   params.addParam<bool>(
      22             :       "use_last_dt_after_last_t",
      23      143598 :       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       71799 :   return params;
      27           0 : }
      28             : 
      29         238 : TimeSequenceStepperBase::TimeSequenceStepperBase(const InputParameters & parameters)
      30             :   : TimeStepper(parameters),
      31         238 :     _use_last_dt_after_last_t(getParam<bool>("use_last_dt_after_last_t")),
      32         238 :     _current_step(declareRestartableData<unsigned int>("current_step", 0)),
      33         476 :     _time_sequence(declareRestartableData<std::vector<Real>>("time_sequence"))
      34             : {
      35         238 : }
      36             : 
      37             : void
      38         262 : TimeSequenceStepperBase::setupSequence(const std::vector<Real> & times)
      39             : {
      40             :   // In case of half transient, transient's end time needs to be reset to
      41             :   // be able to imprint TimeSequenceStepperBase's end time
      42         262 :   if (_app.testCheckpointHalfTransient())
      43          11 :     _executioner.endTime() = _executioner.endTime() * 2.0 - _executioner.getStartTime();
      44             : 
      45             :   // only set up _time_sequence if the app is _not_ recovering
      46         262 :   if (!_app.isRecovering())
      47             :   {
      48             :     // also we need to do something different when restarting
      49         251 :     if (!_app.isRestarting())
      50             :     {
      51             :       // sync _executioner.startTime and endTime with _time_sequence
      52         211 :       Real start_time = _executioner.getStartTime();
      53         211 :       Real end_time = _executioner.endTime();
      54             : 
      55             :       // make sure time sequence is in strictly ascending order
      56         211 :       if (!std::is_sorted(times.begin(), times.end(), std::less_equal<Real>()))
      57           8 :         paramError("time_sequence", "Time points must be in strictly ascending order.");
      58             : 
      59         203 :       _time_sequence.push_back(start_time);
      60        1130 :       for (unsigned int j = 0; j < times.size(); ++j)
      61             :       {
      62         927 :         if (times[j] > start_time && times[j] < end_time)
      63         633 :           _time_sequence.push_back(times[j]);
      64             :       }
      65         203 :       _time_sequence.push_back(end_time);
      66             :     }
      67             :     else
      68             :     {
      69             :       // in case of restart it should be allowed to modify _time_sequence if it follows the
      70             :       // following rule:
      71             :       // all times up to _current_step are identical
      72             :       // 1. start time cannot be modified
      73             :       // 2. the entries in _time_sequence and times must be equal up to entry with index
      74             :       // _current_step
      75             : 
      76          40 :       if (!MooseUtils::absoluteFuzzyEqual(_executioner.getStartTime(), _time_sequence[0]))
      77           0 :         mooseError("Timesequencestepper does not allow the start time to be modified.");
      78             : 
      79             :       // sync _executioner.endTime with _time_sequence
      80          40 :       Real end_time = _executioner.endTime();
      81             : 
      82             :       // make sure time sequence is in ascending order
      83         229 :       for (unsigned int j = 0; j < times.size() - 1; ++j)
      84         189 :         if (times[j + 1] <= times[j])
      85           0 :           mooseError("time_sequence must be in ascending order.");
      86             : 
      87             :       // save the restarted time_sequence
      88          40 :       std::vector<Real> saved_time_sequence = _time_sequence;
      89          40 :       _time_sequence.clear();
      90             : 
      91             :       // step 1: fill in the entries up to _current_step
      92         153 :       for (unsigned int j = 0; j <= _current_step; ++j)
      93             :       {
      94         120 :         if (!MooseUtils::absoluteFuzzyEqual(times[j], saved_time_sequence[j]))
      95          14 :           mooseError("The timesequence provided in the restart file must be identical to "
      96             :                      "the one in the old file up to entry number ",
      97           7 :                      _current_step + 1,
      98             :                      " = ",
      99           7 :                      saved_time_sequence[_current_step]);
     100             : 
     101         113 :         _time_sequence.push_back(saved_time_sequence[j]);
     102             :       }
     103             : 
     104             :       // step 2: fill in the entries up after _current_step
     105         121 :       for (unsigned int j = _current_step + 1; j < times.size(); ++j)
     106             :       {
     107          88 :         if (times[j] < end_time)
     108          66 :           _time_sequence.push_back(times[j]);
     109             :       }
     110          33 :       _time_sequence.push_back(end_time);
     111          33 :     }
     112             :   }
     113             : 
     114         247 :   if (_app.testCheckpointHalfTransient())
     115             :   {
     116          11 :     unsigned int half = (_time_sequence.size() - 1) / 2;
     117          11 :     _executioner.endTime() = _time_sequence[half];
     118             :   }
     119         247 : }
     120             : 
     121             : void
     122        1219 : TimeSequenceStepperBase::acceptStep()
     123             : {
     124        1219 :   TimeStepper::acceptStep();
     125        1219 :   if (MooseUtils::absoluteFuzzyGreaterEqual(_time, getNextTimeInSequence()))
     126         785 :     increaseCurrentStep();
     127        1219 : }
     128             : 
     129             : Real
     130         292 : TimeSequenceStepperBase::computeInitialDT()
     131             : {
     132         292 :   return computeDT();
     133             : }
     134             : 
     135             : Real
     136         735 : TimeSequenceStepperBase::computeDT()
     137             : {
     138         735 :   if (_use_last_dt_after_last_t)
     139             :   {
     140             :     // last *provided* time value index; actual last index corresponds to end time
     141          84 :     const auto last_t_index = _time_sequence.size() - 2;
     142          84 :     if (_current_step + 1 > last_t_index)
     143          24 :       return _time_sequence[last_t_index] - _time_sequence[last_t_index - 1];
     144             :     else
     145          60 :       return _time_sequence[_current_step + 1] - _time_sequence[_current_step];
     146             :   }
     147             :   else
     148         651 :     return _time_sequence[_current_step + 1] - _time_sequence[_current_step];
     149             : }
     150             : 
     151             : Real
     152           9 : TimeSequenceStepperBase::computeFailedDT()
     153             : {
     154           9 :   if (computeDT() <= _dt_min)
     155           0 :     mooseError("Solve failed and timestep already at or below dtmin, cannot continue!");
     156             : 
     157             :   // cut the time step in a half if possible
     158           9 :   Real dt = _cutback_factor_at_failure * computeDT();
     159           9 :   if (dt < _dt_min)
     160           0 :     dt = _dt_min;
     161           9 :   _time_sequence.insert(_time_sequence.begin() + _current_step + 1,
     162           9 :                         _time_sequence[_current_step] + dt);
     163           9 :   return computeDT();
     164             : }

Generated by: LCOV version 1.14