Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
BDF2 (Backward-Difference-Formula-2) time stepper.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
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 Teuchos::RCP< StepperObserver< Scalar > > getObserver() const
Get Observer.
virtual bool isExplicit() const
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual Scalar getBeta(const Scalar) const
Return beta = d(x)/dx.
Teuchos::RCP< Stepper< Scalar > > startUpStepper_
Teuchos::RCP< StepperObserverComposite< Scalar > > stepperObserver_
virtual void computeStartUp(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Compute the first time step given the supplied startup stepper.
Thyra Base interface for time steppers.
Thyra Base interface for implicit time steppers.
virtual Scalar getAlpha(const Scalar dt) const
Return alpha = d(xDot)/dx.
Teuchos::RCP< StepperBDF2Observer< Scalar > > stepperBDF2Observer_
virtual Scalar getOrderMin() const
StepperObserver class for Stepper class.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOld_
virtual OrderODE getOrderODE() const
Stepper integrates first-order ODEs.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
virtual Scalar getOrder() const
StepperBDF2TimeDerivative(Scalar dt, Scalar dtOld, Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOld, Teuchos::RCP< const Thyra::VectorBase< Scalar > > xOldOld)
Constructor.
virtual bool isOneStepMethod() const
virtual bool isExplicitImplicit() const
This interface defines the time derivative connection between an implicit Stepper and WrapperModelEva...
virtual bool isMultiStepMethod() const
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 Scalar dtOld) const
virtual Scalar getOrderMax() const
virtual bool getICConsistencyCheckDefault() const
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() 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.
virtual bool isImplicit() const