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-2025 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
37namespace 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 {
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
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(
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 {
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
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(
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 {
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
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 =
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 {
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.
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.
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
FaceGeometry class definition: This policy class is used to allow construction of face elements that ...
Definition elements.h:5002
A general Finite Element class.
Definition elements.h:1317
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....
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.
const double & residual_multiplier() const
Return the value of the residual multiplier.
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_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(FiniteElement *const &element_pt, const int &face_index)
Constructor used for hijacking face elements.
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_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...
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()
Constructor, call the constructors of the base 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...
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.
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
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
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).