Tempus  Version of the Day
Time Integration
Tempus_StepperBDF2_decl.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_StepperBDF2_decl_hpp
10 #define Tempus_StepperBDF2_decl_hpp
11 
12 #include "Tempus_StepperImplicit.hpp"
14 #include "Tempus_StepperObserverComposite.hpp"
16 
17 
18 namespace Tempus {
19 
20 /** \brief BDF2 (Backward-Difference-Formula-2) time stepper.
21  *
22  * For the implicit ODE system, \f$\mathcal{F}(\dot{x},x,t) = 0\f$,
23  * the solution, \f$\dot{x}\f$ and \f$x\f$, is determined using a
24  * solver (e.g., a non-linear solver, like NOX). This stepper allows
25  * for a variable time-step, \f$\Delta t\f$. It is a 2-step method.
26  *
27  * <b> Algorithm </b>
28  * - For \f$n=0\f$, set the initial condition, \f$x_0\f$.
29  * - For \f$n=1\f$, use a one-step startup stepper, e.g., Backward Euler
30  * or RK4. The default startup stepper is 'IRK 1 Stage Theta Method'
31  * which second order.
32  * - For \f$n>1\f$, solve for \f$x_n\f$ via
33  * \f$ f\left(x_n, \dot{x}_n, t_n\right) = 0\f$
34  * where \f$
35  * \dot{x}_{n} = \frac{2\tau_n + \tau_{n-1}}{\tau_n + \tau_{n-1}}
36  * \left[ \frac{x_n-x_{n-1}}{\tau_n}\right]
37  * - \frac{\tau_n}{\tau_n + \tau_{n-1}}
38  * \left[ \frac{x_{n-1}-x_{n-2}}{\tau_{n-1}}\right], \f$
39  * and \f$\Delta t_n = \tau_n = t_n - t_{n-1}\f$.
40  * - \f$\dot{x}_n \leftarrow
41  * \dot{x}_{n} = \frac{2\tau_n + \tau_{n-1}}{\tau_n + \tau_{n-1}}
42  * \left[ \frac{x_n-x_{n-1}}{\tau_n}\right]
43  * - \frac{\tau_n}{\tau_n + \tau_{n-1}}
44  * \left[ \frac{x_{n-1}-x_{n-2}}{\tau_{n-1}}\right], \f$
45  *
46  * The First-Step-As-Last (FSAL) principle is not needed BDF2.
47  * The default is to set useFSAL=false, however useFSAL=true will also work
48  * but have no affect (i.e., no-op).
49  *
50  * <b> Iteration Matrix, \f$W\f$.</b>
51  * Recalling that the definition of the iteration matrix, \f$W\f$, is
52  * \f[
53  * W = \alpha \frac{\partial \mathcal{F}_n}{\partial \dot{x}_n}
54  * + \beta \frac{\partial \mathcal{F}_n}{\partial x_n},
55  * \f]
56  * where \f$ \alpha \equiv \frac{\partial \dot{x}_n(x_n) }{\partial x_n}, \f$
57  * and \f$ \beta \equiv \frac{\partial x_n}{\partial x_n} = 1\f$, and
58  * the time derivative for BDF2 is
59  * \f[
60  * \dot{x}_n(x_n) = \frac{2\tau_n + \tau_{n-1}}{\tau_n + \tau_{n-1}}
61  * \left[ \frac{x_n-x_{n-1}}{\tau_n}\right]
62  * - \frac{\tau_n}{\tau_n + \tau_{n-1}}
63  * \left[ \frac{x_{n-1}-x_{n-2}}{\tau_{n-1}}\right],
64  * \f]
65  * where \f$\Delta t_n = \tau_n = t_n - t_{n-1}\f$,
66  * we can determine that
67  * \f$ \alpha = \frac{2\tau_n + \tau_{n-1}}{(\tau_n + \tau_{n-1})\tau_n}\f$
68  * and \f$ \beta = 1 \f$, and therefore write
69  * \f[
70  * W = \frac{2\tau_n + \tau_{n-1}}{(\tau_n + \tau_{n-1})\tau_n}
71  \frac{\partial \mathcal{F}_n}{\partial \dot{x}_n}
72  * + \frac{\partial \mathcal{F}_n}{\partial x_n}.
73  * \f]
74  */
75 template<class Scalar>
76 class StepperBDF2 : virtual public Tempus::StepperImplicit<Scalar>
77 {
78 public:
79 
80  /** \brief Default constructor.
81  *
82  * - Requires the following calls before takeStep():
83  * setModel() and initialize().
84  */
85  StepperBDF2();
86 
87  /** \brief Constructor.
88  *
89  * Constructs a fully initialized stepper.
90  */
92  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
93  const Teuchos::RCP<StepperObserver<Scalar> >& obs,
94  const Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> >& solver,
95  const Teuchos::RCP<Stepper<Scalar> >& startUpStepper,
96  bool useFSAL,
97  std::string ICConsistency,
98  bool ICConsistencyCheck,
99  bool zeroInitialGuess);
100 
101  /// \name Basic stepper methods
102  //@{
103  virtual void setModel(
104  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel);
105 
106  virtual void setObserver(
107  Teuchos::RCP<StepperObserver<Scalar> > obs = Teuchos::null);
108 
109  virtual Teuchos::RCP<StepperObserver<Scalar> > getObserver() const
110  { return this->stepperObserver_; }
111 
112  /// Set the stepper to use in first step
113  void setStartUpStepper(std::string startupStepperType);
114  void setStartUpStepper(Teuchos::RCP<Stepper<Scalar> > startupStepper);
115 
116  /// Initialize during construction and after changing input parameters.
117  virtual void initialize();
118 
119  /// Set the initial conditions and make them consistent.
120  virtual void setInitialConditions (
121  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory);
122 
123  /// Take the specified timestep, dt, and return true if successful.
124  virtual void takeStep(
125  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory);
126 
127  /// Get a default (initial) StepperState
128  virtual Teuchos::RCP<Tempus::StepperState<Scalar> > getDefaultStepperState();
129  virtual Scalar getOrder() const {return order_;}
130  virtual Scalar getOrderMin() const {return 1.0;}
131  virtual Scalar getOrderMax() const {return 2.0;}
132 
133  virtual bool isExplicit() const {return false;}
134  virtual bool isImplicit() const {return true;}
135  virtual bool isExplicitImplicit() const
136  {return isExplicit() and isImplicit();}
137  virtual bool isOneStepMethod() const {return false;}
138  virtual bool isMultiStepMethod() const {return !isOneStepMethod();}
139 
140  virtual OrderODE getOrderODE() const {return FIRST_ORDER_ODE;}
141  //@}
142 
143  /// Return alpha = d(xDot)/dx.
144  virtual Scalar getAlpha(const Scalar dt) const {return getAlpha(dt,dt);}
145  virtual Scalar getAlpha(const Scalar dt, const Scalar dtOld) const
146  { return (Scalar(2.0)*dt + dtOld)/(dt*(dt + dtOld)); }
147  /// Return beta = d(x)/dx.
148  virtual Scalar getBeta (const Scalar ) const { return Scalar(1.0); }
149 
150  /// Compute the first time step given the supplied startup stepper
151  virtual void computeStartUp(
152  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory);
153 
154  virtual bool getICConsistencyCheckDefault() const { return false; }
155  Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const;
156 
157  /// \name Overridden from Teuchos::Describable
158  //@{
159  virtual void describe(Teuchos::FancyOStream & out,
160  const Teuchos::EVerbosityLevel verbLevel) const;
161  //@}
162 
163  virtual bool isValidSetup(Teuchos::FancyOStream & out) const;
164 
165 private:
166 
167  Teuchos::RCP<Stepper<Scalar> > startUpStepper_;
168  Teuchos::RCP<StepperObserverComposite<Scalar> > stepperObserver_;
169  Teuchos::RCP<StepperBDF2Observer<Scalar> > stepperBDF2Observer_;
170  Scalar order_ = Scalar(2.0);
171 };
172 
173 /** \brief Time-derivative interface for BDF2.
174  *
175  * Given the state \f$x_n\f$, compute the BDF2 time-derivative,
176  * \f[
177  * \dot{x}_{n} = \frac{2\tau_n + \tau_{n-1}}{\tau_n + \tau_{n-1}}
178  * \left[ \frac{x_n-x_{n-1}}{\tau_n}\right]
179  * - \frac{\tau_n}{\tau_n + \tau_{n-1}}
180  * \left[ \frac{x_{n-1}-x_{n-2}}{\tau_{n-1}}\right]
181  * \f]
182  * where
183  * \f[
184  * \tau_n = t_n - t_{n-1}.
185  * \f]
186  * \f$\ddot{x}\f$ is not used and set to null.
187  */
188 template <typename Scalar>
190  : virtual public Tempus::TimeDerivative<Scalar>
191 {
192 public:
193 
194  /// Constructor
196  Scalar dt, Scalar dtOld, Teuchos::RCP<const Thyra::VectorBase<Scalar> > xOld,
197  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xOldOld)
198  { initialize(dt, dtOld, xOld, xOldOld); }
199 
200  /// Destructor
202 
203  /// Compute the time derivative.
204  virtual void compute(
205  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x,
206  Teuchos::RCP< Thyra::VectorBase<Scalar> > xDot,
207  Teuchos::RCP< Thyra::VectorBase<Scalar> > xDotDot = Teuchos::null)
208  {
209  xDotDot = Teuchos::null;
210  // Calculate the BDF2 x dot vector
211  const Scalar a = ((Scalar(2.0)*dt_ + dtOld_)/(dt_ + dtOld_))/dt_;
212  const Scalar b = ( dt_/(dt_ + dtOld_))/dtOld_;
213  //xDot = a*(x_n - x_{n-1}) - b*(x_{n-1} - x_{n-2})
214  Thyra::V_StVpStV(xDot.ptr(), a, *x, -(a+b), *xOld_);
215  Thyra::Vp_StV(xDot.ptr(), b, *xOldOld_);
216  }
217 
218  virtual void initialize(Scalar dt, Scalar dtOld,
219  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xOld,
220  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xOldOld)
221  { dt_ = dt; dtOld_ = dtOld; xOld_ = xOld; xOldOld_ = xOldOld;}
222 
223 private:
224 
225  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xOld_;
226  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xOldOld_;
227  Scalar dt_; // = t_n - t_{n-1}
228  Scalar dtOld_; // = t_{n-1} - t_{n-2}
229 };
230 
231 
232 } // namespace Tempus
233 
234 #endif // Tempus_StepperBDF2_decl_hpp
virtual Scalar getOrderMin() const
BDF2 (Backward-Difference-Formula-2) time stepper.
virtual Scalar getBeta(const Scalar) const
Return beta = d(x)/dx.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
virtual bool isOneStepMethod() const
virtual Teuchos::RCP< StepperObserver< Scalar > > getObserver() const
Get Observer.
Time-derivative interface for BDF2.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
virtual void compute(Teuchos::RCP< const Thyra::VectorBase< Scalar > > x, Teuchos::RCP< Thyra::VectorBase< Scalar > > xDot, Teuchos::RCP< Thyra::VectorBase< Scalar > > xDotDot=Teuchos::null)
Compute the time derivative.
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
virtual OrderODE getOrderODE() const
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
virtual Scalar getOrder() const
virtual bool isImplicit() const
Teuchos::RCP< Stepper< Scalar > > startUpStepper_
virtual bool isExplicitImplicit() const
virtual Scalar getAlpha(const Scalar dt, const Scalar dtOld) const
Teuchos::RCP< StepperObserverComposite< Scalar > > stepperObserver_
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
virtual void computeStartUp(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Compute the first time step given the supplied startup stepper.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Thyra Base interface for time steppers.
Thyra Base interface for implicit time steppers.
Teuchos::RCP< StepperBDF2Observer< Scalar > > stepperBDF2Observer_
virtual bool isExplicit() const
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
StepperObserver class for Stepper class.
virtual bool isMultiStepMethod() const
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual bool getICConsistencyCheckDefault() const
Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOld_
Stepper integrates first-order ODEs.
StepperBDF2TimeDerivative(Scalar dt, Scalar dtOld, Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOld, Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOldOld)
Constructor.
This interface defines the time derivative connection between an implicit Stepper and WrapperModelEva...
virtual void initialize(Scalar dt, Scalar dtOld, Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOld, Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOldOld)
virtual Scalar getAlpha(const Scalar dt) const
Return alpha = d(xDot)/dx.
virtual Scalar getOrderMax() const
Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOldOld_
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
void setStartUpStepper(std::string startupStepperType)
Set the stepper to use in first step.
virtual void initialize()
Initialize during construction and after changing input parameters.
StepperBDF2()
Default constructor.