https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PIDTransientControl.C
Go to the documentation of this file.
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 "PIDTransientControl.h"
11#include "Function.h"
12#include "TransientBase.h"
13#include "TimeStepper.h"
14#include "FEProblemBase.h"
15#include "MooseApp.h"
16
18
21{
24 "Sets the value of a 'Real' input parameter (or postprocessor) based on a Proportional "
25 "Integral Derivative control of a postprocessor to match a target a target value.");
26 params.addRequiredParam<PostprocessorName>(
27 "postprocessor", "The postprocessor to watch for controlling the specified parameter.");
28 params.addRequiredParam<FunctionName>("target",
29 "The target value 1D time function for the postprocessor");
30 params.addRequiredParam<Real>("K_integral", "The coefficient multiplying the integral term");
31 params.addRequiredParam<Real>("K_proportional",
32 "The coefficient multiplying the difference term");
33 params.addRequiredParam<Real>("K_derivative", "The coefficient multiplying the derivative term");
34 params.addParam<std::string>(
35 "parameter",
36 "The input parameter(s) to control. Specify a single parameter name and all "
37 "parameters in all objects matching the name will be updated");
38 params.addParam<std::string>("parameter_pp",
39 "The postprocessor to control. Should be accessed by reference by "
40 "the objects depending on its value.");
41 params.addParam<Real>(
42 "start_time", -std::numeric_limits<Real>::max(), "The time to start the PID controller at");
43 params.addParam<Real>(
44 "stop_time", std::numeric_limits<Real>::max(), "The time to stop the PID controller at");
45 params.addParam<bool>(
46 "reset_every_timestep",
47 false,
48 "Reset the PID integral when changing timestep, for coupling iterations within a timestep");
49 params.addParam<bool>("reset_integral_windup",
50 true,
51 "Reset the PID integral when the error crosses zero and the integral is "
52 "larger than the error.");
53
54 params.addParam<Real>("maximum_output_value",
55 std::numeric_limits<Real>::max(),
56 "Can be used to limit the maximum value output by the PID controller.");
57 params.addParam<Real>("minimum_output_value",
58 -std::numeric_limits<Real>::max(),
59 "Can be used to limit the minimum value output by the PID controller.");
60 params.addRangeCheckedParam<Real>(
61 "maximum_change_rate",
62 std::numeric_limits<Real>::max(),
63 "maximum_change_rate>0",
64 "Can be used to limit the absolute rate of change per second of value "
65 "output by the PID controller.");
66 return params;
67}
68
70 : Control(parameters),
71 _current(getPostprocessorValueByName(getParam<PostprocessorName>("postprocessor"))),
72 _target(getFunction("target")),
73 _Kint(getParam<Real>("K_integral")),
74 _Kpro(getParam<Real>("K_proportional")),
75 _Kder(getParam<Real>("K_derivative")),
76 _start_time(getParam<Real>("start_time")),
77 _stop_time(getParam<Real>("stop_time")),
78 _reset_every_timestep(getParam<bool>("reset_every_timestep")),
79 _reset_integral_windup(getParam<bool>("reset_integral_windup")),
80 _maximum_output_value(getParam<Real>("maximum_output_value")),
81 _minimum_output_value(getParam<Real>("minimum_output_value")),
82 _maximum_change_rate(getParam<Real>("maximum_change_rate")),
83 _integral(declareRestartableData<Real>("pid_integral", 0)),
84 _integral_old(declareRestartableData<Real>("pid_integral_old", 0)),
85 _value(declareRestartableData<Real>("pid_value", 0)),
86 _value_old(declareRestartableData<Real>("pid_value_old", 0)),
87 _t_step_old(declareRestartableData<int>("pid_tstep_old", -1)),
88 _old_delta(declareRestartableData<Real>("pid_delta_old", 0)),
89 _has_recovered(false)
90{
92 mooseError("PIDTransientControl is only meant to be used when the problem is transient, for "
93 "example with a Transient Executioner. Support for Steady "
94 "Executioner can be added in the future, however certain parameters are currently "
95 "not well defined for use with Picard iterations.");
96
97 if (isParamValid("parameter") && isParamValid("parameter_pp"))
98 paramError("parameter_pp",
99 "Either a controllable parameter or a postprocessor to control should be specified, "
100 "not both.");
101 if (!isParamValid("parameter") && !isParamValid("parameter_pp"))
102 mooseError("A parameter or a postprocessor to control should be specified.");
103 if (isParamValid("parameter") && _reset_every_timestep)
105 "reset_every_timestep",
106 "Resetting the PID every time step is only supported using controlled postprocessors");
109 "The parameters maximum_output_value and minimum_output_value are inconsistent. The value "
110 "of maximum_output_value should be greater than the value of minimum_output_value.");
111}
112
113void
115{
116 // Dont execute on INITIAL again on a recover.
117 // Executing on INITIAL in a regular simulation is fine, but on a recover we will get the integral
118 // term wrong and set the wrong attributes for the time derivative too. Best to skip
120 {
121 mooseInfo("Skipping execution on recover + INITIAL.");
122 return;
123 }
124
125 if (_t >= _start_time && _t < _stop_time)
126 {
127 // Get the current value of the controllable parameter
128 if (isParamValid("parameter"))
129 {
130 // If just recovering, we must use the restartable value as the parameter value is
131 // not restarted
133 _has_recovered = true;
134 // else get the current value of the parameter
135 else
136 _value = getControllableValue<Real>("parameter");
137 }
138 else
139 _value = getPostprocessorValueByName(getParam<std::string>("parameter_pp"));
140
141 // Compute the delta between the current value of the postprocessor and the desired value
142 Real delta = _current - _target.value(_t);
143
144 // Save integral and controlled value at each time step
145 // if the solver fails, a smaller time step will be used but _t_step is unchanged
146 if (_t_step != _t_step_old)
147 {
148 // Reset the error integral if PID is only used within each timestep
150 _integral = 0;
151
155 _delta_prev_tstep = delta;
157 }
158
159 // If there were coupling/Picard iterations during the transient and they failed,
160 // we need to reset the controlled value and the error integral to their initial value at the
161 // beginning of the coupling process
163 {
166 delta = _delta_prev_tstep;
168 }
169
170 // If desired, reset integral of the error if the error crosses zero
171 if (_reset_integral_windup && delta * _old_delta < 0)
172 _integral = 0;
173
174 // Compute the three error terms and add them to the controlled value
175 _integral += delta * _dt;
176 _value += _Kint * _integral + _Kpro * delta;
177 if (_dt > 0)
178 _value += _Kder * (delta - _old_delta) / _dt;
179
180 // If the maximum rate of change by the pid is fixed
181 if (_maximum_change_rate != std::numeric_limits<Real>::max())
182 _value = std::min(std::max(_value_old - _dt * _maximum_change_rate, _value),
184
185 // Compute the value, within the bounds
187
188 // Set the new value of the parameter or postprocessor
189 if (isParamValid("parameter"))
190 setControllableValue<Real>("parameter", _value);
191 else
192 _fe_problem.setPostprocessorValueByName(getParam<std::string>("parameter_pp"), _value);
193
194 // Keep track of the previous delta for integral windup control
195 // and for time derivative calculation
196 _old_delta = delta;
197 }
198}
199
200void
202{
203 if (_app.isRecovering())
204 {
205 if (isParamValid("parameter"))
206 setControllableValue<Real>("parameter", _value);
207 else
208 _fe_problem.setPostprocessorValueByName(getParam<std::string>("parameter_pp"), _value);
209 }
210}
211
212void
214{
215 const auto * t_ex = dynamic_cast<const TransientBase *>(_app.getExecutioner());
216 if (t_ex && t_ex->getTimeStepper()->justFailedTimeStep() &&
218 {
219 // We need to revert to the timestep begin state
223 if (isParamValid("parameter"))
224 setControllableValue<Real>("parameter", _value);
225 else
226 _fe_problem.setPostprocessorValueByName(getParam<std::string>("parameter_pp"), _value);
227 }
228}
const ExecFlagType EXEC_TIMESTEP_END
Definition Moose.C:36
const ExecFlagType EXEC_INITIAL
Definition Moose.C:30
registerMooseObject("MooseApp", PIDTransientControl)
void ErrorVector unsigned int
Base class for Control objects.
Definition Control.h:44
static InputParameters validParams()
Class constructor.
Definition Control.C:16
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this object.
Definition Control.h:76
FixedPointSolve & fixedPointSolve()
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
void setPostprocessorValueByName(const PostprocessorName &name, const PostprocessorValue &value, std::size_t t_index=0)
Set the value of a PostprocessorValue.
virtual bool isTransient() const override
unsigned int numFixedPointIts() const
Get the number of fixed point iterations performed Because this returns the number of fixed point ite...
virtual Real value(Real t, const Point &p) const
Override this to evaluate the scalar function at point (t,x,y,z), by default this returns zero,...
Definition Function.C:30
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addRequiredParam(const std::string &name, const std::string &doc_string)
This method adds a parameter and documentation string to the InputParameters object that will be extr...
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Definition MooseApp.C:2015
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition MooseApp.C:1669
void paramError(const std::string &param, Args... args) const
Emits an error prefixed with the file and line number of the given param (from the input file) along ...
Definition MooseBase.h:457
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
void mooseInfo(Args &&... args) const
Definition MooseBase.h:334
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
bool contains(const std::string &value) const
Methods for seeing if a value is set in the MultiMooseEnum.
A time-dependent control of an input parameter or a postprocessor, which aims at making a postprocess...
Real _delta_prev_tstep
the difference with the target from the previous time step, used if a time step fails
const bool _reset_integral_windup
Whether to reset the PID integral error when the error crosses 0, to avoid windup.
const Real _minimum_output_value
Limiting minimum value for the output of the PID controller.
bool _has_recovered
whether the app has recovered once, because the logic for setting the value is different after having...
const Function & _target
The target 1D time-dependent function for the postprocessor.
Real & _value
Saved value of the controlled parameter at the end of a timestep.
Real & _integral_old
Saved value of the integral at the beginning of a timestep, to recover from a failed solve.
const PostprocessorValue & _current
The current value of the target postprocessor.
const bool _reset_every_timestep
Whether to reset the PID integral error when changing timestep, to limit its action to within couplin...
const Real _maximum_output_value
Limiting maximum value for the output of the PID controller.
Real & _integral
Integral of the error.
const Real _Kder
The coefficient multiplying the derivative of the error.
const Real _Kpro
The coefficient multiplying the error.
virtual void initialSetup() override
Called once at the beginning of the simulation, used to initialize recovered control values.
Real & _old_delta
the previous value of the difference with the target, to detect changes of sign, and to compute the d...
virtual void timestepSetup() override
Used to reset the PID when failing a timestep and the control is executed on timestep_end.
virtual void execute() override
Execute the control.
const Real _stop_time
The time to stop using the PID controller on.
static InputParameters validParams()
const Real _maximum_change_rate
Limiting maximum value for the rate of change of output of the PID controller.
const Real _start_time
The time to start the PID controller on.
int & _t_step_old
the previous time step
Real & _value_old
Saved value of the controlled parameter at the beginning of a timestep, to recover from a failed solv...
Real _old_delta_prev_tstep
the difference with the target from the second-to-last iteration of previous time step,...
const Real _Kint
The coefficient multiplying the integral of the error.
PIDTransientControl(const InputParameters &parameters)
Class constructor.
virtual const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name) const
Retrieve the value of the Postprocessor.
const ExecFlagEnum & getExecuteOnEnum() const
Return the execute on MultiMooseEnum for this object.
Base class for transient executioners that use a FixedPointSolve solve object for multiapp-main app i...
Real & _dt
Time step size.
int & _t_step
The number of the time step.