LCOV - code coverage report
Current view: top level - src/timesteppers - TimeSequenceStepperBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 66 71 93.0 %
Date: 2025-07-17 01:28:37 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       71761 : TimeSequenceStepperBase::validParams()
      19             : {
      20       71761 :   InputParameters params = TimeStepper::validParams();
      21      215283 :   params.addParam<bool>(
      22             :       "use_last_dt_after_last_t",
      23      143522 :       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       71761 :   return params;
      27           0 : }
      28             : 
      29         219 : TimeSequenceStepperBase::TimeSequenceStepperBase(const InputParameters & parameters)
      30             :   : TimeStepper(parameters),
      31         219 :     _use_last_dt_after_last_t(getParam<bool>("use_last_dt_after_last_t")),
      32         219 :     _current_step(declareRestartableData<unsigned int>("current_step", 0)),
      33         438 :     _time_sequence(declareRestartableData<std::vector<Real>>("time_sequence"))
      34             : {
      35         219 : }
      36             : 
      37             : void
      38         241 : 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         241 :   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         241 :   if (!_app.isRecovering())
      47             :   {
      48             :     // also we need to do something different when restarting
      49         230 :     if (!_app.isRestarting())
      50             :     {
      51             :       // sync _executioner.startTime and endTime with _time_sequence
      52         193 :       Real start_time = _executioner.getStartTime();
      53         193 :       Real end_time = _executioner.endTime();
      54             : 
      55             :       // make sure time sequence is in strictly ascending order
      56         193 :       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         185 :       _time_sequence.push_back(start_time);
      60        1030 :       for (unsigned int j = 0; j < times.size(); ++j)
      61             :       {
      62         845 :         if (times[j] > start_time && times[j] < end_time)
      63         577 :           _time_sequence.push_back(times[j]);
      64             :       }
      65         185 :       _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          37 :       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          37 :       Real end_time = _executioner.endTime();
      81             : 
      82             :       // make sure time sequence is in ascending order
      83         212 :       for (unsigned int j = 0; j < times.size() - 1; ++j)
      84         175 :         if (times[j + 1] <= times[j])
      85           0 :           mooseError("time_sequence must be in ascending order.");
      86             : 
      87             :       // save the restarted time_sequence
      88          37 :       std::vector<Real> saved_time_sequence = _time_sequence;
      89          37 :       _time_sequence.clear();
      90             : 
      91             :       // step 1: fill in the entries up to _current_step
      92         141 :       for (unsigned int j = 0; j <= _current_step; ++j)
      93             :       {
      94         111 :         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         104 :         _time_sequence.push_back(saved_time_sequence[j]);
     102             :       }
     103             : 
     104             :       // step 2: fill in the entries up after _current_step
     105         110 :       for (unsigned int j = _current_step + 1; j < times.size(); ++j)
     106             :       {
     107          80 :         if (times[j] < end_time)
     108          60 :           _time_sequence.push_back(times[j]);
     109             :       }
     110          30 :       _time_sequence.push_back(end_time);
     111          30 :     }
     112             :   }
     113             : 
     114         226 :   if (_app.testCheckpointHalfTransient())
     115             :   {
     116          11 :     unsigned int half = (_time_sequence.size() - 1) / 2;
     117          11 :     _executioner.endTime() = _time_sequence[half];
     118             :   }
     119         226 : }
     120             : 
     121             : void
     122         634 : TimeSequenceStepperBase::step()
     123             : {
     124         634 :   TimeStepper::step();
     125         634 :   if (converged() && !_executioner.fixedPointSolve().XFEMRepeatStep())
     126         634 :     _current_step++;
     127         634 : }
     128             : 
     129             : Real
     130         266 : TimeSequenceStepperBase::computeInitialDT()
     131             : {
     132         266 :   return computeDT();
     133             : }
     134             : 
     135             : Real
     136         669 : TimeSequenceStepperBase::computeDT()
     137             : {
     138         669 :   if (_use_last_dt_after_last_t)
     139             :   {
     140             :     // last *provided* time value index; actual last index corresponds to end time
     141          77 :     const auto last_t_index = _time_sequence.size() - 2;
     142          77 :     if (_current_step + 1 > last_t_index)
     143          22 :       return _time_sequence[last_t_index] - _time_sequence[last_t_index - 1];
     144             :     else
     145          55 :       return _time_sequence[_current_step + 1] - _time_sequence[_current_step];
     146             :   }
     147             :   else
     148         592 :     return _time_sequence[_current_step + 1] - _time_sequence[_current_step];
     149             : }
     150             : 
     151             : Real
     152           8 : TimeSequenceStepperBase::computeFailedDT()
     153             : {
     154           8 :   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           8 :   Real dt = _cutback_factor_at_failure * computeDT();
     159           8 :   if (dt < _dt_min)
     160           0 :     dt = _dt_min;
     161           8 :   _time_sequence.insert(_time_sequence.begin() + _current_step + 1,
     162           8 :                         _time_sequence[_current_step] + dt);
     163           8 :   return computeDT();
     164             : }

Generated by: LCOV version 1.14