Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tempus_TimeStepControlStrategyIntegralController.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ****************************************************************************
3 // Tempus: Copyright (2017) Sandia Corporation
4 //
5 // Distributed under BSD 3-clause license (See accompanying file Copyright.txt)
6 // ****************************************************************************
7 // @HEADER
8 
9 #ifndef Tempus_TimeStepControlStrategy_IntegralController_hpp
10 #define Tempus_TimeStepControlStrategy_IntegralController_hpp
11 
12 #include "Tempus_TimeStepControl.hpp"
14 #include "Tempus_SolutionState.hpp"
15 #include "Tempus_SolutionHistory.hpp"
16 #include "Tempus_StepperState.hpp"
17 
18 
19 namespace Tempus {
20 
21 /** \brief StepControlStrategy class for TimeStepControl
22  *
23  *
24  * Gustaf Soderlind.
25  * Automatic control and adaptive time-stepping.
26  * Numerical Algorithms, 31(1):281–310, Dec 2002.
27  *
28  * The step size is chosen based on "Controller Type":
29  *
30  * PID = Proportional-Integral-Derivative Controller
31  * \f[
32  * (\Delta t)_{n+1} =
33  * (\Delta t)_n \left( \epsilon_n ^{-k_1 / p} \epsilon_{n-1}^{k_2 / p} \epsilon_{n-2}^{-k_3 / p} \right)
34  * \f]
35  *
36  * PI = Proportional-Integral Controller
37  * \f[
38  * (\Delta t)_{n+1} =
39  * (\Delta t)_n \left( \epsilon_n ^{-k_1 / p} \epsilon_{n-1}^{k_2 / p} \right)
40  * \f]
41  *
42  * I = Integral Controller
43  * \f[
44  * (\Delta t)_{n+1} =
45  * (\Delta t)_n \left( \epsilon_n ^{-k_1 / p} \right)
46  * \f]
47  *
48  * where \f$\epsilon_n \f$ is the error at time step \f$n\f$.
49  *
50  * Appropriate for Explicit Methods
51  */
52 template<class Scalar>
54  : virtual public TimeStepControlStrategy<Scalar>
55 {
56 public:
57 
58  /// Constructor
59  TimeStepControlStrategyIntegralController(Teuchos::RCP<Teuchos::ParameterList> pList = Teuchos::null){
60  this->setParameterList(pList);
61  }
62 
63  /// Destructor
65 
66  /** \brief Determine the time step size.*/
67  virtual void getNextTimeStep(const TimeStepControl<Scalar> tsc,
68  Teuchos::RCP<SolutionHistory<Scalar> > solutionHistory,
69  Status & /* integratorStatus */) override
70  {
71 
72  // Take first step with initial time step provided
74  firstSuccessfulStep_ = true;
75  return;
76  }
77 
78  Teuchos::RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
79  const Scalar errorRel = workingState->getErrorRel();
80  Scalar beta = 1.0;
81 
82  // assumes the embedded solution is the low order solution
83  int order = workingState->getOrder() - 1;
84  Scalar dt = workingState->getTimeStep();
85  //bool printDtChanges = tsc.getPrintDtChanges();
86 
87  Teuchos::RCP<Teuchos::FancyOStream> out = tsc.getOStream();
88  Teuchos::OSTab ostab(out,1,"getNextTimeStep");
89 
90  // For now, only time step is changed (not order)
91  /*
92  auto changeOrder = [] (int order_old, int order_new, std::string reason) {
93  std::stringstream message;
94  message << " (order = " << std::setw(2) << order_old
95  << ", new = " << std::setw(2) << order_new
96  << ") " << reason << std::endl;
97  return message.str();
98  };
99  */
100 
101  // update errors
102  errNm2_ = errNm1_;
103  errNm1_ = errN_;
104  errN_ = errorRel;
105 
106  Scalar k1 = Teuchos::as<Scalar>(-k1_ / order);
107  Scalar k2 = Teuchos::as<Scalar>(k2_ / order);
108  Scalar k3 = Teuchos::as<Scalar>(-k3_ / order);
109 
110  k1 = std::pow(errN_, k1);
111  k2 = std::pow(errNm1_, k2);
112  k3 = std::pow(errNm2_, k3);
113 
114  if (controller_ == "I")
115  beta = safetyFactor_*k1;
116  else if (controller_ == "PI")
117  beta = safetyFactor_ *k1*k2;
118  else // (controller_ == "PID")
119  beta = safetyFactor_*k1*k2*k3;
120 
121  beta = std::max(facMin_, beta);
122  beta = std::min(facMax_, beta);
123 
124  // new (optimal) suggested time step
125  dt = beta * dt;
126 
127  if (workingState->getSolutionStatus() == Status::PASSED or
128  workingState->getSolutionStatus() == Status::WORKING) {
129  if(lastStepRejected_){
130  dt = std::min(dt, workingState->getTimeStep());
131  } else {
132  facMax_ = tscsPL_->get<Scalar>("Maximum Safety Factor");
133  }
134  lastStepRejected_ = false;
135  } else {
136  facMax_ = tscsPL_->get<Scalar>("Safety Factor After Step Rejection");
137  lastStepRejected_ = true;
138  }
139 
140  // update dt
141  workingState->setTimeStep(dt);
142  }
143 
144  /// \name Overridden from Teuchos::ParameterListAcceptor
145  //@{
147  const Teuchos::RCP<Teuchos::ParameterList> & pList) override
148  {
149 
150  if (pList == Teuchos::null) {
151  // Create default parameters if null, otherwise keep current parameters.
152  if (tscsPL_ == Teuchos::null) {
153  tscsPL_ = Teuchos::parameterList("TimeStepControlStrategyIntegralController");
154  *tscsPL_= *(this->getValidParameters());
155  }
156  } else {
157  tscsPL_ = pList;
158  }
159  tscsPL_->validateParametersAndSetDefaults(*this->getValidParameters());
160 
161  errN_ = Scalar(1.0);
162  errNm1_ = Scalar(1.0);
163  errNm2_ = Scalar(1.0);
164  k1_ = tscsPL_->get<Scalar>("KI");
165  k2_ = tscsPL_->get<Scalar>("KP");
166  k3_ = tscsPL_->get<Scalar>("KD");
167  safetyFactor_ = tscsPL_->get<Scalar>("Safety Factor");
168  facMax_ = tscsPL_->get<Scalar>("Maximum Safety Factor");
169  facMin_ = tscsPL_->get<Scalar>("Minimum Safety Factor");
170  controller_ = tscsPL_->get<std::string>("Controller Type");
171 
172  TEUCHOS_TEST_FOR_EXCEPTION(safetyFactor_ <= 0.0, std::out_of_range,
173  "Error - Invalid value of Safety Factory= " << safetyFactor_ << "! \n"
174  << "Safety Factor must be > 0.0.\n");
175 
176  TEUCHOS_TEST_FOR_EXCEPTION(facMax_ <= 0.0, std::out_of_range,
177  "Error - Invalid value of Maximum Safety Factory= " << facMax_ << "! \n"
178  << "Maximum Safety Factor must be > 0.0.\n");
179 
180  TEUCHOS_TEST_FOR_EXCEPTION(facMax_<= 0.0, std::out_of_range,
181  "Error - Invalid value of Minimum Safety Factory= " << facMin_ << "! \n"
182  << "Minimum Safety Factor must be > 0.0.\n");
183 
184  TEUCHOS_TEST_FOR_EXCEPTION(((controller_ != "I") and
185  (controller_ != "PI") and
186  (controller_ != "PID")), std::invalid_argument,
187  "Error - Invalid choice of Controller Type = " << controller_ << "! \n"
188  << "Valid Choice are ['I', 'PI', 'PID'].\n");
189 
190  }
191 
192  Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const override
193  {
194  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
195 
196  pl->set<std::string>("Name","Integral Controller","Integral Controller");
197  pl->set<std::string>("Controller Type","PID",
198  "Proportional-Integral-Derivative");
199  pl->set<Scalar>("KI" , 0.58, "Integral gain");
200  pl->set<Scalar>("KP" , 0.21, "Proportional gain");
201  pl->set<Scalar>("KD" , 0.10, "Derivative gain");
202  pl->set<Scalar>("Safety Factor" , 0.90, "Safety Factor");
203  pl->set<Scalar>("Maximum Safety Factor" , 5.0, "Maximum Safety Factor");
204  pl->set<Scalar>("Minimum Safety Factor" , 0.5, "Minimum Safety Factor");
205  pl->set<Scalar>("Safety Factor After Step Rejection" , 0.9,
206  "Safety Factor Following Step Rejection");
207  return pl;
208  }
209 
210  Teuchos::RCP<Teuchos::ParameterList> getNonconstParameterList() override {
211  return tscsPL_;
212  }
213 
214  Teuchos::RCP<Teuchos::ParameterList> unsetParameterList() override {
215  Teuchos::RCP<Teuchos::ParameterList> temp_plist = tscsPL_;
216  tscsPL_ = Teuchos::null;
217  return(temp_plist);
218  }
219  //@}
220 
221 private:
222  Teuchos::RCP<Teuchos::ParameterList> tscsPL_;
223  Scalar k1_;
224  Scalar k2_;
225  Scalar k3_;
226  Scalar errN_;
227  Scalar errNm1_;
228  Scalar errNm2_;
230  Scalar facMax_;
231  Scalar facMin_;
232  bool firstSuccessfulStep_ = false;
233  bool lastStepRejected_ = false;
234  std::string controller_;
235 
236 };
237 } // namespace Tempus
238 #endif // Tempus_TimeStepControlStrategy_IntegralController_hpp
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Status
Status for the Integrator, the Stepper and the SolutionState.
TimeStepControl manages the time step size. There several mechanicisms that effect the time step size...
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &pList) override
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
TimeStepControlStrategyIntegralController(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Constructor.
StepControlStrategy class for TimeStepControl.
virtual void getNextTimeStep(const TimeStepControl< Scalar > tsc, Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory, Status &) override
Determine the time step size.