implicit_midpoint_rule.h
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 #ifndef OOMPH_IMPLICIT_MIDPOINT_RULE_H
31 #define OOMPH_IMPLICIT_MIDPOINT_RULE_H
32 
33 //oomph-lib headers
34 #include "Vector.h"
35 #include "nodes.h"
36 #include "matrices.h"
37 #include "timesteppers.h"
38 #include "explicit_timesteppers.h"
39 
40 namespace oomph
41 {
42 
43  // Forward decl. so that we can have function of Problem*
44  class Problem;
45 
46 
47  /// Implicit midpoint rule base class for the two implementations.
48  class IMRBase : public TimeStepper
49  {
50  public:
51 
52  /// Constructor with initialisation
53  IMRBase(const bool& adaptive=false) :
54  TimeStepper(2,1) // initialise weights later
55  {
56  Adaptive_Flag = adaptive;
57  Is_steady = false;
58  Type = "Midpoint method";
60 
61  // If adaptive then we are storing predicted values in slot
62  // 4. Otherwise we aren't storing them so leave it as -1.
63  if(adaptive)
64  {
66  }
67 
68 
69  // Storage for weights needs to be 2x(2 + 0/2) (the +2 is extra history
70  // for ebdf3 predictor if adaptive). This means we provide ways to
71  // calculate the zeroth and first derivatives and in calculations we
72  // use 2 + 0/2 time values.
73 
74  // But actually (for some reason...) the amount of data storage
75  // allocated for the timestepper in each node is determined by the
76  // size of weight. So we need to store an extra dummy entry in order
77  // to have storage space for the predicted value at t_{n+1}.
78 
79  // Just leave space for predictor values anyway, it's not expensive.
80  Weight.resize(2, 5, 0.0);
81 
82  // Assume that set_weights() or make_steady() is called before use to
83  // set up the values stored in Weight.
84  }
85 
86  /// Destructor
87  virtual ~IMRBase() {}
88 
89  /// Setup weights for time derivative calculations.
90  virtual void set_weights()=0;
91 
92  /// Number of history values to interpolate over to get the "current"
93  /// value.
94  virtual unsigned nprev_values_for_value_at_evaluation_time() const=0;
95 
96  /// Actual order (accuracy) of the scheme
97  unsigned order() const {return 2;}
98 
99  /// Number of timestep increments that are required by the scheme
100  unsigned ndt() const {return nprev_values();}
101 
102  /// ??ds
103  unsigned nprev_values() const {return 4;}
104 
105  /// \short This function advances the Data's time history so that
106  /// we can move on to the next timestep
107  void shift_time_values(Data* const &data_pt);
108 
109  /// \short This function advances the time history of the positions
110  /// at a node.
111  void shift_time_positions(Node* const &node_pt);
112 
113  /// \short Set the weights for the error computation. This is not used
114  /// by midpoint rule.
116 
117  /// \short Set the weights for the predictor previous timestep. This is not
118  /// used by midpint rule.
120 
121  /// not implemented (??ds TODO)
122  void assign_initial_values_impulsive(Data* const &data_pt)
123  {
124  std::string err = "Not implemented";
125  throw OomphLibError(err, OOMPH_CURRENT_FUNCTION,
126  OOMPH_EXCEPTION_LOCATION);
127  }
129  {
130  std::string err = "Not implemented";
131  throw OomphLibError(err, OOMPH_CURRENT_FUNCTION,
132  OOMPH_EXCEPTION_LOCATION);
133  }
134 
135 
136  void calculate_predicted_positions(Node* const &node_pt)
137  {
138  std::string err = "Not implemented";
139  throw OomphLibError(err, OOMPH_CURRENT_FUNCTION,
140  OOMPH_EXCEPTION_LOCATION);
141  }
142 
143  double temporal_error_in_position(Node* const &node_pt, const unsigned &i)
144  {
145  std::string err = "Not implemented";
146  throw OomphLibError(err, OOMPH_CURRENT_FUNCTION,
147  OOMPH_EXCEPTION_LOCATION);
148  }
149 
150  // Adaptivity
151  void calculate_predicted_values(Data* const &data_pt);
152  double temporal_error_in_value(Data* const &data_pt, const unsigned &i);
153  };
154 
155  /// The "real" implementation of the implicit midpoint rule. Implemented
156  /// by calculation of residuals etc. at half step. This requires
157  /// non-trivial modifications to the element's residual and Jacobian
158  /// calculation functions to interpolate values to the midpoint. As such
159  /// IMRByBDF should be preferred.
160  ///
161  /// However this class must be used when multiple different time steppers
162  /// are being used simultaneously for different parts of the problem.
163 class IMR : public IMRBase
164 {
165 public:
166  /// Common mistakes when using this implementation of midpoint:
167  /// * Didn't include the d_u_evaltime_by_du_np1 term in the Jacobian.
168  /// * Didn't properly interpolate time/values/x/derivatives in
169  /// jacobian/residual (all of these MUST be evaluated at the midpoint).
170 
171 
172  /// Constructor with initialisation
173  IMR(const bool& adaptive=false) : IMRBase(adaptive) {}
174 
175  /// Destructor, predictor_pt handled by base
176  virtual ~IMR() {}
177 
178  /// Setup weights for time derivative calculations.
179  void set_weights()
180  {
181  // Set the weights for zero-th derivative (i.e. the value to use in
182  // newton solver calculations, implicit midpoint method uses the
183  // average of previous and current values).
184  Weight(0, 0) = 0.5;
185  Weight(0, 1) = 0.5;
186 
187  // Set the weights for 1st time derivative
188  double dt=Time_pt->dt(0);
189  Weight(1,0) = 1.0/dt;
190  Weight(1,1) = -1.0/dt;
191  }
192 
193  /// \short Number of history values to interpolate over to get the
194  /// "current" value.
195  unsigned nprev_values_for_value_at_evaluation_time() const {return 2;}
196 
197 private:
198 
199  /// Inaccessible copy constructor.
200  IMR(const IMR &dummy) {}
201 
202  /// Inaccessible assignment operator.
203  void operator=(const IMR &dummy) {}
204 };
205 
206 
207 /// Implementation of implicit midpoint rule by taking half a step of bdf1
208 /// then applying an update to all dofs. This implementation *should* work
209 /// with any existing problem for which the BDF methods work.
210 ///
211 /// The exception is when multiple different time steppers are being used
212 /// simultaneously for different parts of the problem. In this case the
213 /// IMR class should be used.
214 class IMRByBDF : public IMRBase
215 {
216 public:
217  /// Constructor with initialisation
218  IMRByBDF(const bool& adaptive=false) : IMRBase(adaptive)
219  {
220  Update_pinned = true;
221  }
222 
223  /// Destructor
224  virtual ~IMRByBDF() {}
225 
226  /// Setup weights for time derivative calculations.
227  void set_weights()
228  {
229  // Use weights from bdf1
230  double dt=Time_pt->dt(0);
231  Weight(1,0) = 1.0/dt;
232  Weight(1,1) = -1.0/dt;
233  }
234 
235  /// \short Number of history values to interpolate over to get the
236  /// "current" value. Evaluation time is the end of the bdf1 "half-step",
237  /// so only need one value as normal.
238  unsigned nprev_values_for_value_at_evaluation_time() const {return 1;}
239 
240  /// Half the timestep before starting solve
241  void actions_before_timestep(Problem* problem_pt);
242 
243  /// Take problem from t={n+1/2} to t=n+1 by algebraic update and restore
244  /// time step.
245  void actions_after_timestep(Problem* problem_pt);
246 
247  /// Should we update pinned variables after the half-step?
249 
250 private:
251 
252  /// Inaccessible copy constructor.
253  IMRByBDF(const IMRByBDF &dummy) {}
254 
255  /// Inaccessible assignment operator.
256  void operator=(const IMRByBDF &dummy) {}
257 
258 };
259 
260 } // End of oomph namespace
261 
262 #endif
virtual void set_weights()=0
Setup weights for time derivative calculations.
unsigned ndt() const
Number of timestep increments that are required by the scheme.
unsigned order() const
Actual order (accuracy) of the scheme.
void operator=(const IMR &dummy)
Inaccessible assignment operator.
void shift_time_positions(Node *const &node_pt)
This function advances the time history of the positions at a node.
virtual void actions_after_timestep(Problem *problem_pt)
Definition: timesteppers.h:618
Implicit midpoint rule base class for the two implementations.
unsigned nprev_values_for_value_at_evaluation_time() const
Number of history values to interpolate over to get the "current" value. Evaluation time is the end o...
void shift_time_values(Data *const &data_pt)
This function advances the Data's time history so that we can move on to the next timestep...
cstr elem_len * i
Definition: cfortran.h:607
std::string Type
String that indicates the type of the timestepper (e.g. "BDF", "Newmark", etc.)
Definition: timesteppers.h:231
unsigned nprev_values_for_value_at_evaluation_time() const
Number of history values to interpolate over to get the "current" value.
The Problem class.
Definition: problem.h:152
void operator=(const IMRByBDF &dummy)
Inaccessible assignment operator.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
int Predictor_storage_index
The time-index in each Data object where predicted values are stored. -1 if not set.
Definition: timesteppers.h:263
bool Predict_by_explicit_step
Flag: is adaptivity done by taking a separate step using an ExplicitTimeStepper object?
Definition: timesteppers.h:250
virtual unsigned nprev_values_for_value_at_evaluation_time() const =0
bool Is_steady
Bool to indicate if the timestepper is steady, i.e. its time-derivatives evaluate to zero...
Definition: timesteppers.h:241
bool Update_pinned
Should we update pinned variables after the half-step?
void set_error_weights()
Set the weights for the error computation. This is not used by midpoint rule.
DenseMatrix< double > Weight
Storage for the weights associated with the timestepper.
Definition: timesteppers.h:227
IMR(const IMR &dummy)
Inaccessible copy constructor.
void calculate_predicted_values(Data *const &data_pt)
IMR(const bool &adaptive=false)
Constructor with initialisation.
void assign_initial_values_impulsive(Data *const &data_pt)
not implemented (??ds TODO)
virtual ~IMRBase()
Destructor.
double & dt(const unsigned &t=0)
Definition: timesteppers.h:137
virtual void actions_before_timestep(Problem *problem_pt)
Definition: timesteppers.h:614
Time * Time_pt
Pointer to discrete time storage scheme.
Definition: timesteppers.h:224
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
unsigned nprev_values() const
??ds
IMRByBDF(const IMRByBDF &dummy)
Inaccessible copy constructor.
bool Adaptive_Flag
Boolean variable to indicate whether the timestepping scheme can be adaptive.
Definition: timesteppers.h:235
double temporal_error_in_position(Node *const &node_pt, const unsigned &i)
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
double temporal_error_in_value(Data *const &data_pt, const unsigned &i)
IMRBase(const bool &adaptive=false)
Constructor with initialisation.
void assign_initial_positions_impulsive(Node *const &node_pt)
Initialiset the positions for the node corresponding to an impulsive start.
void set_predictor_weights()
Set the weights for the predictor previous timestep. This is not used by midpint rule.
void set_weights()
Setup weights for time derivative calculations.
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
Definition: timesteppers.h:219
virtual ~IMR()
Destructor, predictor_pt handled by base.
IMRByBDF(const bool &adaptive=false)
Constructor with initialisation.
virtual ~IMRByBDF()
Destructor.
void set_weights()
Setup weights for time derivative calculations.
void resize(const unsigned long &n)
Definition: matrices.h:511
void calculate_predicted_positions(Node *const &node_pt)
Do the predictor step for the positions at a node (currently empty — overwrite for a specific scheme...