Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tempus_StepperImplicit_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_StepperImplicit_decl_hpp
10 #define Tempus_StepperImplicit_decl_hpp
11 
12 // Tempus
13 #include "Tempus_Stepper.hpp"
14 #include "Tempus_WrapperModelEvaluatorBasic.hpp"
15 
16 
17 namespace Tempus {
18 
19 
20 template<class Scalar>
22 {
23  public:
24  /// Constructor
26  : timeDer_(Teuchos::null), timeStepSize_(Scalar(0.0)),
27  alpha_(Scalar(0.0)), beta_(Scalar(0.0)), evaluationType_(SOLVE_FOR_X),
28  stageNumber_(0)
29  {}
30  /// Constructor
32  Scalar timeStepSize, Scalar alpha, Scalar beta,
33  EVALUATION_TYPE evaluationType = SOLVE_FOR_X,
34  int stageNumber = 0)
35  : timeDer_(timeDer), timeStepSize_(timeStepSize),
36  alpha_(alpha), beta_(beta), evaluationType_(evaluationType),
37  stageNumber_(stageNumber)
38  {}
39 
40  Teuchos::RCP<TimeDerivative<Scalar> > timeDer_;
41  Scalar timeStepSize_;
42  Scalar alpha_;
43  Scalar beta_;
46 };
47 
48 /** \brief Thyra Base interface for implicit time steppers.
49  *
50  For first-order ODEs, we can write the implicit ODE as
51  \f[
52  \mathcal{F}(\dot{x}_n,x_n,t_n) = 0
53  \f]
54  where \f$x_n\f$ is the solution vector, \f$\dot{x}\f$ is the
55  time derivative, \f$t_n\f$ is the time and \f$n\f$ indicates
56  the \f$n^{th}\f$ time level. Note that \f$\dot{x}_n\f$ is
57  different for each time stepper and is a function of other
58  solution states, e.g., for Backward Euler,
59  \f[
60  \dot{x}_n(x_n) = \frac{x_n - x_{n-1}}{\Delta t}
61  \f]
62 
63  <b> Defining the Iteration Matrix</b>
64 
65  Often we use Newton's method or one of its variations to solve
66  for \f$x_n\f$, such as
67  \f[
68  \left[
69  \frac{\partial}{\partial x_n}
70  \left(
71  \mathcal{F}(\dot{x}_n,x_n,t_n)
72  \right)
73  \right] \Delta x_n^\nu = - \mathcal{F}(\dot{x}_n^\nu,x_n^\nu,t_n)
74  \f]
75  where \f$\Delta x_n^\nu = x_n^{\nu+1} - x_n^\nu\f$ and \f$\nu\f$
76  is the iteration index. Using the chain rule for a function
77  with multiple variables, we can write
78  \f[
79  \left[
80 
81  \frac{\partial \dot{x}_n(x_n) }{\partial x_n}
82  \frac{\partial}{\partial \dot{x}_n}
83  \left(
84  \mathcal{F}(\dot{x}_n,x_n,t_n)
85  \right)
86  +
87  \frac{\partial x_n}{\partial x_n}
88  \frac{\partial}{\partial x_n}
89  \left(
90  \mathcal{F}(\dot{x}_n,x_n,t_n)
91  \right)
92 
93  \right] \Delta x_n^\nu = - \mathcal{F}(\dot{x}_n^\nu,x_n^\nu,t_n)
94  \f]
95  Defining the iteration matrix, \f$W\f$, we have
96  \f[
97  W \Delta x_n^\nu = - \mathcal{F}(\dot{x}_n^\nu,x_n^\nu,t_n)
98  \f]
99  using \f$\mathcal{F}_n = \mathcal{F}(\dot{x}_n,x_n,t_n)\f$, where
100  \f[
101  W = \alpha \frac{\partial \mathcal{F}_n}{\partial \dot{x}_n}
102  + \beta \frac{\partial \mathcal{F}_n}{\partial x_n}
103  \f]
104  and
105  \f[
106  W = \alpha M + \beta J
107  \f]
108  where
109  \f[
110  \alpha \equiv \frac{\partial \dot{x}_n(x_n) }{\partial x_n},
111  \quad \quad
112  \beta \equiv \frac{\partial x_n}{\partial x_n} = 1,
113  \quad \quad
114  M = \frac{\partial \mathcal{F}_n}{\partial \dot{x}_n},
115  \quad \quad
116  J = \frac{\partial \mathcal{F}_n}{\partial x_n}
117  \f]
118  and \f$M\f$ is the mass matrix and \f$J\f$ is the Jacobian.
119 
120  Note that sometimes it is helpful to set \f$\alpha=0\f$ and
121  \f$\beta = 1\f$ to obtain the Jacobian, \f$J\f$, from the
122  iteration matrix (i.e., ModelEvaluator), or set \f$\alpha=1\f$
123  and \f$\beta = 0\f$ to obtain the mass matrix, \f$M\f$, from
124  the iteration matrix (i.e., the ModelEvaluator).
125 
126  As a concrete example, the time derivative for Backward Euler is
127  \f[
128  \dot{x}_n(x_n) = \frac{x_n - x_{n-1}}{\Delta t}
129  \f]
130  thus
131  \f[
132  \alpha \equiv \frac{\partial \dot{x}_n(x_n) }{\partial x_n}
133  = \frac{1}{\Delta t}
134  \quad \quad
135  \beta \equiv \frac{\partial x_n}{\partial x_n} = 1
136  \f]
137  and the iteration matrix for Backward Euler is
138  \f[
139  W = \frac{1}{\Delta t} \frac{\partial \mathcal{F}_n}{\partial \dot{x}_n}
140  + \frac{\partial \mathcal{F}_n}{\partial x_n}
141  \f]
142 
143  <b> Dangers of multiplying through by \f$\Delta t\f$. </b>
144  In some time-integration schemes, the application might want
145  to multiply the governing equations by the time-step size,
146  \f$\Delta t\f$, for scaling or other reasons. Here we illustrate
147  what that means and the complications that follow from it.
148 
149  Starting with a simple implicit ODE and multiplying through by
150  \f$\Delta t\f$, we have
151  \f[
152  \mathcal{F}_n = \Delta t \dot{x}_n - \Delta t \bar{f}(x_n,t_n) = 0
153  \f]
154  For the Backward Euler stepper, we recall from above that
155  \f[
156  \dot{x}_n(x_n) = \frac{x_n - x_{n-1}}{\Delta t}
157  \quad\quad
158  \alpha \equiv \frac{\partial \dot{x}_n(x_n) }{\partial x_n}
159  = \frac{1}{\Delta t}
160  \quad \quad
161  \beta \equiv \frac{\partial x_n}{\partial x_n} = 1
162  \f]
163  and we can find for our simple implicit ODE, \f$\mathcal{F}_n\f$,
164  \f[
165  M = \frac{\partial \mathcal{F}_n}{\partial \dot{x}_n} = \Delta t,
166  \quad \quad
167  J = \frac{\partial \mathcal{F}_n}{\partial x_n}
168  = -\Delta t \frac{\partial \bar{f}_n}{\partial x_n}
169  \f]
170  Thus this iteration matrix, \f$W^\ast\f$, is
171  \f[
172  W^\ast = \alpha \frac{\partial \mathcal{F}_n}{\partial \dot{x}_n}
173  + \beta \frac{\partial \mathcal{F}_n}{\partial x_n}
174  = \frac{1}{\Delta t} \Delta t
175  + (1) \left( - \Delta t \frac{\partial \bar{f}_n}{\partial x_n}
176  \right)
177  \f]
178  or simply
179  \f[
180  W^\ast = 1 - \Delta t \frac{\partial \bar{f}_n}{\partial x_n}
181  \f]
182  Note that \f$W^\ast\f$ is not the same as \f$W\f$ from above
183  (i.e., \f$W = \frac{1}{\Delta t} - \frac{\partial \bar{f}_n}{\partial
184  x_n}\f$). But we should <b>not</b> infer from this is that
185  \f$\alpha = 1\f$ or \f$\beta = -\Delta t\f$, as those definitions
186  are unchanged (i.e., \f$\alpha \equiv \frac{\partial \dot{x}_n(x_n)}
187  {\partial x_n} = \frac{1}{\Delta t}\f$ and \f$\beta \equiv
188  \frac{\partial x_n}{\partial x_n} = 1 \f$). However, the mass
189  matrix, \f$M\f$, the Jacobian, \f$J\f$ and the residual,
190  \f$-\mathcal{F}_n\f$, all need to include \f$\Delta t\f$ in
191  their evaluations (i.e., be included in the ModelEvaluator
192  return values for these terms).
193 
194  <b> Dangers of explicitly including time-derivative definition.</b>
195  If we explicitly include the time-derivative defintion for
196  Backward Euler, we find for our simple implicit ODE,
197  \f[
198  \mathcal{F}_n = \frac{x_n - x_{n-1}}{\Delta t} - \bar{f}(x_n,t_n) = 0
199  \f]
200  that the iteration matrix is
201  \f[
202  W^{\ast\ast} =
203  \alpha \frac{\partial \mathcal{F}_n}{\partial \dot{x}_n}
204  + \beta \frac{\partial \mathcal{F}_n}{\partial x_n}
205  = \frac{1}{\Delta t} (0)
206  + (1) \left(\frac{1}{\Delta t}
207  - \frac{\partial \bar{f}_n}{\partial x_n}
208  \right)
209  \f]
210  or simply
211  \f[
212  W^{\ast\ast} =
213  \frac{1}{\Delta t} - \frac{\partial \bar{f}_n}{\partial x_n}
214  \f]
215  which is the same as \f$W\f$ from above for Backward Euler, but
216  again we should <b>not</b> infer that \f$\alpha = \frac{1}{\Delta
217  t}\f$ or \f$\beta = -1\f$. However the major drawback is the
218  mass matrix, \f$M\f$, the Jacobian, \f$J\f$, and the residual,
219  \f$-\mathcal{F}_n\f$ (i.e., the ModelEvaluator) are explicitly
220  written only for Backward Euler. The application would need
221  to write separate ModelEvaluators for each stepper, thus
222  destroying the ability to re-use the ModelEvaluator with any
223  stepper.
224  *
225  */
226 template<class Scalar>
227 class StepperImplicit : virtual public Tempus::Stepper<Scalar>
228 {
229 public:
230 
231  /// \name Basic implicit stepper methods
232  //@{
233  virtual void setModel(
234  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel);
235 
236  virtual Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > getModel()
237  {
238  Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > model;
239  if (wrapperModel_ != Teuchos::null) model = wrapperModel_->getAppModel();
240  return model;
241  }
242 
243  virtual Teuchos::RCP<const WrapperModelEvaluator<Scalar> >
245 
246  virtual void setDefaultSolver();
247 
248  /// Set solver.
249  virtual void setSolver(
250  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver);
251 
252  virtual Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > getSolver() const
253  { return solver_; }
254 
255  /// Set the initial conditions and make them consistent.
256  virtual void setInitialConditions (
257  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory);
258 
259  /// Return alpha = d(xDot)/dx.
260  virtual Scalar getAlpha(const Scalar dt) const = 0;
261 
262  /// Return beta = d(x)/dx.
263  virtual Scalar getBeta (const Scalar dt) const = 0;
264 
265  /// Solve problem using x in-place. (Needs to be deprecated!)
266  const Thyra::SolveStatus<Scalar> solveImplicitODE(
267  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x);
268 
269  /// Solve implicit ODE, f(x, xDot, t, p) = 0.
270  const Thyra::SolveStatus<Scalar> solveImplicitODE(
271  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x,
272  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & xDot,
273  const Scalar time,
274  const Teuchos::RCP<ImplicitODEParameters<Scalar> > & p );
275 
276  /// Evaluate implicit ODE residual, f(x, xDot, t, p).
277  void evaluateImplicitODE(
278  Teuchos::RCP<Thyra::VectorBase<Scalar> > & f,
279  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x,
280  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & xDot,
281  const Scalar time,
282  const Teuchos::RCP<ImplicitODEParameters<Scalar> > & p );
283 
284  /// Pass initial guess to Newton solver (only relevant for implicit solvers)
285  virtual void setInitialGuess(
286  Teuchos::RCP<const Thyra::VectorBase<Scalar> > initialGuess)
287  {
288  initialGuess_ = initialGuess;
289  this->isInitialized_ = false;
290  }
291 
292  /// Set parameter so that the initial guess is set to zero (=True) or use last timestep (=False).
293  virtual void setZeroInitialGuess(bool zIG) {
294  zeroInitialGuess_ = zIG;
295  this->isInitialized_ = false;
296  }
297 
298  virtual bool getZeroInitialGuess() const { return zeroInitialGuess_; }
299 
300  virtual Scalar getInitTimeStep(
301  const Teuchos::RCP<SolutionHistory<Scalar> >& /* solutionHistory */) const
302  {return Scalar(1.0e+99);}
303  //@}
304 
305  /// \name Overridden from Teuchos::Describable
306  //@{
307  virtual void describe(Teuchos::FancyOStream & out,
308  const Teuchos::EVerbosityLevel verbLevel) const;
309  //@}
310 
311  virtual bool isValidSetup(Teuchos::FancyOStream & out) const;
312 
313 protected:
314 
315  Teuchos::RCP<WrapperModelEvaluator<Scalar> > wrapperModel_;
316  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver_;
317  Teuchos::RCP<const Thyra::VectorBase<Scalar> > initialGuess_;
319 
320  Teuchos::RCP<StepperObserver<Scalar> > stepperObserver_;
321 };
322 
323 } // namespace Tempus
324 #endif // Tempus_StepperImplicit_decl_hpp
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
ImplicitODEParameters(Teuchos::RCP< TimeDerivative< Scalar > > timeDer, Scalar timeStepSize, Scalar alpha, Scalar beta, EVALUATION_TYPE evaluationType=SOLVE_FOR_X, int stageNumber=0)
Constructor.
const Thyra::SolveStatus< Scalar > solveImplicitODE(const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x)
Solve problem using x in-place. (Needs to be deprecated!)
EVALUATION_TYPE
EVALUATION_TYPE indicates the evaluation to apply to the implicit ODE.
Teuchos::RCP< const Thyra::VectorBase< Scalar > > initialGuess_
Teuchos::RCP< WrapperModelEvaluator< Scalar > > wrapperModel_
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
virtual Teuchos::RCP< const WrapperModelEvaluator< Scalar > > getWrapperModel()
virtual Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > getSolver() const
Get solver.
bool isInitialized_
True if stepper&#39;s member data is initialized.
virtual Scalar getBeta(const Scalar dt) const =0
Return beta = d(x)/dx.
Teuchos::RCP< TimeDerivative< Scalar > > timeDer_
Thyra Base interface for time steppers.
void evaluateImplicitODE(Teuchos::RCP< Thyra::VectorBase< Scalar > > &f, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &xDot, const Scalar time, const Teuchos::RCP< ImplicitODEParameters< Scalar > > &p)
Evaluate implicit ODE residual, f(x, xDot, t, p).
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver)
Set solver.
Thyra Base interface for implicit time steppers.
virtual Scalar getInitTimeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &) const
Teuchos::RCP< StepperObserver< Scalar > > stepperObserver_
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
virtual void setZeroInitialGuess(bool zIG)
Set parameter so that the initial guess is set to zero (=True) or use last timestep (=False)...
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getModel()
This interface defines the time derivative connection between an implicit Stepper and WrapperModelEva...
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void setInitialGuess(Teuchos::RCP< const Thyra::VectorBase< Scalar > > initialGuess)
Pass initial guess to Newton solver (only relevant for implicit solvers)
virtual Scalar getAlpha(const Scalar dt) const =0
Return alpha = d(xDot)/dx.
Solve for x and determine xDot from x.
Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver_
virtual bool getZeroInitialGuess() const