generalised_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: 1097 $
7 //LIC//
8 //LIC// $LastChangedDate: 2015-12-17 11:53:17 +0000 (Thu, 17 Dec 2015) $
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_GENERALISED_TIMESTEPPERS_HEADER
31 #define OOMPH_GENERALISED_TIMESTEPPERS_HEADER
32 
33 #include <typeinfo>
34 
35 // Config header generated by autoconfig
36 #ifdef HAVE_CONFIG_H
37  #include <oomph-lib-config.h>
38 #endif
39 
40 //OOMPH-LIB headers
41 #include "timesteppers.h"
42 
43 namespace oomph
44 {
45 
46 //======================================================================
47 /// \short Generalised timestepper that can serve a variety of purposes
48 /// in continuation, bifurcation detection and periodic-orbit computations.
49 /// The key generalisation is that more than one of the entries is actually
50 /// a degree of freedom in the problem. These are distinct from our
51 /// standard (implict) Timesteppers in which the only dof is the current
52 /// value (first entry in the storage scheme). These objects will typically
53 /// be used to replace exisiting timesteppers for specific tasks.
54 //====================================================================
56  {
57 
58  protected:
59 
60  //Set the number of entries that correspond to dof storage
62 
63  //Vector that represents the storage entries
64  //Vector<unsigned> Dof_storage_index;
65 
66  ///Constructor that can only be called by derived objects.
67  ///Pass the information directly through to the TimeStepper object
68  GeneralisedTimeStepper(const unsigned &n_tstorage,
69  const unsigned &max_deriv,
70  const unsigned &ndof_storage_entries=1) :
72  {
73  //Dof_storage_index.resize(1,0.0);
74  }
75 
76  /// Broken empty constructor
78 
79  /// Broken copy constructor
81  {
82  BrokenCopy::broken_copy("GeneralisedTimeStepper");
83  }
84 
85  /// Broken assignment operator
87  {
88  BrokenCopy::broken_assign("GeneralisedTimeStepper");
89  }
90 
91  public:
92 
93  /// Return the number of entries that correspond to dof storage
94  unsigned ndof_storage_entries() const {return Ndof_storage_entries;}
95 
96  /// Return the i-th storage index
97  //unsigned dof_storage_index(const unsigned &i) {return Dof_storage_index[i];}
98 
99 };
100 
101 //========================================================================
102 /// \short GeneralisedTimestepper used to store the arclength derivatives
103 /// and pervious solutions required in continuation problems. The data
104 /// is stored as auxilliary data in the (fake) TimeStepper so that
105 /// spatial adaptivity will be handled automatically through our standard
106 /// mechanisms. The adopted storage scheme is that the continuation
107 /// derivatives will be stored at the first auxilliary value and
108 /// the previous value will be the second auixilliary value
109 //====================================================================
111 {
112  //Store the offset for the derivatives
114 
115  //Store the offset for the current values of the dofs
117 
118  public:
119 
120  ///Constructor for the case when we allow adaptive continuation
121  ///It can evaulate up to second derivatives, but doesn't do anything
122  ///the time-derivatives evaluate to zero.
125  {
126  Type="ContinuationStorageScheme";
127  Is_steady=true;
128  }
129 
130 
131  /// Broken copy constructor
133  {
134  BrokenCopy::broken_copy("ContinuationStorageScheme");
135  }
136 
137  ///Modify the scheme based on the underlying timestepper
138  void modify_storage(GeneralisedTimeStepper* const &time_stepper_pt)
139  {
140  //Get the number of "dofs" in the existing timestepper
141  this->Ndof_storage_entries = time_stepper_pt->ndof_storage_entries();
142  //Get the current amount of storage
143  unsigned n_tstorage = time_stepper_pt->ntstorage();
144 
145  //Find the offsets which is always relative to the number of dofs stored
146  //in the existing timestepper
147  Dof_derivative_offset = n_tstorage;
148  Dof_current_offset = n_tstorage + this->Ndof_storage_entries;
149 
150  //Set the new amount of storage twice the dofs to store parameter derivatives
151  //and initial values plus the original storage
152  unsigned n_new_tstorage = 2*this->Ndof_storage_entries + n_tstorage;
153 
154  //Resize the weights accordingly
155  Weight.resize(3,n_new_tstorage,0.0);
156  //Set the weight for the zero-th derivative which is always 1.0
157  Weight(0,0) = 1.0;
158  }
159 
160 
161  /// Broken assignment operator
163  {
164  BrokenCopy::broken_assign("ContinuationStorageScheme");
165  }
166 
167  ///Return the actual order of the scheme. It's a steady
168  ///scheme so it's zero, but that doesn't really make sense.
169  unsigned order() const {return 0;}
170 
171  /// \short This is a steady scheme, so you can't do this
173 
174  /// \short Broken initialisation the time-history for the Data values
175  /// corresponding to an impulsive start.
176  void assign_initial_values_impulsive(Data* const &data_pt)
177  {
179  "Cannot perform impulsive start for ContinuationStorageScheme",
180  OOMPH_CURRENT_FUNCTION,
181  OOMPH_EXCEPTION_LOCATION);
182  }
183 
184  /// \short Broken initialisation of
185  /// the positions for the node corresponding to an impulsive start
187  {
189  "Cannot perform impulsive start for ContinuationStorageScheme",
190  OOMPH_CURRENT_FUNCTION,
191  OOMPH_EXCEPTION_LOCATION);
192  }
193 
194  /// Broken shifting of time values
195  void shift_time_values(Data* const &data_pt)
196  {
197  throw OomphLibError(
198  "Cannot shift time values forContinuationStorageScheme",
199  OOMPH_CURRENT_FUNCTION,
200  OOMPH_EXCEPTION_LOCATION);
201  }
202 
203  /// Broken shifting of time positions
204  void shift_time_positions(Node* const &node_pt)
205  {
206  throw OomphLibError(
207  "Cannot shift time positions forContinuationStorageScheme",
208  OOMPH_CURRENT_FUNCTION,
209  OOMPH_EXCEPTION_LOCATION);
210  }
211 
212  /// Set the weights (Do nothing)
213  void set_weights() {}
214 
215  /// Number of previous values available.
216  unsigned nprev_values() const{return 0;}
217 
218  /// Number of timestep increments that need to be stored by the scheme
219  unsigned ndt() const {return 0;}
220 
221  /// \short Set consistent values of the derivatives and current value when the
222  /// data is pinned. This must be done by the "timestepper" because only it
223  /// knows the local storage scheme
224  void set_consistent_pinned_values(Data* const &data_pt)
225  {
226 #ifdef PARANOID
227  //If the data is not associated with the continuation time stepper then
228  //complain
229  if(this != data_pt->time_stepper_pt())
230  {
231  std::ostringstream error_stream;
232  error_stream << "Data object " << data_pt << " has timestepper of type "
233  << typeid(data_pt->time_stepper_pt()).name()
234  << "\n"
235  << "Please set the data's timestepper to be a "
236  << "ContinuationStorageScheme before calling this function\n";
237  throw OomphLibError(error_stream.str(),
238  OOMPH_CURRENT_FUNCTION,
239  OOMPH_EXCEPTION_LOCATION);
240  }
241 #endif
242 
243  //Loop over the values in the data object
244  const unsigned n_value = data_pt->nvalue();
245  for(unsigned i=0;i<n_value;++i)
246  {
247  //Only bother to do anything if the value is pinned and not a copy
248  if(data_pt->is_pinned(i) && (data_pt->is_a_copy(i) == false))
249  {
250  //ASSUMPTION storage is always at the "front"
251  for(unsigned t=0;t<this->Ndof_storage_entries;t++)
252  {
253  //Set the stored derivatve to be zero
254  data_pt->set_value(Dof_derivative_offset+t,i,0.0);
255  //Set the stored current value to be the same as the present value
256  data_pt->set_value(Dof_current_offset+t,i,data_pt->value(t,i));
257  }
258  }
259  }
260  }
261 
262  /// \short Set consistent values of the derivatives and current value when the
263  /// Nodes position is pinned.
264  /// This must be done by the "timestepper" because only it
265  /// knows the local storage scheme
266  void set_consistent_pinned_positions(Node* const &node_pt)
267  {
268  //Only need to do anything if this is a solid node
269  if(SolidNode* const solid_node_pt = dynamic_cast<SolidNode*>(node_pt))
270  {
271 #ifdef PARANOID
272  //If the data is not associated with the continuation time stepper then
273  //complain
274  if(this != node_pt->position_time_stepper_pt())
275  {
276  std::ostringstream error_stream;
277  error_stream << "Node object " << node_pt
278  << " has position timestepper of type "
279  << typeid(node_pt->position_time_stepper_pt()).name()
280  << "\n"
281  << "Please set the Node's position timestepper to be a "
282  << "ContinuationStorageScheme before calling this function\n";
283  throw OomphLibError(error_stream.str(),
284  OOMPH_CURRENT_FUNCTION,
285  OOMPH_EXCEPTION_LOCATION);
286  }
287 #endif
288 
289  //Find the number of coordinates
290  const unsigned n_dim = solid_node_pt->ndim();
291  //Find the number of position types
292  const unsigned n_position_type = solid_node_pt->nposition_type();
293 
294  //Loop over physical coordinates
295  for(unsigned i=0;i<n_dim;i++)
296  {
297  //Set the appropriate values if it's not a copy
298  if(solid_node_pt->position_is_a_copy(i) == false)
299  {
300  //Loop over generalised dofs
301  for(unsigned k=0;k<n_position_type;k++)
302  {
303  //If it's pinned then set the "history" values
304  if(solid_node_pt->position_is_pinned(k,i))
305  {
306  for(unsigned t=0;t<Ndof_storage_entries;t++)
307  {
308  //Set the derivative to 0
309  solid_node_pt->x_gen(Dof_derivative_offset+t,k,i) = 0.0;
310  //Set the stored current value to the present value
311  solid_node_pt->x_gen(Dof_current_offset+t,k,i) =
312  solid_node_pt->x_gen(t,k,i);
313  }
314  }
315  }
316  }
317  }
318  }
319  }
320 
321  //Return the stored derivative offset
323 
324  //Return the offset for the current values
326 
327 };
328 
329 }
330 
331 #endif
Generalised timestepper that can serve a variety of purposes in continuation, bifurcation detection a...
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
bool is_pinned(const unsigned &i) const
Test whether the i-th variable is pinned (1: true; 0: false).
Definition: nodes.h:403
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
void undo_make_steady()
This is a steady scheme, so you can't do this.
void modify_storage(GeneralisedTimeStepper *const &time_stepper_pt)
Modify the scheme based on the underlying timestepper.
char t
Definition: cfortran.h:572
TimeStepper *& position_time_stepper_pt()
Return a pointer to the position timestepper.
Definition: nodes.h:969
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
unsigned ndt() const
Number of timestep increments that need to be stored by the scheme.
void shift_time_values(Data *const &data_pt)
Broken shifting of time values.
unsigned ntstorage() const
Return the number of doubles required to represent history (one for steady)
Definition: timesteppers.h:562
void set_weights()
Set the weights (Do nothing)
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:448
bool Is_steady
Bool to indicate if the timestepper is steady, i.e. its time-derivatives evaluate to zero...
Definition: timesteppers.h:241
void set_consistent_pinned_positions(Node *const &node_pt)
Set consistent values of the derivatives and current value when the Nodes position is pinned...
DenseMatrix< double > Weight
Storage for the weights associated with the timestepper.
Definition: timesteppers.h:227
ContinuationStorageScheme(const ContinuationStorageScheme &)
Broken copy constructor.
void shift_time_positions(Node *const &node_pt)
Broken shifting of time positions.
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
void assign_initial_values_impulsive(Data *const &data_pt)
Broken initialisation the time-history for the Data values corresponding to an impulsive start...
void operator=(const ContinuationStorageScheme &)
Broken assignment operator.
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
unsigned ndof_storage_entries() const
Return the number of entries that correspond to dof storage.
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
void assign_initial_positions_impulsive(Node *const &node_pt)
Broken initialisation of the positions for the node corresponding to an impulsive start...
GeneralisedTimestepper used to store the arclength derivatives and pervious solutions required in con...
A Class for nodes that deform elastically (i.e. position is an unknown in the problem). The idea is that the Eulerian positions are stored in a Data object and the Lagrangian coordinates are stored in addition. The pointer that addresses the Eulerian positions is set to the pointer to Value in the Data object. Hence, SolidNode uses knowledge of the internal structure of Data and must be a friend of the Data class. In order to allow a mesh to deform via an elastic-style equation in deforming-domain problems, the positions are stored separately from the values, so that elastic problems may be combined with any other type of problem.
Definition: nodes.h:1568
GeneralisedTimeStepper(const GeneralisedTimeStepper &)
Broken copy constructor.
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:246
void set_consistent_pinned_values(Data *const &data_pt)
Set consistent values of the derivatives and current value when the data is pinned. This must be done by the "timestepper" because only it knows the local storage scheme.
unsigned nprev_values() const
Number of previous values available.
void operator=(const GeneralisedTimeStepper &)
Broken assignment operator.
GeneralisedTimeStepper()
Broken empty constructor.
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
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
Definition: timesteppers.h:219
GeneralisedTimeStepper(const unsigned &n_tstorage, const unsigned &max_deriv, const unsigned &ndof_storage_entries=1)
void resize(const unsigned long &n)
Definition: matrices.h:511