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