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