LCOV - code coverage report
Current view: top level - src/executioners - TransientBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 398 429 92.8 %
Date: 2025-08-08 20:01:16 Functions: 26 27 96.3 %
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 "TransientBase.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "Factory.h"
      14             : #include "SubProblem.h"
      15             : #include "TimeStepper.h"
      16             : #include "MooseApp.h"
      17             : #include "Conversion.h"
      18             : #include "FEProblem.h"
      19             : #include "NonlinearSystem.h"
      20             : #include "Control.h"
      21             : #include "TimePeriod.h"
      22             : #include "MooseMesh.h"
      23             : #include "TimeIntegrator.h"
      24             : #include "Console.h"
      25             : #include "AuxiliarySystem.h"
      26             : #include "Convergence.h"
      27             : #include "ConvergenceIterationTypes.h"
      28             : 
      29             : #include "libmesh/implicit_system.h"
      30             : #include "libmesh/nonlinear_implicit_system.h"
      31             : #include "libmesh/transient_system.h"
      32             : #include "libmesh/numeric_vector.h"
      33             : 
      34             : // C++ Includes
      35             : #include <iomanip>
      36             : #include <iostream>
      37             : #include <fstream>
      38             : #include <sstream>
      39             : #include <iomanip>
      40             : 
      41             : InputParameters
      42      168260 : TransientBase::defaultSteadyStateConvergenceParams()
      43             : {
      44      168260 :   InputParameters params = emptyInputParameters();
      45             : 
      46      504780 :   params.addParam<Real>("steady_state_tolerance",
      47      336520 :                         1.0e-08,
      48             :                         "Whenever the relative residual changes by less "
      49             :                         "than this the solution will be considered to be "
      50             :                         "at steady state.");
      51      504780 :   params.addParam<bool>("check_aux",
      52      336520 :                         false,
      53             :                         "Whether to check the auxiliary system for convergence to steady-state. If "
      54             :                         "false, then the solution vector from the solver system is used.");
      55      504780 :   params.addParam<bool>(
      56             :       "normalize_solution_diff_norm_by_dt",
      57      336520 :       true,
      58             :       "Whether to divide the solution difference norm by dt. If taking 'small' "
      59             :       "time steps you probably want this to be true. If taking very 'large' timesteps in an "
      60             :       "attempt to *reach* a steady-state, you probably want this parameter to be false.");
      61             : 
      62      168260 :   params.addParamNamesToGroup("steady_state_tolerance check_aux normalize_solution_diff_norm_by_dt",
      63             :                               "Steady State Detection");
      64             : 
      65      168260 :   return params;
      66           0 : }
      67             : 
      68             : InputParameters
      69       89868 : TransientBase::validParams()
      70             : {
      71       89868 :   InputParameters params = Executioner::validParams();
      72       89868 :   params += TransientBase::defaultSteadyStateConvergenceParams();
      73             : 
      74       89868 :   params.addClassDescription("Executioner for time varying simulations.");
      75             : 
      76       89868 :   std::vector<Real> sync_times(1);
      77       89868 :   sync_times[0] = -std::numeric_limits<Real>::max();
      78             : 
      79             :   /**
      80             :    * For backwards compatibility we'll allow users to set the TimeIntegration scheme inside of the
      81             :    * executioner block
      82             :    * as long as the TimeIntegrator does not have any additional parameters.
      83             :    */
      84             :   MooseEnum schemes("implicit-euler explicit-euler crank-nicolson bdf2 explicit-midpoint dirk "
      85             :                     "explicit-tvd-rk-2 newmark-beta",
      86       89868 :                     "implicit-euler");
      87             : 
      88       89868 :   params.addParam<Real>("start_time", 0.0, "The start time of the simulation");
      89       89868 :   params.addParam<Real>("end_time", 1.0e30, "The end time of the simulation");
      90       89868 :   params.addParam<Real>("dt", 1., "The timestep size between solves");
      91       89868 :   params.addParam<Real>("dtmin", 1.0e-12, "The minimum timestep size in an adaptive run");
      92       89868 :   params.addParam<Real>("dtmax", 1.0e30, "The maximum timestep size in an adaptive run");
      93      269604 :   params.addParam<bool>(
      94      179736 :       "reset_dt", false, "Use when restarting a calculation to force a change in dt.");
      95      269604 :   params.addParam<unsigned int>("num_steps",
      96      179736 :                                 std::numeric_limits<unsigned int>::max(),
      97             :                                 "The number of timesteps in a transient run");
      98       89868 :   params.addParam<int>("n_startup_steps", 0, "The number of timesteps during startup");
      99             : 
     100      269604 :   params.addParam<bool>(
     101      179736 :       "steady_state_detection", false, "Whether or not to check for steady state conditions");
     102       89868 :   params.addParam<ConvergenceName>(
     103             :       "steady_state_convergence",
     104             :       "Name of the Convergence object to use to assess whether the solution has reached a steady "
     105             :       "state. If not provided, a default Convergence will be constructed internally from the "
     106             :       "executioner parameters.");
     107      269604 :   params.addParam<Real>(
     108             :       "steady_state_start_time",
     109      179736 :       0.0,
     110             :       "Minimum amount of time to run before checking for steady state conditions.");
     111             : 
     112       89868 :   params.addParam<std::vector<std::string>>("time_periods", "The names of periods");
     113       89868 :   params.addParam<std::vector<Real>>("time_period_starts", "The start times of time periods");
     114       89868 :   params.addParam<std::vector<Real>>("time_period_ends", "The end times of time periods");
     115      269604 :   params.addParam<bool>(
     116      179736 :       "abort_on_solve_fail", false, "abort if solve not converged rather than cut timestep");
     117      269604 :   params.addParam<bool>(
     118             :       "error_on_dtmin",
     119      179736 :       true,
     120             :       "Throw error when timestep is less than dtmin instead of just aborting solve.");
     121       89868 :   params.addParam<MooseEnum>("scheme", schemes, "Time integration scheme used.");
     122      269604 :   params.addParam<Real>("timestep_tolerance",
     123      179736 :                         1.0e-12,
     124             :                         "the tolerance setting for final timestep size and sync times");
     125             : 
     126      269604 :   params.addParam<bool>("use_multiapp_dt",
     127      179736 :                         false,
     128             :                         "If true then the dt for the simulation will be "
     129             :                         "chosen by the MultiApps.  If false (the "
     130             :                         "default) then the minimum over the master dt "
     131             :                         "and the MultiApps is used");
     132             : 
     133       89868 :   params.addParamNamesToGroup(
     134             :       "steady_state_detection steady_state_convergence steady_state_start_time",
     135             :       "Steady State Detection");
     136             : 
     137       89868 :   params.addParamNamesToGroup("start_time dtmin dtmax n_startup_steps "
     138             :                               "abort_on_solve_fail timestep_tolerance use_multiapp_dt",
     139             :                               "Advanced");
     140             : 
     141       89868 :   params.addParamNamesToGroup("time_periods time_period_starts time_period_ends", "Time Periods");
     142             : 
     143             :   // This Executioner supports --test-restep
     144       89868 :   params.set<bool>("_supports_test_restep") = true;
     145             : 
     146      179736 :   return params;
     147       89868 : }
     148             : 
     149       30620 : TransientBase::TransientBase(const InputParameters & parameters)
     150             :   : Executioner(parameters),
     151       30620 :     _problem(_fe_problem),
     152       61240 :     _aux(_fe_problem.getAuxiliarySystem()),
     153       30620 :     _time_scheme(getParam<MooseEnum>("scheme").getEnum<Moose::TimeIntegratorType>()),
     154       30620 :     _time_stepper(nullptr),
     155       30620 :     _t_step(_problem.timeStep()),
     156       30620 :     _time(_problem.time()),
     157       30620 :     _time_old(_problem.timeOld()),
     158       30620 :     _dt(_problem.dt()),
     159       30620 :     _dt_old(_problem.dtOld()),
     160       30620 :     _unconstrained_dt(declareRecoverableData<Real>("unconstrained_dt", -1)),
     161       30620 :     _at_sync_point(declareRecoverableData<bool>("at_sync_point", false)),
     162       30620 :     _last_solve_converged(declareRecoverableData<bool>("last_solve_converged", true)),
     163       30620 :     _xfem_repeat_step(false),
     164       30620 :     _end_time(getParam<Real>("end_time")),
     165       30620 :     _dtmin(getParam<Real>("dtmin")),
     166       30620 :     _dtmax(getParam<Real>("dtmax")),
     167       30620 :     _num_steps(getParam<unsigned int>("num_steps")),
     168       30620 :     _n_startup_steps(getParam<int>("n_startup_steps")),
     169       30620 :     _steady_state_detection(getParam<bool>("steady_state_detection")),
     170       30620 :     _steady_state_start_time(getParam<Real>("steady_state_start_time")),
     171       30620 :     _sync_times(_app.getOutputWarehouse().getSyncTimes()),
     172       30620 :     _abort(getParam<bool>("abort_on_solve_fail")),
     173       30620 :     _error_on_dtmin(getParam<bool>("error_on_dtmin")),
     174       30620 :     _time_interval(declareRecoverableData<bool>("time_interval", false)),
     175       30620 :     _start_time(getParam<Real>("start_time")),
     176       30620 :     _timestep_tolerance(getParam<Real>("timestep_tolerance")),
     177       30620 :     _target_time(declareRecoverableData<Real>("target_time", -std::numeric_limits<Real>::max())),
     178       30620 :     _use_multiapp_dt(getParam<bool>("use_multiapp_dt")),
     179       61240 :     _testing_restep(false)
     180             : {
     181       30620 :   _t_step = 0;
     182       30620 :   _dt = 0;
     183       30620 :   _next_interval_output_time = 0.0;
     184             : 
     185             :   // Either a start_time has been forced on us, or we want to tell the App about what our start time
     186             :   // is (in case anyone else is interested.
     187       30620 :   if (_app.hasStartTime())
     188           0 :     _start_time = _app.getStartTime();
     189       30620 :   else if (parameters.isParamSetByUser("start_time"))
     190        3949 :     _app.setStartTime(_start_time);
     191             : 
     192       30620 :   _time = _time_old = _start_time;
     193       30620 :   _problem.transient(true);
     194             : 
     195       30620 :   setupTimeIntegrator();
     196             : 
     197             :   // Cut timesteps and end_time in half
     198       30616 :   if (_app.testCheckpointHalfTransient())
     199             :   {
     200             :     mooseAssert(!_app.testReStep(), "Cannot use with restep");
     201        2039 :     _end_time = (_start_time + _end_time) / 2.0;
     202        2039 :     _num_steps /= 2.0;
     203             : 
     204        2039 :     if (_num_steps == 0) // Always do one step in the first half
     205         748 :       _num_steps = 1;
     206             :   }
     207             :   // Retest a timestep (see options below for which timestep)
     208       28577 :   else if (_app.testReStep())
     209             :   {
     210        1394 :     if (_problem.shouldSolve())
     211             :     {
     212             :       // If num_steps is defined, we'll use that to determine restep timestep
     213        1127 :       if (!parameters.isParamSetByAddParam("num_steps"))
     214         865 :         _test_restep_step = _t_step + (_num_steps + 1) / 2;
     215             :       // If end_time is defined, we'll use the half time to determine when to restep
     216        1127 :       if (!parameters.isParamSetByAddParam("end_time"))
     217         300 :         _test_restep_time = (_start_time + _end_time) / 2;
     218             :       // If neither was set or we are doing pseudo-transient, pick the second timestep
     219        1127 :       if ((!_test_restep_step && !_test_restep_time) || _steady_state_detection)
     220          30 :         _test_restep_step = 2;
     221             : 
     222        1127 :       std::stringstream msg;
     223        1127 :       if (_test_restep_step && _test_restep_time)
     224          57 :         msg << "Timestep " << *_test_restep_step << " or time " << *_test_restep_time
     225          57 :             << " (whichever happens first)";
     226        1070 :       else if (_test_restep_step)
     227         827 :         msg << "Timestep " << *_test_restep_step;
     228         243 :       else if (_test_restep_time)
     229         243 :         msg << "Time " << *_test_restep_time;
     230        1127 :       mooseInfo(msg.str(), " will be forcefully retried due to --test-restep.");
     231        1127 :     }
     232             :     else
     233         267 :       mooseInfo(
     234             :           "A timestep is not being retried with --test-restep because Problem/solve=false.\n\nTo "
     235             :           "avoid this test being ran, you could set `restep = false` in the test specification.");
     236             :   }
     237             : 
     238       30616 :   if (isParamValid("steady_state_convergence"))
     239          38 :     _problem.setSteadyStateConvergenceName(getParam<ConvergenceName>("steady_state_convergence"));
     240             :   else
     241             :     // Note that we create a steady-state Convergence object even if steady_state_detection ==
     242             :     // false. This could possibly be changed in the future, but TransientMultiApp would need to be
     243             :     // able to signal for the Convergence object to be created in case it uses steady-state
     244             :     // detection for sub-stepping.
     245       30578 :     _problem.setNeedToAddDefaultSteadyStateConvergence();
     246       30616 : }
     247             : 
     248             : void
     249       29845 : TransientBase::init()
     250             : {
     251       29845 :   _problem.execute(EXEC_PRE_MULTIAPP_SETUP);
     252       29845 :   _problem.initialSetup();
     253       29656 :   _fixed_point_solve->initialSetup();
     254             : 
     255             :   mooseAssert(getTimeStepper(), "No time stepper was set");
     256             : 
     257       29656 :   _time_stepper->init();
     258             : 
     259       29633 :   auto & conv = _problem.getConvergence(_problem.getSteadyStateConvergenceName());
     260       29633 :   conv.checkIterationType(ConvergenceIterationTypes::STEADY_STATE);
     261             : 
     262       29633 :   if (_app.isRecovering()) // Recover case
     263             :   {
     264        2138 :     if (_t_step == 0)
     265           0 :       mooseError(
     266             :           "Internal error in TransientBase executioner: _t_step is equal to 0 while recovering "
     267             :           "in init().");
     268             : 
     269        2138 :     _dt_old = _dt;
     270             :   }
     271       29633 : }
     272             : 
     273             : void
     274       30013 : TransientBase::preExecute()
     275             : {
     276       30013 :   _time_stepper->preExecute();
     277             : 
     278       30013 :   if (!_app.isRecovering())
     279             :   {
     280       27984 :     _t_step = 0;
     281       27984 :     _dt = 0;
     282       27984 :     _next_interval_output_time = 0.0;
     283       27984 :     if (!_app.isRestarting())
     284       27589 :       _time = _time_old = _start_time;
     285             : 
     286       27984 :     _problem.outputStep(EXEC_INITIAL);
     287             : 
     288       27984 :     computeDT();
     289       27980 :     _dt = getDT();
     290       27980 :     if (_dt == 0)
     291           4 :       mooseError("Time stepper computed zero time step size on initial which is not allowed.\n"
     292             :                  "1. If you are using an existing time stepper, double check the values in your "
     293             :                  "input file or report an error.\n"
     294             :                  "2. If you are developing a new time stepper, make sure that initial time step "
     295             :                  "size in your code is computed correctly.");
     296       27976 :     const auto & tis = getTimeIntegrators();
     297       56029 :     for (auto & ti : tis)
     298       28057 :       ti->init();
     299       27972 :   }
     300       30001 : }
     301             : 
     302             : void
     303      184013 : TransientBase::preStep()
     304             : {
     305      184013 :   _time_stepper->preStep();
     306      184013 : }
     307             : 
     308             : void
     309      209299 : TransientBase::postStep()
     310             : {
     311      209299 :   _time_stepper->postStep();
     312      209299 : }
     313             : 
     314             : void
     315       21571 : TransientBase::execute()
     316             : {
     317       21571 :   preExecute();
     318             : 
     319             :   // Start time loop...
     320      199048 :   while (keepGoing())
     321             :   {
     322      177760 :     incrementStepOrReject();
     323      177756 :     preStep();
     324      177756 :     computeDT();
     325      177635 :     takeStep();
     326      177489 :     endStep();
     327      177489 :     postStep();
     328             :   }
     329             : 
     330       21284 :   if (lastSolveConverged())
     331             :   {
     332       21242 :     _t_step++;
     333             : 
     334             :     /*
     335             :      * Call the multi-app executioners endStep and
     336             :      * postStep methods when doing Picard or when not automatically advancing sub-applications for
     337             :      * some other reason. We do not perform these calls for loose-coupling/auto-advancement
     338             :      * problems because TransientBase::endStep and TransientBase::postStep get called from
     339             :      * TransientBaseMultiApp::solveStep in that case.
     340             :      */
     341       21242 :     if (!_fixed_point_solve->autoAdvance())
     342             :     {
     343        1082 :       _problem.finishMultiAppStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN,
     344             :                                   /*recurse_through_multiapp_levels=*/true);
     345        1082 :       _problem.finishMultiAppStep(EXEC_TIMESTEP_BEGIN, /*recurse_through_multiapp_levels=*/true);
     346        1082 :       _problem.finishMultiAppStep(EXEC_TIMESTEP_END, /*recurse_through_multiapp_levels=*/true);
     347        1082 :       _problem.finishMultiAppStep(EXEC_MULTIAPP_FIXED_POINT_END,
     348             :                                   /*recurse_through_multiapp_levels=*/true);
     349             :     }
     350             :   }
     351             : 
     352       21284 :   if (!_app.testCheckpointHalfTransient())
     353             :   {
     354       19894 :     TIME_SECTION("final", 1, "Executing Final Objects");
     355       19894 :     _problem.execMultiApps(EXEC_FINAL);
     356       19894 :     _problem.finalizeMultiApps();
     357       19894 :     _problem.execute(EXEC_FINAL);
     358       19890 :     _problem.outputStep(EXEC_FINAL);
     359       19890 :   }
     360             : 
     361             :   // This method is to finalize anything else we want to do on the problem side.
     362       21280 :   _problem.postExecute();
     363             : 
     364             :   // This method can be overridden for user defined activities in the Executioner.
     365       21280 :   postExecute();
     366             : 
     367       21280 :   if (_test_restep_step || _test_restep_time)
     368           4 :     mooseError((_test_restep_step ? "Timestep " : "Time "),
     369           4 :                (_test_restep_step ? *_test_restep_step : *_test_restep_time),
     370             :                " was never retried because the simulation did not get to this timestep.\n\nTo "
     371             :                "support restep testing, specify `num_steps` in the input.\nOtherwise, set "
     372             :                "`restep = false` in this test specification.");
     373       21276 : }
     374             : 
     375             : void
     376      236497 : TransientBase::computeDT()
     377             : {
     378             :   // We're repeating the solve of the previous timestep,
     379             :   // so we use the same dt
     380      236497 :   if (_testing_restep)
     381             :   {
     382             :     mooseAssert(!_test_restep_step && !_test_restep_time, "Should not be set");
     383        1123 :     return;
     384             :   }
     385             : 
     386      235374 :   _time_stepper->computeStep(); // This is actually when DT gets computed
     387             : }
     388             : 
     389             : void
     390      202006 : TransientBase::incrementStepOrReject()
     391             : {
     392      202006 :   if (lastSolveConverged())
     393             :   {
     394      196778 :     if (!_xfem_repeat_step)
     395             :     {
     396             : #ifdef LIBMESH_ENABLE_AMR
     397      196778 :       if (_t_step != 0)
     398      176696 :         _problem.adaptMesh();
     399             : #endif
     400             : 
     401      196778 :       _time_old = _time;
     402      196778 :       _t_step++;
     403             : 
     404      196778 :       bool advance_problem_state = true;
     405      196778 :       const auto & tis = getTimeIntegrators();
     406      397801 :       for (auto & ti : tis)
     407             :         // We do not want to advance the problem state here if a time integrator is already doing so
     408             :         // itself
     409      201023 :         if (ti->advancesProblemState())
     410             :         {
     411           0 :           advance_problem_state = false;
     412           0 :           break;
     413             :         }
     414             : 
     415      196778 :       if (advance_problem_state)
     416      196778 :         _problem.advanceState();
     417           0 :       else if (tis.size() > 1)
     418           0 :         mooseError("Either there must be a single time integrator which advances state or none of "
     419             :                    "the time integrators should advance state.");
     420             : 
     421      196778 :       if (_t_step == 1)
     422       20082 :         return;
     423             : 
     424             :       /*
     425             :        * Call the multi-app executioners endStep and
     426             :        * postStep methods when doing Picard or when not automatically advancing sub-applications for
     427             :        * some other reason. We do not perform these calls for loose-coupling/auto-advancement
     428             :        * problems because TransientBase::endStep and TransientBase::postStep get called from
     429             :        * TransientBaseMultiApp::solveStep in that case.
     430             :        */
     431      176696 :       if (!_fixed_point_solve->autoAdvance())
     432             :       {
     433        8316 :         _problem.finishMultiAppStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
     434        8316 :         _problem.finishMultiAppStep(EXEC_TIMESTEP_BEGIN);
     435        8316 :         _problem.finishMultiAppStep(EXEC_TIMESTEP_END);
     436        8316 :         _problem.finishMultiAppStep(EXEC_MULTIAPP_FIXED_POINT_END);
     437             :       }
     438             : 
     439             :       /*
     440             :        * Ensure that we increment the sub-application time steps so that
     441             :        * when dt selection is made in the master application, we are using
     442             :        * the correct time step information
     443             :        */
     444      176696 :       _problem.incrementMultiAppTStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
     445      176696 :       _problem.incrementMultiAppTStep(EXEC_TIMESTEP_BEGIN);
     446      176696 :       _problem.incrementMultiAppTStep(EXEC_TIMESTEP_END);
     447      176696 :       _problem.incrementMultiAppTStep(EXEC_MULTIAPP_FIXED_POINT_END);
     448      196778 :     }
     449             :   }
     450             :   else
     451             :   {
     452        5228 :     _problem.restoreMultiApps(EXEC_MULTIAPP_FIXED_POINT_BEGIN, true);
     453        5228 :     _problem.restoreMultiApps(EXEC_TIMESTEP_BEGIN, true);
     454        5228 :     _problem.restoreMultiApps(EXEC_TIMESTEP_END, true);
     455        5228 :     _problem.restoreMultiApps(EXEC_MULTIAPP_FIXED_POINT_END, true);
     456        5228 :     _time_stepper->rejectStep();
     457        5224 :     _time = _time_old;
     458             :   }
     459             : }
     460             : 
     461             : void
     462      253427 : TransientBase::takeStep(Real input_dt)
     463             : {
     464      253427 :   if (lastSolveConverged())
     465      248319 :     _dt_old = _dt;
     466             : 
     467             :   // We're repeating the solve of the previous timestep,
     468             :   // so we use the same dt
     469      253427 :   if (_testing_restep)
     470             :   {
     471             :     mooseAssert(!_test_restep_step && !_test_restep_time, "Should not be set");
     472        1123 :     _testing_restep = false;
     473             :   }
     474      252304 :   else if (input_dt == -1.0)
     475      182769 :     _dt = computeConstrainedDT();
     476             :   else
     477       69535 :     _dt = input_dt;
     478             : 
     479      253423 :   _time_stepper->preSolve();
     480             : 
     481             :   // Increment time
     482      253423 :   _time = _time_old + _dt;
     483             : 
     484      253423 :   _problem.timestepSetup();
     485             : 
     486      253423 :   _problem.onTimestepBegin();
     487             : 
     488      253423 :   _time_stepper->step();
     489      253281 :   _xfem_repeat_step = _fixed_point_solve->XFEMRepeatStep();
     490             : 
     491      253281 :   _last_solve_converged = _time_stepper->converged();
     492             : 
     493             :   // We're running with --test-restep and we have just solved
     494             :   // the timestep we are to repeat for the first time
     495      508511 :   if ((_test_restep_step && *_test_restep_step == _t_step) ||
     496      255230 :       (_test_restep_time && _time >= *_test_restep_time))
     497             :   {
     498             :     mooseAssert(!_testing_restep, "Should not be set");
     499             : 
     500        1123 :     mooseInfo("Aborting and retrying solve for timestep ", _t_step, " due to --test-restep");
     501        1123 :     _last_solve_converged = false;
     502        1123 :     _testing_restep = true;
     503        1123 :     _test_restep_step.reset();
     504        1123 :     _test_restep_time.reset();
     505             : 
     506        1123 :     return;
     507             :   }
     508             : 
     509      252158 :   if (!lastSolveConverged())
     510             :   {
     511        4245 :     _console << "Aborting as solve did not converge" << std::endl;
     512        4245 :     return;
     513             :   }
     514             : 
     515      247913 :   if (!(_problem.haveXFEM() && _fixed_point_solve->XFEMRepeatStep()))
     516             :   {
     517      247913 :     if (lastSolveConverged())
     518      247913 :       _time_stepper->acceptStep();
     519             :     else
     520           0 :       _time_stepper->rejectStep();
     521             :   }
     522             : 
     523      247913 :   _time = _time_old;
     524             : 
     525      247913 :   _time_stepper->postSolve();
     526             : 
     527      247913 :   return;
     528             : }
     529             : 
     530             : void
     531      209254 : TransientBase::endStep(Real input_time)
     532             : {
     533      209254 :   if (input_time == -1.0)
     534      209229 :     _time = _time_old + _dt;
     535             :   else
     536          25 :     _time = input_time;
     537             : 
     538      209254 :   if (lastSolveConverged())
     539             :   {
     540      204003 :     if (_xfem_repeat_step)
     541           0 :       _time = _time_old;
     542             :     else
     543             :     {
     544             :       // TODO: add linear system support
     545      204003 :       const auto & tis = getTimeIntegrators();
     546      412251 :       for (auto & ti : tis)
     547      208248 :         ti->postStep();
     548             : 
     549             :       // Compute the Error Indicators and Markers
     550      204003 :       _problem.computeIndicators();
     551      204003 :       _problem.computeMarkers();
     552             : 
     553             :       // Perform the output of the current time step
     554      204003 :       _problem.outputStep(EXEC_TIMESTEP_END);
     555             : 
     556             :       // output
     557      204003 :       if (_time_interval && (_time + _timestep_tolerance >= _next_interval_output_time))
     558           0 :         _next_interval_output_time += _time_interval_output_interval;
     559      204003 :     }
     560             :   }
     561      209254 : }
     562             : 
     563             : Real
     564      182769 : TransientBase::computeConstrainedDT()
     565             : {
     566             :   //  // If start up steps are needed
     567             :   //  if (_t_step == 1 && _n_startup_steps > 1)
     568             :   //    _dt = _input_dt/(double)(_n_startup_steps);
     569             :   //  else if (_t_step == 1+_n_startup_steps && _n_startup_steps > 1)
     570             :   //    _dt = _input_dt;
     571             : 
     572      182769 :   Real dt_cur = _dt;
     573      182769 :   std::ostringstream diag;
     574             : 
     575             :   // After startup steps, compute new dt
     576      182769 :   if (_t_step > _n_startup_steps)
     577      182665 :     dt_cur = getDT();
     578             : 
     579             :   else
     580             :   {
     581             :     diag << "Timestep < n_startup_steps, using old dt: " << std::setw(9) << std::setprecision(6)
     582         104 :          << std::setfill('0') << std::showpoint << std::left << _dt << " tstep: " << _t_step
     583         104 :          << " n_startup_steps: " << _n_startup_steps << std::endl;
     584             :   }
     585      182769 :   _unconstrained_dt = dt_cur;
     586             : 
     587      182769 :   if (_verbose)
     588        5684 :     _console << diag.str();
     589             : 
     590      182769 :   diag.str("");
     591      182769 :   diag.clear();
     592             : 
     593             :   // Allow the time stepper to limit the time step
     594      182769 :   _at_sync_point = _time_stepper->constrainStep(dt_cur);
     595             : 
     596             :   // Don't let time go beyond next time interval output if specified
     597      182765 :   if ((_time_interval) && (_time + dt_cur + _timestep_tolerance >= _next_interval_output_time))
     598             :   {
     599           0 :     dt_cur = _next_interval_output_time - _time;
     600           0 :     _at_sync_point = true;
     601             : 
     602             :     diag << "Limiting dt for time interval output at time: " << std::setw(9) << std::setprecision(6)
     603           0 :          << std::setfill('0') << std::showpoint << std::left << _next_interval_output_time
     604           0 :          << " dt: " << std::setw(9) << std::setprecision(6) << std::setfill('0') << std::showpoint
     605           0 :          << std::left << dt_cur << std::endl;
     606             :   }
     607             : 
     608             :   // If a target time is set and the current dt would exceed it, limit dt to match the target
     609      189022 :   if (_target_time > -std::numeric_limits<Real>::max() + _timestep_tolerance &&
     610        6257 :       _time + dt_cur + _timestep_tolerance >= _target_time)
     611             :   {
     612        1654 :     dt_cur = _target_time - _time;
     613        1654 :     _at_sync_point = true;
     614             : 
     615             :     diag << "Limiting dt for target time: " << std::setw(9) << std::setprecision(6)
     616        1654 :          << std::setfill('0') << std::showpoint << std::left << _next_interval_output_time
     617        1654 :          << " dt: " << std::setw(9) << std::setprecision(6) << std::setfill('0') << std::showpoint
     618        1654 :          << std::left << dt_cur << std::endl;
     619             :   }
     620             : 
     621             :   // Constrain by what the multi apps are doing
     622      182765 :   constrainDTFromMultiApp(dt_cur, diag, EXEC_MULTIAPP_FIXED_POINT_BEGIN);
     623      182765 :   constrainDTFromMultiApp(dt_cur, diag, EXEC_TIMESTEP_BEGIN);
     624      182765 :   constrainDTFromMultiApp(dt_cur, diag, EXEC_TIMESTEP_END);
     625      182765 :   constrainDTFromMultiApp(dt_cur, diag, EXEC_MULTIAPP_FIXED_POINT_END);
     626             : 
     627      182765 :   if (_verbose)
     628        5684 :     _console << diag.str();
     629             : 
     630      182765 :   return dt_cur;
     631      182765 : }
     632             : 
     633             : void
     634      731060 : TransientBase::constrainDTFromMultiApp(Real & dt_cur,
     635             :                                        std::ostringstream & diag,
     636             :                                        const ExecFlagType & execute_on) const
     637             : {
     638      731060 :   Real multi_app_dt = _problem.computeMultiAppsDT(execute_on);
     639      731060 :   if (_use_multiapp_dt || multi_app_dt < dt_cur)
     640             :   {
     641        1949 :     dt_cur = multi_app_dt;
     642        1949 :     _at_sync_point = false;
     643        1949 :     diag << "Limiting dt for MultiApps on " << execute_on.name() << ": " << std::setw(9)
     644        1949 :          << std::setprecision(6) << std::setfill('0') << std::showpoint << std::left << dt_cur
     645        1949 :          << std::endl;
     646             :   }
     647      731060 : }
     648             : 
     649             : Real
     650      236960 : TransientBase::getDT()
     651             : {
     652      236960 :   return _time_stepper->getCurrentDT();
     653             : }
     654             : 
     655             : bool
     656      199048 : TransientBase::keepGoing()
     657             : {
     658      199048 :   bool keep_going = !_problem.isSolveTerminationRequested();
     659             : 
     660             :   // Check for stop condition based upon steady-state check flag:
     661      199048 :   if (lastSolveConverged())
     662             :   {
     663      193804 :     if (!_xfem_repeat_step)
     664             :     {
     665      193804 :       if (_steady_state_detection == true && _time > _steady_state_start_time)
     666             :       {
     667             :         // Check solution difference relative norm against steady-state tolerance
     668       13814 :         if (convergedToSteadyState())
     669             :         {
     670         375 :           _console << "Steady-State Solution Achieved at time: " << _time << std::endl;
     671             :           // Output last solve if not output previously by forcing it
     672         375 :           keep_going = false;
     673             :         }
     674             :       }
     675             : 
     676             :       // Check for stop condition based upon number of simulation steps and/or solution end time:
     677      193800 :       if (static_cast<unsigned int>(_t_step) >= _num_steps)
     678       16840 :         keep_going = false;
     679             : 
     680      193800 :       if ((_time >= _end_time) || (fabs(_time - _end_time) <= _timestep_tolerance))
     681        4180 :         keep_going = false;
     682             :     }
     683             :   }
     684        5244 :   else if (_abort)
     685             :   {
     686          20 :     _console << "Aborting as solve did not converge and input selected to abort" << std::endl;
     687          20 :     keep_going = false;
     688             :   }
     689        5224 :   else if (!_error_on_dtmin && _dt <= _dtmin)
     690             :   {
     691          22 :     _console << "Aborting as timestep already at or below dtmin" << std::endl;
     692          22 :     keep_going = false;
     693             :   }
     694             : 
     695      199044 :   return keep_going;
     696             : }
     697             : 
     698             : void
     699           0 : TransientBase::estimateTimeError()
     700             : {
     701           0 : }
     702             : 
     703             : bool
     704     1493291 : TransientBase::lastSolveConverged() const
     705             : {
     706     1493291 :   return _last_solve_converged;
     707             : }
     708             : 
     709             : void
     710       28638 : TransientBase::postExecute()
     711             : {
     712       28638 :   _time_stepper->postExecute();
     713       28638 : }
     714             : 
     715             : void
     716        1734 : TransientBase::setTargetTime(Real target_time)
     717             : {
     718        1734 :   _target_time = target_time;
     719        1734 : }
     720             : 
     721             : Real
     722       19246 : TransientBase::computeSolutionChangeNorm(bool check_aux, bool normalize_by_dt) const
     723             : {
     724       19246 :   return relativeSolutionDifferenceNorm(check_aux) / (normalize_by_dt ? _dt : Real(1));
     725             : }
     726             : 
     727             : void
     728       30620 : TransientBase::setupTimeIntegrator()
     729             : {
     730       30620 :   if (_pars.isParamSetByUser("scheme") && _problem.hasTimeIntegrator())
     731           4 :     mooseError("You cannot specify time_scheme in the Executioner and independently add a "
     732             :                "TimeIntegrator to the system at the same time");
     733             : 
     734       30616 :   if (!_problem.hasTimeIntegrator())
     735             :   {
     736             :     // backwards compatibility
     737       29497 :     std::string ti_str;
     738             :     using namespace Moose;
     739             : 
     740       29497 :     switch (_time_scheme)
     741             :     {
     742       29165 :       case TI_IMPLICIT_EULER:
     743       29165 :         ti_str = "ImplicitEuler";
     744       29165 :         break;
     745          78 :       case TI_EXPLICIT_EULER:
     746          78 :         ti_str = "ExplicitEuler";
     747          78 :         break;
     748          49 :       case TI_CRANK_NICOLSON:
     749          49 :         ti_str = "CrankNicolson";
     750          49 :         break;
     751         166 :       case TI_BDF2:
     752         166 :         ti_str = "BDF2";
     753         166 :         break;
     754           0 :       case TI_EXPLICIT_MIDPOINT:
     755           0 :         ti_str = "ExplicitMidpoint";
     756           0 :         break;
     757           0 :       case TI_LSTABLE_DIRK2:
     758           0 :         ti_str = "LStableDirk2";
     759           0 :         break;
     760           0 :       case TI_EXPLICIT_TVD_RK_2:
     761           0 :         ti_str = "ExplicitTVDRK2";
     762           0 :         break;
     763          39 :       case TI_NEWMARK_BETA:
     764          39 :         ti_str = "NewmarkBeta";
     765          39 :         break;
     766           0 :       default:
     767           0 :         mooseError("Unknown scheme: ", _time_scheme);
     768             :         break;
     769             :     }
     770             : 
     771       58994 :     InputParameters params = _app.getFactory().getValidParams(ti_str);
     772       29497 :     _problem.addTimeIntegrator(ti_str, ti_str, params);
     773       29497 :   }
     774       30616 : }
     775             : 
     776             : std::string
     777       25236 : TransientBase::getTimeStepperName() const
     778             : {
     779       25236 :   if (_time_stepper)
     780             :   {
     781       25236 :     TimeStepper & ts = *_time_stepper;
     782       25236 :     return demangle(typeid(ts).name());
     783             :   }
     784             :   else
     785           0 :     return std::string();
     786             : }
     787             : 
     788             : std::vector<std::string>
     789       25236 : TransientBase::getTimeIntegratorNames() const
     790             : {
     791       25236 :   const auto & tis = getTimeIntegrators();
     792       25236 :   if (tis.empty())
     793           0 :     mooseError("Time integrator has not been built yet so we can't retrieve its name");
     794             : 
     795       25236 :   std::vector<std::string> ret;
     796       50556 :   for (const auto & ti : tis)
     797             :   {
     798       25320 :     const auto & sys = ti->getCheckedPointerParam<SystemBase *>("_sys")->system();
     799       25320 :     const auto & uvars = ti->getParam<std::vector<VariableName>>("variables");
     800             : 
     801       25320 :     std::vector<VariableName> vars;
     802       25436 :     for (const auto & var : uvars)
     803         116 :       if (sys.has_variable(var))
     804         116 :         vars.push_back(var);
     805             : 
     806       25320 :     if (!uvars.empty() && vars.empty())
     807           0 :       continue;
     808             : 
     809       25320 :     if (tis.size() > 1)
     810             :     {
     811         168 :       const std::string sys_prefix = _problem.numSolverSystems() > 1 ? sys.name() : "";
     812         168 :       const std::string var_prefix = MooseUtils::join(vars, ", ");
     813         168 :       const bool both = !sys_prefix.empty() && !var_prefix.empty();
     814         168 :       ret.push_back("[" + sys_prefix + (both ? " (" : "") + var_prefix + (both ? ")" : "") + "]:");
     815         168 :     }
     816             : 
     817       25320 :     ret.push_back(ti->type());
     818       25320 :   }
     819       50472 :   return ret;
     820       25236 : }
     821             : 
     822             : void
     823       30508 : TransientBase::setTimeStepper(TimeStepper & ts)
     824             : {
     825             :   mooseAssert(!_time_stepper, "Already set");
     826       30508 :   _time_stepper = &ts;
     827       30508 : }
     828             : 
     829             : bool
     830       20052 : TransientBase::convergedToSteadyState() const
     831             : {
     832       20052 :   auto & convergence = _problem.getConvergence(_problem.getSteadyStateConvergenceName());
     833       20052 :   const auto status = convergence.checkConvergence(_t_step);
     834             : 
     835       20052 :   if (status == Convergence::MooseConvergenceStatus::DIVERGED)
     836           8 :     mooseError(
     837           4 :         "The steady-state Convergence object (", convergence.name(), ") reported divergence.");
     838       20048 :   else if (status == Convergence::MooseConvergenceStatus::CONVERGED)
     839         743 :     return true;
     840             :   else // status == Convergence::MooseConvergenceStatus::ITERATING
     841       19305 :     return false;
     842             : }
     843             : 
     844             : void
     845          77 : TransientBase::parentOutputPositionChanged()
     846             : {
     847          77 :   _fe_problem.parentOutputPositionChanged();
     848          77 : }

Generated by: LCOV version 1.14