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