Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_TimeStepControlStrategyIntegralController.hpp
Go to the documentation of this file.
1 //@HEADER
2 // *****************************************************************************
3 // Tempus: Time Integration and Sensitivity Analysis Package
4 //
5 // Copyright 2017 NTESS and the Tempus contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 //@HEADER
9 
10 #ifndef Tempus_TimeStepControlStrategy_IntegralController_hpp
11 #define Tempus_TimeStepControlStrategy_IntegralController_hpp
12 
13 #include "Tempus_config.hpp"
16 #include "Tempus_SolutionState.hpp"
17 #include "Tempus_SolutionHistory.hpp"
18 #include "Tempus_StepperState.hpp"
19 
20 namespace Tempus {
21 
58 template <class Scalar>
60  : virtual public TimeStepControlStrategy<Scalar> {
61  public:
64  : controller_("PID"),
65  KI_(0.58),
66  KP_(0.21),
67  KD_(0.10),
68  safetyFactor_(0.90),
70  facMax_(5.0),
71  facMin_(0.5)
72  {
74 
75  this->setStrategyType("Integral Controller");
76  this->setStepType("Variable");
77  this->setName("Integral Controller");
78  this->initialize();
79  }
80 
83  std::string controller, Scalar KI, Scalar KP, Scalar KD,
84  Scalar safetyFactor, Scalar safetyFactorAfterReject, Scalar facMax,
85  Scalar facMin, std::string name = "Integral Controller")
86  : controller_(controller),
87  KI_(KI),
88  KP_(KP),
89  KD_(KD),
90  safetyFactor_(safetyFactor),
91  safetyFactorAfterReject_(safetyFactorAfterReject),
92  facMax_(facMax),
93  facMin_(facMin)
94  {
96 
97  this->setStrategyType("Integral Controller");
98  this->setStepType("Variable");
99  this->setName(name);
100  this->initialize();
101  }
102 
105 
107  virtual void setNextTimeStep(
108  const TimeStepControl<Scalar> &tsc,
109  Teuchos::RCP<SolutionHistory<Scalar> > solutionHistory,
110  Status & /* integratorStatus */) override
111  {
112  using Teuchos::RCP;
113 
114  this->checkInitialized();
115 
116  // Take first step with initial time step provided
117  if (!firstSuccessfulStep_) {
118  firstSuccessfulStep_ = true;
119  return;
120  }
121 
122  RCP<SolutionState<Scalar> > workingState =
123  solutionHistory->getWorkingState();
124  Scalar beta = 1.0;
125 
126  // assumes the embedded solution is the low order solution
127  int order = workingState->getOrder() - 1;
128  Scalar dt = workingState->getTimeStep();
129 
130  // Get the relative errors.
131  Scalar errN = workingState->getErrorRel();
132  Scalar errNm1 = workingState->getErrorRelNm1();
133  Scalar errNm2 = workingState->getErrorRelNm2();
134 
135  if (errN < numericalTol<Scalar>()) errN = 1.0;
136  if (errNm1 < numericalTol<Scalar>()) errNm1 = 1.0;
137  if (errNm2 < numericalTol<Scalar>()) errNm2 = 1.0;
138 
139  Scalar k1 = Teuchos::as<Scalar>(-KI_ / order);
140  Scalar k2 = Teuchos::as<Scalar>(KP_ / order);
141  Scalar k3 = Teuchos::as<Scalar>(-KD_ / order);
142 
143  k1 = std::pow(errN, k1);
144  k2 = std::pow(errNm1, k2);
145  k3 = std::pow(errNm2, k3);
146 
147  if (controller_ == "I")
148  beta = safetyFactor_ * k1;
149  else if (controller_ == "PI")
150  beta = safetyFactor_ * k1 * k2;
151  else // (controller_ == "PID")
152  beta = safetyFactor_ * k1 * k2 * k3;
153 
154  beta = std::max(facMin_, beta);
155  beta = std::min(facMax_, beta);
156 
157  // new (optimal) suggested time step
158  dt = beta * dt;
159 
160  if (workingState->getSolutionStatus() == Status::PASSED ||
161  workingState->getSolutionStatus() == Status::WORKING) {
162  if (lastStepRejected_) {
163  dt = std::min(dt, workingState->getTimeStep());
164  }
165  else {
167  }
168  lastStepRejected_ = false;
169  }
170  else {
172  lastStepRejected_ = true;
173  }
174 
175  // update dt
176  workingState->setTimeStep(dt);
177  workingState->setTime(solutionHistory->getCurrentState()->getTime() + dt);
178  }
179 
181 
182  std::string description() const override
183  {
184  return "Tempus::TimeStepControlStrategyIntegralController";
185  }
186 
188  const Teuchos::EVerbosityLevel verbLevel) const override
189  {
190  auto l_out = Teuchos::fancyOStream(out.getOStream());
191  Teuchos::OSTab ostab(*l_out, 2, this->description());
192  l_out->setOutputToRootOnly(0);
193 
194  *l_out << "\n--- " << this->description() << " ---" << std::endl;
195 
196  if (Teuchos::as<int>(verbLevel) >= Teuchos::as<int>(Teuchos::VERB_MEDIUM)) {
197  *l_out << " Strategy Type = "
198  << this->getStrategyType() << std::endl
199  << " Step Type = " << this->getStepType()
200  << std::endl
201  << " Controller Type = " << getController()
202  << std::endl
203  << " KI = " << getKI()
204  << std::endl
205  << " KP = " << getKP()
206  << std::endl
207  << " KD = " << getKD()
208  << std::endl
209  << " Safety Factor = " << getSafetyFactor()
210  << std::endl
211  << " Safety Factor After Step Rejection = "
212  << getSafetyFactorAfterReject() << std::endl
213  << " Maximum Safety Factor (INPUT) = " << facMaxINPUT_
214  << std::endl
215  << " Maximum Safety Factor = " << getFacMax()
216  << std::endl
217  << " Minimum Safety Factor = " << getFacMin()
218  << std::endl;
219  *l_out << std::string(this->description().length() + 8, '-') << std::endl;
220  }
221  }
223 
226  const override
227  {
229  Teuchos::parameterList("Time Step Control Strategy");
230 
231  pl->set<std::string>("Strategy Type", this->getStrategyType(),
232  "Integral Controller");
233  pl->set<std::string>("Controller Type", getController(),
234  "Proportional-Integral-Derivative");
235  pl->set<Scalar>("KI", getKI(), "Integral gain");
236  pl->set<Scalar>("KP", getKP(), "Proportional gain");
237  pl->set<Scalar>("KD", getKD(), "Derivative gain");
238  pl->set<Scalar>("Safety Factor", getSafetyFactor(), "Safety Factor");
239  pl->set<Scalar>("Safety Factor After Step Rejection",
241  "Safety Factor Following Step Rejection");
242  pl->set<Scalar>("Maximum Safety Factor", getFacMax(),
243  "Maximum Safety Factor");
244  pl->set<Scalar>("Minimum Safety Factor", getFacMin(),
245  "Minimum Safety Factor");
246  return pl;
247  }
248 
249  virtual void initialize() const override
250  {
251  TEUCHOS_TEST_FOR_EXCEPTION(safetyFactor_ <= 0.0, std::out_of_range,
252  "Error - Invalid value of Safety Factory= "
253  << safetyFactor_ << "! \n"
254  << "Safety Factor must be > 0.0.\n");
255 
257  facMax_ <= 0.0, std::out_of_range,
258  "Error - Invalid value of Maximum Safety Factory= "
259  << facMax_ << "! \n"
260  << "Maximum Safety Factor must be > 0.0.\n");
261 
263  facMax_ <= 0.0, std::out_of_range,
264  "Error - Invalid value of Minimum Safety Factory= "
265  << facMin_ << "! \n"
266  << "Minimum Safety Factor must be > 0.0.\n");
267 
268  TEUCHOS_TEST_FOR_EXCEPTION(((controller_ != "I") && (controller_ != "PI") &&
269  (controller_ != "PID")),
270  std::invalid_argument,
271  "Error - Invalid choice of Controller Type = "
272  << controller_ << "! \n"
273  << "Valid Choice are ['I', 'PI', 'PID'].\n");
274 
275  this->isInitialized_ = true; // Only place where this is set to true!
276  }
277 
278  virtual std::string getController() const { return controller_; }
279  virtual Scalar getKI() const { return KI_; }
280  virtual Scalar getKP() const { return KP_; }
281  virtual Scalar getKD() const { return KD_; }
282  virtual Scalar getSafetyFactor() const { return safetyFactor_; }
283  virtual Scalar getSafetyFactorAfterReject() const
284  {
286  }
287  virtual Scalar getFacMax() const { return facMax_; }
288  virtual Scalar getFacMin() const { return facMin_; }
289 
290  virtual void setController(std::string c)
291  {
292  controller_ = c;
293  this->isInitialized_ = false;
294  }
295  virtual void setKI(Scalar k)
296  {
297  KI_ = k;
298  this->isInitialized_ = false;
299  }
300  virtual void setKP(Scalar k)
301  {
302  KP_ = k;
303  this->isInitialized_ = false;
304  }
305  virtual void setKD(Scalar k)
306  {
307  KD_ = k;
308  this->isInitialized_ = false;
309  }
310  virtual void setSafetyFactor(Scalar f)
311  {
312  safetyFactor_ = f;
313  this->isInitialized_ = false;
314  }
315  virtual void setSafetyFactorAfterReject(Scalar f)
316  {
318  this->isInitialized_ = false;
319  }
320  virtual void setFacMax(Scalar f)
321  {
322  facMax_ = f;
323  facMaxINPUT_ = f;
324  this->isInitialized_ = false;
325  }
326  virtual void setFacMin(Scalar f)
327  {
328  facMin_ = f;
329  this->isInitialized_ = false;
330  }
331 
332  private:
333  std::string controller_;
334  Scalar KI_;
335  Scalar KP_;
336  Scalar KD_;
337  Scalar safetyFactor_;
339  Scalar facMaxINPUT_;
340  Scalar facMax_;
341  Scalar facMin_;
342  bool firstSuccessfulStep_ = false;
343  bool lastStepRejected_ = false;
344 };
345 
346 // Nonmember constructor.
347 template <class Scalar>
351  std::string name = "Integral Controller")
352 {
353  using Teuchos::rcp;
355  if (pList == Teuchos::null || pList->numParams() == 0) return tscs;
356 
358  pList->get<std::string>("Strategy Type") != "Integral Controller",
359  std::logic_error,
360  "Error - Strategy Type != 'Integral Controller'. (='" +
361  pList->get<std::string>("Strategy Type") + "')\n");
362 
363  pList->validateParametersAndSetDefaults(*tscs->getValidParameters());
364 
365  tscs->setController(pList->get<std::string>("Controller Type"));
366  tscs->setKI(pList->get<Scalar>("KI"));
367  tscs->setKP(pList->get<Scalar>("KP"));
368  tscs->setKD(pList->get<Scalar>("KD"));
369  tscs->setSafetyFactor(pList->get<Scalar>("Safety Factor"));
370  tscs->setSafetyFactorAfterReject(
371  pList->get<Scalar>("Safety Factor After Step Rejection"));
372  tscs->setFacMax(pList->get<Scalar>("Maximum Safety Factor"));
373  tscs->setFacMin(pList->get<Scalar>("Minimum Safety Factor"));
374 
375  tscs->setName(name);
376  tscs->initialize();
377 
378  return tscs;
379 }
380 
382 template <class Scalar>
385 {
387  return Teuchos::rcp_const_cast<Teuchos::ParameterList>(
388  t->getValidParameters());
389 }
390 
391 } // namespace Tempus
392 #endif // Tempus_TimeStepControlStrategy_IntegralController_hpp
virtual Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Return ParameterList with current values.
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Ordinal numParams() const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Status
Status for the Integrator, the Stepper and the SolutionState.
bool isInitialized_
Bool if strategy is initialized.
TimeStepControl manages the time step size. There several mechanisms that effect the time step size a...
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
std::string controller_
Control type [&#39;I&#39;, &#39;PI&#39;, &#39;PID&#39;].
Teuchos::RCP< Teuchos::ParameterList > getTimeStepControlStrategyIntegralControllerPL()
Nonmember function to return ParameterList with default values.
TimeStepControlStrategyIntegralController(std::string controller, Scalar KI, Scalar KP, Scalar KD, Scalar safetyFactor, Scalar safetyFactorAfterReject, Scalar facMax, Scalar facMin, std::string name="Integral Controller")
Full Constructor.
virtual void setNextTimeStep(const TimeStepControl< Scalar > &tsc, Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory, Status &) override
Set the time step size.
Teuchos::RCP< TimeStepControlStrategyIntegralController< Scalar > > createTimeStepControlStrategyIntegralController(const Teuchos::RCP< Teuchos::ParameterList > pList, std::string name="Integral Controller")
RCP< std::basic_ostream< char_type, traits_type > > getOStream()
TimeStepControlStrategy class for TimeStepControl.