Tempus  Version of the Day
Time Integration
Tempus_TimeStepControlStrategyBasicVS.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_BasicVS_hpp
10 #define Tempus_TimeStepControlStrategy_BasicVS_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 //Thyra
20 #include "Thyra_VectorStdOps.hpp"
21 
22 namespace Tempus {
23 
24 /** \brief StepControlStrategy class for TimeStepControl
25  *
26  * This TimeStepControlStrategy primarily tries to maintain a
27  * certain level of change in the solution ill-respective of the
28  * error involved, e.g., the solution should change by 1% every
29  * time step. The relative solution change is measured by
30  * \f[
31  * \eta_{n-1} = \frac{|| x_{n-1} - x_{n-2} ||}{ || x_{n-2} || + \epsilon }
32  * \f]
33  * where \f$\epsilon\f$ is a small constant to ensure that \f$\eta_n\f$
34  * remains finite. The user can select the desired relative
35  * change in the solution by choosing a range for \f$\eta_n\f$
36  * \f[
37  * \eta_{min} < \eta_n < \eta_{max}
38  * \f]
39  * If the solution change is outside this range, an amplification
40  * (\f$\rho\f$) or reduction factor (\f$\sigma\f$) is applied to
41  * the timestep to bring the solution change back into the desired
42  * range. This can be written as
43  * \f[
44  * \Delta t_n = \left\{
45  * \begin{array}{rll}
46  * \sigma \Delta t_{n-1} & \mbox{if $\eta_{n-1} > \eta_{max}$}
47  * & \mbox{where $0 < \sigma < 1$} \\
48  * \rho \Delta t_{n-1} & \mbox{else if $\eta_{n-1} < \eta_{min}$}
49  * & \mbox{where $\rho > 1$} \\
50  * \Delta t_{n-1} &
51  * \mbox{else if $\eta_{min}<\eta_{n-1}<\eta_{max}$} \\
52  * \end{array}
53  * \right.
54  * \f]
55  * In the full implementation, several other mechanisms can amplify
56  * or reduce the timestep.
57  * - Stepper fails
58  * - Maximum Absolute error, \f$e_{abs}^{max}\f$
59  * - Maximum Relative error, \f$e_{rel}^{max}\f$
60  * - Order, \f$p\f$
61  * \f[
62  * \Delta t_n = \left\{
63  * \begin{array}{rll}
64  * \sigma \Delta t_{n-1} & \mbox{if Stepper fails}
65  * & \mbox{where $0 < \sigma < 1$} \\
66  * \rho \Delta t_{n-1} & \mbox{else if $\eta_{n-1} < \eta_{min}$}
67  * & \mbox{where $\rho > 1$} \\
68  * \sigma \Delta t_{n-1} & \mbox{else if $\eta_{n-1} > \eta_{max}$}
69  * & \mbox{where $0 < \sigma < 1$} \\
70  * \sigma \Delta t_{n-1} & \mbox{else if $e_{abs} > e_{abs}^{max}$}
71  * & \mbox{where $0 < \sigma < 1$} \\
72  * \sigma \Delta t_{n-1} & \mbox{else if $e_{rel} > e_{rel}^{max}$}
73  * & \mbox{where $0 < \sigma < 1$} \\
74  * \rho \Delta t_{n-1} & \mbox{else if $p < p_{min}$}
75  * & \mbox{where $\rho > 1$} \\
76  * \sigma \Delta t_{n-1} & \mbox{else if $p > p_{max}$}
77  * & \mbox{where $0 < \sigma < 1$} \\
78  * \Delta t_{n-1} & \mbox{else} & \\
79  * \end{array}
80  * \right.
81  * \f]
82  *
83  * Note
84  * - Only one amplification or reduction is applied each timestep.
85  * - The priority is specified by the order of list.
86  * - The timestep, \f$\Delta t_n\f$, is still constrained to the
87  * maximum and minimum timestep size.
88  * \f$\Delta t_{min} < \Delta t_n < \Delta t_{max}\f$
89  * - If \f$ \eta_{min} < \eta_n < \eta_{max}\f$, the timestep
90  * is unchanged, i.e., constant timestep size.
91  * - To have constant timesteps, set \f$\eta_{min}=0\f$ and
92  * \f$\eta_{max}=10^{16}\f$. These are the defaults.
93  * - From (Denner, 2014), amplification factor, \f$\rho\f$, is
94  * required to be less than 1.91 for stability (\f$\rho < 1.91\f$).
95  * - Denner (2014) suggests that \f$\eta_{min} = 0.1*\eta_{max}\f$
96  * and the numerical tests confirm this for their problems.
97  *
98  * #### References
99  * Section 2.2.1 / Algorithm 2.4 of A. Denner, "Experiments on
100  * Temporal Variable Step BDF2 Algorithms", Masters Thesis,
101  * U Wisconsin-Madison, 2014.
102  *
103  */
104 template<class Scalar>
106  : virtual public TimeStepControlStrategy<Scalar>
107 {
108 public:
109 
110  /// Constructor
112  Teuchos::RCP<Teuchos::ParameterList> pList = Teuchos::null){
113  this->setParameterList(pList);
114  }
115 
116  /// Destructor
118 
119  /** \brief Determine the time step size.*/
120  virtual void getNextTimeStep(
121  const TimeStepControl<Scalar> tsc,
123  Status & integratorStatus) override
124  {
125  using Teuchos::RCP;
126  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
127  RCP<SolutionStateMetaData<Scalar> > metaData = workingState->getMetaData();
128  const Scalar errorAbs = metaData->getErrorAbs();
129  const Scalar errorRel = metaData->getErrorRel();
130  int order = metaData->getOrder();
131  Scalar dt = metaData->getDt();
132  bool printChanges = solutionHistory->getVerbLevel() !=
133  Teuchos::as<int>(Teuchos::VERB_NONE);
134 
135  RCP<Teuchos::FancyOStream> out = tsc.getOStream();
136  Teuchos::OSTab ostab(out,1,"getNextTimeStep");
137 
138  auto changeDT = [] (Scalar dt_old, Scalar dt_new, std::string reason) {
139  std::stringstream message;
140  message <<
141  " (dt = "<<std::scientific<<std::setw(9)<<std::setprecision(3)<<dt_old
142  << ", new = "<<std::scientific<<std::setw(9)<<std::setprecision(3)<<dt_new
143  << ") " << reason << std::endl;
144  return message.str();
145  };
146 
147  Scalar rho = getAmplFactor();
148  Scalar sigma = getReductFactor();
149  Scalar eta = computeEta(tsc, solutionHistory);
150 
151  // General rule: only increase/decrease dt once for any given reason.
152  if (workingState->getSolutionStatus() == Status::FAILED) {
153  if (printChanges) *out << changeDT(dt, dt*sigma,
154  "Stepper failure - Decreasing dt.");
155  dt *= sigma;
156  }
157  else { //Stepper passed
158  if (eta < getMinEta()) { // increase dt
159  if (printChanges) *out << changeDT(dt, dt*rho,
160  "Monitoring Value (eta) is too small ("
161  + std::to_string(eta) + " < " + std::to_string(getMinEta())
162  + "). Increasing dt.");
163  dt *= rho;
164  }
165  else if (eta > getMaxEta()) { // reduce dt
166  if (printChanges) *out << changeDT(dt, dt*sigma,
167  "Monitoring Value (eta) is too large ("
168  + std::to_string(eta) + " > " + std::to_string(getMaxEta())
169  + "). Decreasing dt.");
170  dt *= sigma;
171  }
172  else if (errorAbs > tsc.getMaxAbsError()) { // reduce dt
173  if (printChanges) *out << changeDT(dt, dt*sigma,
174  "Absolute error is too large ("
175  + std::to_string(errorAbs)+" > "+std::to_string(tsc.getMaxAbsError())
176  + "). Decreasing dt.");
177  dt *= sigma;
178  }
179  else if (errorRel > tsc.getMaxRelError()) { // reduce dt
180  if (printChanges) *out << changeDT(dt, dt*sigma,
181  "Relative error is too large ("
182  + std::to_string(errorRel)+" > "+std::to_string(tsc.getMaxRelError())
183  + "). Decreasing dt.");
184  dt *= sigma;
185  }
186  else if (order < tsc.getMinOrder()) { // order too low, increase dt
187  if (printChanges) *out << changeDT(dt, dt*rho,
188  "Order is too small ("
189  + std::to_string(order) + " < " + std::to_string(tsc.getMinOrder())
190  + "). Increasing dt.");
191  dt *= rho;
192  }
193  else if (order > tsc.getMaxOrder()) { // order too high, reduce dt
194  if (printChanges) *out << changeDT(dt, dt*sigma,
195  "Order is too large ("
196  + std::to_string(order) + " > " + std::to_string(tsc.getMaxOrder())
197  + "). Decreasing dt.");
198  dt *= sigma;
199  }
200  }
201 
202  if (dt < tsc.getMinTimeStep()) { // decreased below minimum dt
203  if (printChanges) *out << changeDT(dt, tsc.getMinTimeStep(),
204  "dt is too small. Resetting to minimum dt.");
205  dt = tsc.getMinTimeStep();
206  }
207  if (dt > tsc.getMaxTimeStep()) { // increased above maximum dt
208  if (printChanges) *out << changeDT(dt, tsc.getMaxTimeStep(),
209  "dt is too large. Resetting to maximum dt.");
210  dt = tsc.getMaxTimeStep();
211  }
212 
213  metaData->setOrder(order);
214  metaData->setDt(dt);
215  }
216 
217  /// \name Overridden from Teuchos::ParameterListAcceptor
218  //@{
220  const Teuchos::RCP<Teuchos::ParameterList> & pList) override
221  {
222  if (pList == Teuchos::null) {
223  // Create default parameters if null, otherwise keep current parameters.
224  if (tscsPL_ == Teuchos::null) {
225  tscsPL_ = Teuchos::parameterList("TimeStepControlStrategyBasicVS");
226  *tscsPL_= *(this->getValidParameters());
227  }
228  } else {
229  tscsPL_ = pList;
230  }
231  tscsPL_->validateParametersAndSetDefaults(*this->getValidParameters());
232 
233  TEUCHOS_TEST_FOR_EXCEPTION(getAmplFactor() <= 1.0, std::out_of_range,
234  "Error - Invalid value of Amplification Factor = " << getAmplFactor()
235  << "! \n" << "Amplification Factor must be > 1.0.\n");
236 
237  TEUCHOS_TEST_FOR_EXCEPTION(getReductFactor() >= 1.0, std::out_of_range,
238  "Error - Invalid value of Reduction Factor = " << getReductFactor()
239  << "! \n" << "Reduction Factor must be < 1.0.\n");
240 
241  TEUCHOS_TEST_FOR_EXCEPTION(getMinEta() > getMaxEta(), std::out_of_range,
242  "Error - Invalid values of 'Minimum Value Monitoring Function' = "
243  << getMinEta() << "\n and 'Maximum Value Monitoring Function' = "
244  << getMaxEta() <<"! \n Mininum Value cannot be > Maximum Value! \n");
245 
246  }
247 
248  Teuchos::RCP<const Teuchos::ParameterList>
249  getValidParameters() const override {
250  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
251 
252  // From (Denner, 2014), amplification factor can be at most 1.91 for
253  // stability.
254  pl->set<double>("Amplification Factor", 1.75, "Amplification factor");
255  pl->set<double>("Reduction Factor" , 0.5 , "Reduction factor");
256  // From (Denner, 2014), it seems a reasonable choice for eta_min is
257  // 0.1*eta_max. Numerical tests confirm this.
258  pl->set<double>("Minimum Value Monitoring Function", 0.0 , "Min value eta");
259  pl->set<double>("Maximum Value Monitoring Function", 1.0e-16, "Max value eta");
260  pl->set<std::string>("Name", "Basic VS");
261  return pl;
262  }
263 
264  Teuchos::RCP<Teuchos::ParameterList> getNonconstParameterList() override {
265  return tscsPL_;
266  }
267 
268  Teuchos::RCP<Teuchos::ParameterList> unsetParameterList() override {
269  Teuchos::RCP<Teuchos::ParameterList> temp_plist = tscsPL_;
270  tscsPL_ = Teuchos::null;
271  return(temp_plist);
272  }
273  //@}
274 
275  virtual Scalar getAmplFactor() const
276  { return tscsPL_->get<double>("Amplification Factor"); }
277  virtual Scalar getReductFactor() const
278  { return tscsPL_->get<double>("Reduction Factor");}
279  virtual Scalar getMinEta() const
280  { return tscsPL_->get<double>("Minimum Value Monitoring Function"); }
281  virtual Scalar getMaxEta() const
282  { return tscsPL_->get<double>("Maximum Value Monitoring Function"); }
283 
285  const Teuchos::RCP<SolutionHistory<Scalar> > & solutionHistory)
286  {
287  using Teuchos::RCP;
288  Scalar eta;
289  const double eps = 1.0e4*std::numeric_limits<double>::epsilon();
290  RCP<Teuchos::FancyOStream> out = tsc.getOStream();
291  int numStates = solutionHistory->getNumStates();
292  //Compute eta
293  if (numStates < 3) {
294  eta = getMinEta();
295  return eta;
296  }
297  RCP<const Thyra::VectorBase<Scalar> > xOld = (*solutionHistory)[numStates-3]->getX();
298  RCP<const Thyra::VectorBase<Scalar> > x = (*solutionHistory)[numStates-1]->getX();
299  //IKT: uncomment the following to get some debug output
300  //#define VERBOSE_DEBUG_OUTPUT
301 #ifdef VERBOSE_DEBUG_OUTPUT
302  Teuchos::Range1D range;
303  *out << "\n*** xOld ***\n";
304  RTOpPack::ConstSubVectorView<Scalar> xOldv;
305  xOld->acquireDetachedView(range, &xOldv);
306  auto xoa = xOldv.values();
307  for (auto i = 0; i < xoa.size(); ++i) *out << xoa[i] << " ";
308  *out << "\n*** xOld ***\n";
309  *out << "\n*** x ***\n";
310  RTOpPack::ConstSubVectorView<Scalar> xv;
311  x->acquireDetachedView(range, &xv);
312  auto xa = xv.values();
313  for (auto i = 0; i < xa.size(); ++i) *out << xa[i] << " ";
314  *out << "\n*** x ***\n";
315 #endif
316  //xDiff = x - xOld
317  RCP<Thyra::VectorBase<Scalar> > xDiff = Thyra::createMember(x->space());
318  Thyra::V_VmV(xDiff.ptr(), *x, *xOld);
319  Scalar xDiffNorm = Thyra::norm(*xDiff);
320  Scalar xOldNorm = Thyra::norm(*xOld);
321  //eta = ||x^(n+1)-x^n||/(||x^n||+eps)
322  eta = xDiffNorm/(xOldNorm + eps);
323 #ifdef VERBOSE_DEBUG_OUTPUT
324  *out << "IKT xDiffNorm, xOldNorm, eta = " << xDiffNorm << ", " << xOldNorm
325  << ", " << eta << "\n";
326 #endif
327  return eta;
328  }
329 
330 private:
331  Teuchos::RCP<Teuchos::ParameterList> tscsPL_;
332 };
333 } // namespace Tempus
334 #endif // Tempus_TimeStepControlStrategy_BasicVS_hpp
Tempus::TimeStepControlStrategyBasicVS::getMaxEta
virtual Scalar getMaxEta() const
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:281
Tempus::TimeStepControl::getMaxRelError
virtual Scalar getMaxRelError() const
Definition: Tempus_TimeStepControl_decl.hpp:110
Tempus::TimeStepControl::getMaxOrder
virtual int getMaxOrder() const
Definition: Tempus_TimeStepControl_decl.hpp:116
Tempus::solutionHistory
Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Nonmember constructor.
Definition: Tempus_SolutionHistory_impl.hpp:504
Tempus_TimeStepControlStrategy.hpp
Tempus
Definition: Tempus_AdjointAuxSensitivityModelEvaluator_decl.hpp:20
Tempus::TimeStepControl::getMinOrder
virtual int getMinOrder() const
Definition: Tempus_TimeStepControl_decl.hpp:112
Tempus::TimeStepControlStrategyBasicVS::getNonconstParameterList
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList() override
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:264
Tempus::TimeStepControlStrategyBasicVS::getAmplFactor
virtual Scalar getAmplFactor() const
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:275
Tempus::TimeStepControlStrategyBasicVS::getReductFactor
virtual Scalar getReductFactor() const
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:277
Tempus::TimeStepControl::getMinTimeStep
virtual Scalar getMinTimeStep() const
Definition: Tempus_TimeStepControl_decl.hpp:98
Tempus_StepperState.hpp
Tempus::TimeStepControl
TimeStepControl manages the time step size. There several mechanicisms that effect the time step size...
Definition: Tempus_Integrator.hpp:26
Tempus::TimeStepControlStrategyBasicVS::setParameterList
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &pList) override
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:219
Tempus::SolutionHistory
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Definition: Tempus_Integrator.hpp:25
Tempus::TimeStepControlStrategyBasicVS::getValidParameters
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:249
Tempus::TimeStepControlStrategyBasicVS::~TimeStepControlStrategyBasicVS
virtual ~TimeStepControlStrategyBasicVS()
Destructor.
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:117
Tempus::TimeStepControlStrategyBasicVS::computeEta
Scalar computeEta(const TimeStepControl< Scalar > tsc, const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:284
Tempus::TimeStepControl::getMaxAbsError
virtual Scalar getMaxAbsError() const
Definition: Tempus_TimeStepControl_decl.hpp:108
Tempus::TimeStepControlStrategy
StepControlStrategy class for TimeStepControl.
Definition: Tempus_TimeStepControlStrategy.hpp:26
Tempus::FAILED
Definition: Tempus_Types.hpp:18
Tempus::TimeStepControlStrategyBasicVS::unsetParameterList
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList() override
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:268
Tempus::TimeStepControlStrategyBasicVS::getNextTimeStep
virtual void getNextTimeStep(const TimeStepControl< Scalar > tsc, Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory, Status &integratorStatus) override
Determine the time step size.
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:120
Tempus::TimeStepControlStrategyBasicVS::TimeStepControlStrategyBasicVS
TimeStepControlStrategyBasicVS(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Constructor.
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:111
Tempus::Status
Status
Status for the Integrator, the Stepper and the SolutionState.
Definition: Tempus_Types.hpp:16
Tempus::TimeStepControlStrategyBasicVS::tscsPL_
Teuchos::RCP< Teuchos::ParameterList > tscsPL_
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:331
Tempus::TimeStepControlStrategyBasicVS
StepControlStrategy class for TimeStepControl.
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:105
Tempus::TimeStepControl::getMaxTimeStep
virtual Scalar getMaxTimeStep() const
Definition: Tempus_TimeStepControl_decl.hpp:102
Tempus::TimeStepControlStrategyBasicVS::getMinEta
virtual Scalar getMinEta() const
Definition: Tempus_TimeStepControlStrategyBasicVS.hpp:279