LCOV - code coverage report
Current view: top level - src/outputs - Output.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #31653 (2d163b) with base 0cc44f Lines: 177 191 92.7 %
Date: 2025-11-04 20:38:02 Functions: 14 16 87.5 %
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             : // Standard includes
      11             : #include <cmath>
      12             : #include <limits>
      13             : 
      14             : // MOOSE includes
      15             : #include "Output.h"
      16             : #include "FEProblem.h"
      17             : #include "DisplacedProblem.h"
      18             : #include "MooseApp.h"
      19             : #include "Postprocessor.h"
      20             : #include "Restartable.h"
      21             : #include "FileMesh.h"
      22             : #include "MooseUtils.h"
      23             : #include "MooseApp.h"
      24             : #include "Console.h"
      25             : #include "Function.h"
      26             : #include "PiecewiseLinear.h"
      27             : #include "Times.h"
      28             : 
      29             : #include "libmesh/equation_systems.h"
      30             : 
      31             : InputParameters
      32     1046063 : Output::validParams()
      33             : {
      34             :   // Get the parameters from the parent object
      35     1046063 :   InputParameters params = MooseObject::validParams();
      36     1046063 :   params += SetupInterface::validParams();
      37             : 
      38             :   // Displaced Mesh options
      39     3138189 :   params.addParam<bool>(
      40     2092126 :       "use_displaced", false, "Enable/disable the use of the displaced mesh for outputting");
      41             : 
      42             :   // Output intervals and timing
      43     5230315 :   params.addRangeCheckedParam<unsigned int>(
      44             :       "time_step_interval",
      45     2092126 :       1,
      46             :       "time_step_interval > 0",
      47             :       "The interval (number of time steps) at which output occurs. "
      48             :       "Unless explicitly set, the default value of this parameter is set "
      49             :       "to infinity if the wall_time_interval is explicitly set.");
      50     3138189 :   params.addParam<Real>(
      51     2092126 :       "min_simulation_time_interval", 0.0, "The minimum simulation time between output steps");
      52     3138189 :   params.addParam<Real>("simulation_time_interval",
      53     2092126 :                         std::numeric_limits<Real>::max(),
      54             :                         "The target simulation time interval (in seconds) at which to output");
      55     5230315 :   params.addRangeCheckedParam<Real>(
      56             :       "wall_time_interval",
      57     2092126 :       std::numeric_limits<Real>::max(),
      58             :       "wall_time_interval > 0",
      59             :       "The target wall time interval (in seconds) at which to output");
      60     4184252 :   params.addParam<std::vector<Real>>(
      61             :       "sync_times", {}, "Times at which the output and solution is forced to occur");
      62     4184252 :   params.addParam<TimesName>(
      63             :       "sync_times_object",
      64             :       "Times object providing the times at which the output and solution is forced to occur");
      65     4184252 :   params.addParam<bool>("sync_only", false, "Only export results at sync times");
      66     4184252 :   params.addParam<Real>("start_time", "Time at which this output object begins to operate");
      67     4184252 :   params.addParam<Real>("end_time", "Time at which this output object stop operating");
      68     4184252 :   params.addParam<int>("start_step", "Time step at which this output object begins to operate");
      69     4184252 :   params.addParam<int>("end_step", "Time step at which this output object stop operating");
      70     3138189 :   params.addParam<Real>(
      71     2092126 :       "time_tolerance", 1e-14, "Time tolerance utilized checking start and end times");
      72     6276378 :   params.addDeprecatedParam<FunctionName>(
      73             :       "output_limiting_function",
      74             :       "Piecewise base function that sets sync_times",
      75             :       "Replaced by using the Times system with the sync_times_objects parameter");
      76             : 
      77             :   // Update the 'execute_on' input parameter for output
      78     1046063 :   ExecFlagEnum & exec_enum = params.set<ExecFlagEnum>("execute_on", true);
      79     1046063 :   exec_enum = Output::getDefaultExecFlagEnum();
      80     3138189 :   exec_enum = {EXEC_INITIAL, EXEC_TIMESTEP_END};
      81     3138189 :   params.setDocString("execute_on", exec_enum.getDocString());
      82             : 
      83             :   // Add ability to append to the 'execute_on' list
      84     3138189 :   params.addParam<ExecFlagEnum>("additional_execute_on", exec_enum, exec_enum.getDocString());
      85     2092126 :   params.set<ExecFlagEnum>("additional_execute_on").clearSetValues();
      86     4184252 :   params.addParamNamesToGroup("execute_on additional_execute_on", "Execution scheduling");
      87             : 
      88             :   // 'Timing' group
      89     3138189 :   params.addParamNamesToGroup("time_tolerance time_step_interval sync_times sync_times_object "
      90             :                               "sync_only start_time end_time "
      91             :                               "start_step end_step min_simulation_time_interval "
      92             :                               "simulation_time_interval wall_time_interval",
      93             :                               "Timing and frequency of output");
      94             : 
      95             :   // Add a private parameter for indicating if it was created with short-cut syntax
      96     2092126 :   params.addPrivateParam<bool>("_built_by_moose", false);
      97             : 
      98             :   // Register this class as base class
      99     3138189 :   params.declareControllable("enable");
     100     1046063 :   params.registerBase("Output");
     101             : 
     102     1046063 :   return params;
     103     1046063 : }
     104             : 
     105             : ExecFlagEnum
     106     1115520 : Output::getDefaultExecFlagEnum()
     107             : {
     108     1115520 :   ExecFlagEnum exec_enum = MooseUtils::getDefaultExecFlagEnum();
     109     1115520 :   exec_enum.addAvailableFlags(EXEC_FAILED);
     110     1115520 :   return exec_enum;
     111           0 : }
     112             : 
     113      298121 : Output::Output(const InputParameters & parameters)
     114             :   : MooseObject(parameters),
     115             :     Restartable(this, "Output"),
     116             :     MeshChangedInterface(parameters),
     117             :     SetupInterface(this),
     118             :     FunctionInterface(this),
     119             :     PostprocessorInterface(this),
     120             :     VectorPostprocessorInterface(this),
     121             :     ReporterInterface(this),
     122             :     PerfGraphInterface(this),
     123      298121 :     _problem_ptr(getParam<FEProblemBase *>("_fe_problem_base")),
     124      298121 :     _transient(_problem_ptr->isTransient()),
     125      596242 :     _use_displaced(getParam<bool>("use_displaced")),
     126      298121 :     _es_ptr(nullptr),
     127      298121 :     _mesh_ptr(nullptr),
     128      596242 :     _execute_on(getParam<ExecFlagEnum>("execute_on")),
     129      298121 :     _current_execute_flag(EXEC_NONE),
     130      298121 :     _time(_problem_ptr->time()),
     131      298121 :     _time_old(_problem_ptr->timeOld()),
     132      298121 :     _t_step(_problem_ptr->timeStep()),
     133      298121 :     _dt(_problem_ptr->dt()),
     134      298121 :     _dt_old(_problem_ptr->dtOld()),
     135      298121 :     _num(0),
     136      298121 :     _time_step_interval_set_by_addparam(parameters.isParamSetByAddParam("time_step_interval")),
     137             :     // If wall_time_interval is user-specified and time_step_interval is not,
     138             :     // override default value of time_step_interval so output does not occur
     139             :     // after every time step.
     140      298121 :     _time_step_interval(
     141      596257 :         (parameters.isParamSetByUser("wall_time_interval") && _time_step_interval_set_by_addparam)
     142      596242 :             ? std::numeric_limits<unsigned int>::max()
     143      894363 :             : getParam<unsigned int>("time_step_interval")),
     144      596242 :     _min_simulation_time_interval(getParam<Real>("min_simulation_time_interval")),
     145      596242 :     _simulation_time_interval(getParam<Real>("simulation_time_interval")),
     146      596242 :     _wall_time_interval(getParam<Real>("wall_time_interval")),
     147      596242 :     _sync_times(std::set<Real>(getParam<std::vector<Real>>("sync_times").begin(),
     148      894363 :                                getParam<std::vector<Real>>("sync_times").end())),
     149      596242 :     _sync_times_object(isParamValid("sync_times_object")
     150      298138 :                            ? static_cast<Times *>(&_problem_ptr->getUserObject<Times>(
     151      298172 :                                  getParam<TimesName>("sync_times_object")))
     152             :                            : nullptr),
     153      894389 :     _start_time(isParamValid("start_time") ? getParam<Real>("start_time")
     154      298095 :                                            : std::numeric_limits<Real>::lowest()),
     155      894389 :     _end_time(isParamValid("end_time") ? getParam<Real>("end_time")
     156      298095 :                                        : std::numeric_limits<Real>::max()),
     157      895141 :     _start_step(isParamValid("start_step") ? getParam<int>("start_step")
     158      297343 :                                            : std::numeric_limits<int>::lowest()),
     159      894389 :     _end_step(isParamValid("end_step") ? getParam<int>("end_step")
     160      298095 :                                        : std::numeric_limits<int>::max()),
     161      596242 :     _t_tol(getParam<Real>("time_tolerance")),
     162      596242 :     _sync_only(getParam<bool>("sync_only")),
     163      298121 :     _allow_output(true),
     164      298121 :     _is_advanced(false),
     165      298121 :     _advanced_execute_on(_execute_on, parameters),
     166      298121 :     _last_output_simulation_time(declareRestartableData<Real>("last_output_simulation_time",
     167      298121 :                                                               std::numeric_limits<Real>::lowest())),
     168     1192484 :     _last_output_wall_time(std::chrono::steady_clock::now())
     169             : {
     170      298121 :   if (_use_displaced)
     171             :   {
     172         155 :     std::shared_ptr<DisplacedProblem> dp = _problem_ptr->getDisplacedProblem();
     173         155 :     if (dp != nullptr)
     174             :     {
     175         147 :       _es_ptr = &dp->es();
     176         147 :       _mesh_ptr = &dp->mesh();
     177             :     }
     178             :     else
     179             :     {
     180           8 :       mooseWarning(
     181           8 :           name(),
     182             :           ": Parameter 'use_displaced' ignored, there is no displaced problem in your simulation.");
     183           0 :       _es_ptr = &_problem_ptr->es();
     184           0 :       _mesh_ptr = &_problem_ptr->mesh();
     185             :     }
     186         147 :   }
     187             :   else
     188             :   {
     189      297966 :     _es_ptr = &_problem_ptr->es();
     190      297966 :     _mesh_ptr = &_problem_ptr->mesh();
     191             :   }
     192             : 
     193             :   // Apply the additional output flags
     194      894339 :   if (isParamValid("additional_execute_on"))
     195             :   {
     196          40 :     const ExecFlagEnum & add = getParam<ExecFlagEnum>("additional_execute_on");
     197          40 :     for (auto & me : add)
     198          20 :       _execute_on.setAdditionalValue(me);
     199             :   }
     200             : 
     201      894339 :   if (isParamValid("output_limiting_function"))
     202             :   {
     203          26 :     const Function & olf = getFunction("output_limiting_function");
     204          13 :     const PiecewiseBase * pwb_olf = dynamic_cast<const PiecewiseBase *>(&olf);
     205          13 :     if (pwb_olf == nullptr)
     206           0 :       mooseError("Function muse have a piecewise base!");
     207             : 
     208          52 :     for (auto i = 0; i < pwb_olf->functionSize(); i++)
     209          39 :       _sync_times.insert(pwb_olf->domain(i));
     210             :   }
     211             : 
     212             :   // Get sync times from Times object if using
     213      298113 :   if (_sync_times_object)
     214             :   {
     215          85 :     if (isParamValid("output_limiting_function") || isParamSetByUser("sync_times"))
     216           0 :       paramError("sync_times_object",
     217             :                  "Only one method of specifying sync times is supported at a time");
     218             :     else
     219             :       // Sync times for the time steppers are taken from the output warehouse. The output warehouse
     220             :       // takes sync times from the output objects immediately after the object is constructed. Hence
     221             :       // we must ensure that we set the `_sync_times` in the constructor
     222          17 :       _sync_times = _sync_times_object->getUniqueTimes();
     223             :   }
     224      298113 : }
     225             : 
     226             : void
     227      736871 : Output::solveSetup()
     228             : {
     229      736871 : }
     230             : 
     231             : void
     232    13246428 : Output::outputStep(const ExecFlagType & type)
     233             : {
     234             :   // Output is not allowed
     235    13246428 :   if (!_allow_output && type != EXEC_FORCED)
     236       38428 :     return;
     237             : 
     238             :   // If recovering disable output of initial condition, it was already output
     239    13208000 :   if (type == EXEC_INITIAL && _app.isRecovering())
     240           0 :     return;
     241             : 
     242             :   // Return if the current output is not on the desired interval and there is
     243             :   // no signal to process
     244    13208000 :   const bool on_interval_or_exec_final = (onInterval() || (type == EXEC_FINAL));
     245             :   // Sync across processes and only output one time per signal received.
     246    13207996 :   comm().max(Moose::interrupt_signal_number);
     247    13207996 :   const bool signal_received = Moose::interrupt_signal_number;
     248    13207996 :   if (!(on_interval_or_exec_final || signal_received))
     249      394855 :     return;
     250             : 
     251             :   // set current type
     252    12813141 :   _current_execute_flag = type;
     253             : 
     254             :   // Check whether we should output, then do it.
     255    12813141 :   if (shouldOutput())
     256             :   {
     257             :     // store current simulation time
     258     4290337 :     _last_output_simulation_time = _time;
     259             : 
     260             :     // store current wall time of output
     261     4290337 :     _last_output_wall_time = std::chrono::steady_clock::now();
     262             : 
     263    21451685 :     TIME_SECTION("outputStep", 2, "Outputting Step");
     264     4290337 :     output();
     265     4290329 :   }
     266             : 
     267    12813133 :   _current_execute_flag = EXEC_NONE;
     268             : }
     269             : 
     270             : bool
     271    13716242 : Output::shouldOutput()
     272             : {
     273    13716242 :   if (_execute_on.isValueSet(_current_execute_flag) || _current_execute_flag == EXEC_FORCED)
     274     4234258 :     return true;
     275     9481984 :   return false;
     276             : }
     277             : 
     278             : bool
     279    19961092 : Output::onInterval()
     280             : {
     281             :   // The output flag to return
     282    19961092 :   bool output = false;
     283             : 
     284             :   // Return true if the current step on the current output interval and within the output time range
     285             :   // and within the output step range
     286    19961092 :   if (_time >= _start_time && _time <= _end_time && _t_step >= _start_step &&
     287    19639743 :       _t_step <= _end_step && (_t_step % _time_step_interval) == 0)
     288    19522494 :     output = true;
     289             : 
     290             :   // Return false if 'sync_only' is set to true
     291    19961092 :   if (_sync_only)
     292       10478 :     output = false;
     293             : 
     294    19961092 :   if (_sync_times_object)
     295             :   {
     296         372 :     const auto & sync_times = _sync_times_object->getUniqueTimes();
     297         372 :     if (sync_times != _sync_times)
     298           4 :       mooseError("The provided sync times object has changing time values. Only static time "
     299             :                  "values are supported since time steppers take sync times from the output "
     300             :                  "warehouse which determines its sync times at output construction time.");
     301         368 :   }
     302             : 
     303             :   // If sync times are not skipped, return true if the current time is a sync_time
     304    20152884 :   for (const auto _sync_time : _sync_times)
     305             :   {
     306      191796 :     if (std::abs(_sync_time - _time) < _t_tol)
     307        7365 :       output = true;
     308             :   }
     309             : 
     310             :   // check if enough simulation time has passed between outputs
     311    19961088 :   if (_time > _last_output_simulation_time &&
     312     9000699 :       _last_output_simulation_time + _min_simulation_time_interval > _time + _t_tol)
     313        2038 :     output = false;
     314             : 
     315             :   // check if enough wall time has passed between outputs
     316    19961088 :   const auto now = std::chrono::steady_clock::now();
     317             :   // count below returns an interger type, so lets express on a millisecond
     318             :   // scale and convert to seconds for finer resolution
     319    19961088 :   _wall_time_since_last_output =
     320    19961088 :       std::chrono::duration_cast<std::chrono::milliseconds>(now - _last_output_wall_time).count() /
     321             :       1000.0;
     322             :   // Take the maximum wall time since last output accross all processors
     323    19961088 :   _communicator.max(_wall_time_since_last_output);
     324    19961088 :   if (_wall_time_since_last_output >= _wall_time_interval)
     325        5203 :     output = true;
     326             : 
     327             :   // Return the output status
     328    19961088 :   return output;
     329             : }
     330             : 
     331             : void
     332       51018 : Output::setWallTimeIntervalFromCommandLineParam()
     333             : {
     334      153054 :   if (_app.isParamValid("output_wall_time_interval"))
     335             :   {
     336         110 :     _wall_time_interval = _app.getParam<Real>("output_wall_time_interval");
     337             : 
     338             :     // If default value of _wall_time_interval was just overriden and user did not
     339             :     // explicitly specify _time_step_interval, override default value of
     340             :     // _time_step_interval so output does not occur after every time step
     341          55 :     if (_time_step_interval_set_by_addparam)
     342          55 :       _time_step_interval = std::numeric_limits<unsigned int>::max();
     343             :   }
     344       51018 : }
     345             : 
     346             : Real
     347     1242393 : Output::time()
     348             : {
     349     1242393 :   if (_transient)
     350     1090686 :     return _time;
     351             :   else
     352      151707 :     return _t_step;
     353             : }
     354             : 
     355             : Real
     356        8227 : Output::timeOld()
     357             : {
     358        8227 :   if (_transient)
     359        8227 :     return _time_old;
     360             :   else
     361           0 :     return _t_step - 1;
     362             : }
     363             : 
     364             : Real
     365      259900 : Output::dt()
     366             : {
     367      259900 :   if (_transient)
     368      259900 :     return _dt;
     369             :   else
     370           0 :     return 1;
     371             : }
     372             : 
     373             : Real
     374           0 : Output::dtOld()
     375             : {
     376           0 :   if (_transient)
     377           0 :     return _dt_old;
     378             :   else
     379           0 :     return 1;
     380             : }
     381             : 
     382             : int
     383      357266 : Output::timeStep()
     384             : {
     385      357266 :   return _t_step;
     386             : }
     387             : 
     388             : const MultiMooseEnum &
     389          50 : Output::executeOn() const
     390             : {
     391          50 :   return _execute_on;
     392             : }
     393             : 
     394             : bool
     395          50 : Output::isAdvanced()
     396             : {
     397          50 :   return _is_advanced;
     398             : }
     399             : 
     400             : const OutputOnWarehouse &
     401           0 : Output::advancedExecuteOn() const
     402             : {
     403           0 :   mooseError("The output object ", name(), " is not an AdvancedOutput, use isAdvanced() to check.");
     404             :   return _advanced_execute_on;
     405             : }

Generated by: LCOV version 1.14