hijacked_elements.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 //Header file for hijacked elements
31 
32 //Include guards to prevent multiple inclusion of the header
33 #ifndef OOMPH_HIJACKED_ELEMENTS_HEADER
34 #define OOMPH_HIJACKED_ELEMENTS_HEADER
35 
36 
37 //oomph-lib header
38 #include "elements.h"
39 #include "spines.h"
40 
41 namespace oomph
42 {
43 
44 //========================================================================
45 /// HijackedElement base class that provides storage and access funcitons
46 /// for pointers to the global equation numbers that are hijacked by
47 /// the HijackedElement. A default residuals multiplier is also provided.
48 //========================================================================
50 {
51  public:
52 
53  /// \short Constructor, initialise the pointer to the equation numbers
54  /// for the storage to zero
57  {
58  //Set the default value of the pointer to the residuals multiplier.
59  //The default value is zero, so that the element is "completely hijacked"
60  //and the exisiting contributions to the residuals and jacobian are
61  //totally wiped
63  }
64 
65  /// Destructor, destroy the storage for the equation numbers
66  virtual ~HijackedElementBase();
67 
68  /// \short Reset the hijacked data pt, so that none of the equations in the
69  /// element are hijacked.
71 
72  /// Return the value of the residual multiplier
73  inline const double &residual_multiplier() const
74  {return *Residual_multiplier_pt;}
75 
76  /// Return the pointer to the residual multiplier
77  inline double* &residual_multiplier_pt() {return Residual_multiplier_pt;}
78 
79  protected:
80 
81  /// Pointer to a Set of pointers to the equation numbers that will be
82  /// hijacked by this element. Note that these MUST be pointers because
83  /// hijacking information is set BEFORE global equation numbers have
84  /// been assigned.
86 
87  /// \short Pointer to a vector of integers
88  /// containing the local equation numbers of
89  /// any hijacked variables in the element.
91 
92  /// \short Pointer to a double that multiplies the contribution to
93  /// the residuals from the original element.
94  /// This is usually used as a homotopy parameter to permit a smooth
95  /// transition between different types of boundary conditions, rather than
96  /// switching them on or off abruptly
98 
99  /// Static default value for the double that multiplies the original residuals
101 
102  /// \short Mark the global equation, addressed by global_eqn_pt,
103  /// as hijacked by this element.
104  void hijack_global_eqn(long* const &global_eqn_pt);
105 
106  /// \short The global equation, addressed by global_eqn_pt,
107  /// is no longer hijacked by this element.
108  void unhijack_global_eqn(long* const &global_eqn_pt);
109 
110 };
111 
112 
113 //========================================================================
114 /// \short Hijacked elements are elements in which one or more
115 /// Data values that affect the element's residuals, are determined
116 /// by another element -- the data values are then said to have
117 /// been hijacked by another element. The main functionality
118 /// added by the Hijacked element class is that it wipes out
119 /// those entries in the element's residual vector and those rows in
120 /// the element's Jacobian matrix that are determined by the "other"
121 /// elements that have hijacked the values. Note that for continuation
122 /// in homotopy parameters, it may be desriable to multiply the residuals
123 /// and corresponding jacobian entries by a "homotopy parameter". The
124 /// value of this parameter can be set by assigning residual_multiplier_pt()
125 /// which has a default value of zero. Note: it would be possible to extend
126 /// the functionality so that different residuals are multiplied by
127 /// different values, but will this ever be required?
128 //========================================================================
129 template<class ELEMENT>
130 class Hijacked : public virtual ELEMENT, public virtual HijackedElementBase
131 {
132 
133 public:
134 
135  /// Constructor, call the constructors of the base elements
136  Hijacked() : ELEMENT(), HijackedElementBase() {}
137 
138  /// Constructor used for hijacking face elements
139  Hijacked(FiniteElement* const &element_pt, const int &face_index) :
140  ELEMENT(element_pt, face_index),
142 
143 
144  /// \short Constructor used for hijacking face elements with specification of
145  /// ID of additional variables
146  Hijacked(FiniteElement* const &element_pt,
147  const int &face_index,
148  const unsigned &id=0) :
149  ELEMENT(element_pt, face_index,id),
151 
152 
153  /// \short Hijack the i-th value stored at internal data n.
154  /// Return a custom-made (copied) data object that contains only
155  /// the hijacked value. This can be used as the input to other elements.
156  /// Note that the calling program assumes responsibility for this
157  /// data object and must clean it up.
158  Data *hijack_internal_value(const unsigned &n, const unsigned &i)
159  {
160  //Create a new Data object containing only the value that is to be hijacked
161  Data* temp_data_pt = new HijackedData(i,this->internal_data_pt(n));
162 
163  //Mark the value as hijacked
164  hijack_global_eqn(this->internal_data_pt(n)->eqn_number_pt(i));
165 
166  //Return the pointer to the data
167  return temp_data_pt;
168  }
169 
170 
171  /// \short Hijack the i-th value stored at external data n.
172  /// Return a custom-made (copied) data object that contains only
173  /// the hijacked value. Note that the calling program assumes
174  /// responsibility for this data object and must clean it up
175  Data *hijack_external_value(const unsigned &n, const unsigned &i)
176  {
177  //Create a new Data object containing only the value that is to be hijacked
178  Data* temp_data_pt = new HijackedData(i,this->external_data_pt(n));
179 
180  //Mark the value as hijacked
181  hijack_global_eqn(this->external_data_pt(n)->eqn_number_pt(i));
182 
183  //Return the pointer to the data
184  return temp_data_pt;
185  }
186 
187  /// \short Hijack the i-th value stored at node n.
188  /// Return a custom-made (copied) data object that contains only
189  /// the hijacked value. Once again, the calling program must
190  /// clean up the allocated Data object.
191  Data* hijack_nodal_value(const unsigned &n, const unsigned &i)
192  {
193  //Create a new Data object containing only the value that is to be hijacked
194  Data* temp_data_pt = new HijackedData(i,this->node_pt(n));
195 
196  //Mark the value as hijacked
197  hijack_global_eqn(this->node_pt(n)->eqn_number_pt(i));
198 
199  //Return the pointer to the data
200  return temp_data_pt;
201  }
202 
203  /// \short Hijack the i-th positional value stored at node n.
204  /// Return a custom-made (copied) data object that contains only
205  /// the hijacked value. Again, responsibility for the memory allocated
206  /// lies with the calling function.
207  Data* hijack_nodal_position_value(const unsigned &n,
208  const unsigned &i)
209  {
210  //Can we do the casting?
211  SolidNode* solid_node_pt = dynamic_cast<SolidNode*>(this->node_pt(n));
212  if(solid_node_pt == 0)
213  {
214  std::string error_message = "Failed to cast to SolidNode\n ";
215  error_message +=
216  "You may be trying to hijack a non-elastic element\n";
217 
218  throw OomphLibError(error_message,
219  OOMPH_CURRENT_FUNCTION,
220  OOMPH_EXCEPTION_LOCATION);
221  }
222 
223  //Create a new Data object containing only the value that is to be hijacked
224  Data* temp_data_pt =
225  new HijackedData(i,solid_node_pt->variable_position_pt());
226 
227  //Mark the value as hijacked
229 
230  //Return the pointer to the data
231  return temp_data_pt;
232  }
233 
234  /// \short Hijack the i-th value stored at the spine that affects
235  /// local node n.
236  /// Return a custom-made (copied) data object that contains only
237  /// the hijacked value. Deletion must be handled at the higher level
238  Data* hijack_nodal_spine_value(const unsigned &n, const unsigned &i)
239  {
240  //Can we actually do this casting
241  SpineNode* spine_node_pt = dynamic_cast<SpineNode*>(this->node_pt(n));
242  if(spine_node_pt == 0)
243  {
244  std::string error_message = "Failed to cast to SpineNode\n ";
245  error_message +=
246  "You may be trying to hijack a non-spine element\n";
247 
248  throw OomphLibError(error_message,
249  OOMPH_CURRENT_FUNCTION,
250  OOMPH_EXCEPTION_LOCATION);
251  }
252 
253  //Create a new Data object containing only the value that is to be hijacked
254  Data* temp_data_pt = new HijackedData(i,spine_node_pt->
255  spine_pt()->spine_height_pt());
256 
257  //Mark the data as hijacked
258  hijack_global_eqn(spine_node_pt->spine_pt()->
259  spine_height_pt()->eqn_number_pt(i));
260 
261  //Return the pointer to the data
262  return temp_data_pt;
263  }
264 
265 
266  /// \short Set up the local equation numbers for the underlying element,
267  /// then set up the local arrays to hold the hijacked variables.
268  /// If the boolean argument is true then pointers to the associated degrees
269  /// of freedom are stored in the array Dof_pt
270  void assign_local_eqn_numbers(const bool &store_local_dof_pt)
271  {
272  //If things have already been allocated,
273  //clear the local hijacked array, so that if the equation numbers
274  //are reassigned after changes in the boundary conditions, the
275  //correct terms will be in the array.
277  {Hijacked_local_eqn_number_pt->clear();}
278  //Otherwise allocate it
279  else
281 
282 
283  //Call the hijacked element's assign_local_eqn_numbers
284  ELEMENT::assign_local_eqn_numbers(store_local_dof_pt);
285 
286  //If any values have been hijacked, we need to find the corresponding
287  //local equation numbers
289  {
290  //Now loop over the local array that stores GLOBAL equation numbers
291  //to check if any of the local values have in fact been hijacked
292  // by "somebody"
293  unsigned n_dof = this->ndof();
294  for(unsigned i=0;i<n_dof;i++)
295  {
296  //Loop over *all* hijacked data
297  for(std::set<long*>::iterator it=Hijacked_global_eqn_number_pt->begin();
298  it!=Hijacked_global_eqn_number_pt->end();++it)
299  {
300 
301  //If the hijacked (global!) equation is not pinned
302  if(*(*it) >= 0)
303  {
304  //Get the (unsigned) global equation number:
305  //Note that it is only unsigned AFTER the test above.
306  unsigned long hijacked_eqn_number= *(*it);
307 
308  //If a GLOBAL variable used by this element is hijacked add the
309  //variable's LOCAL index to the array
310  if(hijacked_eqn_number == this->eqn_number(i))
311  {
312  Hijacked_local_eqn_number_pt->push_back(i);
313  break;
314  }
315  }
316  }
317  }
318  }
319  }
320 
321  /// \short Get the residuals from the underlying element, but then wipe the
322  /// entries in the residual vector that correspond to hijacked
323  /// values -- they will be computed by other elements.
324  void get_residuals(Vector<double> &residuals)
325  {
326  //Get parent redisuals
327  ELEMENT::get_residuals(residuals);
328  //Multiply any hijacked dofs by the residual multiplier
329  //(default value is zero)
330  unsigned n_hijacked = Hijacked_local_eqn_number_pt->size();
331  for(unsigned i=0;i<n_hijacked;i++)
332  {
333  residuals[(*Hijacked_local_eqn_number_pt)[i]] *= residual_multiplier();
334  }
335  }
336 
337 
338  /// \short Get the residuals and Jacobian matrix from the underlying
339  /// element, but then wipe the entries in the residual vector and the
340  /// rows in the Jacobian matrix that correspond to hijacked
341  /// values -- they will be computed by other elements.
342  void get_jacobian(Vector<double> &residuals,
343  DenseMatrix<double> &jacobian)
344  {
345  //Call the element's get jacobian function
346  ELEMENT::get_jacobian(residuals,jacobian);
347  //Wipe any hijacked dofs
348  unsigned n_hijacked = Hijacked_local_eqn_number_pt->size();
349  unsigned n_dof = this->ndof();
350  for(unsigned i=0;i<n_hijacked;i++)
351  {
352  //Multiply any hijacked dofs by the residual multiplier
353  //(default value is zero)
354  residuals[(*Hijacked_local_eqn_number_pt)[i]] *= residual_multiplier();
355  //Multiply the row in the Jacobian matrix by the residual
356  //multiplier for consistency
357  for(unsigned j=0;j<n_dof;j++)
358  {
359  jacobian((*Hijacked_local_eqn_number_pt)[i],j) *= residual_multiplier();
360  }
361  }
362  }
363 
364 
365 };
366 
367 
368 
369 //============================================================================
370 ///\short Explicit definition of the face geometry of hijacked elements:
371 ///the same as the face geometry of the underlying element
372 //============================================================================
373 template<class ELEMENT>
374 class FaceGeometry<Hijacked<ELEMENT> >:
375 public virtual FaceGeometry<ELEMENT>
376 {
377  public:
378 
379  /// Constructor
380  FaceGeometry() : FaceGeometry<ELEMENT>() {}
381 
382  protected:
383 };
384 
385 //============================================================================
386 ///\short Explicit definition of the face geometry of hijacked elements:
387 ///the same as the face geometry of the underlying element
388 //============================================================================
389 template<class ELEMENT>
390 class FaceGeometry<FaceGeometry<Hijacked<ELEMENT> > >:
391 public virtual FaceGeometry<FaceGeometry<ELEMENT> >
392 {
393  public:
394 
395  /// Constructor
397 
398  protected:
399 };
400 
401 //============================================================================
402 ///\short Explicit definition of the face geometry of hijacked elements:
403 ///the same as the face geometry of the underlying element
404 //============================================================================
405 template<class ELEMENT>
406 class FaceGeometry<Hijacked<FaceGeometry<ELEMENT> > >:
407 public virtual FaceGeometry<FaceGeometry<ELEMENT> >
408 {
409  public:
410 
411  /// Constructor
413 
414  protected:
415 };
416 
417 
418 }
419 
420 #endif
Hijacked()
Constructor, call the constructors of the base elements.
Data * hijack_nodal_value(const unsigned &n, const unsigned &i)
Hijack the i-th value stored at node n. Return a custom-made (copied) data object that contains only ...
void hijack_global_eqn(long *const &global_eqn_pt)
Mark the global equation, addressed by global_eqn_pt, as hijacked by this element.
long * eqn_number_pt(const unsigned &i)
Return the pointer to the equation number of the i-th stored variable.
Definition: nodes.h:356
cstr elem_len * i
Definition: cfortran.h:607
double * Residual_multiplier_pt
Pointer to a double that multiplies the contribution to the residuals from the original element...
A general Finite Element class.
Definition: elements.h:1271
Custom Data class that is used when HijackingData. The class always contains a single value that is c...
Definition: nodes.h:530
Vector< int > * Hijacked_local_eqn_number_pt
Pointer to a vector of integers containing the local equation numbers of any hijacked variables in th...
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
Definition: nodes.h:1654
double *& residual_multiplier_pt()
Return the pointer to the residual multiplier.
const double & residual_multiplier() const
Return the value of the residual multiplier.
Data * hijack_external_value(const unsigned &n, const unsigned &i)
Hijack the i-th value stored at external data n. Return a custom-made (copied) data object that conta...
Data * hijack_internal_value(const unsigned &n, const unsigned &i)
Hijack the i-th value stored at internal data n. Return a custom-made (copied) data object that conta...
static double Default_residual_multiplier
Static default value for the double that multiplies the original residuals.
void assign_local_eqn_numbers(const bool &store_local_dof_pt)
Set up the local equation numbers for the underlying element, then set up the local arrays to hold th...
virtual ~HijackedElementBase()
Destructor, destroy the storage for the equation numbers.
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
Hijacked(FiniteElement *const &element_pt, const int &face_index, const unsigned &id=0)
Constructor used for hijacking face elements with specification of ID of additional variables...
Hijacked(FiniteElement *const &element_pt, const int &face_index)
Constructor used for hijacking face elements.
void get_residuals(Vector< double > &residuals)
Get the residuals from the underlying element, but then wipe the entries in the residual vector that ...
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
Data * hijack_nodal_position_value(const unsigned &n, const unsigned &i)
Hijack the i-th positional value stored at node n. Return a custom-made (copied) data object that con...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
Hijacked elements are elements in which one or more Data values that affect the element's residuals...
void unhijack_global_eqn(long *const &global_eqn_pt)
The global equation, addressed by global_eqn_pt, is no longer hijacked by this element.
Spine *& spine_pt()
Access function to spine.
Definition: spines.h:347
std::set< long * > * Hijacked_global_eqn_number_pt
void unhijack_all_data()
Reset the hijacked data pt, so that none of the equations in the element are hijacked.
void get_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Get the residuals and Jacobian matrix from the underlying element, but then wipe the entries in the r...
HijackedElementBase()
Constructor, initialise the pointer to the equation numbers for the storage to zero.
Data * hijack_nodal_spine_value(const unsigned &n, const unsigned &i)
Hijack the i-th value stored at the spine that affects local node n. Return a custom-made (copied) da...