LCOV - code coverage report
Current view: top level - src/executioners - TransientBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 375 408 91.9 %
Date: 2025-07-17 01:28:37 Functions: 25 26 96.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 "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             : 
      27             : #include "libmesh/implicit_system.h"
      28             : #include "libmesh/nonlinear_implicit_system.h"
      29             : #include "libmesh/transient_system.h"
      30             : #include "libmesh/numeric_vector.h"
      31             : 
      32             : // C++ Includes
      33             : #include <iomanip>
      34             : #include <iostream>
      35             : #include <fstream>
      36             : #include <sstream>
      37             : #include <iomanip>
      38             : 
      39             : InputParameters
      40       85434 : TransientBase::validParams()
      41             : {
      42       85434 :   InputParameters params = Executioner::validParams();
      43       85434 :   params.addClassDescription("Executioner for time varying simulations.");
      44             : 
      45       85434 :   std::vector<Real> sync_times(1);
      46       85434 :   sync_times[0] = -std::numeric_limits<Real>::max();
      47             : 
      48             :   /**
      49             :    * For backwards compatibility we'll allow users to set the TimeIntegration scheme inside of the
      50             :    * executioner block
      51             :    * as long as the TimeIntegrator does not have any additional parameters.
      52             :    */
      53             :   MooseEnum schemes("implicit-euler explicit-euler crank-nicolson bdf2 explicit-midpoint dirk "
      54             :                     "explicit-tvd-rk-2 newmark-beta",
      55       85434 :                     "implicit-euler");
      56             : 
      57       85434 :   params.addParam<Real>("start_time", 0.0, "The start time of the simulation");
      58       85434 :   params.addParam<Real>("end_time", 1.0e30, "The end time of the simulation");
      59       85434 :   params.addParam<Real>("dt", 1., "The timestep size between solves");
      60       85434 :   params.addParam<Real>("dtmin", 1.0e-12, "The minimum timestep size in an adaptive run");
      61       85434 :   params.addParam<Real>("dtmax", 1.0e30, "The maximum timestep size in an adaptive run");
      62      256302 :   params.addParam<bool>(
      63      170868 :       "reset_dt", false, "Use when restarting a calculation to force a change in dt.");
      64      256302 :   params.addParam<unsigned int>("num_steps",
      65      170868 :                                 std::numeric_limits<unsigned int>::max(),
      66             :                                 "The number of timesteps in a transient run");
      67       85434 :   params.addParam<int>("n_startup_steps", 0, "The number of timesteps during startup");
      68             : 
      69      256302 :   params.addDeprecatedParam<bool>("trans_ss_check",
      70      170868 :                                   false,
      71             :                                   "Whether or not to check for steady state conditions",
      72             :                                   "Use steady_state_detection instead");
      73      256302 :   params.addDeprecatedParam<Real>("ss_check_tol",
      74      170868 :                                   1.0e-08,
      75             :                                   "Whenever the relative residual changes by less "
      76             :                                   "than this the solution will be considered to be "
      77             :                                   "at steady state.",
      78             :                                   "Use steady_state_tolerance instead");
      79      256302 :   params.addDeprecatedParam<Real>(
      80             :       "ss_tmin",
      81      170868 :       0.0,
      82             :       "Minimum amount of time to run before checking for steady state conditions.",
      83             :       "Use steady_state_start_time instead");
      84             : 
      85      256302 :   params.addParam<bool>(
      86      170868 :       "steady_state_detection", false, "Whether or not to check for steady state conditions");
      87      256302 :   params.addParam<Real>("steady_state_tolerance",
      88      170868 :                         1.0e-08,
      89             :                         "Whenever the relative residual changes by less "
      90             :                         "than this the solution will be considered to be "
      91             :                         "at steady state.");
      92      256302 :   params.addParam<Real>(
      93             :       "steady_state_start_time",
      94      170868 :       0.0,
      95             :       "Minimum amount of time to run before checking for steady state conditions.");
      96      256302 :   params.addParam<bool>(
      97             :       "normalize_solution_diff_norm_by_dt",
      98      170868 :       true,
      99             :       "Whether to divide the solution difference norm by dt. If taking 'small' "
     100             :       "time steps you probably want this to be true. If taking very 'large' timesteps in an "
     101             :       "attempt to *reach* a steady-state, you probably want this parameter to be false.");
     102             : 
     103       85434 :   params.addParam<std::vector<std::string>>("time_periods", "The names of periods");
     104       85434 :   params.addParam<std::vector<Real>>("time_period_starts", "The start times of time periods");
     105       85434 :   params.addParam<std::vector<Real>>("time_period_ends", "The end times of time periods");
     106      256302 :   params.addParam<bool>(
     107      170868 :       "abort_on_solve_fail", false, "abort if solve not converged rather than cut timestep");
     108      256302 :   params.addParam<bool>(
     109             :       "error_on_dtmin",
     110      170868 :       true,
     111             :       "Throw error when timestep is less than dtmin instead of just aborting solve.");
     112       85434 :   params.addParam<MooseEnum>("scheme", schemes, "Time integration scheme used.");
     113      256302 :   params.addParam<Real>("timestep_tolerance",
     114      170868 :                         1.0e-12,
     115             :                         "the tolerance setting for final timestep size and sync times");
     116             : 
     117      256302 :   params.addParam<bool>("use_multiapp_dt",
     118      170868 :                         false,
     119             :                         "If true then the dt for the simulation will be "
     120             :                         "chosen by the MultiApps.  If false (the "
     121             :                         "default) then the minimum over the master dt "
     122             :                         "and the MultiApps is used");
     123             : 
     124      256302 :   params.addParam<bool>("check_aux",
     125      170868 :                         false,
     126             :                         "Whether to check the auxiliary system for convergence to steady-state. If "
     127             :                         "false, then the nonlinear system is used.");
     128             : 
     129       85434 :   params.addParamNamesToGroup(
     130             :       "steady_state_detection steady_state_tolerance steady_state_start_time check_aux",
     131             :       "Steady State Detection");
     132             : 
     133       85434 :   params.addParamNamesToGroup("start_time dtmin dtmax n_startup_steps trans_ss_check ss_check_tol "
     134             :                               "ss_tmin abort_on_solve_fail timestep_tolerance use_multiapp_dt",
     135             :                               "Advanced");
     136             : 
     137       85434 :   params.addParamNamesToGroup("time_periods time_period_starts time_period_ends", "Time Periods");
     138             : 
     139      170868 :   return params;
     140       85434 : }
     141             : 
     142       28403 : TransientBase::TransientBase(const InputParameters & parameters)
     143             :   : Executioner(parameters),
     144       28403 :     _problem(_fe_problem),
     145       56806 :     _aux(_fe_problem.getAuxiliarySystem()),
     146       28403 :     _check_aux(getParam<bool>("check_aux")),
     147       28403 :     _time_scheme(getParam<MooseEnum>("scheme").getEnum<Moose::TimeIntegratorType>()),
     148       28403 :     _time_stepper(nullptr),
     149       28403 :     _t_step(_problem.timeStep()),
     150       28403 :     _time(_problem.time()),
     151       28403 :     _time_old(_problem.timeOld()),
     152       28403 :     _dt(_problem.dt()),
     153       28403 :     _dt_old(_problem.dtOld()),
     154       28403 :     _unconstrained_dt(declareRecoverableData<Real>("unconstrained_dt", -1)),
     155       28403 :     _at_sync_point(declareRecoverableData<bool>("at_sync_point", false)),
     156       28403 :     _last_solve_converged(declareRecoverableData<bool>("last_solve_converged", true)),
     157       28403 :     _xfem_repeat_step(false),
     158       28403 :     _end_time(getParam<Real>("end_time")),
     159       28403 :     _dtmin(getParam<Real>("dtmin")),
     160       28403 :     _dtmax(getParam<Real>("dtmax")),
     161       28403 :     _num_steps(getParam<unsigned int>("num_steps")),
     162       28403 :     _n_startup_steps(getParam<int>("n_startup_steps")),
     163       28403 :     _steady_state_detection(getParam<bool>("steady_state_detection")),
     164       28403 :     _steady_state_tolerance(getParam<Real>("steady_state_tolerance")),
     165       28403 :     _steady_state_start_time(getParam<Real>("steady_state_start_time")),
     166       28403 :     _sync_times(_app.getOutputWarehouse().getSyncTimes()),
     167       28403 :     _abort(getParam<bool>("abort_on_solve_fail")),
     168       28403 :     _error_on_dtmin(getParam<bool>("error_on_dtmin")),
     169       28403 :     _time_interval(declareRecoverableData<bool>("time_interval", false)),
     170       28403 :     _start_time(getParam<Real>("start_time")),
     171       28403 :     _timestep_tolerance(getParam<Real>("timestep_tolerance")),
     172       28403 :     _target_time(declareRecoverableData<Real>("target_time", -std::numeric_limits<Real>::max())),
     173       28403 :     _use_multiapp_dt(getParam<bool>("use_multiapp_dt")),
     174       28403 :     _solution_change_norm(declareRecoverableData<Real>("solution_change_norm", 0.0)),
     175       56806 :     _normalize_solution_diff_norm_by_dt(getParam<bool>("normalize_solution_diff_norm_by_dt"))
     176             : {
     177             :   // Handle deprecated parameters
     178       28403 :   if (!parameters.isParamSetByAddParam("trans_ss_check"))
     179           0 :     _steady_state_detection = getParam<bool>("trans_ss_check");
     180             : 
     181       28403 :   if (!parameters.isParamSetByAddParam("ss_check_tol"))
     182           0 :     _steady_state_tolerance = getParam<Real>("ss_check_tol");
     183             : 
     184       28403 :   if (!parameters.isParamSetByAddParam("ss_tmin"))
     185           0 :     _steady_state_start_time = getParam<Real>("ss_tmin");
     186             : 
     187       28403 :   _t_step = 0;
     188       28403 :   _dt = 0;
     189       28403 :   _next_interval_output_time = 0.0;
     190             : 
     191             :   // Either a start_time has been forced on us, or we want to tell the App about what our start time
     192             :   // is (in case anyone else is interested.
     193       28403 :   if (_app.hasStartTime())
     194           0 :     _start_time = _app.getStartTime();
     195       28403 :   else if (parameters.isParamSetByUser("start_time"))
     196        3663 :     _app.setStartTime(_start_time);
     197             : 
     198       28403 :   _time = _time_old = _start_time;
     199       28403 :   _problem.transient(true);
     200             : 
     201       28403 :   setupTimeIntegrator();
     202             : 
     203       28399 :   if (_app.testCheckpointHalfTransient()) // Cut timesteps and end_time in half...
     204             :   {
     205        2042 :     _end_time = (_start_time + _end_time) / 2.0;
     206        2042 :     _num_steps /= 2.0;
     207             : 
     208        2042 :     if (_num_steps == 0) // Always do one step in the first half
     209         748 :       _num_steps = 1;
     210             :   }
     211       28399 : }
     212             : 
     213             : void
     214       27628 : TransientBase::init()
     215             : {
     216       27628 :   _problem.execute(EXEC_PRE_MULTIAPP_SETUP);
     217       27628 :   _problem.initialSetup();
     218             : 
     219             :   mooseAssert(getTimeStepper(), "No time stepper was set");
     220             : 
     221       27443 :   _time_stepper->init();
     222             : 
     223       27420 :   if (_app.isRecovering()) // Recover case
     224             :   {
     225        2141 :     if (_t_step == 0)
     226           0 :       mooseError(
     227             :           "Internal error in TransientBase executioner: _t_step is equal to 0 while recovering "
     228             :           "in init().");
     229             : 
     230        2141 :     _dt_old = _dt;
     231             :   }
     232       27420 : }
     233             : 
     234             : void
     235       27723 : TransientBase::preExecute()
     236             : {
     237       27723 :   _time_stepper->preExecute();
     238             : 
     239       27723 :   if (!_app.isRecovering())
     240             :   {
     241       25691 :     _t_step = 0;
     242       25691 :     _dt = 0;
     243       25691 :     _next_interval_output_time = 0.0;
     244       25691 :     if (!_app.isRestarting())
     245       25331 :       _time = _time_old = _start_time;
     246             : 
     247       25691 :     _problem.outputStep(EXEC_INITIAL);
     248             : 
     249       25691 :     computeDT();
     250       25687 :     _dt = getDT();
     251       25687 :     if (_dt == 0)
     252           4 :       mooseError("Time stepper computed zero time step size on initial which is not allowed.\n"
     253             :                  "1. If you are using an existing time stepper, double check the values in your "
     254             :                  "input file or report an error.\n"
     255             :                  "2. If you are developing a new time stepper, make sure that initial time step "
     256             :                  "size in your code is computed correctly.");
     257       25683 :     const auto & tis = getTimeIntegrators();
     258       51440 :     for (auto & ti : tis)
     259       25761 :       ti->init();
     260       25679 :   }
     261       27711 : }
     262             : 
     263             : void
     264      168255 : TransientBase::preStep()
     265             : {
     266      168255 :   _time_stepper->preStep();
     267      168255 : }
     268             : 
     269             : void
     270      191188 : TransientBase::postStep()
     271             : {
     272      191188 :   _time_stepper->postStep();
     273      191188 : }
     274             : 
     275             : void
     276       19943 : TransientBase::execute()
     277             : {
     278       19943 :   preExecute();
     279             : 
     280             :   // Start time loop...
     281      182263 :   while (keepGoing())
     282             :   {
     283      162603 :     incrementStepOrReject();
     284      162599 :     preStep();
     285      162599 :     computeDT();
     286      162478 :     takeStep();
     287      162332 :     endStep();
     288      162332 :     postStep();
     289             :   }
     290             : 
     291       19660 :   if (lastSolveConverged())
     292             :   {
     293       19619 :     _t_step++;
     294             : 
     295             :     /*
     296             :      * Call the multi-app executioners endStep and
     297             :      * postStep methods when doing Picard or when not automatically advancing sub-applications for
     298             :      * some other reason. We do not perform these calls for loose-coupling/auto-advancement
     299             :      * problems because TransientBase::endStep and TransientBase::postStep get called from
     300             :      * TransientBaseMultiApp::solveStep in that case.
     301             :      */
     302       19619 :     if (!_fixed_point_solve->autoAdvance())
     303             :     {
     304        1006 :       _problem.finishMultiAppStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN,
     305             :                                   /*recurse_through_multiapp_levels=*/true);
     306        1006 :       _problem.finishMultiAppStep(EXEC_TIMESTEP_BEGIN, /*recurse_through_multiapp_levels=*/true);
     307        1006 :       _problem.finishMultiAppStep(EXEC_TIMESTEP_END, /*recurse_through_multiapp_levels=*/true);
     308        1006 :       _problem.finishMultiAppStep(EXEC_MULTIAPP_FIXED_POINT_END,
     309             :                                   /*recurse_through_multiapp_levels=*/true);
     310             :     }
     311             :   }
     312             : 
     313       19660 :   if (!_app.testCheckpointHalfTransient())
     314             :   {
     315       18271 :     TIME_SECTION("final", 1, "Executing Final Objects");
     316       18271 :     _problem.execMultiApps(EXEC_FINAL);
     317       18271 :     _problem.finalizeMultiApps();
     318       18271 :     _problem.execute(EXEC_FINAL);
     319       18267 :     _problem.outputStep(EXEC_FINAL);
     320       18267 :   }
     321             : 
     322             :   // This method is to finalize anything else we want to do on the problem side.
     323       19656 :   _problem.postExecute();
     324             : 
     325             :   // This method can be overridden for user defined activities in the Executioner.
     326       19656 :   postExecute();
     327       19656 : }
     328             : 
     329             : void
     330      216619 : TransientBase::computeDT()
     331             : {
     332      216619 :   _time_stepper->computeStep(); // This is actually when DT gets computed
     333      216494 : }
     334             : 
     335             : void
     336      184903 : TransientBase::incrementStepOrReject()
     337             : {
     338      184903 :   if (lastSolveConverged())
     339             :   {
     340      180749 :     if (!_xfem_repeat_step)
     341             :     {
     342             : #ifdef LIBMESH_ENABLE_AMR
     343      180749 :       if (_t_step != 0)
     344      162287 :         _problem.adaptMesh();
     345             : #endif
     346             : 
     347      180749 :       _time_old = _time;
     348      180749 :       _t_step++;
     349             : 
     350      180749 :       bool advance_problem_state = true;
     351      180749 :       const auto & tis = getTimeIntegrators();
     352      365446 :       for (auto & ti : tis)
     353             :         // We do not want to advance the problem state here if a time integrator is already doing so
     354             :         // itself
     355      184697 :         if (ti->advancesProblemState())
     356             :         {
     357           0 :           advance_problem_state = false;
     358           0 :           break;
     359             :         }
     360             : 
     361      180749 :       if (advance_problem_state)
     362      180749 :         _problem.advanceState();
     363           0 :       else if (tis.size() > 1)
     364           0 :         mooseError("Either there must be a single time integrator which advances state or none of "
     365             :                    "the time integrators should advance state.");
     366             : 
     367      180749 :       if (_t_step == 1)
     368       18462 :         return;
     369             : 
     370             :       /*
     371             :        * Call the multi-app executioners endStep and
     372             :        * postStep methods when doing Picard or when not automatically advancing sub-applications for
     373             :        * some other reason. We do not perform these calls for loose-coupling/auto-advancement
     374             :        * problems because TransientBase::endStep and TransientBase::postStep get called from
     375             :        * TransientBaseMultiApp::solveStep in that case.
     376             :        */
     377      162287 :       if (!_fixed_point_solve->autoAdvance())
     378             :       {
     379        7669 :         _problem.finishMultiAppStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
     380        7669 :         _problem.finishMultiAppStep(EXEC_TIMESTEP_BEGIN);
     381        7669 :         _problem.finishMultiAppStep(EXEC_TIMESTEP_END);
     382        7669 :         _problem.finishMultiAppStep(EXEC_MULTIAPP_FIXED_POINT_END);
     383             :       }
     384             : 
     385             :       /*
     386             :        * Ensure that we increment the sub-application time steps so that
     387             :        * when dt selection is made in the master application, we are using
     388             :        * the correct time step information
     389             :        */
     390      162287 :       _problem.incrementMultiAppTStep(EXEC_MULTIAPP_FIXED_POINT_BEGIN);
     391      162287 :       _problem.incrementMultiAppTStep(EXEC_TIMESTEP_BEGIN);
     392      162287 :       _problem.incrementMultiAppTStep(EXEC_TIMESTEP_END);
     393      162287 :       _problem.incrementMultiAppTStep(EXEC_MULTIAPP_FIXED_POINT_END);
     394      180749 :     }
     395             :   }
     396             :   else
     397             :   {
     398        4154 :     _problem.restoreMultiApps(EXEC_MULTIAPP_FIXED_POINT_BEGIN, true);
     399        4154 :     _problem.restoreMultiApps(EXEC_TIMESTEP_BEGIN, true);
     400        4154 :     _problem.restoreMultiApps(EXEC_TIMESTEP_END, true);
     401        4154 :     _problem.restoreMultiApps(EXEC_MULTIAPP_FIXED_POINT_END, true);
     402        4154 :     _time_stepper->rejectStep();
     403        4150 :     _time = _time_old;
     404             :   }
     405             : }
     406             : 
     407             : void
     408      231980 : TransientBase::takeStep(Real input_dt)
     409             : {
     410      231980 :   _dt_old = _dt;
     411             : 
     412      231980 :   if (input_dt == -1.0)
     413      168134 :     _dt = computeConstrainedDT();
     414             :   else
     415       63846 :     _dt = input_dt;
     416             : 
     417      231976 :   _time_stepper->preSolve();
     418             : 
     419             :   // Increment time
     420      231976 :   _time = _time_old + _dt;
     421             : 
     422      231976 :   _problem.timestepSetup();
     423             : 
     424      231976 :   _problem.onTimestepBegin();
     425             : 
     426      231976 :   _time_stepper->step();
     427      231834 :   _xfem_repeat_step = _fixed_point_solve->XFEMRepeatStep();
     428             : 
     429      231834 :   _last_solve_converged = _time_stepper->converged();
     430             : 
     431      231834 :   if (!lastSolveConverged())
     432             :   {
     433        4292 :     _console << "Aborting as solve did not converge" << std::endl;
     434        4292 :     return;
     435             :   }
     436             : 
     437      227542 :   if (!(_problem.haveXFEM() && _fixed_point_solve->XFEMRepeatStep()))
     438             :   {
     439      227542 :     if (lastSolveConverged())
     440      227542 :       _time_stepper->acceptStep();
     441             :     else
     442           0 :       _time_stepper->rejectStep();
     443             :   }
     444             : 
     445      227542 :   _time = _time_old;
     446             : 
     447      227542 :   _time_stepper->postSolve();
     448             : 
     449      227542 :   _solution_change_norm =
     450      227542 :       relativeSolutionDifferenceNorm() / (_normalize_solution_diff_norm_by_dt ? _dt : Real(1));
     451             : 
     452      227542 :   return;
     453             : }
     454             : 
     455             : void
     456      191148 : TransientBase::endStep(Real input_time)
     457             : {
     458      191148 :   if (input_time == -1.0)
     459      191126 :     _time = _time_old + _dt;
     460             :   else
     461          22 :     _time = input_time;
     462             : 
     463      191148 :   if (lastSolveConverged())
     464             :   {
     465      186971 :     if (_xfem_repeat_step)
     466           0 :       _time = _time_old;
     467             :     else
     468             :     {
     469             :       // TODO: add linear system support
     470      186971 :       const auto & tis = getTimeIntegrators();
     471      377890 :       for (auto & ti : tis)
     472      190919 :         ti->postStep();
     473             : 
     474             :       // Compute the Error Indicators and Markers
     475      186971 :       _problem.computeIndicators();
     476      186971 :       _problem.computeMarkers();
     477             : 
     478             :       // Perform the output of the current time step
     479      186971 :       _problem.outputStep(EXEC_TIMESTEP_END);
     480             : 
     481             :       // output
     482      186971 :       if (_time_interval && (_time + _timestep_tolerance >= _next_interval_output_time))
     483           0 :         _next_interval_output_time += _time_interval_output_interval;
     484      186971 :     }
     485             :   }
     486      191148 : }
     487             : 
     488             : Real
     489      168134 : TransientBase::computeConstrainedDT()
     490             : {
     491             :   //  // If start up steps are needed
     492             :   //  if (_t_step == 1 && _n_startup_steps > 1)
     493             :   //    _dt = _input_dt/(double)(_n_startup_steps);
     494             :   //  else if (_t_step == 1+_n_startup_steps && _n_startup_steps > 1)
     495             :   //    _dt = _input_dt;
     496             : 
     497      168134 :   Real dt_cur = _dt;
     498      168134 :   std::ostringstream diag;
     499             : 
     500             :   // After startup steps, compute new dt
     501      168134 :   if (_t_step > _n_startup_steps)
     502      168038 :     dt_cur = getDT();
     503             : 
     504             :   else
     505             :   {
     506             :     diag << "Timestep < n_startup_steps, using old dt: " << std::setw(9) << std::setprecision(6)
     507          96 :          << std::setfill('0') << std::showpoint << std::left << _dt << " tstep: " << _t_step
     508          96 :          << " n_startup_steps: " << _n_startup_steps << std::endl;
     509             :   }
     510      168134 :   _unconstrained_dt = dt_cur;
     511             : 
     512      168134 :   if (_verbose)
     513        5258 :     _console << diag.str();
     514             : 
     515      168134 :   diag.str("");
     516      168134 :   diag.clear();
     517             : 
     518             :   // Allow the time stepper to limit the time step
     519      168134 :   _at_sync_point = _time_stepper->constrainStep(dt_cur);
     520             : 
     521             :   // Don't let time go beyond next time interval output if specified
     522      168130 :   if ((_time_interval) && (_time + dt_cur + _timestep_tolerance >= _next_interval_output_time))
     523             :   {
     524           0 :     dt_cur = _next_interval_output_time - _time;
     525           0 :     _at_sync_point = true;
     526             : 
     527             :     diag << "Limiting dt for time interval output at time: " << std::setw(9) << std::setprecision(6)
     528           0 :          << std::setfill('0') << std::showpoint << std::left << _next_interval_output_time
     529           0 :          << " dt: " << std::setw(9) << std::setprecision(6) << std::setfill('0') << std::showpoint
     530           0 :          << std::left << dt_cur << std::endl;
     531             :   }
     532             : 
     533             :   // If a target time is set and the current dt would exceed it, limit dt to match the target
     534      173786 :   if (_target_time > -std::numeric_limits<Real>::max() + _timestep_tolerance &&
     535        5656 :       _time + dt_cur + _timestep_tolerance >= _target_time)
     536             :   {
     537        1542 :     dt_cur = _target_time - _time;
     538        1542 :     _at_sync_point = true;
     539             : 
     540             :     diag << "Limiting dt for target time: " << std::setw(9) << std::setprecision(6)
     541        1542 :          << std::setfill('0') << std::showpoint << std::left << _next_interval_output_time
     542        1542 :          << " dt: " << std::setw(9) << std::setprecision(6) << std::setfill('0') << std::showpoint
     543        1542 :          << std::left << dt_cur << std::endl;
     544             :   }
     545             : 
     546             :   // Constrain by what the multi apps are doing
     547      168130 :   constrainDTFromMultiApp(dt_cur, diag, EXEC_MULTIAPP_FIXED_POINT_BEGIN);
     548      168130 :   constrainDTFromMultiApp(dt_cur, diag, EXEC_TIMESTEP_BEGIN);
     549      168130 :   constrainDTFromMultiApp(dt_cur, diag, EXEC_TIMESTEP_END);
     550      168130 :   constrainDTFromMultiApp(dt_cur, diag, EXEC_MULTIAPP_FIXED_POINT_END);
     551             : 
     552      168130 :   if (_verbose)
     553        5258 :     _console << diag.str();
     554             : 
     555      168130 :   return dt_cur;
     556      168130 : }
     557             : 
     558             : void
     559      672520 : TransientBase::constrainDTFromMultiApp(Real & dt_cur,
     560             :                                        std::ostringstream & diag,
     561             :                                        const ExecFlagType & execute_on) const
     562             : {
     563      672520 :   Real multi_app_dt = _problem.computeMultiAppsDT(execute_on);
     564      672520 :   if (_use_multiapp_dt || multi_app_dt < dt_cur)
     565             :   {
     566        1896 :     dt_cur = multi_app_dt;
     567        1896 :     _at_sync_point = false;
     568        1896 :     diag << "Limiting dt for MultiApps on " << execute_on.name() << ": " << std::setw(9)
     569        1896 :          << std::setprecision(6) << std::setfill('0') << std::showpoint << std::left << dt_cur
     570        1896 :          << std::endl;
     571             :   }
     572      672520 : }
     573             : 
     574             : Real
     575      217955 : TransientBase::getDT()
     576             : {
     577      217955 :   return _time_stepper->getCurrentDT();
     578             : }
     579             : 
     580             : bool
     581      182263 : TransientBase::keepGoing()
     582             : {
     583      182263 :   bool keep_going = !_problem.isSolveTerminationRequested();
     584             : 
     585             :   // Check for stop condition based upon steady-state check flag:
     586      182263 :   if (lastSolveConverged())
     587             :   {
     588      178094 :     if (!_xfem_repeat_step)
     589             :     {
     590      178094 :       if (_steady_state_detection == true && _time > _steady_state_start_time)
     591             :       {
     592             :         // Check solution difference relative norm against steady-state tolerance
     593       12074 :         if (convergedToSteadyState())
     594             :         {
     595         305 :           _console << "Steady-State Solution Achieved at time: " << _time << std::endl;
     596             :           // Output last solve if not output previously by forcing it
     597         305 :           keep_going = false;
     598             :         }
     599             :         else // keep going
     600             :         {
     601             :           // Print steady-state relative error norm
     602       11769 :           _console << "Steady-State Relative Differential Norm: " << _solution_change_norm
     603       11769 :                    << std::endl;
     604             :         }
     605             :       }
     606             : 
     607             :       // Check for stop condition based upon number of simulation steps and/or solution end time:
     608      178094 :       if (static_cast<unsigned int>(_t_step) >= _num_steps)
     609       15597 :         keep_going = false;
     610             : 
     611      178094 :       if ((_time >= _end_time) || (fabs(_time - _end_time) <= _timestep_tolerance))
     612        3858 :         keep_going = false;
     613             :     }
     614             :   }
     615        4169 :   else if (_abort)
     616             :   {
     617          20 :     _console << "Aborting as solve did not converge and input selected to abort" << std::endl;
     618          20 :     keep_going = false;
     619             :   }
     620        4149 :   else if (!_error_on_dtmin && _dt <= _dtmin)
     621             :   {
     622          21 :     _console << "Aborting as timestep already at or below dtmin" << std::endl;
     623          21 :     keep_going = false;
     624             :   }
     625             : 
     626      182263 :   return keep_going;
     627             : }
     628             : 
     629             : void
     630           0 : TransientBase::estimateTimeError()
     631             : {
     632           0 : }
     633             : 
     634             : bool
     635     1128196 : TransientBase::lastSolveConverged() const
     636             : {
     637     1128196 :   return _last_solve_converged;
     638             : }
     639             : 
     640             : void
     641       26393 : TransientBase::postExecute()
     642             : {
     643       26393 :   _time_stepper->postExecute();
     644       26393 : }
     645             : 
     646             : void
     647        1572 : TransientBase::setTargetTime(Real target_time)
     648             : {
     649        1572 :   _target_time = target_time;
     650        1572 : }
     651             : 
     652             : Real
     653        5637 : TransientBase::getSolutionChangeNorm()
     654             : {
     655        5637 :   return _solution_change_norm;
     656             : }
     657             : 
     658             : void
     659       28403 : TransientBase::setupTimeIntegrator()
     660             : {
     661       28403 :   if (_pars.isParamSetByUser("scheme") && _problem.hasTimeIntegrator())
     662           4 :     mooseError("You cannot specify time_scheme in the Executioner and independently add a "
     663             :                "TimeIntegrator to the system at the same time");
     664             : 
     665       28399 :   if (!_problem.hasTimeIntegrator())
     666             :   {
     667             :     // backwards compatibility
     668       27331 :     std::string ti_str;
     669             :     using namespace Moose;
     670             : 
     671       27331 :     switch (_time_scheme)
     672             :     {
     673       27017 :       case TI_IMPLICIT_EULER:
     674       27017 :         ti_str = "ImplicitEuler";
     675       27017 :         break;
     676          72 :       case TI_EXPLICIT_EULER:
     677          72 :         ti_str = "ExplicitEuler";
     678          72 :         break;
     679          45 :       case TI_CRANK_NICOLSON:
     680          45 :         ti_str = "CrankNicolson";
     681          45 :         break;
     682         161 :       case TI_BDF2:
     683         161 :         ti_str = "BDF2";
     684         161 :         break;
     685           0 :       case TI_EXPLICIT_MIDPOINT:
     686           0 :         ti_str = "ExplicitMidpoint";
     687           0 :         break;
     688           0 :       case TI_LSTABLE_DIRK2:
     689           0 :         ti_str = "LStableDirk2";
     690           0 :         break;
     691           0 :       case TI_EXPLICIT_TVD_RK_2:
     692           0 :         ti_str = "ExplicitTVDRK2";
     693           0 :         break;
     694          36 :       case TI_NEWMARK_BETA:
     695          36 :         ti_str = "NewmarkBeta";
     696          36 :         break;
     697           0 :       default:
     698           0 :         mooseError("Unknown scheme: ", _time_scheme);
     699             :         break;
     700             :     }
     701             : 
     702       54662 :     InputParameters params = _app.getFactory().getValidParams(ti_str);
     703       27331 :     _problem.addTimeIntegrator(ti_str, ti_str, params);
     704       27331 :   }
     705       28399 : }
     706             : 
     707             : std::string
     708       23388 : TransientBase::getTimeStepperName() const
     709             : {
     710       23388 :   if (_time_stepper)
     711             :   {
     712       23388 :     TimeStepper & ts = *_time_stepper;
     713       23388 :     return demangle(typeid(ts).name());
     714             :   }
     715             :   else
     716           0 :     return std::string();
     717             : }
     718             : 
     719             : std::vector<std::string>
     720       23388 : TransientBase::getTimeIntegratorNames() const
     721             : {
     722       23388 :   const auto & tis = getTimeIntegrators();
     723       23388 :   if (tis.empty())
     724           0 :     mooseError("Time integrator has not been built yet so we can't retrieve its name");
     725             : 
     726       23388 :   std::vector<std::string> ret;
     727       46857 :   for (const auto & ti : tis)
     728             :   {
     729       23469 :     const auto & sys = ti->getCheckedPointerParam<SystemBase *>("_sys")->system();
     730       23469 :     const auto & uvars = ti->getParam<std::vector<VariableName>>("variables");
     731             : 
     732       23469 :     std::vector<VariableName> vars;
     733       23583 :     for (const auto & var : uvars)
     734         114 :       if (sys.has_variable(var))
     735         114 :         vars.push_back(var);
     736             : 
     737       23469 :     if (!uvars.empty() && vars.empty())
     738           0 :       continue;
     739             : 
     740       23469 :     if (tis.size() > 1)
     741             :     {
     742         162 :       const std::string sys_prefix = _problem.numSolverSystems() > 1 ? sys.name() : "";
     743         162 :       const std::string var_prefix = MooseUtils::join(vars, ", ");
     744         162 :       const bool both = !sys_prefix.empty() && !var_prefix.empty();
     745         162 :       ret.push_back("[" + sys_prefix + (both ? " (" : "") + var_prefix + (both ? ")" : "") + "]:");
     746         162 :     }
     747             : 
     748       23469 :     ret.push_back(ti->type());
     749       23469 :   }
     750       46776 :   return ret;
     751       23388 : }
     752             : 
     753             : void
     754       28291 : TransientBase::setTimeStepper(TimeStepper & ts)
     755             : {
     756             :   mooseAssert(!_time_stepper, "Already set");
     757       28291 :   _time_stepper = &ts;
     758       28291 : }
     759             : 
     760             : bool
     761       12074 : TransientBase::convergedToSteadyState() const
     762             : {
     763             :   bool converged;
     764             : 
     765       12074 :   if (_check_aux)
     766             :   {
     767             :     // Get the relative change in the norm of each auxvariable
     768         507 :     std::vector<Number> aux_soln_change_norms;
     769         507 :     _aux.variableWiseRelativeSolutionDifferenceNorm(aux_soln_change_norms);
     770             : 
     771         507 :     converged = true;
     772         531 :     for (auto & norm_diff : aux_soln_change_norms)
     773             :     {
     774             :       // Normalize by timestep
     775         519 :       norm_diff /= (_normalize_solution_diff_norm_by_dt ? _dt : Real(1));
     776         519 :       if (norm_diff >= _steady_state_tolerance)
     777             :       {
     778         495 :         converged = false;
     779             :         // No point in checking the rest of the auxvariables
     780         495 :         break;
     781             :       }
     782             :     }
     783             : 
     784             :     // This line is useful since _solution_change_norm will be printed
     785         507 :     _solution_change_norm =
     786         507 :         *std::max_element(aux_soln_change_norms.begin(), aux_soln_change_norms.end());
     787         507 :   }
     788             : 
     789             :   // If not using _check_aux, use relative change in norm from nonlinear system
     790       11567 :   else if (_solution_change_norm < _steady_state_tolerance)
     791         293 :     converged = true;
     792             :   else
     793       11274 :     converged = false;
     794             : 
     795       12074 :   return converged;
     796             : }
     797             : 
     798             : void
     799          72 : TransientBase::parentOutputPositionChanged()
     800             : {
     801          72 :   _fe_problem.parentOutputPositionChanged();
     802          72 : }

Generated by: LCOV version 1.14