self_starting_BDF2_timestepper.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// Copyright (C) 2006-2022 Matthias Heil and Andrew Hazel
7 //LIC//
8 //LIC// This library is free software; you can redistribute it and/or
9 //LIC// modify it under the terms of the GNU Lesser General Public
10 //LIC// License as published by the Free Software Foundation; either
11 //LIC// version 2.1 of the License, or (at your option) any later version.
12 //LIC//
13 //LIC// This library is distributed in the hope that it will be useful,
14 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 //LIC// Lesser General Public License for more details.
17 //LIC//
18 //LIC// You should have received a copy of the GNU Lesser General Public
19 //LIC// License along with this library; if not, write to the Free Software
20 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 //LIC// 02110-1301 USA.
22 //LIC//
23 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 //LIC//
25 //LIC//====================================================================
26 
27 // Include oomph-lib headers
28 #include "generic.h"
29 
30 namespace oomph
31 {
32 
33  //====================================================================
35  //====================================================================
37  {
38  private:
39 
42 
44  double Error_weight;
45 
51  bool BDF1_mode;
52 
53  public:
54 
57  SelfStartingBDF2(const bool& adaptive=false) : TimeStepper(3,1), BDF1_mode(false)
58  {
59  Type="BDF";
60 
61  // If it's adaptive, we need to allocate additional space to
62  // carry along a prediction and an acceleration
63  if(adaptive)
64  {
65  // Set the adaptive flag to be true
66  Adaptive_Flag = true;
67 
68  // Set the size of the Predictor_Weights Vector
69  // N.B. The size is correct for BDF<2>, but may be wrong for others
70  Predictor_weight.resize(4);
71 
72  // The order of the scheme is 1, i.e. Weights has two entries
73 
74  //Resize the weights to the appropriate size
75  Weight.resize(2,5);
76 
77  // Initialise
78  for(unsigned i=0;i<2;i++)
79  {
80  // Initialise each weight to zero
81  for(unsigned j=0;j<5;j++)
82  {
83  Weight(i,j) = 0.0;
84  }
85  }
86  // Set the weight for the zero-th derivative
87  Weight(0,0) = 1.0;
88  }
89  }
90 
93  {
94  BrokenCopy::broken_copy("SelfStartingBDF2");
95  }
96 
99  {
100  BrokenCopy::broken_assign("SelfStartingBDF2");
101  }
102 
104  unsigned order() const { return 2; }
105 
111  {
112  // Update flag
113  BDF1_mode = true;
114 
115  // Reset weights
117  }
118 
120  bool bdf1_mode() { return BDF1_mode; }
121 
125  {
126  // Update flag
127  BDF1_mode = false;
128 
129  // Reset_weights
131  }
132 
136  {
137  // Update flag
138  Is_steady = false;
139 
140  // Reset weights
141  if(BDF1_mode)
142  {
144  }
145  else
146  {
148  }
149  }
150 
153  void assign_initial_values_impulsive(Data* const &data_pt)
154  {
155  // Find number of values stored
156  const unsigned n_value = data_pt->nvalue();
157 
158  // Loop over values
159  for(unsigned j=0;j<n_value;j++)
160  {
161  // Set previous values to the initial value, if not a copy
162  if(data_pt->is_a_copy(j) == false)
163  {
164  for(unsigned t=1;t<=2;t++)
165  {
166  data_pt->set_value(t,j,data_pt->value(j));
167  }
168 
169  // If it's adaptive
170  if(adaptive_flag())
171  {
172  // Initial velocity is zero
173  data_pt->set_value(3,j,0.0);
174  // Initial prediction is the value
175  data_pt->set_value(4,j,data_pt->value(j));
176  }
177  }
178  }
179  }
180 
181 
185  {
186  // Find the dimension of the node
187  const unsigned n_dim = node_pt->ndim();
188  // Find the number of position types at the node
189  const unsigned n_position_type = node_pt->nposition_type();
190 
191  // Loop over the position variables
192  for(unsigned i=0;i<n_dim;i++)
193  {
194  // If the position is not copied
195  // We copy entire coordinates at once
196  if(node_pt->position_is_a_copy(i) == false)
197  {
198  // Loop over the position types
199  for(unsigned k=0;k<n_position_type;k++)
200  {
201  // Set previous values to the initial value, if not a copy
202  for(unsigned t=1;t<=2;t++)
203  {
204  node_pt->x_gen(t,k,i) = node_pt->x_gen(k,i);
205  }
206 
207  // If it's adaptive
208  if(adaptive_flag())
209  {
210  // Initial mesh velocity is zero
211  node_pt->x_gen(3,k,i) = 0.0;
212  // Initial prediction is the value
213  node_pt->x_gen(4,k,i) = node_pt->x_gen(k,i);
214  }
215  }
216  }
217  }
218  }
219 
220 
223  typedef double (*InitialConditionFctPt)(const double& t);
224 
228  void assign_initial_data_values(Data* const &data_pt,
230  initial_value_fct)
231  {
232  // The time history stores the previous function values
233  const unsigned n_time_value = ntstorage();
234 
235  // Find number of values stored
236  const unsigned n_value = data_pt->nvalue();
237 
238  // Loop over current and stored timesteps
239  for(unsigned t=0;t<n_time_value;t++)
240  {
241  // Get corresponding continous time
242  double time = Time_pt->time(t);
243 
244  // Loop over values
245  for(unsigned j=0;j<n_value;j++)
246  {
247  data_pt->set_value(t,j,initial_value_fct[j](time));
248  }
249  }
250  }
251 
255  void shift_time_values(Data* const &data_pt)
256  {
257  // Find number of values stored
258  const unsigned n_value = data_pt->nvalue();
259  // Storage for velocity need to be here to be in scope
260  Vector<double> velocity(n_value);
261 
262  // If adaptive, find the velocities
263  if(adaptive_flag()) { time_derivative(1,data_pt,velocity); }
264 
265  // Loop over the values
266  for(unsigned j=0;j<n_value;j++)
267  {
268  // Set previous values to the previous value, if not a copy
269  if(data_pt->is_a_copy(j) == false)
270  {
271  // Loop over times, in reverse order
272  for(unsigned t=2;t>0;t--)
273  {
274  data_pt->set_value(t,j,data_pt->value(t-1,j));
275  }
276 
277  // If we are using the adaptive scheme
278  if(adaptive_flag())
279  {
280  // Set the velocity
281  data_pt->set_value(3,j,velocity[j]);
282  }
283  }
284  }
285  }
286 
289  void shift_time_positions(Node* const &node_pt)
290  {
291  // Find the number of coordinates
292  const unsigned n_dim = node_pt->ndim();
293  // Find the number of position types
294  const unsigned n_position_type = node_pt->nposition_type();
295 
296  // Find number of stored timesteps
297  const unsigned n_tstorage = ntstorage();
298 
299  // Storage for the velocity
300  double velocity[n_position_type][n_dim];
301 
302  // If adaptive, find the velocities
303  if(adaptive_flag())
304  {
305  // Loop over the variables
306  for(unsigned i=0;i<n_dim;i++)
307  {
308  for(unsigned k=0;k<n_position_type;k++)
309  {
310  // Initialise velocity to zero
311  velocity[k][i] =0.0;
312  // Loop over all history data
313  for(unsigned t=0;t<n_tstorage;t++)
314  {
315  velocity[k][i] += Weight(1,t)*node_pt->x_gen(t,k,i);
316  }
317  }
318  }
319  }
320 
321  // Loop over the positions
322  for(unsigned i=0;i<n_dim;i++)
323  {
324  // If the position is not a copy
325  if(node_pt->position_is_a_copy(i) == false)
326  {
327  // Loop over the position types
328  for(unsigned k=0;k<n_position_type;k++)
329  {
330  // Loop over stored times, and set values to previous values
331  for(unsigned t=2;t>0;t--)
332  {
333  node_pt->x_gen(t,k,i) = node_pt->x_gen(t-1,k,i);
334  }
335 
336  // If we are using the adaptive scheme, set the velocity
337  if(adaptive_flag())
338  {
339  node_pt->x_gen(3,k,i) = velocity[k][i];
340  }
341  }
342  }
343  }
344  }
345 
349  void set_weights()
350  {
351  if(BDF1_mode) { set_weights_bdf1(); }
352  else { set_weights_bdf2(); }
353  }
354 
356  void set_weights_bdf1();
357 
359  void set_weights_bdf2();
360 
362  unsigned nprev_values() const { return 2; }
363 
365  unsigned ndt() const { return 2; }
366 
369 
372 
374  void calculate_predicted_positions_bdf1(Node* const &node_pt);
375 
377  void calculate_predicted_positions_bdf2(Node* const &node_pt);
378 
380  void calculate_predicted_values_bdf1(Data* const &data_pt);
381 
383  void calculate_predicted_values_bdf2(Data* const &data_pt);
384 
386  void set_error_weights_bdf1();
387 
389  void set_error_weights_bdf2();
390 
392  double temporal_error_in_position_bdf1(Node* const &node_pt,
393  const unsigned &i);
394 
396  double temporal_error_in_position_bdf2(Node* const &node_pt,
397  const unsigned &i);
398 
400  double temporal_error_in_value_bdf1(Data* const &data_pt,
401  const unsigned &i);
402 
404  double temporal_error_in_value_bdf2(Data* const &data_pt,
405  const unsigned &i);
406 
407  };
408 
409 
410 
414 
415 
416  // BDF1 functions
417  // --------------
418 
419 
420  //=======================================================================
422  //=======================================================================
424  {
425  // Set BDF1 weights as normal
426  double dt=Time_pt->dt(0);
427  Weight(1,0) = 1.0/dt;
428  Weight(1,1) = -1.0/dt;
429 
430  // Set weight associated with history value 2 to zero so that it has
431  // no effect on the dudt calculation
432  Weight(1,2) = 0.0;
433  }
434 
435 
436  //======================================================================
438  //======================================================================
440  {
441  //Read the value of the previous timesteps
442  //double dt=Time_pt->dt(0);
443  //double dtprev=Time_pt->dt(1);
444 
445  throw OomphLibError("Not implemented yet",
446  "SelfStartingBDF2::set_predictor_weights_bdf1()",
448  }
449 
450 
451  //=======================================================================
455  //=======================================================================
457  {
458  throw OomphLibError("Not implemented yet",
459  "SelfStartingBDF2::calculate_predicted_weights_bdf1()",
461  }
462 
463 
464  //=======================================================================
466  //=======================================================================
468  Node* const &node_pt)
469  {
470  throw OomphLibError("Not implemented yet",
471  "SelfStartingBDF2::calculate_predicted_positions_bdf1()",
473  }
474 
475 
476  //=======================================================================
478  //=======================================================================
480  {
481  throw OomphLibError("Not implemented yet",
482  "SelfStartingBDF2::set_error_weights_bdf1()",
484  }
485 
486  //===================================================================
488  //===================================================================
490  Node* const &node_pt,const unsigned &i)
491  {
492  throw OomphLibError("Not implemented yet",
493  "SelfStartingBDF2::temporal_error_in_position_bdf1()",
495  return 0.0;
496  }
497 
498 
499  //=========================================================================
501  //=========================================================================
503  const unsigned &i)
504  {
505  throw OomphLibError("Not implemented yet",
506  "SelfStartingBDF2::temporal_error_in_value_bdf1()",
508  return 0.0;
509  }
510 
511 
512  // BDF2 functions
513  // --------------
514 
515 
516  //========================================================================
518  //========================================================================
520  {
521  double dt=Time_pt->dt(0);
522  double dtprev=Time_pt->dt(1);
523  Weight(1,0) = 1.0/dt + 1.0/(dt + dtprev);
524  Weight(1,1) = -(dt + dtprev)/(dt*dtprev);
525  Weight(1,2) = dt/((dt+dtprev)*dtprev);
526 
527  if(adaptive_flag())
528  {
529  Weight(1,3) = 0.0;
530  Weight(1,4) = 0.0;
531  }
532  }
533 
534  //======================================================================
536  //======================================================================
538  {
539  //If it's adaptive set the predictor weights
540  if(adaptive_flag())
541  {
542  //Read the value of the previous timesteps
543  double dt=Time_pt->dt(0);
544  double dtprev=Time_pt->dt(1);
545 
546  //Set the predictor weights
547  Predictor_weight[0] = 0.0;
548  Predictor_weight[1] = 1.0 - (dt*dt)/(dtprev*dtprev);
549  Predictor_weight[2] = (dt*dt)/(dtprev*dtprev);
550  //Acceleration term
551  Predictor_weight[3] = (1.0 + dt/dtprev)*dt;
552  }
553  }
554 
555  //=======================================================================
559  //=======================================================================
561  {
562  //If it's adaptive calculate the values
563  if(adaptive_flag())
564  {
565  //Find number of values
566  unsigned n_value = data_pt->nvalue();
567  //Loop over the values
568  for(unsigned j=0;j<n_value;j++)
569  {
570  //If the value is not copied
571  if(data_pt->is_a_copy(j) == false)
572  {
573  //Now Initialise the predictor to zero
574  double predicted_value = 0.0;
575  //Now loop over all the stored data and add appropriate values
576  //to the predictor
577  for(unsigned i=1;i<4;i++)
578  {
579  predicted_value += data_pt->value(i,j)*Predictor_weight[i];
580  }
581  //Store the predicted value
582  //Note that predictor is stored as the FIFTH entry in this scheme
583  data_pt->set_value(4,j,predicted_value);
584  }
585  }
586  }
587  }
588 
589  //=======================================================================
591  //=======================================================================
593  Node* const &node_pt)
594  {
595  //Only do this if adaptive
596  if(adaptive_flag())
597  {
598  //Find number of dimensions of the problem
599  unsigned n_dim = node_pt->ndim();
600  //Loop over the dimensions
601  for(unsigned j=0;j<n_dim;j++)
602  {
603  //If the node is not copied
604  if(node_pt->position_is_a_copy(j) == false)
605  {
606  //Initialise the predictor to zero
607  double predicted_value = 0.0;
608  //Now loop over all the stored data and add appropriate values
609  //to the predictor
610  for(unsigned i=1;i<4;i++)
611  {
612  predicted_value += node_pt->x(i,j)*Predictor_weight[i];
613  }
614  //Store the predicted value
615  //Note that predictor is stored as the FIFTH entry in this scheme
616  node_pt->x(4,j) = predicted_value;
617  }
618  }
619  }
620  }
621 
622 
623  //=======================================================================
625  //=======================================================================
627  {
628  if(adaptive_flag())
629  {
630  double dt=Time_pt->dt(0);
631  double dtprev=Time_pt->dt(1);
632  //Calculate the error weight
633  Error_weight = pow((1.0 + dtprev/dt),2.0)/
634  (1.0 + 3.0*(dtprev/dt) + 4.0*pow((dtprev/dt),2.0) +
635  2.0*pow((dtprev/dt),3.0));
636  }
637  }
638 
639 
640  //===================================================================
642  //===================================================================
644  Node* const &node_pt,const unsigned &i)
645  {
646  if(adaptive_flag())
647  {
648  //Just return the error
649  return Error_weight*(node_pt->x(i) - node_pt->x(4,i));
650  }
651  else
652  {
653  return 0.0;
654  }
655  }
656 
657 
658  //=========================================================================
660  //=========================================================================
662  const unsigned &i)
663  {
664  if(adaptive_flag())
665  {
666  //Just return the error
667  return Error_weight*(data_pt->value(i) - data_pt->value(4,i));
668  }
669  else
670  {
671  return 0.0;
672  }
673  }
674 
675 
676 } // End of namespace oomph
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Definition: nodes.h:86
void set_value(const unsigned &i, const double &value_)
Definition: nodes.h:271
virtual bool is_a_copy() const
Definition: nodes.h:253
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:483
double value(const unsigned &i) const
Definition: nodes.h:293
void resize(const unsigned long &n)
Definition: matrices.h:498
Definition: nodes.h:906
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
double & x_gen(const unsigned &k, const unsigned &i)
Definition: nodes.h:1126
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
virtual bool position_is_a_copy() const
Return whether any position coordinate has been copied (always false)
Definition: nodes.h:1113
unsigned nposition_type() const
Definition: nodes.h:1016
Definition: oomph_definitions.h:222
Self-starting BDF2 timestepper class.
Definition: self_starting_BDF2_timestepper.h:37
void calculate_predicted_positions_bdf1(Node *const &node_pt)
Function to calculate predicted positions at a node (BDF1)
Definition: self_starting_BDF2_timestepper.h:467
void set_error_weights_bdf1()
Function to set the error weights corresponding to BDF1.
Definition: self_starting_BDF2_timestepper.h:479
unsigned order() const
Return the actual order of the scheme.
Definition: self_starting_BDF2_timestepper.h:104
bool BDF1_mode
Definition: self_starting_BDF2_timestepper.h:51
Vector< double > Predictor_weight
Private data for the predictor weights.
Definition: self_starting_BDF2_timestepper.h:41
void set_weights_bdf1()
Set the weights to those corresponding to BDF1.
Definition: self_starting_BDF2_timestepper.h:423
void set_weights()
Definition: self_starting_BDF2_timestepper.h:349
void assign_initial_values_impulsive(Data *const &data_pt)
Definition: self_starting_BDF2_timestepper.h:153
bool bdf1_mode()
Flag to indicate if the timestepper is working in BDF1 mode.
Definition: self_starting_BDF2_timestepper.h:120
void assign_initial_positions_impulsive(Node *const &node_pt)
Definition: self_starting_BDF2_timestepper.h:184
void turn_on_bdf1_mode()
Definition: self_starting_BDF2_timestepper.h:110
double Error_weight
Private data for the error weight.
Definition: self_starting_BDF2_timestepper.h:44
void shift_time_positions(Node *const &node_pt)
Definition: self_starting_BDF2_timestepper.h:289
double temporal_error_in_value_bdf2(Data *const &data_pt, const unsigned &i)
Compute the error in the value i in a Data structure (BDF2)
Definition: self_starting_BDF2_timestepper.h:661
void set_error_weights_bdf2()
Function to set the error weights corresponding to BDF2.
Definition: self_starting_BDF2_timestepper.h:626
void calculate_predicted_values_bdf2(Data *const &data_pt)
Function to calculate predicted data values in a Data object (BDF2)
Definition: self_starting_BDF2_timestepper.h:560
double temporal_error_in_value_bdf1(Data *const &data_pt, const unsigned &i)
Compute the error in the value i in a Data structure (BDF1)
Definition: self_starting_BDF2_timestepper.h:502
void set_weights_bdf2()
Set the weights to those corresponding to BDF2.
Definition: self_starting_BDF2_timestepper.h:519
void operator=(const SelfStartingBDF2 &)
Broken assignment operator.
Definition: self_starting_BDF2_timestepper.h:98
void set_predictor_weights_bdf1()
Function to set the predictor weights corresponding to BDF1.
Definition: self_starting_BDF2_timestepper.h:439
void shift_time_values(Data *const &data_pt)
Definition: self_starting_BDF2_timestepper.h:255
SelfStartingBDF2(const SelfStartingBDF2 &)
Broken copy constructor.
Definition: self_starting_BDF2_timestepper.h:92
void turn_off_bdf1_mode()
Definition: self_starting_BDF2_timestepper.h:124
double temporal_error_in_position_bdf1(Node *const &node_pt, const unsigned &i)
Compute the error in the position i at a node (BDF1)
Definition: self_starting_BDF2_timestepper.h:489
void set_predictor_weights_bdf2()
Function to set the predictor weights corresponding to BDF2.
Definition: self_starting_BDF2_timestepper.h:537
double(* InitialConditionFctPt)(const double &t)
Definition: self_starting_BDF2_timestepper.h:223
void undo_make_steady()
Definition: self_starting_BDF2_timestepper.h:135
SelfStartingBDF2(const bool &adaptive=false)
Definition: self_starting_BDF2_timestepper.h:57
unsigned ndt() const
Number of timestep increments that need to be stored by the scheme.
Definition: self_starting_BDF2_timestepper.h:365
void calculate_predicted_positions_bdf2(Node *const &node_pt)
Function to calculate predicted positions at a node (BDF2)
Definition: self_starting_BDF2_timestepper.h:592
void assign_initial_data_values(Data *const &data_pt, Vector< InitialConditionFctPt > initial_value_fct)
Definition: self_starting_BDF2_timestepper.h:228
double temporal_error_in_position_bdf2(Node *const &node_pt, const unsigned &i)
Compute the error in the position i at a node (BDF2)
Definition: self_starting_BDF2_timestepper.h:643
unsigned nprev_values() const
Number of previous values available.
Definition: self_starting_BDF2_timestepper.h:362
void calculate_predicted_values_bdf1(Data *const &data_pt)
Function to calculate predicted data values in a Data object (BDF1)
Definition: self_starting_BDF2_timestepper.h:456
Definition: timesteppers.h:231
DenseMatrix< double > Weight
Storage for the weights associated with the timestepper.
Definition: timesteppers.h:237
Time * Time_pt
Pointer to discrete time storage scheme.
Definition: timesteppers.h:234
unsigned ntstorage() const
Definition: timesteppers.h:601
std::string Type
Definition: timesteppers.h:241
bool Is_steady
Definition: timesteppers.h:251
bool adaptive_flag() const
Function to indicate whether the scheme is adaptive (false by default)
Definition: timesteppers.h:623
void time_derivative(const unsigned &i, Data *const &data_pt, Vector< double > &deriv)
Definition: timesteppers.h:502
double & time()
Return current value of continous time.
Definition: timesteppers.h:332
bool Adaptive_Flag
Definition: timesteppers.h:245
double & dt(const unsigned &t=0)
Definition: timesteppers.h:136
double & time()
Return the current value of the continuous time.
Definition: timesteppers.h:123
char char char int int * k
Definition: level2_impl.h:374
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
int adaptive
Definition: jeffery_hamel.cc:106
double velocity(const double &t)
Angular velocity as function of time t.
Definition: jeffery_orbit.cc:107
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
Definition: oomph_utilities.cc:195
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
Definition: oomph_utilities.cc:212
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
t
Definition: plotPSD.py:36
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2