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 "FunctionDT.h" 11 : #include "Function.h" 12 : #include "PiecewiseBase.h" 13 : #include <limits> 14 : 15 : registerMooseObject("MooseApp", FunctionDT); 16 : 17 : InputParameters 18 14581 : FunctionDT::validParams() 19 : { 20 14581 : InputParameters params = TimeStepper::validParams(); 21 : // TODO: This will be required when time_t and time_dt is removed 22 14581 : params.addParam<FunctionName>( 23 : "function", "The name of the time-dependent function that prescribes the time step size."); 24 14581 : params.addParam<std::vector<Real>>("time_t", {}, "The values of t"); 25 14581 : params.addParam<std::vector<Real>>("time_dt", {}, "The values of dt"); 26 43743 : params.addParam<Real>("growth_factor", 27 29162 : std::numeric_limits<Real>::max(), 28 : "Maximum ratio of new to previous timestep sizes."); 29 14581 : params.addParam<Real>("min_dt", 0, "The minimal dt to take."); 30 : // TODO: this can be removed when time_t and time_dt is removed 31 43743 : params.addParam<bool>("interpolate", 32 29162 : true, 33 : "Whether or not to interpolate DT between times. " 34 : "This is true by default for historical reasons."); 35 14581 : params.addClassDescription( 36 : "Timestepper whose steps vary over time according to a user-defined function"); 37 : 38 14581 : return params; 39 0 : } 40 : 41 158 : FunctionDT::FunctionDT(const InputParameters & parameters) 42 : : TimeStepper(parameters), 43 : FunctionInterface(this), 44 158 : _time_t(getParam<std::vector<Real>>("time_t")), 45 158 : _time_dt(getParam<std::vector<Real>>("time_dt")), 46 158 : _function(nullptr), 47 158 : _growth_factor(getParam<Real>("growth_factor")), 48 158 : _min_dt(getParam<Real>("min_dt")), 49 474 : _interpolate(getParam<bool>("interpolate")) 50 : { 51 : // TODO: remove this when `time_t` and `time_dt` is removed 52 158 : if ((_time_t.size() && _time_dt.size()) && !isParamValid("function")) 53 0 : mooseDeprecated(name(), 54 : ": Using `time_t` and `time_dt` parameter is deprecated. Switch your input " 55 : "file to using `function` parameter.\n", 56 : " 1. Build a new function. If `interpolate` parameter is true use type = " 57 : "PiecewiseLinear. If it was false, use PiecewiseConstant.\n", 58 : " 2. Copy `time_t` parameter into your function and rename it to `x`.\n", 59 : " 3. Copy `time_dt` parameter into your function and rename it to `y`.\n", 60 : " 4. Use the `function` parameter in your time stepper and pass your new " 61 : "function name into it.\n"); 62 158 : else if ((_time_t.size() && _time_dt.size()) && isParamValid("function")) 63 0 : mooseError(name(), 64 : ": Using `time_t`, `_time_dt` and `function` at the same time. Use only `function`, " 65 : "`time_t` and _time_dt is deprecated."); 66 158 : else if (!isParamValid("function")) 67 0 : mooseError(name(), 68 : ": Please, specify a function (using the `function` parameter) that will prescribe " 69 : "the time step size."); 70 : 71 158 : if (_time_t.size() && _time_dt.size()) 72 : { 73 : try 74 : { 75 0 : _time_ipol = std::make_unique<LinearInterpolation>(_time_t, _time_dt); 76 : } 77 0 : catch (std::domain_error & e) 78 : { 79 0 : mooseError("In FunctionDT ", _name, ": ", e.what()); 80 0 : } 81 : 82 0 : _time_knots = _time_t; 83 0 : _use_function = false; 84 : } 85 : else 86 : { 87 158 : _function = &getFunction("function"); 88 : // If dt is given by piece-wise linear and constant function, we add the domain into 89 : // _time_knots, so that the time stepper hits those time points 90 158 : const PiecewiseBase * pw = dynamic_cast<const PiecewiseBase *>(_function); 91 158 : if (pw) 92 : { 93 108 : unsigned int n_knots = pw->functionSize(); 94 396 : for (unsigned int i = 0; i < n_knots; i++) 95 288 : _time_knots.push_back(pw->domain(i)); 96 : } 97 : 98 158 : _use_function = true; 99 : } 100 158 : } 101 : 102 : void 103 158 : FunctionDT::init() 104 : { 105 158 : removeOldKnots(); 106 158 : } 107 : 108 : void 109 3218 : FunctionDT::removeOldKnots() 110 : { 111 4345 : while ((_time_knots.size() > 0) && 112 4345 : (*_time_knots.begin() <= _time || std::abs(*_time_knots.begin() - _time) < 1e-10)) 113 223 : _time_knots.erase(_time_knots.begin()); 114 3218 : } 115 : 116 : Real 117 298 : FunctionDT::computeInitialDT() 118 : { 119 298 : return computeDT(); 120 : } 121 : 122 : Real 123 3197 : FunctionDT::computeDT() 124 : { 125 3197 : Real local_dt = 0; 126 : 127 3197 : if (_use_function) 128 3197 : local_dt = _function->value(_time, _point_zero); 129 : else 130 : { 131 0 : if (_interpolate) 132 0 : local_dt = _time_ipol->sample(_time); 133 : else // Find where we are 134 : { 135 0 : unsigned int i = 0; 136 0 : if (MooseUtils::relativeFuzzyGreaterEqual(_time, _time_t.back())) 137 : { 138 0 : i = _time_t.size(); 139 : } 140 : else 141 : { 142 0 : for (; i < _time_t.size() - 1; i++) 143 0 : if (MooseUtils::relativeFuzzyLessThan(_time, _time_t[i + 1])) 144 0 : break; 145 : } 146 : 147 : // Use the last dt after the end 148 0 : if (i == _time_t.size()) 149 0 : local_dt = _time_dt.back(); 150 : else 151 0 : local_dt = _time_dt[i]; 152 : } 153 : } 154 : 155 : // sync to time knot 156 3197 : if ((_time_knots.size() > 0) && (_time + local_dt >= (*_time_knots.begin()))) 157 165 : local_dt = (*_time_knots.begin()) - _time; 158 : // honor minimal dt 159 3197 : if (local_dt < _min_dt) 160 11 : local_dt = _min_dt; 161 : 162 3197 : if ((local_dt > (_dt * _growth_factor)) && _dt > 0) 163 0 : local_dt = _dt * _growth_factor; 164 : 165 3197 : return local_dt; 166 : } 167 : 168 : void 169 3060 : FunctionDT::postStep() 170 : { 171 3060 : removeOldKnots(); 172 3060 : }