https://mooseframework.inl.gov
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 "Transient.h"
13 #include "FEProblemBase.h"
14 
16 
19 {
21  params.addClassDescription(
22  "Sets the value of a 'Real' input parameter (or postprocessor) based on a Proportional "
23  "Integral Derivative control of a postprocessor to match a target a target value.");
24  params.addRequiredParam<PostprocessorName>(
25  "postprocessor", "The postprocessor to watch for controlling the specified parameter.");
26  params.addRequiredParam<FunctionName>("target",
27  "The target value 1D time function for the postprocessor");
28  params.addRequiredParam<Real>("K_integral", "The coefficient multiplying the integral term");
29  params.addRequiredParam<Real>("K_proportional",
30  "The coefficient multiplying the difference term");
31  params.addRequiredParam<Real>("K_derivative", "The coefficient multiplying the derivative term");
32  params.addParam<std::string>(
33  "parameter",
34  "The input parameter(s) to control. Specify a single parameter name and all "
35  "parameters in all objects matching the name will be updated");
36  params.addParam<std::string>("parameter_pp",
37  "The postprocessor to control. Should be accessed by reference by "
38  "the objects depending on its value.");
39  params.addParam<Real>(
40  "start_time", -std::numeric_limits<Real>::max(), "The time to start the PID controller at");
41  params.addParam<Real>(
42  "stop_time", std::numeric_limits<Real>::max(), "The time to stop the PID controller at");
43  params.addParam<bool>(
44  "reset_every_timestep",
45  false,
46  "Reset the PID integral when changing timestep, for coupling iterations within a timestep");
47  params.addParam<bool>("reset_integral_windup",
48  true,
49  "Reset the PID integral when the error crosses zero and the integral is "
50  "larger than the error.");
51 
52  params.addParam<Real>("maximum_output_value",
54  "Can be used to limit the maximum value output by the PID controller.");
55  params.addParam<Real>("minimum_output_value",
57  "Can be used to limit the minimum value output by the PID controller.");
58  params.addRangeCheckedParam<Real>(
59  "maximum_change_rate",
61  "maximum_change_rate>0",
62  "Can be used to limit the absolute rate of change per second of value "
63  "output by the PID controller.");
64  return params;
65 }
66 
68  : Control(parameters),
69  _current(getPostprocessorValueByName(getParam<PostprocessorName>("postprocessor"))),
70  _target(getFunction("target")),
71  _Kint(getParam<Real>("K_integral")),
72  _Kpro(getParam<Real>("K_proportional")),
73  _Kder(getParam<Real>("K_derivative")),
74  _start_time(getParam<Real>("start_time")),
75  _stop_time(getParam<Real>("stop_time")),
76  _reset_every_timestep(getParam<bool>("reset_every_timestep")),
77  _reset_integral_windup(getParam<bool>("reset_integral_windup")),
78  _maximum_output_value(getParam<Real>("maximum_output_value")),
79  _minimum_output_value(getParam<Real>("minimum_output_value")),
80  _maximum_change_rate(getParam<Real>("maximum_change_rate")),
81  _integral(declareRestartableData<Real>("pid_integral", 0)),
82  _integral_old(declareRestartableData<Real>("pid_integral_old", 0)),
83  _value(declareRestartableData<Real>("pid_value", 0)),
84  _value_old(declareRestartableData<Real>("pid_value_old", 0)),
85  _t_step_old(declareRestartableData<int>("pid_tstep_old", -1)),
86  _old_delta(declareRestartableData<Real>("pid_delta_old", 0)),
87  _has_recovered(false)
88 {
89  if (!_fe_problem.isTransient())
90  mooseError("PIDTransientControl is only meant to be used when the problem is transient, for "
91  "example with a Transient Executioner. Support for Steady "
92  "Executioner can be added in the future, however certain parameters are currently "
93  "not well defined for use with Picard iterations.");
94 
95  if (isParamValid("parameter") && isParamValid("parameter_pp"))
96  paramError("parameter_pp",
97  "Either a controllable parameter or a postprocessor to control should be specified, "
98  "not both.");
99  if (!isParamValid("parameter") && !isParamValid("parameter_pp"))
100  mooseError("A parameter or a postprocessor to control should be specified.");
101  if (isParamValid("parameter") && _reset_every_timestep)
102  paramError(
103  "reset_every_timestep",
104  "Resetting the PID every time step is only supported using controlled postprocessors");
106  mooseError(
107  "The parameters maximum_output_value and minimum_output_value are inconsistent. The value "
108  "of maximum_output_value should be greater than the value of minimum_output_value.");
109 }
110 
111 void
113 {
114  // Dont execute on INITIAL again on a recover.
115  // Executing on INITIAL in a regular simulation is fine, but on a recover we will get the integral
116  // term wrong and set the wrong attributes for the time derivative too. Best to skip
118  {
119  mooseInfo("Skipping execution on recover + INITIAL.");
120  return;
121  }
122 
123  if (_t >= _start_time && _t < _stop_time)
124  {
125  // Get the current value of the controllable parameter
126  if (isParamValid("parameter"))
127  {
128  // If just recovering, we must use the restartable value as the parameter value is
129  // not restarted
130  if (_app.isRecovering() && !_has_recovered)
131  _has_recovered = true;
132  // else get the current value of the parameter
133  else
134  _value = getControllableValue<Real>("parameter");
135  }
136  else
137  _value = getPostprocessorValueByName(getParam<std::string>("parameter_pp"));
138 
139  // Compute the delta between the current value of the postprocessor and the desired value
140  Real delta = _current - _target.value(_t);
141 
142  // Save integral and controlled value at each time step
143  // if the solver fails, a smaller time step will be used but _t_step is unchanged
144  if (_t_step != _t_step_old)
145  {
146  // Reset the error integral if PID is only used within each timestep
148  _integral = 0;
149 
151  _value_old = _value;
153  _delta_prev_tstep = delta;
155  }
156 
157  // If there were coupling/Picard iterations during the transient and they failed,
158  // we need to reset the controlled value and the error integral to their initial value at the
159  // beginning of the coupling process
161  {
163  _value = _value_old;
164  delta = _delta_prev_tstep;
166  }
167 
168  // If desired, reset integral of the error if the error crosses zero
169  if (_reset_integral_windup && delta * _old_delta < 0)
170  _integral = 0;
171 
172  // Compute the three error terms and add them to the controlled value
173  _integral += delta * _dt;
174  _value += _Kint * _integral + _Kpro * delta;
175  if (_dt > 0)
176  _value += _Kder * (delta - _old_delta) / _dt;
177 
178  // If the maximum rate of change by the pid is fixed
182 
183  // Compute the value, within the bounds
185 
186  // Set the new value of the postprocessor
187  if (isParamValid("parameter"))
188  setControllableValue<Real>("parameter", _value);
189  else
190  _fe_problem.setPostprocessorValueByName(getParam<std::string>("parameter_pp"), _value);
191 
192  // Keep track of the previous delta for integral windup control
193  // and for time derivative calculation
194  _old_delta = delta;
195  }
196 }
const Real _Kint
The coefficient multiplying the integral of the error.
const PostprocessorValue & _current
The current value of the target postprocessor.
static InputParameters validParams()
Class constructor.
Definition: Control.C:16
Real & _integral
Integral of the error.
const Real _stop_time
The time to stop using the PID controller on.
static InputParameters validParams()
const bool _reset_every_timestep
Whether to reset the PID integral error when changing timestep, to limit its action to within couplin...
void setPostprocessorValueByName(const PostprocessorName &name, const PostprocessorValue &value, std::size_t t_index=0)
Set the value of a PostprocessorValue.
void mooseInfo(Args &&... args) const
const ExecFlagType & getCurrentExecuteOnFlag() const
Return/set the current execution flag.
const Real _Kder
The coefficient multiplying the derivative of the error.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
Real _delta_prev_tstep
the difference with the target from the previous time step, used if a time step fails ...
Real & _dt
Time step size.
const bool _reset_integral_windup
Whether to reset the PID integral error when the error crosses 0, to avoid windup.
Real & _value_old
Saved value of the controlled parameter at the beginning of a timestep, to recover from a failed solv...
unsigned int numFixedPointIts() const
Get the number of fixed point iterations performed Because this returns the number of fixed point ite...
registerMooseObject("MooseApp", PIDTransientControl)
Real & _value
Saved value of the controlled parameter at the end of a timestep.
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...
A time-dependent control of an input parameter or a postprocessor, which aims at making a postprocess...
auto max(const L &left, const R &right)
bool _has_recovered
whether the app has recovered once, because the logic for setting the value is different after having...
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
int & _t_step
The number of the time step.
const Real _minimum_output_value
Limiting minimum value for the output of the PID controller.
const Real _Kpro
The coefficient multiplying the error.
const Real _maximum_output_value
Limiting maximum value for the output of the PID controller.
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this object.
Definition: Control.h:74
const Function & _target
The target 1D time-dependent function for the postprocessor.
virtual void execute() override
Execute the control.
Real & _old_delta
the previous value of the difference with the target, to detect changes of sign, and to compute the d...
Real _old_delta_prev_tstep
the difference with the target from the second-to-last iteration of previous time step...
const Real _start_time
The time to start the PID controller on.
MooseApp & _app
The MOOSE application this is associated with.
Definition: MooseBase.h:84
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 ...
int & _t_step_old
the previous time step
Executioner * getExecutioner() const
Retrieve the Executioner for this App.
Definition: MooseApp.C:2118
virtual const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name) const
Retrieve the value of the Postprocessor.
Real & _integral_old
Saved value of the integral at the beginning of a timestep, to recover from a failed solve...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Base class for Control objects.
Definition: Control.h:33
PIDTransientControl(const InputParameters &parameters)
Class constructor.
FixedPointSolve & fixedPointSolve()
Definition: Executioner.h:124
const Real _maximum_change_rate
Limiting maximum value for the rate of change of output of the PID controller.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type.
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 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 addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
virtual bool isTransient() const override
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:44
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition: MooseApp.C:1802
auto min(const L &left, const R &right)
void ErrorVector unsigned int
const ExecFlagType EXEC_INITIAL
Definition: Moose.C:28