timesteppers.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 //This header contains classes and function prototypes for the Time,
31 //TimeStepper and derived objects
32 
33 //Include guard to prevent multiple inclusions of the header
34 #ifndef OOMPH_TIME_STEPPERS_HEADER
35 #define OOMPH_TIME_STEPPERS_HEADER
36 
37 // Config header generated by autoconfig
38 #ifdef HAVE_CONFIG_H
39  #include <oomph-lib-config.h>
40 #endif
41 
42 #ifdef OOMPH_HAS_MPI
43 #include "mpi.h"
44 #endif
45 
46 //oomph-lib headers
47 #include "Vector.h"
48 #include "nodes.h"
49 #include "matrices.h"
50 
51 namespace oomph
52 {
53 
54  class Problem;
55  class ExplicitTimeStepper;
56 
57 //====================================================================
58 /// \short Class to keep track of discrete/continous time. It is essential
59 /// to have a single Time object when using multiple time-stepping schemes;
60 /// e.g., in fluid-structure interaction problems, it is common to use
61 /// different schemes for the fluid and solid domains.
62 /// Storage is allocated for the current value
63 /// of the (continuous) time and a limited history of previous timesteps.
64 /// The number of previous timesteps must be equal to the number required
65 /// by the "highest order" scheme.
66 //====================================================================
67 class Time
68 {
69 private:
70 
71  /// Pointer to the value of the continuous time.
73 
74  /// Vector that stores the values of the current and previous timesteps.
76 
77  public:
78 
79  /// \short Constructor: Do not allocate any storage for previous timesteps,
80  /// but set the initial value of the time to zero
81  Time() : Continuous_time(0.0) {}
82 
83  /// \short Constructor: Pass the number of timesteps to be stored
84  /// and set the initial value of time to zero.
85  Time(const unsigned &ndt) : Continuous_time(0.0)
86  {
87  // Allocate memory for the timestep storage and initialise values to one
88  // to avoid division by zero.
89  Dt.resize(ndt,1.0);
90  }
91 
92  /// Broken copy constructor
93  Time(const Time&)
94  {
96  }
97 
98  /// Broken assignment operator
99  void operator=(const Time&)
100  {
102  }
103 
104  /// \short Resize the vector holding the number of previous timesteps
105  /// and initialise the new values to zero.
106  void resize(const unsigned &n_dt) {Dt.resize(n_dt,0.0);}
107 
108  /// \short Set all timesteps to the same value, dt.
109  void initialise_dt(const double& dt_)
110  {
111  unsigned ndt = Dt.size();
112  Dt.assign(ndt, dt_);
113  }
114 
115  /// \short Set the value of the timesteps to be equal to the values passed in
116  /// a vector
117  void initialise_dt(const Vector<double>& dt_)
118  {
119  // Assign the values from the vector dt_, but preserve the size of Dt and
120  // any Dt[i] s.t. i > dt_.size() (which is why we can't just use
121  // assignment operator).
122  unsigned n_dt=dt_.size();
123  for (unsigned i=0;i<n_dt;i++) {Dt[i]=dt_[i];}
124  }
125 
126  /// Destructor: empty
127  ~Time() {}
128 
129  /// Return the current value of the continuous time
130  double& time() {return Continuous_time;}
131 
132  /// Return the number of timesteps stored
133  unsigned ndt() const {return Dt.size();}
134 
135  /// Return the value of the t-th stored timestep (t=0: present; t>0:
136  /// previous).
137  double& dt(const unsigned &t=0) {return Dt[t];}
138 
139  /// Return the value of the t-th stored timestep (t=0: present; t>0:
140  /// previous), const version.
141  double dt(const unsigned &t=0) const {return Dt[t];}
142 
143  /// \short Return the value of the continuous time at the t-th previous
144  /// time level (t=0: current; t>0 previous).
145  double time(const unsigned &t=0) const
146  {
147 #ifdef PARANOID
148  if(t > ndt())
149  {
150  using namespace StringConversion;
151  std::string error_msg = "Timestep " + to_string(t) + " out of range!";
152  throw OomphLibError(error_msg, OOMPH_CURRENT_FUNCTION,
153  OOMPH_EXCEPTION_LOCATION);
154  }
155 #endif
156  //Load the current value of the time
157  double time_local = Continuous_time;
158  //Loop over the t previous timesteps and subtract each dt
159  for (unsigned i=0;i<t;i++) {time_local -= Dt[i];}
160  return time_local;
161  }
162 
163  /// \short Update all stored values of dt by shifting each value along
164  /// the array. This function must be called before starting to solve at a
165  /// new time level.
166  void shift_dt()
167  {
168  unsigned n_dt=Dt.size();
169  //Return straight away if there are no stored timesteps
170  if(n_dt == 0) {return;}
171  //Start from the end of the array and shift every entry back by one
172  for (unsigned i=(n_dt-1);i>0;i--) {Dt[i]=Dt[i-1];}
173  }
174 
175 };
176 
177 
178 
179 /////////////////////////////////////////////////////////////////////////
180 /////////////////////////////////////////////////////////////////////////
181 /////////////////////////////////////////////////////////////////////////
182 
183 
184 
185 //====================================================================
186 /// \short Base class for time-stepping schemes.
187 /// Timestepper provides an approximation of the temporal derivatives of
188 /// Data such that the i-th derivative of the j-th value in Data is
189 /// represented as
190 /// \code
191 /// unsigned n_value=data_pt->nvalue();
192 /// Vector<double> time_derivative(n_value);
193 /// for (unsigned j=0;j<n_value;j++)
194 /// {
195 /// time_derivative[j]=0.0;
196 /// for (unsigned t=0;t<ntstorage();t++)
197 /// {
198 /// time_derivative[j] += data_pt->value(t,j)*weight(i,t);
199 /// }
200 /// }
201 /// \endcode
202 /// where the time index \c t is such that
203 /// - \c t \c = \c 0 refers to the current value of the Data
204 /// - \c t \c > \c 0 refers to the `history' values, i.e. the doubles that
205 /// are stored in Data to represent the value's time derivatives. For BDF
206 /// schemes these doubles are the values at previous times;
207 /// for other timestepping schemes they can represent quantities
208 /// such as previous first and second derivatives, etc.
209 ///
210 /// TimeSteppers can evaluate all derivatives up to their \c order().
211 ///
212 /// The first \c nprev_values() `history values' represent the
213 /// values at the previous timesteps. For BDF schemes,
214 /// \c nprev_values() \c = \c ntstorage()-1 , i.e. all `history values'
215 /// represent previous values. For \c Newmark<NSTEPS>, only the first
216 /// NSTEPS `history values' represent previous values (NSTEPS=1
217 /// gives the normal Newmark scheme).
218 //====================================================================
220 {
221  protected:
222 
223  /// Pointer to discrete time storage scheme
225 
226  /// Storage for the weights associated with the timestepper
228 
229  /// \short String that indicates the type of the timestepper
230  ///(e.g. "BDF", "Newmark", etc.)
232 
233  /// \short Boolean variable to indicate whether the timestepping scheme can be
234  /// adaptive
236 
237  /// \short Bool to indicate if the timestepper is steady, i.e. its
238  /// time-derivatives evaluate to zero. This status may be achieved
239  /// temporarily by calling make_steady(). It can be reset to the
240  /// appropriate default by the function undo_make_steady().
241  bool Is_steady;
242 
243  /// \short Boolean to indicate if the timestepper will output warnings when
244  /// setting possibly an incorrect number of initial data values from function
245  /// pointers
247 
248  /// \short Flag: is adaptivity done by taking a separate step using an
249  /// ExplicitTimeStepper object?
251 
252  /// Pointer to explicit time stepper to use as predictor if
253  /// Predict_by_explicit_step is set.
254  /// ??ds merge the two? predict by explicit if pointer is set?
256 
257  /// Store the time that the predicted values currently stored are at, to
258  /// compare for paranoid checks.
259  double Predicted_time;
260 
261  /// \short The time-index in each Data object where predicted values are
262  /// stored. -1 if not set.
264 
265 public:
266 
267  /// \short Constructor. Pass the amount of storage required by
268  /// timestepper (present value + history values) and the
269  /// order of highest time-derivative.
270  TimeStepper(const unsigned &tstorage, const unsigned &max_deriv)
271  : Time_pt(0),
272  Adaptive_Flag(false),
273  Is_steady(false),
274  Shut_up_in_assign_initial_data_values(false),
275  Predict_by_explicit_step(false)
276  {
277  //Resize Weights matrix and initialise each weight to zero
278  Weight.resize(max_deriv+1,tstorage,0.0);
279 
280  // Set the weight for zero-th derivative, which is always 1.0
281  Weight(0,0)=1.0;
282 
283  // Set predictor storage index to negative value so that we can catch
284  // cases where it has not been set to a correct value by the inheriting
285  // constructor.
286  Predictor_storage_index = -1;
287 
288  Explicit_predictor_pt = 0;
289  }
290 
291  /// Broken empty constructor
293  {
294  throw OomphLibError("Don't call default constructor for TimeStepper!",
295  OOMPH_CURRENT_FUNCTION,
296  OOMPH_EXCEPTION_LOCATION);
297  }
298 
299  /// Broken copy constructor
301  {
302  BrokenCopy::broken_copy("TimeStepper");
303  }
304 
305  /// Broken assignment operator
306  void operator=(const TimeStepper&)
307  {
308  BrokenCopy::broken_assign("TimeStepper");
309  }
310 
311  /// virtual destructor
312  virtual ~TimeStepper();
313 
314  /// Highest order derivative that the scheme can compute
315  unsigned highest_derivative() const
316  {return Weight.nrow()-1;}
317 
318  /// Actual order (accuracy) of the scheme
319  virtual unsigned order() const {return 0;}
320 
321  /// Return current value of continous time
322  // (can't have a paranoid test for null pointers because this could be
323  // used as a set function)
324  double& time(){return Time_pt->time();}
325 
326  /// Return current value of continous time.
327  double time() const
328  {
329 #ifdef PARANOID
330  if(Time_pt == 0)
331  {
332  std::string error_msg = "Time pointer is null!";
333  throw OomphLibError(error_msg, OOMPH_CURRENT_FUNCTION,
334  OOMPH_EXCEPTION_LOCATION);
335  }
336 #endif
337  return Time_pt->time();
338  }
339 
340  /// Number of timestep increments that are required by the scheme
341  virtual unsigned ndt() const=0;
342 
343  /// \short Number of previous values needed to calculate the value at the
344  /// current time. i.e. how many previous values must we loop over to
345  /// calculate the values at the evaluation time. For most methods this is
346  /// 1, i.e. just use the value at t_{n+1}. See midpoint method for a
347  /// counter-example.
348  virtual unsigned nprev_values_for_value_at_evaluation_time() const {return 1;}
349 
350  /// Number of previous values available: 0 for static, 1 for BDF<1>,...
351  virtual unsigned nprev_values() const=0;
352 
353  /// \short Function to set the weights for present timestep (don't
354  /// need to pass present timestep or previous timesteps as they
355  /// are available via Time_pt)
356  virtual void set_weights()=0;
357 
358  /// \short Function to make the time stepper temporarily steady. This
359  /// is trivially achieved by setting all the weights to zero
360  void make_steady()
361  {
362  // Zero the matrix
363  Weight.initialise(0);
364 
365  // Weight of current step in calculation of current step is always 1 in
366  // steady state. All other entries left at zero.
367  Weight(0, 0) = 1.0;
368 
369  // Update flag
370  Is_steady=true;
371  }
372 
373  /// \short Flag to indicate if a timestepper has been made steady (possibly
374  /// temporarily to switch off time-dependence)
375  bool is_steady() const
376  {
377  return Is_steady;
378  }
379 
380  /// \short Flag: is adaptivity done by taking a separate step using an
381  /// ExplicitTimeStepper object?
383  {
384  return Predict_by_explicit_step;
385  }
386 
387  /// Get the pointer to the explicit timestepper to use as a predictor in
388  /// adaptivity if Predict_by_explicit_step is set.
389  ExplicitTimeStepper* explicit_predictor_pt() {return Explicit_predictor_pt;}
390 
391  /// Set the pointer to the explicit timestepper to use as a predictor in
392  /// adaptivity if Predict_by_explicit_step is set.
394  {
395  Explicit_predictor_pt = _pred_pt;
396  }
397 
398  /// Set the time that the current predictions apply for, only needed for
399  /// paranoid checks when doing Predict_by_explicit_step.
400  void update_predicted_time(const double& new_time)
401  {
402  Predicted_time = new_time;
403  }
404 
405  /// Check that the predicted values are the ones we want.
407  {
408 #ifdef PARANOID
409  if(std::abs(time_pt()->time() - Predicted_time) > 1e-15)
410  {
411  throw OomphLibError("Predicted values are not from the correct time step",
412  OOMPH_EXCEPTION_LOCATION,
413  OOMPH_CURRENT_FUNCTION);
414  }
415 #endif
416  }
417 
418  /// \short Return the time-index in each Data where predicted values are
419  /// stored if the timestepper is adaptive.
420  unsigned predictor_storage_index() const
421  {
422  // Error if time stepper is non-adaptive (because then the index doesn't
423  // exist so using it would give a potentially difficult to find
424  // segault).
425 #ifdef PARANOID
426  if(Predictor_storage_index > 0)
427  {
428  return unsigned(Predictor_storage_index);
429  }
430  else
431  {
432  std::string err = "Predictor storage index is negative, this probably";
433  err += " means it hasn't been set for this timestepper.";
434  throw OomphLibError(err, OOMPH_EXCEPTION_LOCATION,
435  OOMPH_CURRENT_FUNCTION);
436  }
437 #else
438  return unsigned(Predictor_storage_index);
439 #endif
440  }
441 
442  /// \short Enable the output of warnings due to possible fct pointer vector
443  /// size mismatch in assign_initial_data_values (Default)
445  {Shut_up_in_assign_initial_data_values=false;}
446 
447  /// \short Disable the output of warnings due to possible fct pointer vector
448  /// size mismatch in assign_initial_data_values
450  {Shut_up_in_assign_initial_data_values=true;}
451 
452  /// \short Get a (const) pointer to the weights.
453  const DenseMatrix<double>* weights_pt() const {return &Weight;}
454 
455  /// \short Reset the is_steady status of a specific TimeStepper to its
456  /// default and re-assign the weights.
457  virtual void undo_make_steady()
458  {
459  Is_steady=false;
460  set_weights();
461  }
462 
463  /// \short Return string that indicates the type of the timestepper
464  /// (e.g. "BDF", "Newmark", etc.)
465  std::string type() const {return Type;}
466 
467  //??ds I think that the Data and Node cases below couldp robably be
468  // handled with a template argument. However they can't be handled by
469  // normal polymorphism because data.value is different to node.value and
470  // value is not a virtual function.
471 
472  /// \short Evaluate i-th derivative of all values in Data and return in
473  /// Vector deriv[].
474  void time_derivative(const unsigned &i,
475  Data* const &data_pt, Vector<double>& deriv)
476  {
477  // Number of values stored in the Data object
478  unsigned nvalue=data_pt->nvalue();
479  deriv.assign(nvalue, 0.0);
480 
481  // Loop over all values
482  for(unsigned j=0;j<nvalue;j++)
483  {
484  deriv[j]=time_derivative(i, data_pt, j);
485  }
486  }
487 
488  /// \short Evaluate i-th derivative of j-th value in Data.
489  double time_derivative(const unsigned &i, Data* const &data_pt,
490  const unsigned& j)
491  {
492  double deriv=0.0;
493  unsigned n_tstorage = ntstorage();
494  // Loop over all history data and add the appropriate contribution
495  // to the derivative
496  for(unsigned t=0;t<n_tstorage;t++)
497  {
498  deriv+=Weight(i,t)*data_pt->value(t,j);
499  }
500  return deriv;
501  }
502 
503  /// \short Evaluate i-th derivative of all values in Node and return in
504  /// Vector deriv[] (this can't be simply combined with time_derivative(..,
505  /// Data, ...) because of differences with haning nodes).
506  void time_derivative(const unsigned &i,
507  Node* const &node_pt, Vector<double>& deriv)
508  {
509  // Number of values stored in the Data object
510  unsigned nvalue = node_pt->nvalue();
511  deriv.assign(nvalue, 0.0);
512 
513  // Loop over all values
514  for(unsigned j=0;j<nvalue;j++)
515  {
516  deriv[j]=time_derivative(i, node_pt, j);
517  }
518  }
519 
520  /// \short Evaluate i-th derivative of j-th value in Node. Note the use of
521  /// the node's value() function so that hanging nodes are taken into
522  /// account (this is why the functions for Data and Node cannot be
523  /// combined through simple polymorphism: value is not virtual).
524  double time_derivative(const unsigned &i, Node* const &node_pt,
525  const unsigned& j)
526  {
527  double deriv=0.0;
528  unsigned n_tstorage = ntstorage();
529  // Loop over all history data and add the appropriate contribution
530  // to the derivative
531  for(unsigned t=0;t<n_tstorage;t++)
532  {
533  deriv+=weight(i,t)*node_pt->value(t,j);
534  }
535  return deriv;
536  }
537 
538 
539  ///Access function for the pointer to time (const version)
540  Time* const &time_pt() const {
541 #ifdef PARANOID
542  if(Time_pt == 0)
543  {
544  std::string error_msg("Time_pt is null, probably because it is a steady time stepper.");
545  throw OomphLibError(error_msg, OOMPH_CURRENT_FUNCTION,
546  OOMPH_EXCEPTION_LOCATION);
547  }
548 #endif
549  return Time_pt;
550  }
551 
552  /// Access function for the pointer to time (can't have a paranoid test
553  /// for null pointers because this is used as a set function).
554  Time*& time_pt() {return Time_pt;}
555 
556  /// Access function for j-th weight for the i-th derivative
557  virtual double weight(const unsigned &i, const unsigned &j) const
558  {return Weight(i,j);}
559 
560  /// \short Return the number of doubles required to represent history
561  /// (one for steady)
562  unsigned ntstorage() const
563  {return (Weight.ncol());}
564 
565  /// \short Initialise the time-history for the Data values
566  /// corresponding to an impulsive start.
567  virtual void assign_initial_values_impulsive(Data* const &data_pt)=0;
568 
569  /// \short Initialiset the positions for the node corresponding to
570  /// an impulsive start
571  virtual void assign_initial_positions_impulsive(Node* const &node_pt)=0;
572 
573  /// \short This function advances the Data's time history so that
574  /// we can move on to the next timestep
575  virtual void shift_time_values(Data* const &data_pt)=0;
576 
577  ///\short This function advances the time history of the positions
578  ///at a node. The default should be OK, but would need to be overloaded
579  virtual void shift_time_positions(Node* const &node_pt)=0;
580 
581  /// Function to indicate whether the scheme is adaptive (false by default)
582  bool adaptive_flag() const {return Adaptive_Flag;}
583 
584  /// \short Set the weights for the predictor
585  /// previous timestep (currently empty -- overwrite for specific scheme)
586  virtual void set_predictor_weights() {}
587 
588  /// \short Do the predictor step for data stored in a Data object
589  /// (currently empty -- overwrite for specific scheme)
590  virtual void calculate_predicted_values(Data* const &data_pt) {}
591 
592  ///\short Do the predictor step for the positions at a node
593  /// (currently empty --- overwrite for a specific scheme)
594  virtual void calculate_predicted_positions(Node* const &node_pt) {}
595 
596  /// \short Set the weights for the error computation,
597  /// (currently empty -- overwrite for specific scheme)
598  virtual void set_error_weights() {}
599 
600  /// Compute the error in the position i at a node
601  /// zero here -- overwrite for specific scheme.
602  virtual double temporal_error_in_position(Node* const &node_pt,
603  const unsigned &i)
604  {return 0.0;}
605 
606  /// Compute the error in the value i in a Data structure
607  /// zero here -- overwrite for specific scheme.
608  virtual double temporal_error_in_value(Data* const &data_pt,
609  const unsigned &i)
610  {return 0.0;}
611 
612  /// Interface for any actions that need to be performed before a time
613  /// step.
614  virtual void actions_before_timestep(Problem* problem_pt) {}
615 
616  /// Interface for any actions that need to be performed after a time
617  /// step.
618  virtual void actions_after_timestep(Problem* problem_pt) {}
619 };
620 
621 
622 /////////////////////////////////////////////////////////////////////////
623 /////////////////////////////////////////////////////////////////////////
624 /////////////////////////////////////////////////////////////////////////
625 
626 
627 
628 //====================================================================
629 /// Faux time-stepper for steady problems. Allows storage
630 /// for NSTEPS previous values.
631 //====================================================================
632 template<unsigned NSTEPS>
633 class Steady : virtual public TimeStepper
634 {
635 
636 public:
637 
638  /// \short Constructor: Creates storage for NSTEPS previous timesteps
639  /// and can evaluate up to 2nd derivatives (though it doesn't
640  /// actually do anything -- all time-derivatives
641  /// evaluate to zero)
642  Steady() : TimeStepper(NSTEPS+1,2)
643  {
644  Type="Steady";
645  Time_pt=&Dummy_time;
646 
647  //Overwrite default assignment in base constructor -- this TimeStepper
648  //actually is steady all the time.
649  Is_steady=true;
650  }
651 
652 
653  /// Broken copy constructor
654  Steady(const Steady&)
655  {
656  BrokenCopy::broken_copy("Steady");
657  }
658 
659  /// Broken assignment operator
660  void operator=(const Steady&)
661  {
662  BrokenCopy::broken_assign("Steady");
663  }
664 
665  /// \short Return the actual order of the scheme. Returning zero here --
666  /// doesn't make much sense, though
667  unsigned order() const {return 0;}
668 
669  /// \short Initialise the time-history for the Data values,
670  /// corresponding to an impulsive start.
671  void assign_initial_values_impulsive(Data* const &data_pt)
672  {
673  //Find number of values stored
674  unsigned n_value = data_pt->nvalue();
675  //Loop over values
676  for(unsigned j=0;j<n_value;j++)
677  {
678  //Set previous values to the initial value, if not a copy
679  if(data_pt->is_a_copy(j) == false)
680  {
681  for(unsigned t=1;t<=NSTEPS;t++)
682  {
683  data_pt->set_value(t,j,data_pt->value(j));
684  }
685  }
686  }
687  }
688 
689  /// \short Initialise the time-history for the nodal positions
690  /// corresponding to an impulsive start.
692  {
693  //Find the number of coordinates
694  unsigned n_dim = node_pt->ndim();
695  //Find the number of positoin types
696  unsigned n_position_type = node_pt->nposition_type();
697 
698  //Loop over values
699  for(unsigned i=0;i<n_dim;i++)
700  {
701  //Set previous values to the initial value, if not a copy
702  if(node_pt->position_is_a_copy(i) == false)
703  {
704  for(unsigned k=0;k<n_position_type;k++)
705  {
706  for(unsigned t=1;t<=NSTEPS;t++)
707  {
708  node_pt->x_gen(t,k,i) = node_pt->x_gen(k,i);
709  }
710  }
711  }
712  }
713  }
714 
715 
716  /// \short Typedef for function that returns the (scalar) initial
717  /// value at a given value of the continuous time t.
718  typedef double (*InitialConditionFctPt)(const double& t);
719 
720  /// \short Initialise the time-history for the Data values,
721  /// corresponding to given time history, specified by
722  /// Vector of function pointers.
723  void assign_initial_data_values(Data* const &data_pt,
725  initial_value_fct)
726  {
727  // The time history stores the previous function values
728  unsigned n_time_value = ntstorage();
729 
730  //Find number of values stored
731  unsigned n_value = data_pt->nvalue();
732 
733  //Loop over current and stored timesteps
734  for(unsigned t=0;t<n_time_value;t++)
735  {
736  // Get corresponding continous time
737  double time_local=Time_pt->time(t);
738 
739  //Loop over values
740  for(unsigned j=0;j<n_value;j++)
741  {
742  data_pt->set_value(t,j,initial_value_fct[j](time_local));
743  }
744  }
745  }
746 
747  /// \short This function updates the Data's time history so that
748  /// we can advance to the next timestep. As for BDF schemes,
749  /// we simply push the values backwards...
750  void shift_time_values(Data* const &data_pt)
751  {
752  //Find number of values stored
753  unsigned n_value = data_pt->nvalue();
754 
755  //Loop over the values
756  for(unsigned j=0;j<n_value;j++)
757  {
758  //Set previous values to the previous value, if not a copy
759  if(data_pt->is_a_copy(j) == false)
760  {
761  //Loop over times, in reverse order
762  for(unsigned t=NSTEPS;t>0;t--)
763  {
764  data_pt->set_value(t,j,data_pt->value(t-1,j));
765  }
766  }
767  }
768  }
769 
770  ///\short This function advances the time history of the positions
771  ///at a node.
772  void shift_time_positions(Node* const &node_pt)
773  {
774  //Find the number of coordinates
775  unsigned n_dim = node_pt->ndim();
776  //Find the number of position types
777  unsigned n_position_type = node_pt->nposition_type();
778 
779  //Loop over the positions
780  for(unsigned i=0;i<n_dim;i++)
781  {
782  //If the position is not a copy
783  if(node_pt->position_is_a_copy(i) == false)
784  {
785  for(unsigned k=0;k<n_position_type;k++)
786  {
787  //Loop over stored times, and set values to previous values
788  for(unsigned t=NSTEPS;t>0;t--)
789  {
790  node_pt->x_gen(t,k,i) = node_pt->x_gen(t-1,k,i);
791  }
792  }
793  }
794  }
795  }
796 
797  ///Set weights
798  void set_weights()
799  {
800  // Loop over higher derivatives
801  unsigned max_deriv=highest_derivative();
802  for (unsigned i=0;i<max_deriv;i++)
803  {
804  for (unsigned j=0;j<NSTEPS;j++)
805  {
806  Weight(i,j) = 0.0;
807  }
808  }
809 
810  // Zeroth derivative must return the value itself:
811  Weight(0,0)=1.0;
812  }
813 
814  /// Number of previous values available.
815  unsigned nprev_values() const {return NSTEPS;}
816 
817  /// Number of timestep increments that need to be stored by the scheme
818  unsigned ndt() const {return NSTEPS;}
819 
820  /// Dummy: Access function for j-th weight for the i-th derivative
821  double weight(const unsigned &i, const unsigned &j) const
822  {
823  if ((i==0)&&(j==0))
824  {
825  return One;
826  }
827  else
828  {
829  return Zero;
830  }
831  }
832 
833 private:
834 
835  /// Static variable to hold the value 1.0
836  static double One;
837 
838  /// Static variable to hold the value 0.0
839  static double Zero;
840 
841  // Default Time object
842  static Time Dummy_time;
843 };
844 
845 
846 
847 
848 /////////////////////////////////////////////////////////////////////////
849 /////////////////////////////////////////////////////////////////////////
850 /////////////////////////////////////////////////////////////////////////
851 
852 
853 
854 //====================================================================
855 /// \short Newmark scheme for second time deriv. Stored data represents
856 /// - t=0: value at at present time, Time_pt->time()
857 /// - t=1: value at previous time, Time_pt->time()-dt
858 /// - ...
859 /// - t=NSTEPS: value at previous time, Time_pt->time()-NSTEPS*dt
860 /// - t=NSTEPS+1: 1st time deriv (= "velocity") at previous time,
861 /// Time_pt->time()-dt
862 /// - t=NSTEPS+2: 2nd time deriv (= "acceleration") at previous time,
863 /// Time_pt->time()-dt
864 ///
865 /// NSTEPS=1 gives normal Newmark.
866 //====================================================================
867 template<unsigned NSTEPS>
868 class Newmark : public TimeStepper
869 {
870 
871  public:
872 
873  /// \short Constructor: Pass pointer to global time. We set up a
874  /// timestepping scheme with NSTEPS+2 doubles to represent the history and
875  /// the highest deriv is 2.
876  Newmark() : TimeStepper(NSTEPS+3,2)
877  {
878  Type="Newmark";
879 
880  // Standard Newmark parameters
881  Beta1=0.5;
882  Beta2=0.5;
883  }
884 
885  /// Broken copy constructor
886  Newmark(const Newmark&)
887  {
888  BrokenCopy::broken_copy("Newmark");
889  }
890 
891  /// Broken assignment operator
892  void operator=(const Newmark&)
893  {
894  BrokenCopy::broken_assign("Newmark");
895  }
896 
897 
898  ///The actual order (accuracy of the scheme)
899  unsigned order() const
900  {
901  std::string error_message =
902  "Can't remember the order of the Newmark scheme";
903  error_message += " -- I think it's 2nd order...\n";
904 
905  OomphLibWarning(error_message,"Newmark::order()",
906  OOMPH_EXCEPTION_LOCATION);
907  return 2;
908  }
909 
910  /// \short Initialise the time-history for the values,
911  /// corresponding to an impulsive start.
912  void assign_initial_values_impulsive(Data* const &data_pt);
913 
914  /// \short Initialise the time-history for the values,
915  /// corresponding to an impulsive start.
916  void assign_initial_positions_impulsive(Node* const &node_pt);
917 
918  /// \short Typedef for function that returns the (scalar) initial
919  /// value at a given value of the continuous time t.
920  typedef double (*InitialConditionFctPt)(const double& t);
921 
922  /// \short Initialise the time-history for the Data values,
923  /// so that the Newmark representations for current veloc and
924  /// acceleration are exact.
925  void assign_initial_data_values(Data* const & data_pt,
927  initial_value_fct,
929  initial_veloc_fct,
931  initial_accel_fct);
932 
933 
934  /// \short Typedef for function that returns the (scalar) initial
935  /// value at a given value of the continuous time t and the spatial
936  /// coordinate -- appropriate for assignement of initial conditions for
937  /// nodes
938  typedef double (*NodeInitialConditionFctPt)(const double& t,
939  const Vector<double>& x);
940 
941  /// \short Initialise the time-history for the nodal values,
942  /// so that the Newmark representations for current veloc and
943  /// acceleration are exact.
944  void assign_initial_data_values(Node* const & node_pt,
946  initial_value_fct,
948  initial_veloc_fct,
950  initial_accel_fct);
951 
952  /// \short First step in a two-stage procedure to assign
953  /// the history values for the Newmark scheme so
954  /// that the veloc and accel that are computed by the scheme
955  /// are correct at the current time.
956  ///
957  /// Call this function for t_deriv=0,1,2,3.
958  /// When calling with
959  /// - t_deriv=0 : data_pt(0,*) should contain the values at the
960  /// previous timestep
961  /// - t_deriv=1 : data_pt(0,*) should contain the current values;
962  /// they get stored (temporarily) in data_pt(1,*).
963  /// - t_deriv=2 : data_pt(0,*) should contain the current velocities
964  /// (first time derivs); they get stored (temporarily)
965  /// in data_pt(NSTEPS+1,*).
966  /// - t_deriv=3 : data_pt(0,*) should contain the current accelerations
967  /// (second time derivs); they get stored (temporarily)
968  /// in data_pt(NSTEPS+2,*).
969  /// .
970  /// Follow this by calls to
971  /// \code
972  /// assign_initial_data_values_stage2(...)
973  /// \endcode
974  void assign_initial_data_values_stage1(const unsigned t_deriv,
975  Data* const &data_pt);
976 
977  /// \short Second step in a two-stage procedure to assign
978  /// the history values for the Newmark scheme so
979  /// that the veloc and accel that are computed by the scheme
980  /// are correct at the current time.
981  ///
982  /// This assigns appropriate values for the "previous
983  /// velocities and accelerations" so that their current
984  /// values, which were defined in assign_initial_data_values_stage1(...),
985  /// are represented exactly by the Newmark scheme.
986  void assign_initial_data_values_stage2(Data* const &data_pt);
987 
988 
989  /// \short This function updates the Data's time history so that
990  /// we can advance to the next timestep.
991  void shift_time_values(Data* const &data_pt);
992 
993  /// \short This function updates a nodal time history so that
994  /// we can advance to the next timestep.
995  void shift_time_positions(Node* const &node_pt);
996 
997  ///Set weights
998  void set_weights();
999 
1000  /// Number of previous values available.
1001  unsigned nprev_values() const {return NSTEPS;}
1002 
1003  /// Number of timestep increments that need to be stored by the scheme
1004  unsigned ndt() const {return NSTEPS;}
1005 
1006 
1007  protected:
1008 
1009  /// First Newmark parameter (usually 0.5)
1010  double Beta1;
1011 
1012  /// Second Newmark parameter (usually 0.5)
1013  double Beta2;
1014 
1015 };
1016 
1017 
1018 /////////////////////////////////////////////////////////////////////////
1019 /////////////////////////////////////////////////////////////////////////
1020 /////////////////////////////////////////////////////////////////////////
1021 
1022 
1023 
1024 //====================================================================
1025 /// \short Newmark scheme for second time deriv with first derivatives
1026 /// calculated using BDF. . Stored data represents
1027 /// - t=0: value at at present time, Time_pt->time()
1028 /// - t=1: value at previous time, Time_pt->time()-dt
1029 /// - ...
1030 /// - t=NSTEPS: value at previous time, Time_pt->time()-NSTEPS*dt
1031 /// - t=NSTEPS+1: 1st time deriv (= "velocity") at previous time,
1032 /// Time_pt->time()-dt
1033 /// - t=NSTEPS+2: 2nd time deriv (= "acceleration") at previous time,
1034 /// Time_pt->time()-dt
1035 ///
1036 /// NSTEPS=1 gives normal Newmark.
1037 //====================================================================
1038 template<unsigned NSTEPS>
1039 class NewmarkBDF : public Newmark<NSTEPS>
1040 {
1041  public:
1042 
1043  /// \short Constructor: Pass pointer to global time. We set up a
1044  /// timestepping scheme with NSTEPS+2 doubles to represent the history and
1045  /// the highest deriv is 2.
1047  {
1048  this->Type="NewmarkBDF";
1049  Degrade_to_bdf1_for_first_derivs=false;
1050  Newmark_veloc_weight.resize(NSTEPS+3);
1051  }
1052 
1053  /// Broken copy constructor
1055  {
1056  BrokenCopy::broken_copy("NewmarkBDF");
1057  }
1058 
1059  /// Broken assignment operator
1060  void operator=(const NewmarkBDF&)
1061  {
1062  BrokenCopy::broken_assign("NewmarkBDF");
1063  }
1064 
1065  ///Set weights
1066  void set_weights();
1067 
1068  /// \short This function updates the Data's time history so that
1069  /// we can advance to the next timestep.
1070  void shift_time_values(Data* const &data_pt);
1071 
1072  /// \short This function updates a nodal time history so that
1073  /// we can advance to the next timestep.
1074  void shift_time_positions(Node* const &node_pt);
1075 
1076  /// \short Degrade scheme to first order BDF (for first derivs/veloc); usually
1077  /// for start-up.
1079  {
1080  Degrade_to_bdf1_for_first_derivs=true;
1081  }
1082 
1083 
1084  /// \short Disable degradation to first order BDF.
1086  {
1087  Degrade_to_bdf1_for_first_derivs=false;
1088  }
1089 
1090  private:
1091 
1092 
1093  /// \short Set original Newmark weights for velocities (needed when
1094  /// shifting history values -- they're used when updating the
1095  /// previous accelerations and doing this with bdf can make the
1096  /// scheme unstable...
1097  void set_newmark_veloc_weights(const double& dt)
1098  {
1099  Newmark_veloc_weight[0]=this->Beta1*dt*this->Weight(2,0);
1100  Newmark_veloc_weight[1]=this->Beta1*dt*this->Weight(2,1);
1101  for (unsigned t=2;t<=NSTEPS;t++)
1102  {
1103  Newmark_veloc_weight[t]=0.0;
1104  }
1105  Newmark_veloc_weight[NSTEPS+1]=
1106  1.0+this->Beta1*dt*this->Weight(2,NSTEPS+1);
1107  Newmark_veloc_weight[NSTEPS+2]=
1108  dt*(1.0-this->Beta1)+this->Beta1*dt*this->Weight(2,NSTEPS+2);
1109  }
1110 
1111  /// \short Boolean flag to indicate degradation of scheme to first
1112  /// order BDF (for first derivs/veloc); usually for start-up.
1114 
1115  /// \short Original Newmark weights for velocities (needed when
1116  /// shifting history values -- they're used when updating the
1117  /// previous accelerations and doing this with bdf can make the
1118  /// scheme unstable...
1120 
1121 };
1122 
1123 
1124 
1125 /////////////////////////////////////////////////////////////////////////
1126 /////////////////////////////////////////////////////////////////////////
1127 /////////////////////////////////////////////////////////////////////////
1128 
1129 
1130 
1131 //====================================================================
1132 /// \short Templated class for BDF-type time-steppers with fixed or
1133 /// variable timestep.
1134 /// 1st time derivative recovered directly from the previous function
1135 /// values. Template parameter represents the number of previous timesteps
1136 /// stored, so that BDF<1> is the classical first order
1137 /// backward Euler scheme.
1138 /// Need to reset weights after every change in timestep.
1139 //====================================================================
1140 template<unsigned NSTEPS>
1141 class BDF : public TimeStepper
1142 {
1143  // A BDF<1> time data set consists of:
1144  // [y_np1, y_n, dy_n, y^P_np1]
1145  // Or in english:
1146  // * y-value at time being/just been solved for
1147  // * y-value at previous time
1148  // * approximation to y derivative at previous time (also refered to as
1149  // velocity in some places, presumably it corresponds to velocity in
1150  // solid mechanics).
1151  // * predicted y-value at time n+1
1152 
1153  // A BDF<2> time data set consists of:
1154  // [y_np1, y_n, y_nm1, dy_n, y^P_np1]
1155  // i.e. the same thing but with one more previous time value. Also the
1156  // derivative approximation will be more accurate.
1157 
1158  // If the adaptive flag is set to false then the final two pieces of data
1159  // in each are not stored (derivative and predictor value).
1160 
1161  private:
1162 
1163  ///Private data for the predictor weights
1165 
1166  /// Private data for the error weight
1168 
1169  public:
1170 
1171  ///Constructor for the case when we allow adaptive timestepping
1172  BDF(const bool& adaptive=false) : TimeStepper(NSTEPS+1,1)
1173  {
1174  Type="BDF";
1175 
1176  //If it's adaptive, we need to allocate additional space to
1177  //carry along a prediction and an acceleration
1178  if(adaptive)
1179  {
1180  //Set the adaptive flag to be true
1181  Adaptive_Flag = true;
1182 
1183  //Set the size of the Predictor_Weights Vector N.B. The size is
1184  //correct for BDF1 and 2, but may be wrong for others.
1185  Predictor_weight.resize(NSTEPS+2);
1186 
1187  //Resize the weights to the appropriate size
1188  Weight.resize(2, NSTEPS+3, 0.0);
1189 
1190  // Storing predicted values in slot after other information
1191  Predictor_storage_index = NSTEPS + 2;
1192  }
1193 
1194  //Set the weight for the zero-th derivative
1195  Weight(0,0) = 1.0;
1196  }
1197 
1198 
1199  /// Broken copy constructor
1200  BDF(const BDF&)
1201  {
1202  BrokenCopy::broken_copy("BDF");
1203  }
1204 
1205  /// Broken assignment operator
1206  void operator=(const BDF&)
1207  {
1209  }
1210 
1211  ///Return the actual order of the scheme
1212  unsigned order() const {return NSTEPS;}
1213 
1214  /// \short Initialise the time-history for the Data values,
1215  /// corresponding to an impulsive start.
1217  {
1218  //Find number of values stored
1219  unsigned n_value = data_pt->nvalue();
1220  //Loop over values
1221  for(unsigned j=0;j<n_value;j++)
1222  {
1223  //Set previous values to the initial value, if not a copy
1224  if(data_pt->is_a_copy(j) == false)
1225  {
1226  for(unsigned t=1;t<=NSTEPS;t++)
1227  {
1228  data_pt->set_value(t,j,data_pt->value(j));
1229  }
1230 
1231  //If it's adaptive
1232  if(adaptive_flag())
1233  {
1234  //Initial velocity is zero
1235  data_pt->set_value(NSTEPS+1,j,0.0);
1236  //Initial prediction is the value
1237  data_pt->set_value(NSTEPS+2,j,data_pt->value(j));
1238  }
1239  }
1240  }
1241  }
1242 
1243  /// \short Initialise the time-history for the nodal positions
1244  /// corresponding to an impulsive start.
1246  {
1247  //Find the dimension of the node
1248  unsigned n_dim = node_pt->ndim();
1249  //Find the number of position types at the node
1250  unsigned n_position_type = node_pt->nposition_type();
1251 
1252  //Loop over the position variables
1253  for(unsigned i=0;i<n_dim;i++)
1254  {
1255  //If the position is not copied
1256  //We copy entire coordinates at once
1257  if(node_pt->position_is_a_copy(i) == false)
1258  {
1259  //Loop over the position types
1260  for(unsigned k=0;k<n_position_type;k++)
1261  {
1262  //Set previous values to the initial value, if not a copy
1263  for(unsigned t=1;t<=NSTEPS;t++)
1264  {
1265  node_pt->x_gen(t,k,i) = node_pt->x_gen(k,i);
1266  }
1267 
1268  //If it's adaptive
1269  if(adaptive_flag())
1270  {
1271  //Initial mesh velocity is zero
1272  node_pt->x_gen(NSTEPS+1,k,i) = 0.0;
1273  //Initial prediction is the value
1274  node_pt->x_gen(NSTEPS+2,k,i) = node_pt->x_gen(k,i);
1275  }
1276  }
1277  }
1278  }
1279  }
1280 
1281 
1282  /// \short Typedef for function that returns the (scalar) initial
1283  /// value at a given value of the continuous time t.
1284  typedef double (*InitialConditionFctPt)(const double& t);
1285 
1286  /// \short Initialise the time-history for the Data values,
1287  /// corresponding to given time history, specified by
1288  /// Vector of function pointers.
1289  void assign_initial_data_values(Data* const &data_pt,
1291  initial_value_fct)
1292  {
1293  // The time history stores the previous function values
1294  unsigned n_time_value = ntstorage();
1295 
1296  //Find number of values stored
1297  unsigned n_value = data_pt->nvalue();
1298 
1299  //Loop over current and stored timesteps
1300  for(unsigned t=0;t<n_time_value;t++)
1301  {
1302 
1303  // Get corresponding continous time
1304  double time_local=Time_pt->time(t);
1305 
1306  //Loop over values
1307  for(unsigned j=0;j<n_value;j++)
1308  {
1309  data_pt->set_value(t,j,initial_value_fct[j](time_local));
1310  }
1311  }
1312  }
1313 
1314  /// \short This function updates the Data's time history so that
1315  /// we can advance to the next timestep. For BDF schemes,
1316  /// we simply push the values backwards...
1317  void shift_time_values(Data* const &data_pt)
1318  {
1319  //Find number of values stored
1320  unsigned n_value = data_pt->nvalue();
1321  //Storage for velocity need to be here to be in scope
1322  Vector<double> velocity(n_value);
1323 
1324  // Find the number of history values that are stored
1325  const unsigned nt_value = nprev_values();
1326 
1327  //If adaptive, find the velocities
1328  if(adaptive_flag()) {time_derivative(1,data_pt,velocity);}
1329 
1330  //Loop over the values
1331  for(unsigned j=0;j<n_value;j++)
1332  {
1333  //Set previous values to the previous value, if not a copy
1334  if(data_pt->is_a_copy(j) == false)
1335  {
1336  //Loop over times, in reverse order
1337  for(unsigned t=nt_value;t>0;t--)
1338  {
1339  data_pt->set_value(t,j,data_pt->value(t-1,j));
1340  }
1341 
1342  //If we are using the adaptive scheme
1343  if(adaptive_flag())
1344  {
1345  //Set the velocity
1346  data_pt->set_value(nt_value+1, j, velocity[j]);
1347  }
1348  }
1349  }
1350  }
1351 
1352  ///\short This function advances the time history of the positions
1353  ///at a node.
1354  void shift_time_positions(Node* const &node_pt)
1355  {
1356  //Find the number of coordinates
1357  unsigned n_dim = node_pt->ndim();
1358  //Find the number of position types
1359  unsigned n_position_type = node_pt->nposition_type();
1360 
1361  //Find number of stored timesteps
1362  unsigned n_tstorage = ntstorage();
1363 
1364  //Storage for the velocity
1365  double velocity[n_position_type][n_dim];
1366 
1367  //If adaptive, find the velocities
1368  if(adaptive_flag())
1369  {
1370  //Loop over the variables
1371  for(unsigned i=0;i<n_dim;i++)
1372  {
1373  for(unsigned k=0;k<n_position_type;k++)
1374  {
1375  //Initialise velocity to zero
1376  velocity[k][i] =0.0;
1377  //Loop over all history data
1378  for(unsigned t=0;t<n_tstorage;t++)
1379  {
1380  velocity[k][i] += Weight(1,t)*node_pt->x_gen(t,k,i);
1381  }
1382  }
1383  }
1384  }
1385 
1386  //Loop over the positions
1387  for(unsigned i=0;i<n_dim;i++)
1388  {
1389  //If the position is not a copy
1390  if(node_pt->position_is_a_copy(i) == false)
1391  {
1392  //Loop over the position types
1393  for(unsigned k=0;k<n_position_type;k++)
1394  {
1395  //Loop over stored times, and set values to previous values
1396  for(unsigned t=NSTEPS;t>0;t--)
1397  {
1398  node_pt->x_gen(t,k,i) = node_pt->x_gen(t-1,k,i);
1399  }
1400 
1401  //If we are using the adaptive scheme, set the velocity
1402  if(adaptive_flag())
1403  {
1404  node_pt->x_gen(NSTEPS+1,k,i) = velocity[k][i];
1405  }
1406  }
1407  }
1408  }
1409  }
1410 
1411  /// Set the weights
1412  void set_weights();
1413 
1414  /// Number of previous values available.
1415  unsigned nprev_values() const {return NSTEPS;}
1416 
1417  /// Number of timestep increments that need to be stored by the scheme
1418  unsigned ndt() const {return NSTEPS;}
1419 
1420  /// Function to set the predictor weights
1421  void set_predictor_weights();
1422 
1423  ///Function to calculate predicted positions at a node
1424  void calculate_predicted_positions(Node* const &node_pt);
1425 
1426  ///Function to calculate predicted data values in a Data object
1427  void calculate_predicted_values(Data* const &data_pt);
1428 
1429  ///Function to set the error weights
1430  void set_error_weights();
1431 
1432  /// Compute the error in the position i at a node
1433  double temporal_error_in_position(Node* const &node_pt,
1434  const unsigned &i);
1435 
1436  /// Compute the error in the value i in a Data structure
1437  double temporal_error_in_value(Data* const &data_pt,
1438  const unsigned &i);
1439 
1440 };
1441 
1442 }
1443 
1444 #endif
void disable_warning_in_assign_initial_data_values()
Disable the output of warnings due to possible fct pointer vector size mismatch in assign_initial_dat...
Definition: timesteppers.h:449
void assign_initial_positions_impulsive(Node *const &node_pt)
Initialise the time-history for the nodal positions corresponding to an impulsive start...
void enable_degrade_first_derivatives_to_bdf1()
Degrade scheme to first order BDF (for first derivs/veloc); usually for start-up. ...
void make_steady()
Function to make the time stepper temporarily steady. This is trivially achieved by setting all the w...
Definition: timesteppers.h:360
virtual double temporal_error_in_value(Data *const &data_pt, const unsigned &i)
Definition: timesteppers.h:608
Vector< double > Predictor_weight
Private data for the predictor weights.
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
Definition: nodes.h:291
virtual double temporal_error_in_position(Node *const &node_pt, const unsigned &i)
Definition: timesteppers.h:602
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
void operator=(const BDF &)
Broken assignment operator.
TimeStepper()
Broken empty constructor.
Definition: timesteppers.h:292
unsigned long nrow() const
Return the number of rows of the matrix.
Definition: matrices.h:504
Steady(const Steady &)
Broken copy constructor.
Definition: timesteppers.h:654
virtual void actions_after_timestep(Problem *problem_pt)
Definition: timesteppers.h:618
Newmark(const Newmark &)
Broken copy constructor.
Definition: timesteppers.h:886
void initialise(const T &val)
Initialize all values in the matrix to val.
Definition: matrices.h:523
void operator=(const NewmarkBDF &)
Broken assignment operator.
bool Shut_up_in_assign_initial_data_values
Boolean to indicate if the timestepper will output warnings when setting possibly an incorrect number...
Definition: timesteppers.h:246
BDF(const BDF &)
Broken copy constructor.
double time(const unsigned &t=0) const
Return the value of the continuous time at the t-th previous time level (t=0: current; t>0 previous)...
Definition: timesteppers.h:145
unsigned long ncol() const
Return the number of columns of the matrix.
Definition: matrices.h:507
double Error_weight
Private data for the error weight.
Newmark()
Constructor: Pass pointer to global time. We set up a timestepping scheme with NSTEPS+2 doubles to re...
Definition: timesteppers.h:876
unsigned ndt() const
Number of timestep increments that need to be stored by the scheme.
Time(const Time &)
Broken copy constructor.
Definition: timesteppers.h:93
double Beta1
First Newmark parameter (usually 0.5)
static double Zero
Static variable to hold the value 0.0.
Definition: timesteppers.h:839
cstr elem_len * i
Definition: cfortran.h:607
virtual void set_predictor_weights()
Set the weights for the predictor previous timestep (currently empty – overwrite for specific scheme...
Definition: timesteppers.h:586
double & time()
Return current value of continous time.
Definition: timesteppers.h:324
Class to keep track of discrete/continous time. It is essential to have a single Time object when usi...
Definition: timesteppers.h:67
std::string Type
String that indicates the type of the timestepper (e.g. "BDF", "Newmark", etc.)
Definition: timesteppers.h:231
unsigned nprev_values() const
Number of previous values available.
void shift_time_values(Data *const &data_pt)
This function updates the Data&#39;s time history so that we can advance to the next timestep. For BDF schemes, we simply push the values backwards...
ExplicitTimeStepper * Explicit_predictor_pt
Definition: timesteppers.h:255
The Problem class.
Definition: problem.h:152
void shift_dt()
Update all stored values of dt by shifting each value along the array. This function must be called b...
Definition: timesteppers.h:166
Vector< double > Newmark_veloc_weight
Original Newmark weights for velocities (needed when shifting history values – they&#39;re used when upd...
unsigned order() const
The actual order (accuracy of the scheme)
Definition: timesteppers.h:899
unsigned order() const
Return the actual order of the scheme.
void check_predicted_values_up_to_date() const
Check that the predicted values are the ones we want.
Definition: timesteppers.h:406
void shift_time_positions(Node *const &node_pt)
This function advances the time history of the positions at a node.
Definition: timesteppers.h:772
char t
Definition: cfortran.h:572
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
Templated class for BDF-type time-steppers with fixed or variable timestep. 1st time derivative recov...
Time(const unsigned &ndt)
Constructor: Pass the number of timesteps to be stored and set the initial value of time to zero...
Definition: timesteppers.h:85
int Predictor_storage_index
The time-index in each Data object where predicted values are stored. -1 if not set.
Definition: timesteppers.h:263
static double One
Static variable to hold the value 1.0.
Definition: timesteppers.h:836
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:448
NewmarkBDF()
Constructor: Pass pointer to global time. We set up a timestepping scheme with NSTEPS+2 doubles to re...
const DenseMatrix< double > * weights_pt() const
Get a (const) pointer to the weights.
Definition: timesteppers.h:453
static Time Dummy_time
Definition: timesteppers.h:842
bool Predict_by_explicit_step
Flag: is adaptivity done by taking a separate step using an ExplicitTimeStepper object?
Definition: timesteppers.h:250
e
Definition: cfortran.h:575
void operator=(const Newmark &)
Broken assignment operator.
Definition: timesteppers.h:892
double Beta2
Second Newmark parameter (usually 0.5)
bool Is_steady
Bool to indicate if the timestepper is steady, i.e. its time-derivatives evaluate to zero...
Definition: timesteppers.h:241
Newmark scheme for second time deriv. Stored data represents.
Definition: timesteppers.h:868
virtual unsigned nprev_values_for_value_at_evaluation_time() const
Number of previous values needed to calculate the value at the current time. i.e. how many previous v...
Definition: timesteppers.h:348
void assign_initial_data_values(Data *const &data_pt, Vector< InitialConditionFctPt > initial_value_fct)
Initialise the time-history for the Data values, corresponding to given time history, specified by Vector of function pointers.
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:992
void shift_time_positions(Node *const &node_pt)
This function advances the time history of the positions at a node.
double dt(const unsigned &t=0) const
Definition: timesteppers.h:141
DenseMatrix< double > Weight
Storage for the weights associated with the timestepper.
Definition: timesteppers.h:227
unsigned ndt() const
Number of timestep increments that need to be stored by the scheme.
Definition: timesteppers.h:818
double Zero
Static variable to hold the default value for the pseudo-solid&#39;s inertia parameter Lambda^2...
void initialise_dt(const Vector< double > &dt_)
Set the value of the timesteps to be equal to the values passed in a vector.
Definition: timesteppers.h:117
void set_weights()
Set weights.
Definition: timesteppers.h:798
void set_newmark_veloc_weights(const double &dt)
Set original Newmark weights for velocities (needed when shifting history values – they&#39;re used when...
ExplicitTimeStepper * explicit_predictor_pt()
Definition: timesteppers.h:389
bool adaptive_flag() const
Function to indicate whether the scheme is adaptive (false by default)
Definition: timesteppers.h:582
void set_predictor_pt(ExplicitTimeStepper *_pred_pt)
Definition: timesteppers.h:393
void update_predicted_time(const double &new_time)
Definition: timesteppers.h:400
TimeStepper(const unsigned &tstorage, const unsigned &max_deriv)
Constructor. Pass the amount of storage required by timestepper (present value + history values) and ...
Definition: timesteppers.h:270
TimeStepper(const TimeStepper &)
Broken copy constructor.
Definition: timesteppers.h:300
void set_value(const unsigned &i, const double &value_)
Set the i-th stored data value to specified value. The only reason that we require an explicit set fu...
Definition: nodes.h:267
double & dt(const unsigned &t=0)
Definition: timesteppers.h:137
unsigned nposition_type() const
Number of coordinate types needed in the mapping between local and global coordinates.
Definition: nodes.h:966
virtual void actions_before_timestep(Problem *problem_pt)
Definition: timesteppers.h:614
void operator=(const TimeStepper &)
Broken assignment operator.
Definition: timesteppers.h:306
Time()
Constructor: Do not allocate any storage for previous timesteps, but set the initial value of the tim...
Definition: timesteppers.h:81
Time * Time_pt
Pointer to discrete time storage scheme.
Definition: timesteppers.h:224
bool predict_by_explicit_step() const
Flag: is adaptivity done by taking a separate step using an ExplicitTimeStepper object?
Definition: timesteppers.h:382
unsigned ndt() const
Return the number of timesteps stored.
Definition: timesteppers.h:133
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i).
Definition: nodes.h:1055
void operator=(const Steady &)
Broken assignment operator.
Definition: timesteppers.h:660
void time_derivative(const unsigned &i, Node *const &node_pt, Vector< double > &deriv)
Evaluate i-th derivative of all values in Node and return in Vector deriv[] (this can&#39;t be simply com...
Definition: timesteppers.h:506
unsigned highest_derivative() const
Highest order derivative that the scheme can compute.
Definition: timesteppers.h:315
BDF(const bool &adaptive=false)
Constructor for the case when we allow adaptive timestepping.
void assign_initial_positions_impulsive(Node *const &node_pt)
Initialise the time-history for the nodal positions corresponding to an impulsive start...
Definition: timesteppers.h:691
double & time()
Return the current value of the continuous time.
Definition: timesteppers.h:130
virtual unsigned order() const
Actual order (accuracy) of the scheme.
Definition: timesteppers.h:319
double weight(const unsigned &i, const unsigned &j) const
Dummy: Access function for j-th weight for the i-th derivative.
Definition: timesteppers.h:821
unsigned order() const
Return the actual order of the scheme. Returning zero here – doesn&#39;t make much sense, though.
Definition: timesteppers.h:667
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
Definition: timesteppers.h:562
virtual void undo_make_steady()
Reset the is_steady status of a specific TimeStepper to its default and re-assign the weights...
Definition: timesteppers.h:457
bool Adaptive_Flag
Boolean variable to indicate whether the timestepping scheme can be adaptive.
Definition: timesteppers.h:235
Vector< double > Dt
Vector that stores the values of the current and previous timesteps.
Definition: timesteppers.h:75
void assign_initial_data_values(Data *const &data_pt, Vector< InitialConditionFctPt > initial_value_fct)
Initialise the time-history for the Data values, corresponding to given time history, specified by Vector of function pointers.
Definition: timesteppers.h:723
~Time()
Destructor: empty.
Definition: timesteppers.h:127
std::string type() const
Return string that indicates the type of the timestepper (e.g. "BDF", "Newmark", etc.)
Definition: timesteppers.h:465
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
void initialise_dt(const double &dt_)
Set all timesteps to the same value, dt.
Definition: timesteppers.h:109
Newmark scheme for second time deriv with first derivatives calculated using BDF. ...
double time_derivative(const unsigned &i, Data *const &data_pt, const unsigned &j)
Evaluate i-th derivative of j-th value in Data.
Definition: timesteppers.h:489
void assign_initial_values_impulsive(Data *const &data_pt)
Initialise the time-history for the Data values, corresponding to an impulsive start.
Definition: timesteppers.h:671
void resize(const unsigned &n_dt)
Resize the vector holding the number of previous timesteps and initialise the new values to zero...
Definition: timesteppers.h:106
void enable_warning_in_assign_initial_data_values()
Enable the output of warnings due to possible fct pointer vector size mismatch in assign_initial_data...
Definition: timesteppers.h:444
unsigned ndt() const
Number of timestep increments that need to be stored by the scheme.
Time *const & time_pt() const
Access function for the pointer to time (const version)
Definition: timesteppers.h:540
void shift_time_values(Data *const &data_pt)
This function updates the Data&#39;s time history so that we can advance to the next timestep. As for BDF schemes, we simply push the values backwards...
Definition: timesteppers.h:750
bool Degrade_to_bdf1_for_first_derivs
Boolean flag to indicate degradation of scheme to first order BDF (for first derivs/veloc); usually f...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
unsigned nprev_values() const
Number of previous values available.
Definition: timesteppers.h:815
virtual void calculate_predicted_values(Data *const &data_pt)
Do the predictor step for data stored in a Data object (currently empty – overwrite for specific sch...
Definition: timesteppers.h:590
double time_derivative(const unsigned &i, Node *const &node_pt, const unsigned &j)
Evaluate i-th derivative of j-th value in Node. Note the use of the node&#39;s value() function so that h...
Definition: timesteppers.h:524
virtual bool position_is_a_copy() const
Return whether any position coordinate has been copied (always false)
Definition: nodes.h:1048
double time() const
Return current value of continous time.
Definition: timesteppers.h:327
unsigned nprev_values() const
Number of previous values available.
NewmarkBDF(const NewmarkBDF &)
Broken copy constructor.
bool is_steady() const
Flag to indicate if a timestepper has been made steady (possibly temporarily to switch off time-depen...
Definition: timesteppers.h:375
void time_derivative(const unsigned &i, Data *const &data_pt, Vector< double > &deriv)
Evaluate i-th derivative of all values in Data and return in Vector deriv[].
Definition: timesteppers.h:474
unsigned predictor_storage_index() const
Return the time-index in each Data where predicted values are stored if the timestepper is adaptive...
Definition: timesteppers.h:420
virtual bool is_a_copy() const
Return a boolean to indicate whether the Data objact contains any copied values. A base Data object c...
Definition: nodes.h:255
A Base class for explicit timesteppers.
double Continuous_time
Pointer to the value of the continuous time.
Definition: timesteppers.h:72
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
Definition: timesteppers.h:219
virtual double weight(const unsigned &i, const unsigned &j) const
Access function for j-th weight for the i-th derivative.
Definition: timesteppers.h:557
void operator=(const Time &)
Broken assignment operator.
Definition: timesteppers.h:99
virtual void set_error_weights()
Set the weights for the error computation, (currently empty – overwrite for specific scheme) ...
Definition: timesteppers.h:598
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation...
Definition: nodes.cc:2328
Steady()
Constructor: Creates storage for NSTEPS previous timesteps and can evaluate up to 2nd derivatives (th...
Definition: timesteppers.h:642
std::string to_string(T object, unsigned float_precision=8)
Conversion function that should work for anything with operator<< defined (at least all basic types)...
void assign_initial_values_impulsive(Data *const &data_pt)
Initialise the time-history for the Data values, corresponding to an impulsive start.
virtual 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...
Definition: timesteppers.h:594
void disable_degrade_first_derivatives_to_bdf1()
Disable degradation to first order BDF.
void resize(const unsigned long &n)
Definition: matrices.h:511