nodes.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// This header contains class and function prototypes for Data, Node
27// and associated objects
28
29// Include guard to prevent multiple inclusions of the header
30#ifndef OOMPH_NODES_HEADER
31#define OOMPH_NODES_HEADER
32
33// Config header generated by autoconfig
34#ifdef HAVE_CONFIG_H
35#include <oomph-lib-config.h>
36#endif
37
38#ifdef OOMPH_HAS_MPI
39#include "mpi.h"
40#endif
41
42// C++ headers
43#include <map>
44#include <set>
45#include <climits>
46#include <string>
47
48// oomph-lib headers
49#include "Vector.h"
50#include "matrices.h"
51#include "oomph_utilities.h"
52
53namespace oomph
54{
55 // The following classes are used in the Data class,
56 // so we provide forward references here
57 class TimeStepper;
58 class SolidNode;
59 class HijackedData;
60 class CopiedData;
61 class BoundaryNodeBase;
62 template<class NODE_TYPE>
63 class BoundaryNode;
64
65 //=====================================================================
66 /// A class that represents a collection of data;
67 /// each Data object may contain many different individual values,
68 /// as would be natural in non-scalar problems.
69 /// Data provides storage for auxiliary `history' values that are
70 /// used by TimeStepper objects to calculate the time derivatives of the
71 /// stored data and also stores a pointer to the appropriate TimeStepper
72 /// object.
73 /// In addition, an associated (global) equation number is
74 /// stored for each value.
75 ///
76 /// The Data class permits copies of the stored data values and equation
77 /// numbers into another Data object using the copy() function.
78 /// Shallow (pointer based) copies of
79 /// the values can be obtained by using specific derived classes. In such
80 /// cases pointers to the objects that contain the pointer-based copies
81 /// should be stored in the original Data class
82 /// (in the array Copy_of_data_pt)
83 /// so that resize and destruction operations can be performed safely.
84 //=====================================================================
85 class Data
86 {
87 private:
88 // We wish certain classes to have access to the internal data
89 // storage model so that the pointers to the values and equations can be
90 // used for efficiency reasons. In particular, any derived classes
91 // that contains shallow copies of Data values
92 //(BoundaryNodeBase, CopiedData and HijackedData) must have pointer-access.
93 friend class HijackedData;
94 friend class CopiedData;
95 friend class BoundaryNodeBase;
96 template<class NODE_TYPE>
97 friend class BoundaryNode;
98
99 // SolidNodes use their knowledge of
100 // the internal storage of the data values to efficiently implement
101 // the use of positions as variables for solid mechanics problems.
102 friend class SolidNode;
103
104 /// C-style array of pointers to data values and
105 /// possible history values. The data must be ordered in such a way
106 /// that Value[i][t] gives the i-th data value at the time value t.
107 /// The ordering is chosen so that all the time levels of a particular
108 /// value can be access from a single pointer to a double. This is
109 /// required for copying/hijacking functionality.
110 /// The data should be accessed by using the member functions
111 /// value(time,ival) and set_value(time,ival,value), where time=0: present.
112 double** Value;
113
114 /// C-style array of pointers to the (global) equation numbers
115 /// of the values.
117
118 /// Pointer to a Timestepper.
119 /// The inclusion of a Timestepper pointer in the Data class, ensures that
120 /// time-derivatives can be calculated and storage can be managed at the
121 /// low (Data) level.
123
124 protected:
125 /// C-style array of any Data objects that contain copies
126 /// of the current Data object's data values.
128
129 /// Number of Data that contain copies of this Data object's
130 /// values
131 unsigned Ncopies;
132
133 private:
134 /// Number of values stored in the data object.
135 unsigned Nvalue;
136
137#ifdef OOMPH_HAS_MPI
138
139 /// Non-halo processor ID for Data; -1 if it's not a halo.
141
142#endif
143
144 /// Check that the arguments are within
145 /// the range of the stored data values and timesteps.
146 void range_check(const unsigned& t, const unsigned& i) const;
147
148 /// Delete all storage allocated by the Data object for values
149 /// and equation numbers.
151
152 /// Add the pointer data_pt to the array Copy_of_data_pt.
153 /// This should be used whenever copies are made of the data.
154 void add_copy(Data* const& data_pt);
155
156 /// Remove the pointer data_pt from the array Copy_of_data_pt.
157 /// This should be used whenever copies of the data are deleted.
158 void remove_copy(Data* const& data_pt);
159
160 protected:
161 /// Default (static) timestepper used in steady problems.
163
164 /// Helper function that should be overloaded in derived classes
165 /// that can contain copies of Data. The function must
166 /// reset the internal pointers to the copied data. This is used
167 /// when resizing data to ensure that all the pointers remain valid.
168 /// The default implementation throws an error beacause Data cannot be
169 /// a copy.
170 virtual void reset_copied_pointers();
171
172 public:
173 /// Helper function that should be overloaded derived classes
174 /// that contain copies of data. The function must
175 /// unset (NULL out) the internal pointers to the copied data.
176 /// This is used when destructing data to ensure that all pointers remain
177 /// valid. The default implementation throws an error because Data cannot
178 /// be a copy.
179 virtual void clear_copied_pointers();
180
181 /// Static "Magic number" used in place of the equation number to
182 /// indicate that the value is pinned.
183 static long Is_pinned;
184
185 /// Static "Magic number" used in place of the equation number to
186 /// indicate that the value is pinned, but only for the duration of a
187 /// segregated solve.
189
190 /// Static "Magic number" used in place of the equation number to
191 /// denote a value that hasn't been classified as pinned or free.
192 static long Is_unclassified;
193
194 /// Static "Magic number" used in place of the equation number to
195 /// indicate that the value is constrained because it is associated
196 /// with non-conforming element boundaries --- a hanging node ---
197 /// (and is therefore pinned)
198 static long Is_constrained;
199
200 /// Default: Just set pointer to (steady) timestepper.
201 /// No storage for values is allocated.
202 Data();
203
204 /// Default constructor for steady problems:
205 /// assign memory for initial_n_value values.
206 Data(const unsigned& initial_n_value);
207
208 /// Constructor for unsteady problems: assign memory for
209 /// initial_n_value values and any memory required by the Timestepper for
210 /// the storage of history values.
211 // ALH: Note the "awkward" C++ syntax for passing a constant reference to
212 // a pointer. N.B. We cannot change the pointer, but we can change
213 // what it points to. We could use a const pointer, to prevent change of the
214 // object, but that brings in a whole additional layer of complexity.
216 const unsigned& initial_n_value,
217 const bool& allocate_storage = true);
218
219 /// Broken copy constructor.
220 Data(const Data& data) = delete;
221
222 /// Broken assignment operator.
223 void operator=(const Data&) = delete;
224
225 /// Output operator: output all values at all times, along with any extra
226 /// information stored for the timestepper.
227 friend std::ostream& operator<<(std::ostream& out, const Data& d);
228
229 /// Destructor, deallocates memory assigned for data.
230 virtual ~Data();
231
232 /// Set a new timestepper by resizing the appropriate storage.
233 /// If already assigned the equation numbering will not be altered
235 const bool& preserve_existing_data);
236
237 /// Return the pointer to the timestepper.
239 {
240 return Time_stepper_pt;
241 }
242
243 /// Return the pointer to the timestepper (const version).
245 {
246 return Time_stepper_pt;
247 }
248
249 /// Return a boolean to indicate whether
250 /// the Data objact contains any copied values.
251 /// A base Data object can never be a copy so the default implementation
252 /// always returns false.
253 virtual bool is_a_copy() const
254 {
255 return false;
256 }
257
258 /// Return flag to indicate whether the i-th value is a copy.
259 /// A base Data object can never be a copy so the default implementation
260 /// always returns false.
261 virtual bool is_a_copy(const unsigned& i) const
262 {
263 return false;
264 }
265
266 /// Set the i-th stored data value to specified value.
267 /// The only reason that we require an explicit set function is
268 /// because we redefine value() in the Node class to interpolate
269 /// the values for nodes that are hanging and so we cannot
270 /// return a reference to the value in this case.
271 void set_value(const unsigned& i, const double& value_)
272 {
273#ifdef RANGE_CHECKING
274 range_check(0, i);
275#endif
276 Value[i][0] = value_;
277 }
278
279 /// Set the t-th history value of the i-th stored data value to
280 /// specified value.
281 void set_value(const unsigned& t, const unsigned& i, const double& value_)
282 {
283#ifdef RANGE_CHECKING
284 range_check(t, i);
285#endif
286 Value[i][t] = value_;
287 }
288
289 /// Return i-th stored value.
290 /// This function is not virtual so that it can be inlined.
291 /// This means that if we have an explicit pointer to a Data object
292 /// Data* data_pt->value() always returns the "raw" stored value.
293 double value(const unsigned& i) const
294 {
295#ifdef RANGE_CHECKING
296 range_check(0, i);
297#endif
298 return Value[i][0];
299 }
300
301 /// Return i-th value at time level t (t=0: present, t>0: previous)
302 /// This function is not virtual so that it can be inlined.
303 /// This means that if we have an explicit pointer to a Data object
304 /// Data* data_pt->value() always returns to the "raw" stored value.
305 double value(const unsigned& t, const unsigned& i) const
306 {
307#ifdef RANGE_CHECKING
308 range_check(t, i);
309#endif
310 return Value[i][t];
311 }
312
313 /// Compute Vector of values for the Data value.
314 void value(Vector<double>& values) const;
315
316 /// Compute Vector of values (dofs or pinned) in this data
317 /// at time level t (t=0: present; t>0: previous).
318 void value(const unsigned& t, Vector<double>& values) const;
319
320 /// Return the pointer to the i-the stored value.
321 /// Typically this is required when direct access
322 /// to the stored value is required, e.g. when writing functions that
323 /// return a reference to a variable that is stored in a Data object.
324 double* value_pt(const unsigned& i) const
325 {
326#ifdef RANGE_CHECKING
327 range_check(0, i);
328#endif
329 return Value[i];
330 }
331
332 /// Return the pointer to the i-th stored value,
333 /// or any of its history values (const version).
334 /// Typically this is required when direct access
335 /// to the stored value is required, e.g. when writing functions that
336 /// return a reference to a variable that is stored in a Data object.
337 double* value_pt(const unsigned& t, const unsigned& i) const
338 {
339#ifdef RANGE_CHECKING
340 range_check(t, i);
341#endif
342 return &Value[i][t];
343 }
344
345 /// Check whether the pointer parameter_pt addresses internal data values
346 bool does_pointer_correspond_to_value(double* const& parameter_pt);
347
348 /// Copy Data values from specified Data object
349 void copy(Data* orig_data_pt);
350
351 /// Dump the data object to a file.
352 void dump(std::ostream& dump_file) const;
353
354 /// Read data object from a file.
355 void read(std::ifstream& restart_file);
356
357 /// Return the pointer to the equation number of the i-th stored variable.
358 long* eqn_number_pt(const unsigned& i)
359 {
360#ifdef RANGE_CHECKING
361 range_check(0, i);
362#endif
363 return &Eqn_number[i];
364 }
365
366 /// Return the equation number of the i-th stored variable.
367 inline long& eqn_number(const unsigned& i)
368 {
369#ifdef RANGE_CHECKING
370 range_check(0, i);
371#endif
372 return Eqn_number[i];
373 }
374
375 /// Return the equation number of the i-th stored variable.
376 inline long eqn_number(const unsigned& i) const
377 {
378#ifdef RANGE_CHECKING
379 range_check(0, i);
380#endif
381 return Eqn_number[i];
382 }
383
384 /// Pin the i-th stored variable.
385 inline void pin(const unsigned& i)
386 {
388 }
389
390 /// Unpin the i-th stored variable.
391 inline void unpin(const unsigned& i)
392 {
394 }
395
396 /// Pin all the stored variables
397 void pin_all()
398 {
399 const unsigned n_value = Nvalue;
400 for (unsigned i = 0; i < n_value; i++)
401 {
403 }
404 }
405
406 /// Unpin all the stored variables
408 {
409 const unsigned n_value = Nvalue;
410 for (unsigned i = 0; i < n_value; i++)
411 {
413 }
414 }
415
416 /// Test whether the i-th variable is pinned (1: true; 0: false).
417 bool is_pinned(const unsigned& i) const
418 {
419 return (Eqn_number[i] == Is_pinned);
420 }
421
422 /// Test whether the i-th variable is temporaily pinned for a
423 /// segregated solve.
424 bool is_segregated_solve_pinned(const unsigned& i)
425 {
427 }
428
429 /// Constrain the i-th stored variable when making hanging data
430 /// If the data is already pinned leave it along, otherwise mark as
431 /// constrained (hanging)
432 inline void constrain(const unsigned& i)
433 {
434 if (eqn_number(i) != Is_pinned)
435 {
437 }
438 }
439
440 /// Unconstrain the i-th stored variable when make the data
441 /// nonhanging. Only unconstrain if it was actually constrained (hanging)
442 inline void unconstrain(const unsigned& i)
443 {
445 {
447 }
448 }
449
450 /// Constrain all the stored variables when the data is made hanging
452 {
453 const unsigned n_value = Nvalue;
454 for (unsigned i = 0; i < n_value; i++)
455 {
456 constrain(i);
457 }
458 }
459
460 /// Unconstrain all the stored variables when the data is made nonhanging
462 {
463 const unsigned n_value = Nvalue;
464 for (unsigned i = 0; i < n_value; i++)
465 {
466 unconstrain(i);
467 }
468 }
469
470 /// Test whether the i-th variable is constrained (1: true; 0:
471 /// false).
472 bool is_constrained(const unsigned& i)
473 {
474 return (Eqn_number[i] == Is_constrained);
475 }
476
477
478 /// Self-test: Have all values been classified as pinned/unpinned?
479 /// Return 0 if OK.
480 unsigned self_test();
481
482 /// Return number of values stored in data object (incl pinned ones).
483 unsigned nvalue() const
484 {
485 return Nvalue;
486 }
487
488 /// Return total number of doubles stored per value
489 /// to record time history of each value (one for steady problems).
490 unsigned ntstorage() const;
491
492 /// Assign global equation numbers; increment global number
493 /// of unknowns, global_ndof; and add any new dofs to the dof_pt.
494 virtual void assign_eqn_numbers(unsigned long& global_ndof,
495 Vector<double*>& dof_pt);
496
497 /// Function to describe the dofs of the Node. The ostream
498 /// specifies the output stream to which the description
499 /// is written; the string stores the currently
500 /// assembled output that is ultimately written to the
501 /// output stream by Data::describe_dofs(...); it is typically
502 /// built up incrementally as we descend through the
503 /// call hierarchy of this function when called from
504 /// Problem::describe_dofs(...)
505 virtual void describe_dofs(std::ostream& out,
506 const std::string& current_string) const;
507
508 /// Change (increase) the number of values that may be stored.
509 virtual void resize(const unsigned& n_value);
510
511 /// Add pointers to all unpinned and unconstrained data to a map
512 /// indexed by (global) equation number
513 virtual void add_value_pt_to_map(
514 std::map<unsigned, double*>& map_of_value_pt);
515
516#ifdef OOMPH_HAS_MPI
517
518 /// Label the node as halo and specify processor that holds
519 /// non-halo counterpart
520 void set_halo(const unsigned& non_halo_proc_ID)
521 {
523 }
524
525 /// Label the node as not being a halo
527 {
528 Non_halo_proc_ID = -1;
529 }
530
531 /// Is this Data a halo?
532 bool is_halo() const
533 {
534 return (Non_halo_proc_ID != -1);
535 }
536
537 /// ID of processor ID that holds non-halo counterpart
538 /// of halo node; negative if not a halo.
540 {
541 return Non_halo_proc_ID;
542 }
543
544 /// Add all data and time history values to the vector in
545 /// the internal storage order
546 virtual void add_values_to_vector(Vector<double>& vector_of_values);
547
548 /// Read all data and time history values from the vector
549 /// starting from index. On return the index will be
550 /// set to the value at the end of the data that has been read in
551 virtual void read_values_from_vector(const Vector<double>& vector_of_values,
552 unsigned& index);
553
554
555 /// Add all equation numbers to the vector in
556 /// the internal storage order
557 virtual void add_eqn_numbers_to_vector(Vector<long>& vector_of_eqn_numbers);
558
559 /// Read all equation numbers from the vector
560 /// starting from index. On return the index will be
561 /// set to the value at the end of the data that has been read in
562 virtual void read_eqn_numbers_from_vector(
563 const Vector<long>& vector_of_eqn_numbers, unsigned& index);
564
565
566#endif
567 };
568
569 //=========================================================================
570 /// Custom Data class that is used when HijackingData.
571 /// The class always contains a single value that is
572 /// copied from another Data object.
573 //=========================================================================
574 class HijackedData : public Data
575 {
576 private:
577 /// Pointer to the Data object from which the value is copied
579
580 /// Index of the value that is copied from within the Data object
581 unsigned Copied_index;
582
583 /// Reset the pointers to the copied data.
585
586 public:
587 /// Clear the pointers to the copied data
589
590 /// Constructor
591 HijackedData(const unsigned& copied_value, Data* const& data_pt);
592
593 /// (Shallow) copy constructor
594 HijackedData(const Data& data) = delete;
595
596 /// Broken assignment operator
597 void operator=(const HijackedData&) = delete;
598
599 /// Destructor informs original object that the copy is
600 /// being deleted and clears its pointers to the stored values.
602 {
603 // Inform the Copied data that this copy is being deleted
604 // If the original has already been deleted
605 // Copied_data_pt will be set to NULL and this will not be
606 // necessary
607 if (Copied_data_pt)
608 {
610 }
611 // Now null out the storage
612 Copied_data_pt = 0;
613 Value = 0;
614 Eqn_number = 0;
615 }
616
617 /// Return a boolean to indicate whether the data contains
618 /// any copied values. Hijacked data is always a copy
619 bool is_a_copy() const
620 {
621 return true;
622 }
623
624 /// Return a boolean to indicate whether
625 /// the i-th value is a copied value.
626 /// Hijacked data is always a copy
627 bool is_a_copy(const unsigned& i) const
628 {
629 return true;
630 }
631
632 /// HijackedData is always a copy, so no equation numbers
633 /// should be allocated. This function just returns.
634 void assign_eqn_numbers(unsigned long& global_ndof, Vector<double*>& dof_pt)
635 {
636 return;
637 }
638
639
640 /// We cannot resize HijackedData, so the resize function
641 /// throws a warning.
642 void resize(const unsigned& n_value);
643 };
644
645
646 //=========================================================================
647 /// Custom Data class that is used when making a shallow copy
648 /// of a data object. The class contains a copy of an entire other
649 /// Data object.
650 //=========================================================================
651 class CopiedData : public Data
652 {
653 private:
654 /// Pointer to the Data object from which the values are copied
656
657 /// Reset the pointers to the copied data.
659
660 public:
661 /// Clear the pointers to the copied data
663
664 /// Constructor
665 CopiedData(Data* const& data_pt);
666
667 /// (Shallow) copy constructor
668 CopiedData(const Data& data) = delete;
669
670 /// Broken assignment operator
671 void operator=(const CopiedData&) = delete;
672
673 /// Destructor informs original object that the copy is
674 /// being deleted and clears its pointers to the stored values.
676 {
677 // Inform the Copied data that this copy is being deleted
678 // If the original has already been deleted
679 // Copied_data_pt will be set to NULL and this will not be
680 // necessary
681 if (Copied_data_pt)
682 {
684 }
685 // Now null out the storage
686 Copied_data_pt = 0;
687 Value = 0;
688 Eqn_number = 0;
689 }
690
691 /// Return a boolean to indicate whether the data contains
692 /// any copied values. Copied data is always a copy
693 bool is_a_copy() const
694 {
695 return true;
696 }
697
698 /// Return a boolean to indicate whether
699 /// the i-th value is a copied value.
700 /// All copied data is always a copy
701 bool is_a_copy(const unsigned& i) const
702 {
703 return true;
704 }
705
706 /// CopiedData is always a copy, so no equation numbers
707 /// should be allocated. This function just returns.
708 void assign_eqn_numbers(unsigned long& global_ndof, Vector<double*>& dof_pt)
709 {
710 return;
711 }
712
713
714 /// We cannot resize CopiedData, so the resize function
715 /// throws a warning.
716 void resize(const unsigned& n_value);
717 };
718
719
720 // Nodes are required in the HangInfo class, so we need a forward reference
721 class Node;
722
723
724 //=====================================================================
725 /// Class that contains data for hanging nodes.
726 ///
727 /// To ensure inter-element continuity, the values and nodal positions
728 /// of hanging nodes must be linear combinations of the
729 /// values and positions on certain adjacent "master" nodes.
730 /// For every hanging node \f$ J \f$ ,
731 /// \f[ {\bf U}_J = \sum_{K} {\bf U}_{K} \omega_{JK} \f]
732 /// and
733 /// \f[ {\bf X}_J = \sum_{K} {\bf X}_{K} \omega_{JK} \f],
734 /// where \f$ {\bf U}_I \f$ and \f$ {\bf U}_I \f$ are Vectors containing
735 /// the nodal values and positions of node
736 /// \f$ I \f$ respectively; the sum is taken over the hanging node's
737 /// master nodes \f$ K \f$ and \f$ \omega_{JK} \f$ are suitable weights.
738 /// This class provides storage and access functions for the
739 /// pointers to the master nodes and their associated weights.
740 //=====================================================================
742 {
743 public:
744 /// Default constructor, initialise vectors to have size zero
746 {
747#ifdef LEAK_CHECK
749#endif
750 }
751
752 /// Alternative constructor when the number of master nodes is known
753 HangInfo(const unsigned& n_master) : Nmaster(n_master)
754 {
755#ifdef LEAK_CHECK
757#endif
758 Master_nodes_pt = new Node*[n_master];
759 Master_weights = new double[n_master];
760 }
761
762 /// Delete the storage
764 {
765#ifdef LEAK_CHECK
767#endif
768 // If there is any storage, then delete it
769 if (Nmaster > 0)
770 {
771 delete[] Master_nodes_pt;
772 Master_nodes_pt = 0;
773 delete[] Master_weights;
774 Master_weights = 0;
775 }
776 }
777
778 /// Broken copy constructor
779 HangInfo(const HangInfo&) = delete;
780
781 /// Broken assignment operator
782 void operator=(const HangInfo&) = delete;
783
784 /// Return the number of master nodes
785 unsigned nmaster() const
786 {
787 return Nmaster;
788 }
789
790 /// Return a pointer to the i-th master node
791 Node* const& master_node_pt(const unsigned& i) const
792 {
793#ifdef PARANOID
794 if (Nmaster == 0)
795 {
796 throw OomphLibError("Hanging node data hasn't been setup yet \n",
797 OOMPH_CURRENT_FUNCTION,
798 OOMPH_EXCEPTION_LOCATION);
799 }
800#endif
801#ifdef RANGE_CHECKING
802 range_check(i);
803#endif
804 return Master_nodes_pt[i];
805 }
806
807 /// Return weight for dofs on i-th master node
808 double const& master_weight(const unsigned& i) const
809 {
810#ifdef PARANOID
811 if (Nmaster == 0)
812 {
813 throw OomphLibError("Hanging node data hasn't been setup yet \n",
814 OOMPH_CURRENT_FUNCTION,
815 OOMPH_EXCEPTION_LOCATION);
816 }
817#endif
818#ifdef RANGE_CHECKING
819 range_check(i);
820#endif
821 return Master_weights[i];
822 }
823
824 /// Set the pointer to the i-th master node and its weight
825 void set_master_node_pt(const unsigned& i,
826 Node* const& master_node_pt,
827 const double& weight);
828
829 /// Add (pointer to) master node and corresponding weight to
830 /// the internally stored (pointers to) master nodes and weights
831 void add_master_node_pt(Node* const& master_node_pt, const double& weight);
832
833 private:
834 /// Check that the argument is within the range of
835 /// stored data values.
836 void range_check(const unsigned& i) const;
837
838 /// C-style array of pointers to nodes that this hanging node depends on
840
841 /// C-style array of weights for the dofs on the master nodes
843
844 /// Number of master nodes required by this hanging node
845 unsigned Nmaster;
846 };
847
848 // Geometric objects are (now) required in the Node class, so we
849 // put a forward reference here
850 class GeomObject;
851
852
853 //=====================================================================
854 /// Nodes are derived from Data, but, in addition, have a
855 /// definite (Eulerian) position in a space of a given dimension.
856 ///
857 /// The nodal coordinates are used in the elements' mapping
858 /// between local and global coordinates and in the simplest
859 /// case (stationary nodes in Lagrange-type elements) this mapping
860 /// is given by
861 /// \f[ x_i = \sum_{j=1}^{N_{node}} X_{ij} \psi_{j}(s_k) \f]
862 /// so we need only access to the nodal coordinates
863 /// \f$ X_{ij}\ (i=1..DIM) \f$ of all nodes \f$ j \f$ : provided
864 /// by the Node member function
865 /// \code Node::x(i) \endcode
866 ///
867 /// If the nodal positions are time-dependent, the mapping becomes
868 /// \f[ x_i(t) = \sum_{j=1}^{N_{node}} X_{ij}(t) \ \psi_{j}(s_k). \f]
869 /// Within the computation (where time is only evaluated at discrete
870 /// levels) this becomes
871 /// \f[ x_{ti} = \sum_{j=1}^{N_{node}} X_{ijt} \ \psi_{j}(s_k). \f]
872 /// and we need access to the nodal coordinates \f$ X_{ijt} \ (i=1..DIM) \f$
873 /// of all nodes \f$ j \f$ at the present (t=0) and previous (t>0) timesteps:
874 /// provided by the Node member function
875 /// \code Node::x(t,i) \endcode
876 /// \b Note: The interpretation of the history values is slightly more
877 /// subtle than that. Depending on the positional TimeStepper
878 /// used, only a limited number of the positional history values accessed
879 /// \c Node::x(t,i) represent previous nodal positions; the others
880 /// are generalised history values that the TimeStepper uses to
881 /// determine approximations for the time-derivatives of the
882 /// nodal positions.
883 ///
884 /// Finally, some elements employ mappings
885 /// that involve additional, generalised coordinates. For instance,
886 /// in Hermite elements the mapping between local and global coordinates
887 /// is based on an independent interpolation for the global coordinates
888 /// and their derivative w.r.t. to the local coordinates. In such
889 /// elements, the mapping becomes
890 /// \f[ x_i = \sum_{j=1}^{N_{node}} \sum_{k=1}^{N_{type}} X_{ijk} \psi_{jk}(s_k) \f]
891 /// where \f$ N_{type} \f$ is the number of the different types of generalised
892 /// coordinates involved in the mapping. For instance, in 1D Hermite elements
893 /// \f$ N_{type}=2 \f$ and k=0 corresponds to the global coordinates while
894 /// k=1 corresponds to the
895 /// derivative of the global coordinates w.r.t. to the local coordinate.
896 /// In such cases we need access to the generalised nodal coordinates
897 /// \f$ X_{ijk} \ (i=1..DIM, \ k=1..N_{type}) \f$ of all nodes \f$ j \f$.
898 /// Access is provided by the Node member function
899 /// \code Node::x_gen(k,i) \endcode
900 /// and the corresponding time-dependent version
901 /// \code Node::x_gen(t,k,i) \endcode
902 /// While this is all pretty straightforward, it does make the
903 /// argument list of the Node constructors rather lengthy.
904 //=====================================================================
905 class Node : public Data
906 {
907 public:
908 /// Function pointer to auxiliary node update function
909 typedef void (*AuxNodeUpdateFctPt)(Node*);
910
911 // The BoundaryNodeBase class must use knowledge of the internal data
912 // storage
913 /// to construct periodic Nodes
914 friend class BoundaryNodeBase;
915
916 protected:
917 /// Private function to check that the arguemnts to the position
918 /// functions are in range
919 void x_gen_range_check(const unsigned& t,
920 const unsigned& k,
921 const unsigned& i) const;
922
923 /// Array of pointers to the data holding the Eulerian positions.
924 /// The storage format must be the same as the internal data storage
925 /// so that we can implement the functions x() in generality here without
926 /// the need for virtual functions. The first index will be a flat array
927 /// of position types and coordinates and the second will be the number
928 /// of time history values at each position type.
929 double** X_position;
930
931 /// Pointer to the timestepper associated with the position data.
933
934 /// C-style array of pointers to hanging node info.
935 /// It's set to NULL if the node isn't hanging.
936 /// The first entry (0) is the geometric hanging node data.
937 /// The remaining entries correspond to the hanging data for the
938 /// other values stored at the node. Usually, these entries will be the
939 /// same as the geometric hanging node data represented by Hanging_pt[0],
940 /// but this is not necessarily the case; e.g. the pressure in Taylor Hood
941 /// has different hanging node data from the velocities.
943
944 /// Eulerian dimension of the node
945 unsigned Ndim;
946
947 /// Number of coordinate types used in the mapping between
948 /// local and global coordinates
949 /// (e.g. 1 for Lagrange-type elements; 2 for 1D Hermite elements; 4 for
950 /// 2D Hermite elements, etc).
952
953 /// Flag to indicate that the Node has become
954 /// obsolete --- usually during mesh refinement process
956
957 /// Direct access to the pointer to the i-th stored coordinate data
958 double* x_position_pt(const unsigned& i)
959 {
960 return X_position[i];
961 }
962
963 /// Pointer to auxiliary update function -- this
964 /// can be used to update any nodal values following the update
965 /// of the nodal position. This is needed e.g. to update the no-slip
966 /// condition on moving boundaries.
968
969 public:
970 /// Static "Magic number" used to indicate that there is no
971 /// independent position in a periodic node.
972 static unsigned No_independent_position;
973
974 /// Default constructor
975 Node();
976
977 /// Steady constructor, for a Node of spatial dimension n_dim.
978 /// Allocates storage for initial_n_value values.
979 /// NPosition_type is the number of coordinate types
980 /// needed in the mapping between local and global coordinates
981 /// (e.g. 1 for Lagrange-type elements; 2 for 1D Hermite elements; 4 for
982 /// 2D Hermite elements, etc).
983 Node(const unsigned& n_dim,
984 const unsigned& n_position_type,
985 const unsigned& initial_n_value,
986 const bool& allocate_x_position = true);
987
988 /// Unsteady constructor for a node of spatial dimension n_dim.
989 /// Allocates storage for initial_n_value values with
990 /// history values as required by the timestepper.
991 /// n_position_type: # of coordinate
992 /// types needed in the mapping between local and global coordinates
993 /// (e.g. 1 for Lagrange-type elements; 2 for 1D Hermite elements; 4 for
994 /// 2D Hermite elements).
996 const unsigned& n_dim,
997 const unsigned& n_position_type,
998 const unsigned& initial_n_value,
999 const bool& allocate_x_position = true);
1000
1001 /// Destructor: Clean up the memory allocated for nodal position.
1002 virtual ~Node();
1003
1004 /// Broken copy constructor
1005 Node(const Node& node) = delete;
1006
1007 /// Broken assignment operator
1008 void operator=(const Node&) = delete;
1009
1010 /// Output operator: output location and all values at all times, along with
1011 /// any extra information stored for the timestepper.
1012 friend std::ostream& operator<<(std::ostream& out, const Node& d);
1013
1014 /// Number of coordinate
1015 /// types needed in the mapping between local and global coordinates.
1016 unsigned nposition_type() const
1017 {
1018 return Nposition_type;
1019 }
1020
1021 /// Return a pointer to the position timestepper.
1023 {
1025 }
1026
1027 /// Return a pointer to the position timestepper (const version).
1029 {
1031 }
1032
1033 /// Set a new position timestepper be resizing the appropriate
1034 /// storage
1035 virtual void set_position_time_stepper(
1037 const bool& preserve_existing_data);
1038
1039 /// Check whether the pointer parameter_pt addresses position data
1040 /// values. It never does for a standard node, because the positions are
1041 /// not data
1043 double* const& parameter_pt)
1044 {
1045 return false;
1046 }
1047
1048 /// Assign global equation numbers; increment global number
1049 /// of unknowns, global_ndof; and add any new dofs to the dof_pt.
1050 virtual void assign_eqn_numbers(unsigned long& global_ndof,
1051 Vector<double*>& dof_pt);
1052
1053 /// Return (Eulerian) spatial dimension of the node.
1054 unsigned ndim() const
1055 {
1056 return Ndim;
1057 }
1058
1059 /// Return the i-th nodal coordinate.
1060 double& x(const unsigned& i)
1061 {
1062#ifdef RANGE_CHECKING
1063 x_gen_range_check(0, 0, i);
1064#endif
1065 return X_position[Nposition_type * i][0];
1066 }
1067
1068 /// Return the i-th nodal coordinate (const version).
1069 const double& x(const unsigned& i) const
1070 {
1071#ifdef RANGE_CHECKING
1072 x_gen_range_check(0, 0, i);
1073#endif
1074 return X_position[Nposition_type * i][0];
1075 }
1076
1077 /// Return the position x(i) at previous timestep t
1078 /// (t=0: present; t>0 previous timestep).
1079 double& x(const unsigned& t, const unsigned& i)
1080 {
1081#ifdef RANGE_CHECKING
1082 x_gen_range_check(t, 0, i);
1083#endif
1084 return X_position[Nposition_type * i][t];
1085 }
1086
1087 /// Return the position x(i) at previous timestep t
1088 /// (t=0: present; t>0 previous timestep) (const version)
1089 const double& x(const unsigned& t, const unsigned& i) const
1090 {
1091#ifdef RANGE_CHECKING
1092 x_gen_range_check(t, 0, i);
1093#endif
1094 return X_position[Nposition_type * i][t];
1095 }
1096
1097 /// Return the i-th component of nodal velocity: dx/dt
1098 double dx_dt(const unsigned& i) const;
1099
1100 /// Return the i-th component of j-th derivative of nodal position:
1101 /// d^jx/dt^j.
1102 double dx_dt(const unsigned& j, const unsigned& i) const;
1103
1104 /// Return pointer to copied node (null if the
1105 /// current node is not a copy -- always the case here; it's overloaded
1106 /// for boundary nodes)
1107 virtual Node* copied_node_pt() const
1108 {
1109 return 0;
1110 }
1111
1112 /// Return whether any position coordinate has been copied (always false)
1113 virtual bool position_is_a_copy() const
1114 {
1115 return false;
1116 }
1117
1118 /// Return whether the position coordinate i has been copied (always false)
1119 virtual bool position_is_a_copy(const unsigned& i) const
1120 {
1121 return false;
1122 }
1123
1124 /// Reference to the generalised position x(k,i).
1125 /// `Type': k; Coordinate direction: i.
1126 double& x_gen(const unsigned& k, const unsigned& i)
1127 {
1128#ifdef RANGE_CHECKING
1129 x_gen_range_check(0, k, i);
1130#endif
1131 return X_position[Nposition_type * i + k][0];
1132 }
1133
1134 /// Reference to the generalised position x(k,i).
1135 /// `Type': k; Coordinate direction: i (const version).
1136 const double& x_gen(const unsigned& k, const unsigned& i) const
1137 {
1138#ifdef RANGE_CHECKING
1139 x_gen_range_check(0, k, i);
1140#endif
1141 return X_position[Nposition_type * i + k][0];
1142 }
1143
1144 /// Reference to the generalised position x(k,i) at the previous
1145 /// timestep [t=0: present]. `Type': k; Coordinate direction: i.
1146 double& x_gen(const unsigned& t, const unsigned& k, const unsigned& i)
1147 {
1148#ifdef RANGE_CHECKING
1149 x_gen_range_check(t, k, i);
1150#endif
1151 return X_position[Nposition_type * i + k][t];
1152 }
1153
1154 /// Reference to the generalised position x(k,i) at the previous
1155 /// timestep [t=0: present]. `Type': k; Coordinate direction: i.
1156 /// (const version)
1157 const double& x_gen(const unsigned& t,
1158 const unsigned& k,
1159 const unsigned& i) const
1160 {
1161#ifdef RANGE_CHECKING
1162 x_gen_range_check(t, k, i);
1163#endif
1164 return X_position[Nposition_type * i + k][t];
1165 }
1166
1167 /// i-th component of time derivative (velocity) of the
1168 /// generalised position, dx(k,i)/dt. `Type': k; Coordinate direction: i.
1169 double dx_gen_dt(const unsigned& k, const unsigned& i) const;
1170
1171
1172 /// i-th component of j-th time derivative (velocity) of the
1173 /// generalised position, d^jx(k,i)/dt^j. `Type': k; Coordinate direction:
1174 /// i.
1175 double dx_gen_dt(const unsigned& j,
1176 const unsigned& k,
1177 const unsigned& i) const;
1178
1179 /// Direct access to the i-th coordinate at time level t
1180 /// (t=0: present; t>0: previous)
1181 double* x_pt(const unsigned& t, const unsigned& i)
1182 {
1183 return &X_position[Nposition_type * i][t];
1184 }
1185
1186 /// Copy all nodal data from specified Node object
1187 void copy(Node* orig_node_pt);
1188
1189 /// Dump nodal position and associated data to file for restart
1190 virtual void dump(std::ostream& dump_file) const;
1191
1192 /// Read nodal position and associated data from file for restart
1193 void read(std::ifstream& restart_file);
1194
1195 /// The pin_all() function must be overloaded by SolidNodes,
1196 /// so we put the virtual interface here to avoid virtual functions in Data
1197 virtual void pin_all()
1198 {
1199 Data::pin_all();
1200 }
1201
1202 /// The unpin_all() function must be overloaded by SolidNode,
1203 /// so we put the virtual interface here to avoid virtual functions in Data
1204 virtual void unpin_all()
1205 {
1207 }
1208
1209
1210 /// Code that encapsulates the hanging status of the node (incl. the
1211 /// geometric hanging status) as
1212 /// \f$ \sum_{i=-1}{nval-1} Node::is_hanging(i) 2^{i+1} \f$
1213 unsigned hang_code()
1214 {
1215 unsigned hang_code = 0;
1216 int nval = nvalue();
1217 for (int i = -1; i < nval; i++)
1218 {
1219 hang_code += unsigned(Node::is_hanging(i)) *
1220 unsigned(std::pow(2.0, double(i + 1)));
1221 }
1222 return hang_code;
1223 }
1224
1225
1226 /// Return pointer to hanging node data (this refers to the geometric
1227 /// hanging node status) (const version).
1228 HangInfo* const& hanging_pt() const
1229 {
1230#ifdef PARANOID
1231 if (Hanging_pt == 0)
1232 {
1233 throw OomphLibError(
1234 "Vector of pointers to hanging data is not setup yet\n",
1235 OOMPH_CURRENT_FUNCTION,
1236 OOMPH_EXCEPTION_LOCATION);
1237 }
1238#endif
1239 return Hanging_pt[0];
1240 }
1241
1242 /// Return pointer to hanging node data for value i (const version)
1243 HangInfo* const& hanging_pt(const int& i) const
1244 {
1245#ifdef PARANOID
1246 if (Hanging_pt == 0)
1247 {
1248 std::ostringstream error_message;
1249 error_message << "Vector of pointers to hanging data is not setup yet\n"
1250#ifdef OOMPH_HAS_MPI
1251 << "I'm on processor "
1252 << MPI_Helpers::communicator_pt()->my_rank() << "\n"
1253#endif
1254 << "Coordinates: \n";
1255
1256 unsigned n_dim = ndim();
1257 for (unsigned i = 0; i < n_dim; i++)
1258 {
1259 error_message << this->x(i) << " ";
1260 }
1261 throw OomphLibError(error_message.str(),
1262 OOMPH_CURRENT_FUNCTION,
1263 OOMPH_EXCEPTION_LOCATION);
1264 }
1265#endif
1266#ifdef RANGE_CHECKING
1267 // Range checking code.
1268 // Need to make sure that this is an int otherwise the test
1269 // fails when it shouldn't
1270 const int n_value = static_cast<int>(this->nvalue());
1271 if ((i < -1) || (i > n_value))
1272 {
1273 std::ostringstream error_message;
1274 error_message << "Range Error: Value " << i
1275 << " is not in the range (-1," << n_value << ")";
1276 throw OomphLibError(error_message.str(),
1277 OOMPH_CURRENT_FUNCTION,
1278 OOMPH_EXCEPTION_LOCATION);
1279 }
1280#endif
1281 return Hanging_pt[i + 1];
1282 }
1283
1284 /// Test whether the node is geometrically hanging
1285 bool is_hanging() const
1286 {
1287 if (Hanging_pt == 0)
1288 {
1289 return false;
1290 }
1291 else
1292 {
1293 return (Hanging_pt[0] != 0);
1294 }
1295 }
1296
1297 /// Test whether the i-th value is hanging
1298 bool is_hanging(const int& i) const
1299 {
1300#ifdef RANGE_CHECKING
1301 // Need to make sure that this is an int otherwise the test
1302 // fails when it shouldn't
1303 const int n_value = static_cast<int>(this->nvalue());
1304 if ((i < -1) || (i > n_value))
1305 {
1306 std::ostringstream error_message;
1307 error_message << "Range Error: Value " << i
1308 << " is not in the range (-1," << n_value << ")";
1309 throw OomphLibError(error_message.str(),
1310 OOMPH_CURRENT_FUNCTION,
1311 OOMPH_EXCEPTION_LOCATION);
1312 }
1313#endif
1314
1315 // Test whether the node is geometrically hanging
1316 if (i == -1)
1317 {
1318 return is_hanging();
1319 }
1320 // Otherwise, is the i-th value hanging
1321 else
1322 {
1323 if (Hanging_pt == 0)
1324 {
1325 return false;
1326 }
1327 else
1328 {
1329 return (Hanging_pt[i + 1] != 0);
1330 }
1331 }
1332 }
1333
1334 /// Set the hanging data for the i-th value. (hang_pt=0 to make non-hanging)
1335 void set_hanging_pt(HangInfo* const& hang_pt, const int& i);
1336
1337 /// Label node as non-hanging node by removing all hanging node data.
1338 void set_nonhanging();
1339
1340 /// Resize the number of equations
1341 void resize(const unsigned& n_value);
1342
1343 /// Constrain the positions when the node is made hanging
1344 /// Empty virtual function that is overloaded in SolidNodes
1345 virtual void constrain_positions() {}
1346
1347 /// Unconstrain the positions when the node is made non-hanging
1348 /// Empty virtual function that is overloaded in SolidNodes
1349 virtual void unconstrain_positions() {}
1350
1351 /// Make the node periodic by copying the values from node_pt.
1352 /// Note that the coordinates will always remain independent, even
1353 /// though this may lead to (a little) unrequired information being stored.
1354 /// Broken virtual (only implemented in BoundaryNodes)
1355 virtual void make_periodic(Node* const& node_pt);
1356
1357 /// Make the nodes passed in the vector periodic_nodes share the
1358 /// same data as this node.
1359 virtual void make_periodic_nodes(const Vector<Node*>& periodic_nodes_pt);
1360
1361 /// Return a pointer to set of mesh boundaries that this
1362 /// node occupies; this will be overloaded by BoundaryNodes. The
1363 /// default behaviour is that the Node does not lie on any boundaries
1364 /// so the pointer to the set of boundaries is NULL
1365 virtual void get_boundaries_pt(std::set<unsigned>*& boundaries_pt)
1366 {
1367 boundaries_pt = 0;
1368 }
1369
1370 /// Test whether the Node lies on a boundary. The "bulk" Node
1371 /// cannot lie on a boundary, so return false. This will be overloaded
1372 /// by BoundaryNodes
1373 virtual bool is_on_boundary() const
1374 {
1375 return false;
1376 }
1377
1378 /// Test whether the node lies on mesh boundary b. The "bulk" Node
1379 /// cannot lie on a boundary, so return false. This will be overloaded by
1380 /// BoundaryNodes
1381 virtual bool is_on_boundary(const unsigned& b) const
1382 {
1383 return false;
1384 }
1385
1386 /// Broken interface for adding the node to the mesh boundary b
1387 /// Essentially here for error reporting.
1388 virtual void add_to_boundary(const unsigned& b);
1389
1390 /// Broken interface for removing the node from the mesh boundary b
1391 /// Here to provide error reporting.
1392 virtual void remove_from_boundary(const unsigned& b);
1393
1394 /// Get the number of boundary coordinates on mesh boundary b.
1395 /// Broken virtual interface provides run-time
1396 /// error checking
1397 virtual unsigned ncoordinates_on_boundary(const unsigned& b);
1398
1399 /// Have boundary coordinates been set up? Broken virtual interface
1400 /// provides run-time error checking
1402
1403 /// Return the vector of the k-th generalised boundary coordinates
1404 /// on mesh boundary b. Broken virtual interface provides run-time
1405 /// error checking
1406 virtual void get_coordinates_on_boundary(const unsigned& b,
1407 const unsigned& k,
1408 Vector<double>& boundary_zeta);
1409
1410 /// Set the vector of the k-th generalised boundary coordinates
1411 /// on mesh boundary b. Broken virtual interface provides run-time error
1412 /// checking
1413 virtual void set_coordinates_on_boundary(
1414 const unsigned& b,
1415 const unsigned& k,
1416 const Vector<double>& boundary_zeta);
1417
1418 /// Return the vector of coordinates on mesh boundary b
1419 /// Broken virtual interface provides run-time error checking
1420 virtual void get_coordinates_on_boundary(const unsigned& b,
1421 Vector<double>& boundary_zeta)
1422 {
1423 get_coordinates_on_boundary(b, 0, boundary_zeta);
1424 }
1425
1426 /// Set the vector of coordinates on mesh boundary b
1427 /// Broken virtual interface provides run-time error checking
1429 const unsigned& b, const Vector<double>& boundary_zeta)
1430 {
1431 set_coordinates_on_boundary(b, 0, boundary_zeta);
1432 }
1433
1434
1435 /// Mark node as obsolete
1437 {
1438 Obsolete = true;
1439 }
1440
1441 /// Mark node as non-obsolete
1443 {
1444 Obsolete = false;
1445 }
1446
1447 /// Test whether node is obsolete
1449 {
1450 return Obsolete;
1451 }
1452
1453 /// Return the i-th value stored at the Node. This interface
1454 /// does NOT take the hanging status of the Node into account.
1455 double raw_value(const unsigned& i) const
1456 {
1457 return Data::value(i);
1458 }
1459
1460 /// Return the i-th value at time level t
1461 /// (t=0: present, t>0: previous). This interface does NOT take the
1462 /// hanging status of the Node into account.
1463 double raw_value(const unsigned& t, const unsigned& i) const
1464 {
1465 return Data::value(t, i);
1466 }
1467
1468 /// Return i-th value (dofs or pinned) at this node
1469 /// either directly or via hanging node representation.
1470 /// Note that this REDFINES the interface in Data
1471 /// Thus, the present function will be called
1472 /// provided that it is accessed through a pointer to a node
1473 /// i.e. Node* node_pt->value()
1474 /// will take hanging information into account.
1475 /// If a pointer to a Node has been explicitly down-cast to a pointer to
1476 /// Data then the "wrong" (Data) version of the function will be called.
1477 double value(const unsigned& i) const;
1478
1479 /// Return i-th value at time level t (t=0: present, t>0: previous)
1480 /// either directly or via hanging node representation.
1481 /// Note that this REDEFINES the interface in Data
1482 /// Thus, the present function will be called
1483 /// provided that it is accessed through a pointer to a node
1484 /// i.e. Node* node_pt->value()
1485 /// will take hanging information into account.
1486 /// If a pointer to a Node has been explicitly down-cast to a pointer to
1487 /// Data then the "wrong" (Data) version of the function will be called.
1488 double value(const unsigned& t, const unsigned& i) const;
1489
1490 /// Compute Vector of values for the Data value
1491 /// taking the hanging node status into account.
1492 /// Note that this REDEFINES the interface in Data
1493 /// Thus, the present function will be called
1494 /// provided that it is accessed through a pointer to a node
1495 /// i.e. Node* node_pt->value()
1496 /// will take hanging information into account.
1497 /// If a pointer to a Node has been explicitly down-cast to a pointer to
1498 /// Data then the "wrong" (Data) version of the function will be called.
1499 void value(Vector<double>& values) const;
1500
1501 /// Return vector of values calculated using value(vector).
1503 {
1504 Vector<double> vals(nvalue(), 0.0);
1505 value(vals);
1506 return vals;
1507 }
1508
1509 /// Compute Vector of values (dofs or pinned) in this data
1510 /// at time level t (t=0: present; t>0: previous). This interface
1511 /// explicitly takes the hanging status into account.
1512 /// Thus, the present function will be called
1513 /// provided that it is accessed through a pointer to a node
1514 /// i.e. Node* node_pt->value()
1515 /// will take hanging information into account.
1516 /// If a pointer to a Node has been explicitly down-cast to a pointer to
1517 /// Data then the "wrong" (Data) version of the function will be called.
1518 void value(const unsigned& t, Vector<double>& values) const;
1519
1520 /// Compute Vector of nodal positions
1521 /// either directly or via hanging node representation
1522 void position(Vector<double>& pos) const;
1523
1524 /// Return vector of position of node at current time.
1526 {
1527 Vector<double> pos(ndim(), 0.0);
1528 position(pos);
1529 return pos;
1530 }
1531
1532 /// Compute Vector of nodal position at time level t
1533 /// (t=0: current; t>0: previous timestep),
1534 /// either directly or via hanging node representation.
1535 void position(const unsigned& t, Vector<double>& pos) const;
1536
1537 /// Return i-th nodal coordinate
1538 /// either directly or via hanging node representation.
1539 double position(const unsigned& i) const;
1540
1541 /// Return i-th nodal coordinate at time level t
1542 /// (t=0: current; t>0: previous time level),
1543 /// either directly or via hanging node representation.
1544 double position(const unsigned& t, const unsigned& i) const;
1545
1546 /// Return generalised nodal coordinate
1547 /// either directly or via hanging node representation.
1548 double position_gen(const unsigned& k, const unsigned& i) const;
1549
1550 /// Return generalised nodal coordinate at time level t
1551 /// (t=0: current; t>0: previous time level),
1552 /// either directly or via hanging node representation.
1553 double position_gen(const unsigned& t,
1554 const unsigned& k,
1555 const unsigned& i) const;
1556
1557 /// Return the i-th component of nodal velocity: dx/dt,
1558 /// either directly or via hanging node representation.
1559 double dposition_dt(const unsigned& i) const;
1560
1561 /// Return the i-th component of j-th derivative of nodal position:
1562 /// d^jx/dt^j either directly or via hanging node representation
1563 double dposition_dt(const unsigned& j, const unsigned& i) const;
1564
1565 /// i-th component of time derivative (velocity) of the
1566 /// generalised position, dx(k,i)/dt. `Type': k; Coordinate direction: i.
1567 /// This function uses the hanging node representation if necessary.
1568 double dposition_gen_dt(const unsigned& k, const unsigned& i) const;
1569
1570
1571 /// i-th component of j-th time derivative (velocity) of the
1572 /// generalised position, d^jx(k,i)/dt^j. `Type': k; Coordinate direction:
1573 /// i. This function uses the hanging node representation if necessary
1574 double dposition_gen_dt(const unsigned& j,
1575 const unsigned& k,
1576 const unsigned& i) const;
1577
1578 /// Interface for functions that update the nodal
1579 /// position using algebraic remeshing strategies. The
1580 /// interface is common to SpineNodes, AlgebraicNodes and
1581 /// MacroElementNodeUpdateNodes.
1582 /// The default is that the node does not "update itself"
1583 /// i.e. it is fixed in space. When implemented, this
1584 /// function should also execute the Node's auxiliary
1585 /// node update function (if any).
1586 virtual void node_update(
1587 const bool& update_all_time_levels_for_new_node = false)
1588 {
1589 }
1590
1591
1592 /// Set pointer to auxiliary update function -- this
1593 /// can be used to update any nodal values following the update
1594 /// of the nodal position. This is needed e.g. to update the no-slip
1595 /// condition on moving boundaries.
1597 AuxNodeUpdateFctPt aux_node_update_fct_pt)
1598 {
1599 // Set pointer (by default it's set to NULL)
1600 Aux_node_update_fct_pt = aux_node_update_fct_pt;
1601 }
1602
1603
1604 /// Boolean to indicate if node has a pointer to
1605 /// and auxiliary update function.
1607 {
1608 return (Aux_node_update_fct_pt != 0);
1609 }
1610
1611 /// Execute auxiliary update function (if any) -- this
1612 /// can be used to update any nodal values following the update
1613 /// of the nodal position. This is needed e.g. to update the no-slip
1614 /// condition on moving boundaries.
1616 {
1617 if (Aux_node_update_fct_pt != 0)
1618 {
1620 }
1621 }
1622
1623 /// Return the number of geometric data that affect the nodal
1624 /// position. The default value is zero (node is stationary)
1625 virtual inline unsigned ngeom_data() const
1626 {
1627 return 0;
1628 }
1629
1630 /// Return a pointer to an array of all (geometric) data that affect
1631 /// the nodal position. The default value is zero (node is stationary)
1632 virtual inline Data** all_geom_data_pt()
1633 {
1634 return 0;
1635 }
1636
1637 /// Return the number of geometric objects that affect the nodal
1638 /// position. The default value is zero (node is stationary)
1639 virtual inline unsigned ngeom_object() const
1640 {
1641 return 0;
1642 }
1643
1644 /// Return a pointer to an array of all (geometric) objects that
1645 /// affect the nodal position. The default value is zero (node is
1646 /// stationary)
1648 {
1649 return 0;
1650 }
1651
1652 /// Output nodal position
1653 void output(std::ostream& outfile);
1654
1655
1656#ifdef OOMPH_HAS_MPI
1657
1658 /// Add all data and time history values to the vector.
1659 /// Overloaded to add the position information as well.
1660 void add_values_to_vector(Vector<double>& vector_of_values);
1661
1662 /// Read all data and time history values from the vector
1663 /// starting from index. On return the index will be
1664 /// set the value at the end of the data that has been read in
1665 /// Overload to also read the position information.
1666 void read_values_from_vector(const Vector<double>& vector_of_values,
1667 unsigned& index);
1668
1669#endif
1670 };
1671
1672 //=====================================================================
1673 /// A Class for nodes that deform elastically (i.e. position is an
1674 /// unknown in the problem). The idea is that the Eulerian positions are
1675 /// stored in a Data object and the Lagrangian coordinates are stored in
1676 /// addition. The pointer that addresses the Eulerian positions is
1677 /// set to the pointer to Value in the Data object. Hence,
1678 /// SolidNode uses knowledge of the internal structure of Data and
1679 /// must be a friend of the Data class.
1680 /// In order to allow a mesh to deform via an elastic-style
1681 /// equation in deforming-domain problems, the positions are stored
1682 /// separately from the values, so that elastic problems may be
1683 /// combined with any other type of problem.
1684 //=====================================================================
1685 class SolidNode : public Node
1686 {
1687 private:
1688 /// Private function to check that the arguments to the position
1689 /// functions are in range
1690 void xi_gen_range_check(const unsigned& k, const unsigned& i) const;
1691
1692 protected:
1693 /// Number of Lagrangian coordinates of the node
1694 unsigned Nlagrangian;
1695
1696 /// Number of types of Lagrangian coordinates used to interpolate
1697 /// the Lagrangian coordinates within the element
1699
1700 /// Pointer to data that will hold variable positions in elastic nodes
1702
1703 /// Storage for the Lagrangian positions
1705
1706 public:
1707 /// Default Constructor
1709
1710 /// Steady constructor. The node has n_lagrangian Lagrangian
1711 /// coordinates of n_lagrangian_type types (1 for Lagrange elements,
1712 /// 2 for 1D Hermite etc.).
1713 /// The Eulerian dimension of the Node is n_dim and we have n_position_type
1714 /// (generalised) Eulerian coordinates. There are
1715 /// initial_n_value values stored at
1716 /// this node.
1717 SolidNode(const unsigned& n_lagrangian,
1718 const unsigned& n_lagrangian_type,
1719 const unsigned& n_dim,
1720 const unsigned& n_position_type,
1721 const unsigned& initial_n_value);
1722
1723 /// Unsteady constructor.
1724 /// Allocates storage for initial_n_value nodal values with history values
1725 /// as required by timestepper.
1726 /// The node has n_lagrangian Lagrangian coordinates of
1727 /// n_lagrangian_type types (1 for Lagrange elements, 2 for 1D Hermite
1728 /// etc.)/ The Eulerian dimension of the Node is n_dim and we have
1729 /// n_position_type generalised Eulerian coordinates.
1731 const unsigned& n_lagrangian,
1732 const unsigned& n_lagrangian_type,
1733 const unsigned& n_dim,
1734 const unsigned& Nposition_type,
1735 const unsigned& initial_n_value);
1736
1737 /// Destructor that cleans up the additional memory allocated in SolidNodes
1738 virtual ~SolidNode();
1739
1740 /// Broken copy constructor
1741 SolidNode(const SolidNode& solid_node) = delete;
1742
1743 /// Broken assignment operator
1744 void operator=(const SolidNode&) = delete;
1745
1746 /// Copy nodal positions and associated data from specified
1747 /// node object
1748 void copy(SolidNode* orig_node_pt);
1749
1750 /// Dump nodal positions (variable and fixed) and associated
1751 /// data to file for restart
1752 void dump(std::ostream& dump_file) const;
1753
1754 /// Read nodal positions (variable and fixed) and associated
1755 /// data from file for restart
1756 void read(std::ifstream& restart_file);
1757
1758 /// Return the variable_position data (const version)
1760 {
1761 return *Variable_position_pt;
1762 }
1763
1764 /// Pointer to variable_position data (const version)
1766 {
1767 return Variable_position_pt;
1768 }
1769
1770 /// Set the variable position data from an external data object
1771 void set_external_variable_position_pt(Data* const& data_pt);
1772
1773 /// Set a new position timestepper be resizing the appropriate
1774 /// storage Overloaded from the basic implementation to take into account
1775 /// the fact that position is now Data
1777 const bool& preserve_existing_data);
1778
1779 /// Overload the check whether the pointer parameter_pt addresses
1780 /// position data values
1781 bool does_pointer_correspond_to_position_data(double* const& parameter_pt);
1782
1783 /// Return whether any position component has been copied
1785 {
1787 }
1788
1789 /// Return whether the position coordinate i has been copied
1790 bool position_is_a_copy(const unsigned& i) const
1791 {
1793 }
1794
1795 /// Return the equation number for generalised Eulerian coordinate:
1796 /// type of coordinate: k, coordinate direction: i.
1797 const long& position_eqn_number(const unsigned& k, const unsigned& i) const
1798 {
1800 }
1801
1802 /// Test whether the i-th coordinate is pinned, 0: false; 1: true
1803 bool position_is_pinned(const unsigned& i)
1804 {
1806 }
1807
1808 /// Test whether the k-th type of the i-th coordinate is pinned
1809 /// 0: false; 1: true
1810 bool position_is_pinned(const unsigned& k, const unsigned& i)
1811 {
1813 }
1814
1815 /// Pin the nodal position
1816 void pin_position(const unsigned& i)
1817 {
1819 }
1820
1821 /// Pin the generalised nodal position.
1822 /// `Type': k; Coordinate direction: i.
1823 void pin_position(const unsigned& k, const unsigned& i)
1824 {
1826 }
1827
1828 /// Unpin the nodal position
1829 void unpin_position(const unsigned& i)
1830 {
1832 }
1833
1834 /// Unpin the generalised nodal position.
1835 /// `Type': k; Coordinate direction: i.
1836 void unpin_position(const unsigned& k, const unsigned& i)
1837 {
1839 }
1840
1841 /// Pin all the stored variables (Overloaded)
1842 void pin_all()
1843 {
1844 Node::pin_all();
1846 }
1847
1848 /// Unpin all the stored variables (Overloaded)
1850 {
1853 }
1854
1855 /// Overload the constrain positions function to constrain all
1856 /// position values
1858 {
1860 }
1861
1862 /// Overload the unconstrain positions function to unconstrain all
1863 /// position values
1865 {
1867 }
1868
1869 /// Return number of lagrangian coordinates
1870 unsigned nlagrangian() const
1871 {
1872 return Nlagrangian;
1873 }
1874
1875 /// Number of types of Lagrangian coordinates used to interpolate
1876 /// the Lagrangian coordinates within the element
1877 unsigned nlagrangian_type() const
1878 {
1879 return Nlagrangian_type;
1880 }
1881
1882 /// Reference to i-th Lagrangian position
1883 double& xi(const unsigned& i)
1884 {
1885#ifdef RANGE_CHECKING
1887#endif
1888 return Xi_position[Nlagrangian_type * i];
1889 }
1890
1891 /// Reference to i-th Lagrangian position (const version)
1892 const double& xi(const unsigned& i) const
1893 {
1894#ifdef RANGE_CHECKING
1896#endif
1897 return Xi_position[Nlagrangian_type * i];
1898 }
1899
1900 /// Reference to the generalised Lagrangian position.
1901 /// `Type': k; 'Coordinate direction: i.
1902 double& xi_gen(const unsigned& k, const unsigned& i)
1903 {
1904#ifdef RANGE_CHECKING
1906#endif
1907 return Xi_position[Nlagrangian_type * i + k];
1908 }
1909
1910 /// Reference to the generalised Lagrangian position.
1911 /// `Type': k; 'Coordinate direction: i. (const version
1912 const double& xi_gen(const unsigned& k, const unsigned& i) const
1913 {
1914#ifdef RANGE_CHECKING
1916#endif
1917 return Xi_position[Nlagrangian_type * i + k];
1918 }
1919
1920 /// Return lagrangian coordinate either directly or via
1921 /// hanging node representation
1922 double lagrangian_position(const unsigned& i) const;
1923
1924 /// Return generalised lagrangian coordinate either directly or via
1925 /// hanging node representation
1926 double lagrangian_position_gen(const unsigned& k, const unsigned& i) const;
1927
1928 /// Overload the assign equation numbers routine
1929 void assign_eqn_numbers(unsigned long& global_number,
1930 Vector<double*>& dof_pt);
1931
1932 /// Function to describe the dofs of the Node. The ostream
1933 /// specifies the output stream to which the description
1934 /// is written; the string stores the currently
1935 /// assembled output that is ultimately written to the
1936 /// output stream by Data::describe_dofs(...); it is typically
1937 /// built up incrementally as we descend through the
1938 /// call hierarchy of this function when called from
1939 /// Problem::describe_dofs(...)
1940 void describe_dofs(std::ostream& out,
1941 const std::string& current_string) const;
1942
1943 /// Overload the function add_values_to_map so that it also adds
1944 /// the variable position data
1945 void add_value_pt_to_map(std::map<unsigned, double*>& map_of_value_pt);
1946
1947#ifdef OOMPH_HAS_MPI
1948
1949 /// Add all data, position and time history values to the vector
1950 /// Overload to add the Lagrangian coordinates to the vector
1951 void add_values_to_vector(Vector<double>& vector_of_values);
1952
1953 /// Read all data and time history values from the vector
1954 /// starting from index. On return the index will be
1955 /// set the value at the end of the data that has been read in
1956 /// Overload to add the position information and Lagrangian coordinates
1957 void read_values_from_vector(const Vector<double>& vector_of_values,
1958 unsigned& index);
1959
1960
1961 /// Add all equation numbers to the vector in
1962 /// the internal storage order. Overload to add equation numbers
1963 /// associated with the positional dofs
1964 void add_eqn_numbers_to_vector(Vector<long>& vector_of_eqn_numbers);
1965
1966 /// Read all equation numbers from the vector
1967 /// starting from index. On return the index will be
1968 /// set to the value at the end of the data that has been read in
1969 /// Overload to include the equation numbrs associated with the
1970 /// positional dofs
1971 void read_eqn_numbers_from_vector(const Vector<long>& vector_of_eqn_numbers,
1972 unsigned& index);
1973
1974#endif
1975
1976
1977 /// Overload node update function: Since the position
1978 /// of SolidNodes is determined by unknowns, there's nothing
1979 /// to be done apart from performing the auxiliary node
1980 /// update function (if any)
1981 void node_update(const bool& update_all_time_levels_for_new_node = false)
1982 {
1984 }
1985 };
1986
1987
1988 //======================================================================
1989 /// A class that contains the information required by Nodes that
1990 /// are located on Mesh boundaries. A BoundaryNode of a particular type
1991 /// is obtained by combining a given Node with this class.
1992 /// By differentiating between Nodes and BoundaryNodes we avoid a lot
1993 /// of un-necessary storage in the bulk Nodes.
1994 //======================================================================
1996 {
1997 private:
1998 /// Pointer to a map of pointers to
1999 /// intrinsic boundary coordinates of the Node,
2000 /// indexed by the boundary number. If the Node does not lie
2001 /// on a boundary this map should never be queried because
2002 /// unnecessary storage will then be allocated. Hence, it
2003 /// can only be accessed via the appropriate set and get functions.
2004 std::map<unsigned, DenseMatrix<double>*>* Boundary_coordinates_pt;
2005
2006 /// Pointer to set of mesh boundaries occupied by the Node;
2007 /// NULL if the Node is not on any boundaries
2008 std::set<unsigned>* Boundaries_pt;
2009
2010 protected:
2011 /// Pointer to a map,
2012 /// indexed by the face element identifier it returns
2013 /// the position of the first face element value.
2014 /// If the Node does not lie on a face element
2015 /// this map should never be queried.
2016 std::map<unsigned, unsigned>*
2018
2019 /// If the BoundaryNode is periodic, this pointer is set to
2020 /// the BoundaryNode whose data it shares
2022
2023 /// Helper function that is used to turn BoundaryNodes into
2024 /// peridic boundary nodes by setting the data values of
2025 /// copied_node_pt to those of original_node_pt.
2026 void make_node_periodic(Node* const& node_pt,
2027 Node* const& original_node_pt);
2028
2029 /// Helper function that is used to turn BoundaryNodes into
2030 /// periodic boundary nodes by setting the data values of the nodes
2031 /// in the vector periodic_copies_pt to be the same as those
2032 /// in node_pt.
2033 void make_nodes_periodic(Node* const& node_pt,
2034 Vector<Node*> const& periodic_copies_pt);
2035
2036 public:
2037 /// Member function that allocates storage for a given
2038 /// number of additional degrees of freedom, n_additional_value,
2039 /// associated with a particular face_id to the Node
2040 /// node_pt
2042 const unsigned& n_additional_value, const unsigned& face_id = 0) = 0;
2043
2044 /// Return pointer to the map giving
2045 /// the index of the first face element value.
2047 {
2049 }
2050
2051 /// Return the index of the first value associated with
2052 /// the i-th face element value. If no argument is specified
2053 /// we return the index associated with the first (and assumed to be only)
2054 /// face element attached to this node. Throws error only in paranoid mode
2055 /// if no values have been set by any FaceElements. If you want to
2056 /// catch such cases gracefully in all circumstances (there are examples
2057 /// with complex unstructured 3D meshes where it's not clear a priori
2058 /// if a node has been resized by FaceElements) use alternative
2059 /// version (with leading bool arguments) that always checks and throws
2060 /// so exceptions can be caught gracefully. Returns UINT_MAX if error.
2062 const unsigned& face_id = 0) const
2063 {
2064#ifdef PARANOID
2066 {
2067 std::ostringstream error_message;
2068 error_message
2069 << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
2070 << "Pointer must be set via call to: \n\n"
2071 << " BoundaryNode::assign_additional_values_with_face_id(...), \n\n"
2072 << "typically from FaceElement::add_additional_values(...).";
2073 throw OomphLibError(error_message.str(),
2074 OOMPH_CURRENT_FUNCTION,
2075 OOMPH_EXCEPTION_LOCATION);
2076 return UINT_MAX;
2077 }
2078#endif
2080 }
2081
2082
2083 /// Return the index of the first value associated with
2084 /// the i-th face element value. If no argument id is specified
2085 /// we return the index associated with the first (and assumed to be only)
2086 /// face element attached to this node.
2087 /// If no values have been set by any FaceElements and
2088 /// throw_if_no_value_assigned_by_face_element is set to true, this
2089 /// is caught gracefully in all circumstances (there are examples
2090 /// with complex unstructured 3D meshes where it's not clear a priori
2091 /// if a node has been resized by FaceElements) by throwing an OomphLibError
2092 /// that can be caught gracefully. If throw_quietly is set to true
2093 /// we throw an OomphLibQuietException instead. You can catch either
2094 /// by catching the underlying std::runtime_error. In PARANOID mode
2095 /// we check regardless of the setting of
2096 /// throw_if_no_value_assigned_by_face_element (but respect the
2097 /// request for quietness). Returns UINT_MAX if error.
2099 const bool& throw_if_no_value_assigned_by_face_element,
2100 const bool& throw_quietly,
2101 const unsigned& face_id = 0) const
2102 {
2103 // Over-rule if paranoia rules
2104 bool local_throw_if_no_value_assigned_by_face_element =
2105 throw_if_no_value_assigned_by_face_element;
2106#ifdef PARANOID
2107 local_throw_if_no_value_assigned_by_face_element = true;
2108#endif
2109
2110 if (local_throw_if_no_value_assigned_by_face_element)
2111 {
2113 {
2114 std::ostringstream error_message;
2115 error_message
2116 << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
2117 << "Pointer must be set via call to: \n\n"
2118 << " BoundaryNode::assign_additional_values_with_face_id(...), "
2119 "\n\n"
2120 << "typically from FaceElement::add_additional_values(...).";
2121
2122 if (throw_quietly)
2123 {
2124 throw OomphLibQuietException();
2125 }
2126 else
2127 {
2128 throw OomphLibError(error_message.str(),
2129 OOMPH_CURRENT_FUNCTION,
2130 OOMPH_EXCEPTION_LOCATION);
2131 }
2132 return UINT_MAX;
2133 }
2134 }
2136 }
2137
2138 /// Return the number of values associated with
2139 /// the i-th face element field. If no argument is specified
2140 /// we return the value associated with the first (and assumed to be only)
2141 /// face element attached to this node. Throws error only in paranoid mode
2142 /// if no values have been set by any FaceElements. If you want to
2143 /// catch such cases gracefully in all circumstances (there are examples
2144 /// with complex unstructured 3D meshes where it's not clear a priori
2145 /// if a node has been resized by FaceElements) use alternative
2146 /// version (with leading bool arguments) that always checks and throws
2147 /// so exceptions can be caught gracefully. Returns UINT_MAX if error.
2149 const unsigned& face_id = 0) const = 0;
2150
2151 /// Default constructor, set the pointers to the storage to NULL
2154 Boundaries_pt(0),
2157 {
2158 }
2159
2160 /// Destructor, clean up any allocated storage for the boundaries
2161 virtual ~BoundaryNodeBase();
2162
2163 /// Broken copy constructor
2164 BoundaryNodeBase(const BoundaryNodeBase& boundary_node_base) = delete;
2165
2166 /// Broken assignment operator
2167 void operator=(const BoundaryNodeBase&) = delete;
2168
2169 /// Have boundary coordinates been set up?
2171 {
2172 return (Boundary_coordinates_pt != 0);
2173 }
2174
2175 /// Access to pointer to set of mesh boundaries that this
2176 /// node occupies; NULL if the node is not on any boundary
2177 void get_boundaries_pt(std::set<unsigned>*& boundaries_pt)
2178 {
2179 boundaries_pt = Boundaries_pt;
2180 }
2181
2182 /// Add the node to the mesh boundary b
2183 void add_to_boundary(const unsigned& b);
2184
2185 /// Remove the node from the mesh boundary b
2186 void remove_from_boundary(const unsigned& b);
2187
2188 /// Test whether the node lies on a boundary
2189 bool is_on_boundary() const
2190 {
2191 return !(Boundaries_pt == 0);
2192 }
2193
2194 /// Test whether the node lies on mesh boundary b
2195 bool is_on_boundary(const unsigned& b) const;
2196
2197 /// Get the number of boundary coordinates on mesh boundary b
2198 unsigned ncoordinates_on_boundary(const unsigned& b);
2199
2200 /// Return the vector of boundary coordinates on mesh boundary b
2201 void get_coordinates_on_boundary(const unsigned& b,
2202 Vector<double>& boundary_zeta)
2203 {
2204 // Just return the zero-th one
2205 get_coordinates_on_boundary(b, 0, boundary_zeta);
2206 }
2207
2208
2209 /// Set the vector of boundary coordinates on mesh boundary b
2210 void set_coordinates_on_boundary(const unsigned& b,
2211 const Vector<double>& boundary_zeta)
2212 {
2213 // Just do the zero-th one
2214 set_coordinates_on_boundary(b, 0, boundary_zeta);
2215 }
2216
2217 /// Return the vector of the k-th generalised boundary coordinates
2218 /// on mesh boundary b.
2219 void get_coordinates_on_boundary(const unsigned& b,
2220 const unsigned& k,
2221 Vector<double>& boundary_zeta);
2222
2223 /// Set the vector of the k-th generalised boundary coordinates on
2224 /// mesh boundary b.
2225 void set_coordinates_on_boundary(const unsigned& b,
2226 const unsigned& k,
2227 const Vector<double>& boundary_zeta);
2228 };
2229
2230
2231 //====================================================================
2232 /// A template Class for BoundaryNodes; that is Nodes that MAY live
2233 /// on the boundary of a Mesh. The class is formed by a simple
2234 /// composition of the template parameter NODE_TYPE, which must be
2235 /// a Node class and the BoundaryNodeBase class.
2236 /// Final overloading of functions is always in favour of the
2237 /// BoundaryNodeBase implementation; i.e. these nodes can live on
2238 /// boundaries.
2239 //===================================================================
2240 template<class NODE_TYPE>
2241 class BoundaryNode : public NODE_TYPE, public BoundaryNodeBase
2242 {
2243 private:
2244 /// Set pointers to the copied data used when we have periodic nodes
2246 {
2247#ifdef PARANOID
2248 if (Copied_node_pt == 0)
2249 {
2250 throw OomphLibError("BoundaryNode has not been copied",
2251 OOMPH_CURRENT_FUNCTION,
2252 OOMPH_EXCEPTION_LOCATION);
2253 }
2254#endif
2255
2256 // Set the number of values
2257 this->Nvalue = Copied_node_pt->nvalue();
2258 this->Value = Copied_node_pt->Value;
2259 this->Eqn_number = Copied_node_pt->Eqn_number;
2260 // We won't ever need to worry about updating position pointers
2261 // because periodic solid problems are handled using lagrange multipliers.
2262
2263 // Cast Copied_node_pt to BoundaryNode to copy over the
2264 // Face index pointer
2265 BoundaryNode<NODE_TYPE>* cast_copied_node_pt =
2267
2268 // Check that dynamic cast has worked
2269 if (cast_copied_node_pt)
2270 {
2272 cast_copied_node_pt
2274 }
2275 else
2276 {
2277 std::ostringstream error_stream;
2278 error_stream << "Copied_node_pt is not of type BoundaryNode*"
2279 << std::endl;
2280 throw OomphLibError(
2281 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2282 }
2283 }
2284
2285 /// Copy over additional information so that if the node
2286 /// is periodic it can remain active if the node that holds the periodic
2287 /// data is deleted
2289 {
2290 // Only worry about the face index if it has been assigned
2291 // which it will have been
2293 {
2294 // Allocate new storage for the index of first value assigned by face
2295 // element The other storage will be deleted
2297 new std::map<unsigned, unsigned>;
2298
2299 // Cast copied_node_pt to BoundaryNode so that we can reset the index
2300 BoundaryNode<NODE_TYPE>* cast_copied_node_pt =
2302
2303 // Check that dynamic cast has worked
2304 if (cast_copied_node_pt)
2305 {
2306 // Initialise the values in the map to be those of the original data
2307 // std::map<unsigned,unsigned>::const_iterator it =
2308 // (*(cast_copied_node_pt->
2309 // index_of_first_value_assigned_by_face_element_pt())).begin();
2310 std::map<unsigned, unsigned>::const_iterator end =
2311 (*(cast_copied_node_pt
2313 .end();
2314 for (std::map<unsigned, unsigned>::const_iterator it =
2315 (*(cast_copied_node_pt
2317 .begin();
2318 it != end;
2319 it++)
2320 {
2322 [it->first] = it->second;
2323 }
2324 }
2325 }
2326 }
2327
2328 public:
2329 /// Clear pointers to the copied data used when we have periodic
2330 /// nodes. The shallow (pointer) copy is turned into a deep copy by
2331 /// allocating new data and copying the actual values across.
2333 {
2334#ifdef PARANOID
2335 if (Copied_node_pt == 0)
2336 {
2337 throw OomphLibError("BoundaryNode has not been copied",
2338 OOMPH_CURRENT_FUNCTION,
2339 OOMPH_EXCEPTION_LOCATION);
2340 }
2341#endif
2342
2343 // Simply zeroing these will cause problems during unrefinement because
2344 // the original could be deleted, but the "copy" remain. Instead we
2345 // allocate new storage and copy values over from the original.
2346
2347 // Get the number of values and time storage
2348 //(must be the same as the original)
2349 const unsigned n_value = this->nvalue();
2350 const unsigned n_tstorage = this->ntstorage();
2351
2352 // Allocate storage for equation numbers
2353 this->Eqn_number = new long[n_value];
2354
2355 // Allocate storage for the values
2356 this->Value = new double*[n_value];
2357
2358 // Allocate all data values in one big array
2359 double* values = new double[n_value * n_tstorage];
2360
2361 // Set the pointers to the data values and equation numbers
2362 for (unsigned i = 0; i < n_value; ++i)
2363 {
2364 // Set the pointers
2365 this->Value[i] = &values[i * n_tstorage];
2366 // Initialise all the values to be those of the original data
2367 for (unsigned t = 0; t < n_tstorage; ++t)
2368 {
2369 this->Value[i][t] = Copied_node_pt->value(t, i);
2370 }
2371
2372 // Copy over the values of the equation numbers
2373 this->Eqn_number[i] = Copied_node_pt->eqn_number(i);
2374 }
2375
2376 // The node is no longer a copy
2377 Copied_node_pt = 0;
2378 }
2379
2380
2381 /// Default Constructor
2382 BoundaryNode() : NODE_TYPE(), BoundaryNodeBase() {}
2383
2384 /// Steady constructor, for a BoundaryNode of spatial dimension
2385 /// n_dim. Simply passes all arguments through to the underlying Node
2386 /// constructor which allocates storage for initial_n_value values.
2387 /// NPosition_type is the number of coordinate types
2388 /// needed in the mapping between local and global coordinates
2389 /// (e.g. 1 for Lagrange-type elements; 2 for 1D Hermite elements; 4 for
2390 /// 2D Hermite elements, etc).
2391 BoundaryNode(const unsigned& n_dim,
2392 const unsigned& n_position_type,
2393 const unsigned& initial_n_value)
2394 : NODE_TYPE(n_dim, n_position_type, initial_n_value), BoundaryNodeBase()
2395 {
2396 }
2397
2398 /// Unsteady constructor for a BoundaryNode
2399 /// of spatial dimension n_dim. Simply passes all arguments through to
2400 /// the underlygin Node constructor which
2401 /// allocates storage for initial_n_value values with
2402 /// history values as required by the timestepper.
2403 /// n_position_type: # of coordinate
2404 /// types needed in the mapping between local and global coordinates
2405 /// (e.g. 1 for Lagrange-type elements; 2 for 1D Hermite elements; 4 for
2406 /// 2D Hermite elements).
2407 BoundaryNode(TimeStepper* const& time_stepper_pt,
2408 const unsigned& n_dim,
2409 const unsigned& n_position_type,
2410 const unsigned& initial_n_value)
2411 : NODE_TYPE(time_stepper_pt, n_dim, n_position_type, initial_n_value),
2413 {
2414 }
2415
2416 /// Steady constructor for Solid-type boundary nodes.
2417 /// The node has n_lagrangian Lagrangian
2418 /// coordinates of n_lagrangian_type types (1 for Lagrange elements,
2419 /// 2 for 1D Hermite etc.).
2420 /// The Eulerian dimension of the Node is n_dim and we have n_position_type
2421 /// (generalised) Eulerian coordinates. There are
2422 /// initial_n_value values stored at
2423 /// this node.
2424 BoundaryNode(const unsigned& n_lagrangian,
2425 const unsigned& n_lagrangian_type,
2426 const unsigned& n_dim,
2427 const unsigned& n_position_type,
2428 const unsigned& initial_n_value)
2429 : NODE_TYPE(n_lagrangian,
2430 n_lagrangian_type,
2431 n_dim,
2432 n_position_type,
2433 initial_n_value),
2435 {
2436 }
2437
2438 /// Unsteady constructor for Solid-type boundary nodes
2439 /// Allocates storage for initial_n_value nodal values with history values
2440 /// as required by timestepper.
2441 /// The node has n_lagrangian Lagrangian coordinates of
2442 /// n_lagrangian_type types (1 for Lagrange elements, 2 for 1D Hermite
2443 /// etc.)/ The Eulerian dimension of the Node is n_dim and we have
2444 /// n_position_type generalised Eulerian coordinates.
2445 BoundaryNode(TimeStepper* const& time_stepper_pt,
2446 const unsigned& n_lagrangian,
2447 const unsigned& n_lagrangian_type,
2448 const unsigned& n_dim,
2449 const unsigned& n_position_type,
2450 const unsigned& initial_n_value)
2451 : NODE_TYPE(time_stepper_pt,
2452 n_lagrangian,
2453 n_lagrangian_type,
2454 n_dim,
2455 n_position_type,
2456 initial_n_value),
2458 {
2459 }
2460
2461 /// Destructor resets pointers if
2463 {
2464 // If there are any copies of this Node
2465 // then we need to clear their pointers to information stored in
2466 // this BoundaryNode
2467 // at this level because once we are down to the Node's destructor
2468 // the information no longer exists.
2469 for (unsigned i = 0; i < this->Ncopies; i++)
2470 {
2471 // Is the copied node a boundary node (it should be)
2472 BoundaryNode<NODE_TYPE>* cast_node_pt =
2473 dynamic_cast<BoundaryNode<NODE_TYPE>*>(this->Copy_of_data_pt[i]);
2474 // We can only do this if the node is a boundary node
2475 if (cast_node_pt != 0)
2476 {
2477 // This is required to clear out any pointers to the additional
2478 // data assigned by face elements
2479 cast_node_pt->clear_additional_copied_pointers();
2480 }
2481 // Otherwise there is a problem if it's not Hijacked Data
2482#ifdef PARANOID
2483 else
2484 {
2485 if (dynamic_cast<HijackedData*>(this->Copy_of_data_pt[i]) == 0)
2486 {
2488 "Copy of a BoundaryNode is not a BoundaryNode or HijackedData",
2489 "BoundaryNode::~BoundaryNode",
2490 OOMPH_EXCEPTION_LOCATION);
2491 }
2492 }
2493#endif
2494 }
2495
2496 // If the node was periodic then clear the pointers before deleting
2497 if (Copied_node_pt)
2498 {
2499 // Inform the node that the copy is being deleted
2500 // If the original has been deleted Copied_node_pt will be NULL
2502 Copied_node_pt = 0;
2503 this->Value = 0;
2504 this->Eqn_number = 0;
2505 // Remove the information about the boundary node storage scheme
2507 }
2508 }
2509
2510 /// Broken copy constructor
2512
2513 /// Broken assignment operator
2514 void operator=(const BoundaryNode<NODE_TYPE>&) = delete;
2515
2516 /// Have boundary coordinates been set up?
2518 {
2520 }
2521
2522 /// Access to pointer to set of mesh boundaries that this
2523 /// node occupies; NULL if the node is not on any boundary
2524 /// Final overload
2525 void get_boundaries_pt(std::set<unsigned>*& boundaries_pt)
2526 {
2528 }
2529
2530 /// Test whether the node lies on a boundary
2531 /// Final overload
2532 bool is_on_boundary() const
2533 {
2535 }
2536
2537 /// Test whether the node lies on mesh boundary b
2538 /// Final overload
2539 bool is_on_boundary(const unsigned& b) const
2540 {
2542 }
2543
2544 /// Add the node to mesh boundary b, final overload
2545 void add_to_boundary(const unsigned& b)
2546 {
2548 }
2549
2550 /// Remover the node from mesh boundary b, final overload
2551 void remove_from_boundary(const unsigned& b)
2552 {
2554 }
2555
2556
2557 /// Get the number of boundary coordinates on mesh boundary b.
2558 unsigned ncoordinates_on_boundary(const unsigned& b)
2559 {
2561 }
2562
2563
2564 /// Return the vector of coordinates on mesh boundary b
2565 /// Final overload
2566 void get_coordinates_on_boundary(const unsigned& b,
2567 Vector<double>& boundary_zeta)
2568 {
2570 }
2571
2572 /// Set the vector of coordinates on mesh boundary b
2573 /// Final overload
2574 void set_coordinates_on_boundary(const unsigned& b,
2575 const Vector<double>& boundary_zeta)
2576 {
2578 }
2579
2580
2581 /// Return the vector of k-th generalised boundary coordinates
2582 /// on mesh boundary b Final overload
2583 void get_coordinates_on_boundary(const unsigned& b,
2584 const unsigned& k,
2585 Vector<double>& boundary_zeta)
2586 {
2588 }
2589
2590 /// Set the vector of k-th generalised boundary coordinates
2591 /// on mesh boundary b. Final overload
2592 void set_coordinates_on_boundary(const unsigned& b,
2593 const unsigned& k,
2594 const Vector<double>& boundary_zeta)
2595 {
2597 }
2598
2599
2600 /// Return the number of values associated with
2601 /// the i-th face element field. If no argument is specified
2602 /// we return the value associated with the first (and assumed to be only)
2603 /// face element attached to this node. Throws error only in paranoid mode
2604 /// if no values have been set by any FaceElements. If you want to
2605 /// catch such cases gracefully in all circumstances (there are examples
2606 /// with complex unstructured 3D meshes where it's not clear a priori
2607 /// if a node has been resized by FaceElements) use alternative
2608 /// version (with leading bool arguments) that always checks and throws
2609 /// so exceptions can be caught gracefully. Returns UINT_MAX if error.
2610 unsigned nvalue_assigned_by_face_element(const unsigned& face_id = 0) const
2611 {
2612#ifdef PARANOID
2614 {
2615 std::ostringstream error_message;
2616 error_message
2617 << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
2618 << "Pointer must be set via call to: \n\n"
2619 << " BoundaryNode::assign_additional_values_with_face_id(), \n\n"
2620 << "typically from FaceElement::add_additional_values(...).";
2621 throw OomphLibError(error_message.str(),
2622 OOMPH_CURRENT_FUNCTION,
2623 OOMPH_EXCEPTION_LOCATION);
2624 return UINT_MAX;
2625 }
2626#endif
2627
2628 // How many values are there in total?
2629 unsigned nval = this->nvalue();
2630
2631 // If ID is not present in the map then return 0
2634 {
2635 return 0;
2636 }
2637
2638 // Otherwise the entry is present in the map
2639
2640 // Single entry: Number of values is the difference between
2641 // number of values and first index
2642 else if ((*Index_of_first_value_assigned_by_face_element_pt).size() == 1)
2643 {
2644 return nval -
2645 (*Index_of_first_value_assigned_by_face_element_pt)[face_id];
2646 }
2647 else
2648 {
2649 // Find the next first index: Default: nvalue()
2650 unsigned next_first_index = nval;
2651 unsigned my_first_index =
2652 (*Index_of_first_value_assigned_by_face_element_pt)[face_id];
2653 for (std::map<unsigned, unsigned>::iterator it =
2654 (*Index_of_first_value_assigned_by_face_element_pt).begin();
2655 it != (*Index_of_first_value_assigned_by_face_element_pt).end();
2656 it++)
2657 {
2658 unsigned first_index = (*it).second;
2659 if ((first_index > my_first_index) &&
2660 (first_index < next_first_index))
2661 {
2662 next_first_index = first_index;
2663 }
2664 }
2665 return next_first_index - my_first_index;
2666 }
2667 }
2668
2669
2670 //=====================================================================
2671 /// Member function to allocates storage for a given
2672 /// number of additional degrees of freedom, n_additional_value,
2673 /// associated with a particular face_id to the Node node_pt. Needs
2674 /// to be filled in here so that access to the nodal values is
2675 /// available.
2676 //=====================================================================
2678 const unsigned& n_additional_value, const unsigned& face_id = 0)
2679 {
2680#ifdef PARANOID
2681 // If nothing is being added warn the user
2682 if (n_additional_value == 0)
2683 {
2684 std::ostringstream warn_message;
2685 warn_message
2686 << "No additional data values are being added to the boundary node "
2687 << this << "\n"
2688 << "by face id " << face_id << ".\n"
2689 << "This means that the function \n"
2690 << "BoundaryNode::index_of_first_value_assigned_by_face_element(id) "
2691 "\n"
2692 << "will return a value that is equal to the number of values stored "
2693 "at the Node.\n"
2694 << "Calling Node::value(...) with this index will lead to an "
2695 "out-of-range error.\n"
2696 << "The anticpated usage of a loop from the index over the number of "
2697 "values.\n"
2698 << "will not cause any problems, but if you try to do anything else, "
2699 "you may be surprised.\n"
2700 << "You have been warned!\n";
2702 warn_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2703 }
2704#endif
2705
2706 // Allocate storage if not already assigned
2708 {
2710 new std::map<unsigned, unsigned>;
2711 }
2712
2713 // Find the number of values already stored in the node
2714 const unsigned n_value = this->nvalue();
2715
2716 // If this ID hasn't already been used
2718 face_id) ==
2719 this->Index_of_first_value_assigned_by_face_element_pt->end())
2720 {
2721 // Set the first index to by number of values
2722 (*Index_of_first_value_assigned_by_face_element_pt)[face_id] = n_value;
2723 }
2724 // Otherwise this ID has been used previously
2725 else
2726 {
2727 // Find the number of values associated with this id
2728 const unsigned n_value_for_id =
2729 this->nvalue_assigned_by_face_element(face_id);
2730
2731 // If the number of current values is equal to the desired values
2732 // do nothing and return
2733 if (n_value_for_id == n_additional_value)
2734 {
2735 return;
2736 }
2737 // Otherwise
2738 else
2739 {
2740 // Safety check, are the value associated with this id
2741 // all at the end
2743 [face_id] +
2744 n_value_for_id) != n_value)
2745 {
2746#ifdef PARANOID
2747 std::ostringstream warn_message;
2748 warn_message << "Trying to (resize) number of unknowns associated "
2749 "with face id "
2750 << face_id << "\n"
2751 << "but previous storage for this data is not at the "
2752 "end of the nodal values.\n"
2753 << "The anticipated usage here is within constructors "
2754 "that add additional equations\n"
2755 << "to existing FaceElements in which case we will "
2756 "always be at the end.\n"
2757 << "If you are trying to do something else, then try "
2758 "using a different id.\n"
2759 << " FaceElement::add_additional_values(...)."
2760 << " For consistency with earlier versions, this will "
2761 "do nothing!\n";
2762 OomphLibWarning(warn_message.str(),
2763 OOMPH_CURRENT_FUNCTION,
2764 OOMPH_EXCEPTION_LOCATION);
2765#endif
2766 // Just return without doing anything
2767 return;
2768 }
2769 } // Case when we are actually requesting additional values
2770 } // End case when ID has already been touched
2771
2772 // Now finally resize the storage
2773 this->resize(n_value + n_additional_value);
2774 }
2775
2776
2777 /// Make the node periodic
2778 void make_periodic(Node* const& node_pt)
2779 {
2781 }
2782
2783 /// Make the nodes passed in periodic_nodes periodic from
2784 /// this node
2785 void make_periodic_nodes(const Vector<Node*>& periodic_nodes_pt)
2786 {
2787 BoundaryNodeBase::make_nodes_periodic(this, periodic_nodes_pt);
2788 }
2789
2790 /// Return a boolean to indicate whether the data contains
2791 /// any copied values. If the node is periodic all values are copied
2792 bool is_a_copy() const
2793 {
2794 if (Copied_node_pt)
2795 {
2796 return true;
2797 }
2798 else
2799 {
2800 return false;
2801 }
2802 }
2803
2804 /// Return a boolean to indicate whether
2805 /// the i-th value is a copied value.
2806 /// If the node is periodic all values are copies
2807 bool is_a_copy(const unsigned& i) const
2808 {
2809 if (Copied_node_pt)
2810 {
2811 return true;
2812 }
2813 else
2814 {
2815 return false;
2816 }
2817 }
2818
2819
2820 /// Return pointer to copied node (null if the
2821 /// current node is not a copy)
2823 {
2824 return Copied_node_pt;
2825 }
2826
2827 /// Overload the equation assignment operation
2828 void assign_eqn_numbers(unsigned long& global_ndof, Vector<double*>& dof_pt)
2829 {
2830 // If the boundary node is not periodic call the ususal
2831 // assign equation numbers
2832 if (Copied_node_pt == 0)
2833 {
2834 NODE_TYPE::assign_eqn_numbers(global_ndof, dof_pt);
2835 }
2836 // Otherwise make sure that we assign equation numbers for
2837 // the variable position pointer of the solid node
2838 else
2839 {
2840 // Is it a solid node?
2841 SolidNode* solid_node_pt = dynamic_cast<SolidNode*>(this);
2842 if (solid_node_pt)
2843 {
2844 // If so we must let the variable position pointer take care of
2845 // itself
2846 solid_node_pt->variable_position_pt()->assign_eqn_numbers(global_ndof,
2847 dof_pt);
2848 }
2849 }
2850 }
2851
2852
2853 /// Resize the number of equations
2854 void resize(const unsigned& n_value)
2855 {
2856 // If the node is periodic, warn, but do nothing
2857 if (Copied_node_pt)
2858 {
2859#ifdef PARANOID
2860 unsigned n_value_new = Copied_node_pt->nvalue();
2861 // Check that we have already resized the original
2862 if (n_value_new != n_value)
2863 {
2864 std::ostringstream error_stream;
2865 error_stream
2866 << "Call to resize copied node before original has been resized!"
2867 << std::endl;
2868 throw OomphLibError(error_stream.str(),
2869 OOMPH_CURRENT_FUNCTION,
2870 OOMPH_EXCEPTION_LOCATION);
2871 }
2872#endif
2873 }
2874 // Otherwise call the underlying function
2875 else
2876 {
2877 NODE_TYPE::resize(n_value);
2878 }
2879 }
2880 };
2881
2882
2883 /// Make the node periodic
2884 template<>
2886 {
2887#ifdef PARANOID
2888 std::ostringstream warn_message;
2889 warn_message << "You are trying to make a Solid Node Periodic.\n"
2890 << "This action will reset pointers to stored values and "
2891 << "equation numbers,\n"
2892 << "meaning that all values will be shared by this Node and "
2893 << "its master.\n"
2894 << "Unfortunately, this does not ensure that the variable "
2895 << "nodal coordinates coincide.\n"
2896 << "For matching nodal coordinates the options are:\n"
2897 << "(i) Introduce Lagrange multipliers,\n"
2898 << "(ii) Pin one side and treat the data as dependent,\n"
2899 << "(iii) Hijack the nodal coordinates on one side "
2900 << "and specify an alternative equation.\n\n"
2901 << "If you plan to use refineability, then the easiest\n"
2902 << "option is to use Lagrange multipliers.\n"
2903 << std::endl;
2905 warn_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2906#endif
2907
2909 }
2910
2911
2912} // namespace oomph
2913
2914#endif
cstr elem_len * i
Definition: cfortran.h:603
char t
Definition: cfortran.h:568
A class that contains the information required by Nodes that are located on Mesh boundaries....
Definition: nodes.h:1996
BoundaryNodeBase()
Default constructor, set the pointers to the storage to NULL.
Definition: nodes.h:2152
unsigned ncoordinates_on_boundary(const unsigned &b)
Get the number of boundary coordinates on mesh boundary b.
Definition: nodes.cc:3119
std::set< unsigned > * Boundaries_pt
Pointer to set of mesh boundaries occupied by the Node; NULL if the Node is not on any boundaries.
Definition: nodes.h:2008
unsigned index_of_first_value_assigned_by_face_element(const bool &throw_if_no_value_assigned_by_face_element, const bool &throw_quietly, const unsigned &face_id=0) const
Return the index of the first value associated with the i-th face element value. If no argument id is...
Definition: nodes.h:2098
void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Access to pointer to set of mesh boundaries that this node occupies; NULL if the node is not on any b...
Definition: nodes.h:2177
virtual void assign_additional_values_with_face_id(const unsigned &n_additional_value, const unsigned &face_id=0)=0
Member function that allocates storage for a given number of additional degrees of freedom,...
void set_coordinates_on_boundary(const unsigned &b, const Vector< double > &boundary_zeta)
Set the vector of boundary coordinates on mesh boundary b.
Definition: nodes.h:2210
void make_node_periodic(Node *const &node_pt, Node *const &original_node_pt)
Helper function that is used to turn BoundaryNodes into peridic boundary nodes by setting the data va...
Definition: nodes.cc:2951
BoundaryNodeBase(const BoundaryNodeBase &boundary_node_base)=delete
Broken copy constructor.
void make_nodes_periodic(Node *const &node_pt, Vector< Node * > const &periodic_copies_pt)
Helper function that is used to turn BoundaryNodes into periodic boundary nodes by setting the data v...
Definition: nodes.cc:2896
void add_to_boundary(const unsigned &b)
Add the node to the mesh boundary b.
Definition: nodes.cc:3028
Node * Copied_node_pt
If the BoundaryNode is periodic, this pointer is set to the BoundaryNode whose data it shares.
Definition: nodes.h:2021
void get_coordinates_on_boundary(const unsigned &b, Vector< double > &boundary_zeta)
Return the vector of boundary coordinates on mesh boundary b.
Definition: nodes.h:2201
bool boundary_coordinates_have_been_set_up()
Have boundary coordinates been set up?
Definition: nodes.h:2170
std::map< unsigned, unsigned > *& index_of_first_value_assigned_by_face_element_pt()
Return pointer to the map giving the index of the first face element value.
Definition: nodes.h:2046
unsigned index_of_first_value_assigned_by_face_element(const unsigned &face_id=0) const
Return the index of the first value associated with the i-th face element value. If no argument is sp...
Definition: nodes.h:2061
std::map< unsigned, DenseMatrix< double > * > * Boundary_coordinates_pt
Pointer to a map of pointers to intrinsic boundary coordinates of the Node, indexed by the boundary n...
Definition: nodes.h:2004
void operator=(const BoundaryNodeBase &)=delete
Broken assignment operator.
std::map< unsigned, unsigned > * Index_of_first_value_assigned_by_face_element_pt
Pointer to a map, indexed by the face element identifier it returns the position of the first face el...
Definition: nodes.h:2017
bool is_on_boundary() const
Test whether the node lies on a boundary.
Definition: nodes.h:2189
void remove_from_boundary(const unsigned &b)
Remove the node from the mesh boundary b.
Definition: nodes.cc:3062
virtual ~BoundaryNodeBase()
Destructor, clean up any allocated storage for the boundaries.
Definition: nodes.cc:2993
virtual unsigned nvalue_assigned_by_face_element(const unsigned &face_id=0) const =0
Return the number of values associated with the i-th face element field. If no argument is specified ...
A template Class for BoundaryNodes; that is Nodes that MAY live on the boundary of a Mesh....
Definition: nodes.h:2242
void assign_additional_values_with_face_id(const unsigned &n_additional_value, const unsigned &face_id=0)
Member function to allocates storage for a given number of additional degrees of freedom,...
Definition: nodes.h:2677
BoundaryNode(TimeStepper *const &time_stepper_pt, const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_n_value)
Unsteady constructor for a BoundaryNode of spatial dimension n_dim. Simply passes all arguments throu...
Definition: nodes.h:2407
unsigned ncoordinates_on_boundary(const unsigned &b)
Get the number of boundary coordinates on mesh boundary b.
Definition: nodes.h:2558
~BoundaryNode()
Destructor resets pointers if.
Definition: nodes.h:2462
void operator=(const BoundaryNode< NODE_TYPE > &)=delete
Broken assignment operator.
void set_coordinates_on_boundary(const unsigned &b, const Vector< double > &boundary_zeta)
Set the vector of coordinates on mesh boundary b Final overload.
Definition: nodes.h:2574
BoundaryNode(const BoundaryNode< NODE_TYPE > &node)=delete
Broken copy constructor.
bool is_a_copy() const
Return a boolean to indicate whether the data contains any copied values. If the node is periodic all...
Definition: nodes.h:2792
BoundaryNode(const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_n_value)
Steady constructor, for a BoundaryNode of spatial dimension n_dim. Simply passes all arguments throug...
Definition: nodes.h:2391
void make_periodic_nodes(const Vector< Node * > &periodic_nodes_pt)
Make the nodes passed in periodic_nodes periodic from this node.
Definition: nodes.h:2785
BoundaryNode(const unsigned &n_lagrangian, const unsigned &n_lagrangian_type, const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_n_value)
Steady constructor for Solid-type boundary nodes. The node has n_lagrangian Lagrangian coordinates of...
Definition: nodes.h:2424
bool is_on_boundary() const
Test whether the node lies on a boundary Final overload.
Definition: nodes.h:2532
bool is_a_copy(const unsigned &i) const
Return a boolean to indicate whether the i-th value is a copied value. If the node is periodic all va...
Definition: nodes.h:2807
void clear_copied_pointers()
Clear pointers to the copied data used when we have periodic nodes. The shallow (pointer) copy is tur...
Definition: nodes.h:2332
void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
Overload the equation assignment operation.
Definition: nodes.h:2828
void resize(const unsigned &n_value)
Resize the number of equations.
Definition: nodes.h:2854
void remove_from_boundary(const unsigned &b)
Remover the node from mesh boundary b, final overload.
Definition: nodes.h:2551
BoundaryNode(TimeStepper *const &time_stepper_pt, const unsigned &n_lagrangian, const unsigned &n_lagrangian_type, const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_n_value)
Unsteady constructor for Solid-type boundary nodes Allocates storage for initial_n_value nodal values...
Definition: nodes.h:2445
void make_periodic(Node *const &node_pt)
Make the node periodic.
Definition: nodes.h:2778
void add_to_boundary(const unsigned &b)
Add the node to mesh boundary b, final overload.
Definition: nodes.h:2545
BoundaryNode()
Default Constructor.
Definition: nodes.h:2382
void clear_additional_copied_pointers()
Copy over additional information so that if the node is periodic it can remain active if the node tha...
Definition: nodes.h:2288
void reset_copied_pointers()
Set pointers to the copied data used when we have periodic nodes.
Definition: nodes.h:2245
bool boundary_coordinates_have_been_set_up()
Have boundary coordinates been set up?
Definition: nodes.h:2517
unsigned nvalue_assigned_by_face_element(const unsigned &face_id=0) const
Return the number of values associated with the i-th face element field. If no argument is specified ...
Definition: nodes.h:2610
void get_coordinates_on_boundary(const unsigned &b, Vector< double > &boundary_zeta)
Return the vector of coordinates on mesh boundary b Final overload.
Definition: nodes.h:2566
Node * copied_node_pt() const
Return pointer to copied node (null if the current node is not a copy)
Definition: nodes.h:2822
void set_coordinates_on_boundary(const unsigned &b, const unsigned &k, const Vector< double > &boundary_zeta)
Set the vector of k-th generalised boundary coordinates on mesh boundary b. Final overload.
Definition: nodes.h:2592
void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Access to pointer to set of mesh boundaries that this node occupies; NULL if the node is not on any b...
Definition: nodes.h:2525
void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Return the vector of k-th generalised boundary coordinates on mesh boundary b Final overload.
Definition: nodes.h:2583
bool is_on_boundary(const unsigned &b) const
Test whether the node lies on mesh boundary b Final overload.
Definition: nodes.h:2539
Custom Data class that is used when making a shallow copy of a data object. The class contains a copy...
Definition: nodes.h:652
void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
CopiedData is always a copy, so no equation numbers should be allocated. This function just returns.
Definition: nodes.h:708
~CopiedData()
Destructor informs original object that the copy is being deleted and clears its pointers to the stor...
Definition: nodes.h:675
Data * Copied_data_pt
Pointer to the Data object from which the values are copied.
Definition: nodes.h:655
void clear_copied_pointers()
Clear the pointers to the copied data.
Definition: nodes.cc:1398
void reset_copied_pointers()
Reset the pointers to the copied data.
Definition: nodes.cc:1381
bool is_a_copy(const unsigned &i) const
Return a boolean to indicate whether the i-th value is a copied value. All copied data is always a co...
Definition: nodes.h:701
void resize(const unsigned &n_value)
We cannot resize CopiedData, so the resize function throws a warning.
Definition: nodes.cc:1438
bool is_a_copy() const
Return a boolean to indicate whether the data contains any copied values. Copied data is always a cop...
Definition: nodes.h:693
CopiedData(const Data &data)=delete
(Shallow) copy constructor
void operator=(const CopiedData &)=delete
Broken assignment operator.
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:86
long eqn_number(const unsigned &i) const
Return the equation number of the i-th stored variable.
Definition: nodes.h:376
static TimeStepper * Default_static_time_stepper_pt
Default (static) timestepper used in steady problems.
Definition: nodes.h:162
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:238
void add_copy(Data *const &data_pt)
Add the pointer data_pt to the array Copy_of_data_pt. This should be used whenever copies are made of...
Definition: nodes.cc:76
void pin_all()
Pin all the stored variables.
Definition: nodes.h:397
long * Eqn_number
C-style array of pointers to the (global) equation numbers of the values.
Definition: nodes.h:116
virtual void add_eqn_numbers_to_vector(Vector< long > &vector_of_eqn_numbers)
Add all equation numbers to the vector in the internal storage order.
Definition: nodes.cc:1236
bool does_pointer_correspond_to_value(double *const &parameter_pt)
Check whether the pointer parameter_pt addresses internal data values.
Definition: nodes.cc:568
void constrain(const unsigned &i)
Constrain the i-th stored variable when making hanging data If the data is already pinned leave it al...
Definition: nodes.h:432
virtual void describe_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the dofs of the Node. The ostream specifies the output stream to which the descr...
Definition: nodes.cc:939
virtual void add_value_pt_to_map(std::map< unsigned, double * > &map_of_value_pt)
Add pointers to all unpinned and unconstrained data to a map indexed by (global) equation number.
Definition: nodes.cc:1089
Data(const unsigned &initial_n_value)
Default constructor for steady problems: assign memory for initial_n_value values.
long * eqn_number_pt(const unsigned &i)
Return the pointer to the equation number of the i-th stored variable.
Definition: nodes.h:358
unsigned Nvalue
Number of values stored in the data object.
Definition: nodes.h:135
void set_value(const unsigned &t, const unsigned &i, const double &value_)
Set the t-th history value of the i-th stored data value to specified value.
Definition: nodes.h:281
static long Is_pinned
Static "Magic number" used in place of the equation number to indicate that the value is pinned.
Definition: nodes.h:183
double value(const unsigned &t, const unsigned &i) const
Return i-th value at time level t (t=0: present, t>0: previous) This function is not virtual so that ...
Definition: nodes.h:305
void range_check(const unsigned &t, const unsigned &i) const
Check that the arguments are within the range of the stored data values and timesteps.
Definition: nodes.cc:47
void remove_copy(Data *const &data_pt)
Remove the pointer data_pt from the array Copy_of_data_pt. This should be used whenever copies of the...
Definition: nodes.cc:102
virtual void clear_copied_pointers()
Helper function that should be overloaded derived classes that contain copies of data....
Definition: nodes.cc:176
void pin(const unsigned &i)
Pin the i-th stored variable.
Definition: nodes.h:385
friend class HijackedData
Definition: nodes.h:93
bool is_segregated_solve_pinned(const unsigned &i)
Test whether the i-th variable is temporaily pinned for a segregated solve.
Definition: nodes.h:424
Data ** Copy_of_data_pt
C-style array of any Data objects that contain copies of the current Data object's data values.
Definition: nodes.h:127
void unpin(const unsigned &i)
Unpin the i-th stored variable.
Definition: nodes.h:391
int Non_halo_proc_ID
Non-halo processor ID for Data; -1 if it's not a halo.
Definition: nodes.h:140
friend std::ostream & operator<<(std::ostream &out, const Data &d)
Output operator: output all values at all times, along with any extra information stored for the time...
void copy(Data *orig_data_pt)
Copy Data values from specified Data object.
Definition: nodes.cc:601
void unpin_all()
Unpin all the stored variables.
Definition: nodes.h:407
void unconstrain_all()
Unconstrain all the stored variables when the data is made nonhanging.
Definition: nodes.h:461
bool is_halo() const
Is this Data a halo?
Definition: nodes.h:532
TimeStepper * Time_stepper_pt
Pointer to a Timestepper. The inclusion of a Timestepper pointer in the Data class,...
Definition: nodes.h:122
friend class CopiedData
Definition: nodes.h:94
virtual void read_values_from_vector(const Vector< double > &vector_of_values, unsigned &index)
Read all data and time history values from the vector starting from index. On return the index will b...
Definition: nodes.cc:1182
virtual void add_values_to_vector(Vector< double > &vector_of_values)
Add all data and time history values to the vector in the internal storage order.
Definition: nodes.cc:1112
static long Is_constrained
Static "Magic number" used in place of the equation number to indicate that the value is constrained ...
Definition: nodes.h:198
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:271
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:253
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:483
unsigned Ncopies
Number of Data that contain copies of this Data object's values.
Definition: nodes.h:131
double * value_pt(const unsigned &t, const unsigned &i) const
Return the pointer to the i-th stored value, or any of its history values (const version)....
Definition: nodes.h:337
void dump(std::ostream &dump_file) const
Dump the data object to a file.
Definition: nodes.cc:645
virtual ~Data()
Destructor, deallocates memory assigned for data.
Definition: nodes.cc:483
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:293
TimeStepper *const & time_stepper_pt() const
Return the pointer to the timestepper (const version).
Definition: nodes.h:244
unsigned ntstorage() const
Return total number of doubles stored per value to record time history of each value (one for steady ...
Definition: nodes.cc:879
virtual void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
Assign global equation numbers; increment global number of unknowns, global_ndof; and add any new dof...
Definition: nodes.cc:896
double ** Value
C-style array of pointers to data values and possible history values. The data must be ordered in suc...
Definition: nodes.h:112
void set_nonhalo()
Label the node as not being a halo.
Definition: nodes.h:526
Data(const Data &data)=delete
Broken copy constructor.
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition: nodes.h:367
void constrain_all()
Constrain all the stored variables when the data is made hanging.
Definition: nodes.h:451
bool is_constrained(const unsigned &i)
Test whether the i-th variable is constrained (1: true; 0: false).
Definition: nodes.h:472
static long Is_unclassified
Static "Magic number" used in place of the equation number to denote a value that hasn't been classif...
Definition: nodes.h:192
void delete_value_storage()
Delete all storage allocated by the Data object for values and equation numbers.
Definition: nodes.cc:187
virtual void resize(const unsigned &n_value)
Change (increase) the number of values that may be stored.
Definition: nodes.cc:1002
void set_halo(const unsigned &non_halo_proc_ID)
Label the node as halo and specify processor that holds non-halo counterpart.
Definition: nodes.h:520
Data()
Default: Just set pointer to (steady) timestepper. No storage for values is allocated.
Definition: nodes.cc:237
void unconstrain(const unsigned &i)
Unconstrain the i-th stored variable when make the data nonhanging. Only unconstrain if it was actual...
Definition: nodes.h:442
void set_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Set a new timestepper by resizing the appropriate storage. If already assigned the equation numbering...
Definition: nodes.cc:406
void read(std::ifstream &restart_file)
Read data object from a file.
Definition: nodes.cc:672
static long Is_segregated_solve_pinned
Static "Magic number" used in place of the equation number to indicate that the value is pinned,...
Definition: nodes.h:188
virtual bool is_a_copy(const unsigned &i) const
Return flag to indicate whether the i-th value is a copy. A base Data object can never be a copy so t...
Definition: nodes.h:261
unsigned self_test()
Self-test: Have all values been classified as pinned/unpinned? Return 0 if OK.
Definition: nodes.cc:965
int non_halo_proc_ID()
ID of processor ID that holds non-halo counterpart of halo node; negative if not a halo.
Definition: nodes.h:539
virtual void read_eqn_numbers_from_vector(const Vector< long > &vector_of_eqn_numbers, unsigned &index)
Read all equation numbers from the vector starting from index. On return the index will be set to the...
Definition: nodes.cc:1274
bool is_pinned(const unsigned &i) const
Test whether the i-th variable is pinned (1: true; 0: false).
Definition: nodes.h:417
void operator=(const Data &)=delete
Broken assignment operator.
double * value_pt(const unsigned &i) const
Return the pointer to the i-the stored value. Typically this is required when direct access to the st...
Definition: nodes.h:324
virtual void reset_copied_pointers()
Helper function that should be overloaded in derived classes that can contain copies of Data....
Definition: nodes.cc:162
Data(TimeStepper *const &time_stepper_pt, const unsigned &initial_n_value, const bool &allocate_storage=true)
Constructor for unsteady problems: assign memory for initial_n_value values and any memory required b...
/////////////////////////////////////////////////////////////////////
Definition: geom_objects.h:101
Class that contains data for hanging nodes.
Definition: nodes.h:742
Node ** Master_nodes_pt
C-style array of pointers to nodes that this hanging node depends on.
Definition: nodes.h:839
~HangInfo()
Delete the storage.
Definition: nodes.h:763
HangInfo()
Default constructor, initialise vectors to have size zero.
Definition: nodes.h:745
void operator=(const HangInfo &)=delete
Broken assignment operator.
HangInfo(const unsigned &n_master)
Alternative constructor when the number of master nodes is known.
Definition: nodes.h:753
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Definition: nodes.h:791
void range_check(const unsigned &i) const
Check that the argument is within the range of stored data values.
Definition: nodes.cc:1456
unsigned Nmaster
Number of master nodes required by this hanging node.
Definition: nodes.h:845
unsigned nmaster() const
Return the number of master nodes.
Definition: nodes.h:785
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
Definition: nodes.h:808
double * Master_weights
C-style array of weights for the dofs on the master nodes.
Definition: nodes.h:842
void add_master_node_pt(Node *const &master_node_pt, const double &weight)
Add (pointer to) master node and corresponding weight to the internally stored (pointers to) master n...
Definition: nodes.cc:1489
HangInfo(const HangInfo &)=delete
Broken copy constructor.
void set_master_node_pt(const unsigned &i, Node *const &master_node_pt, const double &weight)
Set the pointer to the i-th master node and its weight.
Definition: nodes.cc:1474
Custom Data class that is used when HijackingData. The class always contains a single value that is c...
Definition: nodes.h:575
Data * Copied_data_pt
Pointer to the Data object from which the value is copied.
Definition: nodes.h:578
~HijackedData()
Destructor informs original object that the copy is being deleted and clears its pointers to the stor...
Definition: nodes.h:601
void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
HijackedData is always a copy, so no equation numbers should be allocated. This function just returns...
Definition: nodes.h:634
unsigned Copied_index
Index of the value that is copied from within the Data object.
Definition: nodes.h:581
bool is_a_copy(const unsigned &i) const
Return a boolean to indicate whether the i-th value is a copied value. Hijacked data is always a copy...
Definition: nodes.h:627
bool is_a_copy() const
Return a boolean to indicate whether the data contains any copied values. Hijacked data is always a c...
Definition: nodes.h:619
void resize(const unsigned &n_value)
We cannot resize HijackedData, so the resize function throws a warning.
Definition: nodes.cc:1363
void reset_copied_pointers()
Reset the pointers to the copied data.
Definition: nodes.cc:1304
void operator=(const HijackedData &)=delete
Broken assignment operator.
HijackedData(const Data &data)=delete
(Shallow) copy constructor
void clear_copied_pointers()
Clear the pointers to the copied data.
Definition: nodes.cc:1318
static OomphCommunicator * communicator_pt()
access to global communicator. This is the oomph-lib equivalent of MPI_COMM_WORLD
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:906
double * x_position_pt(const unsigned &i)
Direct access to the pointer to the i-th stored coordinate data.
Definition: nodes.h:958
double dx_gen_dt(const unsigned &k, const unsigned &i) const
i-th component of time derivative (velocity) of the generalised position, dx(k,i)/dt....
Definition: nodes.cc:1865
virtual void set_coordinates_on_boundary(const unsigned &b, const Vector< double > &boundary_zeta)
Set the vector of coordinates on mesh boundary b Broken virtual interface provides run-time error che...
Definition: nodes.h:1428
virtual bool position_is_a_copy(const unsigned &i) const
Return whether the position coordinate i has been copied (always false)
Definition: nodes.h:1119
void copy(Node *orig_node_pt)
Copy all nodal data from specified Node object.
Definition: nodes.cc:1916
void add_values_to_vector(Vector< double > &vector_of_values)
Add all data and time history values to the vector. Overloaded to add the position information as wel...
Definition: nodes.cc:2777
Vector< double > position() const
Return vector of position of node at current time.
Definition: nodes.h:1525
virtual void set_position_time_stepper(TimeStepper *const &position_time_stepper_pt, const bool &preserve_existing_data)
Set a new position timestepper be resizing the appropriate storage.
Definition: nodes.cc:1752
void operator=(const Node &)=delete
Broken assignment operator.
const double & x_gen(const unsigned &k, const unsigned &i) const
Reference to the generalised position x(k,i). ‘Type’: k; Coordinate direction: i (const version).
Definition: nodes.h:1136
virtual unsigned ncoordinates_on_boundary(const unsigned &b)
Get the number of boundary coordinates on mesh boundary b. Broken virtual interface provides run-time...
Definition: nodes.cc:2363
void set_nonhanging()
Label node as non-hanging node by removing all hanging node data.
Definition: nodes.cc:2281
bool is_obsolete()
Test whether node is obsolete.
Definition: nodes.h:1448
virtual unsigned ngeom_object() const
Return the number of geometric objects that affect the nodal position. The default value is zero (nod...
Definition: nodes.h:1639
virtual bool is_on_boundary() const
Test whether the Node lies on a boundary. The "bulk" Node cannot lie on a boundary,...
Definition: nodes.h:1373
void set_obsolete()
Mark node as obsolete.
Definition: nodes.h:1436
TimeStepper *& position_time_stepper_pt()
Return a pointer to the position timestepper.
Definition: nodes.h:1022
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Return a pointer to set of mesh boundaries that this node occupies; this will be overloaded by Bounda...
Definition: nodes.h:1365
double * x_pt(const unsigned &t, const unsigned &i)
Direct access to the i-th coordinate at time level t (t=0: present; t>0: previous)
Definition: nodes.h:1181
virtual GeomObject ** all_geom_object_pt()
Return a pointer to an array of all (geometric) objects that affect the nodal position....
Definition: nodes.h:1647
virtual void pin_all()
The pin_all() function must be overloaded by SolidNodes, so we put the virtual interface here to avoi...
Definition: nodes.h:1197
const double & x_gen(const unsigned &t, const unsigned &k, const unsigned &i) const
Reference to the generalised position x(k,i) at the previous timestep [t=0: present]....
Definition: nodes.h:1157
void read(std::ifstream &restart_file)
Read nodal position and associated data from file for restart.
Definition: nodes.cc:1996
static unsigned No_independent_position
Static "Magic number" used to indicate that there is no independent position in a periodic node.
Definition: nodes.h:972
bool is_hanging(const int &i) const
Test whether the i-th value is hanging.
Definition: nodes.h:1298
void x_gen_range_check(const unsigned &t, const unsigned &k, const unsigned &i) const
Private function to check that the arguemnts to the position functions are in range.
Definition: nodes.cc:1528
virtual Node * copied_node_pt() const
Return pointer to copied node (null if the current node is not a copy – always the case here; it's ov...
Definition: nodes.h:1107
virtual void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
Assign global equation numbers; increment global number of unknowns, global_ndof; and add any new dof...
Definition: nodes.cc:534
void set_auxiliary_node_update_fct_pt(AuxNodeUpdateFctPt aux_node_update_fct_pt)
Set pointer to auxiliary update function – this can be used to update any nodal values following the ...
Definition: nodes.h:1596
virtual void remove_from_boundary(const unsigned &b)
Broken interface for removing the node from the mesh boundary b Here to provide error reporting.
Definition: nodes.cc:2350
void perform_auxiliary_node_update_fct()
Execute auxiliary update function (if any) – this can be used to update any nodal values following th...
Definition: nodes.h:1615
virtual void get_coordinates_on_boundary(const unsigned &b, Vector< double > &boundary_zeta)
Return the vector of coordinates on mesh boundary b Broken virtual interface provides run-time error ...
Definition: nodes.h:1420
void set_non_obsolete()
Mark node as non-obsolete.
Definition: nodes.h:1442
Vector< double > value() const
Return vector of values calculated using value(vector).
Definition: nodes.h:1502
virtual Data ** all_geom_data_pt()
Return a pointer to an array of all (geometric) data that affect the nodal position....
Definition: nodes.h:1632
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
double & x_gen(const unsigned &t, const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i) at the previous timestep [t=0: present]....
Definition: nodes.h:1146
virtual void make_periodic_nodes(const Vector< Node * > &periodic_nodes_pt)
Make the nodes passed in the vector periodic_nodes share the same data as this node.
Definition: nodes.cc:2270
virtual bool position_is_a_copy() const
Return whether any position coordinate has been copied (always false)
Definition: nodes.h:1113
virtual void constrain_positions()
Constrain the positions when the node is made hanging Empty virtual function that is overloaded in So...
Definition: nodes.h:1345
void output(std::ostream &outfile)
Output nodal position.
Definition: nodes.cc:2760
AuxNodeUpdateFctPt Aux_node_update_fct_pt
Pointer to auxiliary update function – this can be used to update any nodal values following the upda...
Definition: nodes.h:967
const double & x(const unsigned &i) const
Return the i-th nodal coordinate (const version).
Definition: nodes.h:1069
TimeStepper * Position_time_stepper_pt
Pointer to the timestepper associated with the position data.
Definition: nodes.h:932
virtual void unpin_all()
The unpin_all() function must be overloaded by SolidNode, so we put the virtual interface here to avo...
Definition: nodes.h:1204
double ** X_position
Array of pointers to the data holding the Eulerian positions. The storage format must be the same as ...
Definition: nodes.h:929
virtual void add_to_boundary(const unsigned &b)
Broken interface for adding the node to the mesh boundary b Essentially here for error reporting.
Definition: nodes.cc:2336
virtual void set_coordinates_on_boundary(const unsigned &b, const unsigned &k, const Vector< double > &boundary_zeta)
Set the vector of the k-th generalised boundary coordinates on mesh boundary b. Broken virtual interf...
Definition: nodes.cc:2394
HangInfo ** Hanging_pt
C-style array of pointers to hanging node info. It's set to NULL if the node isn't hanging....
Definition: nodes.h:942
void set_hanging_pt(HangInfo *const &hang_pt, const int &i)
Set the hanging data for the i-th value. (hang_pt=0 to make non-hanging)
Definition: nodes.cc:2068
HangInfo *const & hanging_pt(const int &i) const
Return pointer to hanging node data for value i (const version)
Definition: nodes.h:1243
const double & x(const unsigned &t, const unsigned &i) const
Return the position x(i) at previous timestep t (t=0: present; t>0 previous timestep) (const version)
Definition: nodes.h:1089
TimeStepper *const & position_time_stepper_pt() const
Return a pointer to the position timestepper (const version).
Definition: nodes.h:1028
unsigned Nposition_type
Number of coordinate types used in the mapping between local and global coordinates (e....
Definition: nodes.h:951
virtual bool boundary_coordinates_have_been_set_up()
Have boundary coordinates been set up? Broken virtual interface provides run-time error checking.
Definition: nodes.cc:2323
double position_gen(const unsigned &k, const unsigned &i) const
Return generalised nodal coordinate either directly or via hanging node representation.
Definition: nodes.cc:2592
unsigned Ndim
Eulerian dimension of the node.
Definition: nodes.h:945
unsigned hang_code()
Code that encapsulates the hanging status of the node (incl. the geometric hanging status) as .
Definition: nodes.h:1213
virtual bool does_pointer_correspond_to_position_data(double *const &parameter_pt)
Check whether the pointer parameter_pt addresses position data values. It never does for a standard n...
Definition: nodes.h:1042
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
virtual void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Return the vector of the k-th generalised boundary coordinates on mesh boundary b....
Definition: nodes.cc:2379
double raw_value(const unsigned &i) const
Return the i-th value stored at the Node. This interface does NOT take the hanging status of the Node...
Definition: nodes.h:1455
friend std::ostream & operator<<(std::ostream &out, const Node &d)
Output operator: output location and all values at all times, along with any extra information stored...
Definition: nodes.cc:373
virtual void unconstrain_positions()
Unconstrain the positions when the node is made non-hanging Empty virtual function that is overloaded...
Definition: nodes.h:1349
Node(const Node &node)=delete
Broken copy constructor.
void read_values_from_vector(const Vector< double > &vector_of_values, unsigned &index)
Read all data and time history values from the vector starting from index. On return the index will b...
Definition: nodes.cc:2832
virtual void dump(std::ostream &dump_file) const
Dump nodal position and associated data to file for restart.
Definition: nodes.cc:1969
virtual bool is_on_boundary(const unsigned &b) const
Test whether the node lies on mesh boundary b. The "bulk" Node cannot lie on a boundary,...
Definition: nodes.h:1381
virtual unsigned ngeom_data() const
Return the number of geometric data that affect the nodal position. The default value is zero (node i...
Definition: nodes.h:1625
double dposition_dt(const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt, either directly or via hanging node representatio...
Definition: nodes.cc:2659
double & x(const unsigned &t, const unsigned &i)
Return the position x(i) at previous timestep t (t=0: present; t>0 previous timestep).
Definition: nodes.h:1079
bool has_auxiliary_node_update_fct_pt()
Boolean to indicate if node has a pointer to and auxiliary update function.
Definition: nodes.h:1606
double dx_dt(const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt.
Definition: nodes.cc:1817
bool Obsolete
Flag to indicate that the Node has become obsolete — usually during mesh refinement process.
Definition: nodes.h:955
void resize(const unsigned &n_value)
Resize the number of equations.
Definition: nodes.cc:2167
virtual void make_periodic(Node *const &node_pt)
Make the node periodic by copying the values from node_pt. Note that the coordinates will always rema...
Definition: nodes.cc:2257
double raw_value(const unsigned &t, const unsigned &i) const
Return the i-th value at time level t (t=0: present, t>0: previous). This interface does NOT take the...
Definition: nodes.h:1463
virtual void node_update(const bool &update_all_time_levels_for_new_node=false)
Interface for functions that update the nodal position using algebraic remeshing strategies....
Definition: nodes.h:1586
unsigned nposition_type() const
Number of coordinate types needed in the mapping between local and global coordinates.
Definition: nodes.h:1016
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1285
Node()
Default constructor.
Definition: nodes.cc:1574
double & x_gen(const unsigned &k, const unsigned &i)
Reference to the generalised position x(k,i). ‘Type’: k; Coordinate direction: i.
Definition: nodes.h:1126
double dposition_gen_dt(const unsigned &k, const unsigned &i) const
i-th component of time derivative (velocity) of the generalised position, dx(k,i)/dt....
Definition: nodes.cc:2708
virtual ~Node()
Destructor: Clean up the memory allocated for nodal position.
Definition: nodes.cc:1695
void(* AuxNodeUpdateFctPt)(Node *)
Function pointer to auxiliary node update function.
Definition: nodes.h:909
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation....
Definition: nodes.cc:2408
HangInfo *const & hanging_pt() const
Return pointer to hanging node data (this refers to the geometric hanging node status) (const version...
Definition: nodes.h:1228
An OomphLibError object which should be thrown when an run-time error is encountered....
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
An OomphLibWarning object which should be created as a temporary object to issue a warning....
A Class for nodes that deform elastically (i.e. position is an unknown in the problem)....
Definition: nodes.h:1686
void constrain_positions()
Overload the constrain positions function to constrain all position values.
Definition: nodes.h:1857
void xi_gen_range_check(const unsigned &k, const unsigned &i) const
Private function to check that the arguments to the position functions are in range.
Definition: nodes.cc:3312
void unpin_all()
Unpin all the stored variables (Overloaded)
Definition: nodes.h:1849
void set_position_time_stepper(TimeStepper *const &position_time_stepper_pt, const bool &preserve_existing_data)
Set a new position timestepper be resizing the appropriate storage Overloaded from the basic implemen...
Definition: nodes.cc:3548
unsigned Nlagrangian
Number of Lagrangian coordinates of the node.
Definition: nodes.h:1694
void unconstrain_positions()
Overload the unconstrain positions function to unconstrain all position values.
Definition: nodes.h:1864
void add_values_to_vector(Vector< double > &vector_of_values)
Add all data, position and time history values to the vector Overload to add the Lagrangian coordinat...
Definition: nodes.cc:3708
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
Definition: nodes.h:1765
bool does_pointer_correspond_to_position_data(double *const &parameter_pt)
Overload the check whether the pointer parameter_pt addresses position data values.
Definition: nodes.cc:3573
void read_eqn_numbers_from_vector(const Vector< long > &vector_of_eqn_numbers, unsigned &index)
Read all equation numbers from the vector starting from index. On return the index will be set to the...
Definition: nodes.cc:3811
const long & position_eqn_number(const unsigned &k, const unsigned &i) const
Return the equation number for generalised Eulerian coordinate: type of coordinate: k,...
Definition: nodes.h:1797
unsigned nlagrangian_type() const
Number of types of Lagrangian coordinates used to interpolate the Lagrangian coordinates within the e...
Definition: nodes.h:1877
void unpin_position(const unsigned &k, const unsigned &i)
Unpin the generalised nodal position. ‘Type’: k; Coordinate direction: i.
Definition: nodes.h:1836
SolidNode(const SolidNode &solid_node)=delete
Broken copy constructor.
Data * Variable_position_pt
Pointer to data that will hold variable positions in elastic nodes.
Definition: nodes.h:1701
void add_value_pt_to_map(std::map< unsigned, double * > &map_of_value_pt)
Overload the function add_values_to_map so that it also adds the variable position data.
Definition: nodes.cc:3693
unsigned Nlagrangian_type
Number of types of Lagrangian coordinates used to interpolate the Lagrangian coordinates within the e...
Definition: nodes.h:1698
const double & xi_gen(const unsigned &k, const unsigned &i) const
Reference to the generalised Lagrangian position. ‘Type’: k; 'Coordinate direction: i....
Definition: nodes.h:1912
double lagrangian_position(const unsigned &i) const
Return lagrangian coordinate either directly or via hanging node representation.
Definition: nodes.cc:3586
double lagrangian_position_gen(const unsigned &k, const unsigned &i) const
Return generalised lagrangian coordinate either directly or via hanging node representation.
Definition: nodes.cc:3619
SolidNode()
Default Constructor.
Definition: nodes.h:1708
void read_values_from_vector(const Vector< double > &vector_of_values, unsigned &index)
Read all data and time history values from the vector starting from index. On return the index will b...
Definition: nodes.cc:3755
virtual ~SolidNode()
Destructor that cleans up the additional memory allocated in SolidNodes.
Definition: nodes.cc:3416
void describe_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the dofs of the Node. The ostream specifies the output stream to which the descr...
Definition: nodes.cc:3671
bool position_is_a_copy(const unsigned &i) const
Return whether the position coordinate i has been copied.
Definition: nodes.h:1790
void pin_position(const unsigned &i)
Pin the nodal position.
Definition: nodes.h:1816
const Data & variable_position() const
Return the variable_position data (const version)
Definition: nodes.h:1759
double & xi(const unsigned &i)
Reference to i-th Lagrangian position.
Definition: nodes.h:1883
bool position_is_a_copy() const
Return whether any position component has been copied.
Definition: nodes.h:1784
void dump(std::ostream &dump_file) const
Dump nodal positions (variable and fixed) and associated data to file for restart.
Definition: nodes.cc:3470
void pin_all()
Pin all the stored variables (Overloaded)
Definition: nodes.h:1842
void unpin_position(const unsigned &i)
Unpin the nodal position.
Definition: nodes.h:1829
void set_external_variable_position_pt(Data *const &data_pt)
Set the variable position data from an external data object.
Definition: nodes.cc:3532
void read(std::ifstream &restart_file)
Read nodal positions (variable and fixed) and associated data from file for restart.
Definition: nodes.cc:3490
double * Xi_position
Storage for the Lagrangian positions.
Definition: nodes.h:1704
void pin_position(const unsigned &k, const unsigned &i)
Pin the generalised nodal position. ‘Type’: k; Coordinate direction: i.
Definition: nodes.h:1823
const double & xi(const unsigned &i) const
Reference to i-th Lagrangian position (const version)
Definition: nodes.h:1892
void add_eqn_numbers_to_vector(Vector< long > &vector_of_eqn_numbers)
Add all equation numbers to the vector in the internal storage order. Overload to add equation number...
Definition: nodes.cc:3799
double & xi_gen(const unsigned &k, const unsigned &i)
Reference to the generalised Lagrangian position. ‘Type’: k; 'Coordinate direction: i.
Definition: nodes.h:1902
void assign_eqn_numbers(unsigned long &global_number, Vector< double * > &dof_pt)
Overload the assign equation numbers routine.
Definition: nodes.cc:3652
void copy(SolidNode *orig_node_pt)
Copy nodal positions and associated data from specified node object.
Definition: nodes.cc:3433
void node_update(const bool &update_all_time_levels_for_new_node=false)
Overload node update function: Since the position of SolidNodes is determined by unknowns,...
Definition: nodes.h:1981
bool position_is_pinned(const unsigned &k, const unsigned &i)
Test whether the k-th type of the i-th coordinate is pinned 0: false; 1: true.
Definition: nodes.h:1810
unsigned nlagrangian() const
Return number of lagrangian coordinates.
Definition: nodes.h:1870
bool position_is_pinned(const unsigned &i)
Test whether the i-th coordinate is pinned, 0: false; 1: true.
Definition: nodes.h:1803
void operator=(const SolidNode &)=delete
Broken assignment operator.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
Definition: timesteppers.h:231
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...