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$
7 //LIC//
8 //LIC// $LastChangedDate$
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  {
410  return Eqn_number[i] == Is_segregated_solve_pinned;
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)
417  {if(eqn_number(i)!=Is_pinned) {eqn_number(i) = Is_constrained;}}
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)
422  {if(eqn_number(i)==Is_constrained) {eqn_number(i) = Is_unclassified;}}
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  {
483  Non_halo_proc_ID=non_halo_proc_ID;
484  }
485 
486  /// \short Label the node as not being a halo
487  void set_nonhalo() {Non_halo_proc_ID=-1;}
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
568  if(Copied_data_pt) {Copied_data_pt->remove_copy(this);}
569  //Now null out the storage
570  Copied_data_pt=0; Value=0; Eqn_number=0;
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
635  if(Copied_data_pt) {Copied_data_pt->remove_copy(this);}
636  //Now null out the storage
637  Copied_data_pt=0; Value=0; Eqn_number=0;
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
689  HangInfo() : Master_nodes_pt(0), Master_weights(0), Nmaster(0)
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.
913  AuxNodeUpdateFctPt Aux_node_update_fct_pt;
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.
969  TimeStepper* &position_time_stepper_pt() {return Position_time_stepper_pt;}
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
976  virtual void set_position_time_stepper(TimeStepper*
977  const &position_time_stepper_pt,
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  std::ostringstream error_message;
1229  error_message << "Range Error: Value " << i
1230  << " is not in the range (-1," << n_value << ")";
1231  throw OomphLibError(error_message.str(),
1232  OOMPH_CURRENT_FUNCTION,
1233  OOMPH_EXCEPTION_LOCATION);
1234  }
1235 #endif
1236 
1237  //Test whether the node is geometrically hanging
1238  if(i==-1) {return is_hanging();}
1239  //Otherwise, is the i-th value hanging
1240  else
1241  {
1242  if(Hanging_pt==0)
1243  {
1244  return false;
1245  }
1246  else
1247  {
1248  return (Hanging_pt[i+1]!=0);
1249  }
1250  }
1251  }
1252 
1253  /// Set the hanging data for the i-th value. (hang_pt=0 to make non-hanging)
1254  void set_hanging_pt(HangInfo* const &hang_pt, const int &i);
1255 
1256  /// Label node as non-hanging node by removing all hanging node data.
1257  void set_nonhanging();
1258 
1259  /// \short Resize the number of equations
1260  void resize(const unsigned &n_value);
1261 
1262  /// \short Constrain the positions when the node is made hanging
1263  /// Empty virtual function that is overloaded in SolidNodes
1264  virtual void constrain_positions() {}
1265 
1266  /// \short Unconstrain the positions when the node is made non-hanging
1267  /// Empty virtual function that is overloaded in SolidNodes
1268  virtual void unconstrain_positions() {}
1269 
1270  /// \short Make the node periodic by copying the values from node_pt.
1271  /// Note that the coordinates will always remain independent, even
1272  /// though this may lead to (a little) unrequired information being stored.
1273  /// Broken virtual (only implemented in BoundaryNodes)
1274  virtual void make_periodic(Node* const &node_pt);
1275 
1276  /// \short Make the nodes passed in the vector periodic_nodes share the
1277  /// same data as this node.
1278  virtual void make_periodic_nodes(const Vector<Node*> &periodic_nodes_pt);
1279 
1280  /// \short Return a pointer to set of mesh boundaries that this
1281  /// node occupies; this will be overloaded by BoundaryNodes. The
1282  /// default behaviour is that the Node does not lie on any boundaries
1283  /// so the pointer to the set of boundaries is NULL
1284  virtual void get_boundaries_pt(std::set<unsigned>* &boundaries_pt)
1285  {boundaries_pt = 0;}
1286 
1287  /// \short Test whether the Node lies on a boundary. The "bulk" Node
1288  /// cannot lie on a boundary, so return false. This will be overloaded
1289  /// by BoundaryNodes
1290  virtual bool is_on_boundary() const {return false;}
1291 
1292  /// \short Test whether the node lies on mesh boundary b. The "bulk" Node
1293  /// cannot lie on a boundary, so return false. This will be overloaded by
1294  /// BoundaryNodes
1295  virtual bool is_on_boundary(const unsigned &b) const {return false;}
1296 
1297  /// \short Broken interface for adding the node to the mesh boundary b
1298  /// Essentially here for error reporting.
1299  virtual void add_to_boundary(const unsigned &b);
1300 
1301  /// \short Broken interface for removing the node from the mesh boundary b
1302  /// Here to provide error reporting.
1303  virtual void remove_from_boundary(const unsigned &b);
1304 
1305  /// \short Get the number of boundary coordinates on mesh boundary b.
1306  /// Broken virtual interface provides run-time
1307  /// error checking
1308  virtual unsigned ncoordinates_on_boundary(const unsigned &b);
1309 
1310  /// Have boundary coordinates been set up? Broken virtual interface
1311  /// provides run-time error checking
1312  virtual bool boundary_coordinates_have_been_set_up();
1313 
1314  /// \short Return the vector of the k-th generalised boundary coordinates
1315  /// on mesh boundary b. Broken virtual interface provides run-time
1316  /// error checking
1317  virtual void get_coordinates_on_boundary(const unsigned &b, const unsigned& k,
1318  Vector<double> &boundary_zeta);
1319 
1320  /// \short Set the vector of the k-th generalised boundary coordinates
1321  /// on mesh boundary b. Broken virtual interface provides run-time error
1322  /// checking
1323  virtual void set_coordinates_on_boundary(const unsigned &b, const unsigned& k,
1324  const Vector<double> &boundary_zeta);
1325 
1326  /// \short Return the vector of coordinates on mesh boundary b
1327  /// Broken virtual interface provides run-time error checking
1328  virtual void get_coordinates_on_boundary(const unsigned &b,
1329  Vector<double> &boundary_zeta)
1330  {
1331  get_coordinates_on_boundary(b,0,boundary_zeta);
1332  }
1333 
1334  /// \short Set the vector of coordinates on mesh boundary b
1335  /// Broken virtual interface provides run-time error checking
1336  virtual void set_coordinates_on_boundary(const unsigned &b,
1337  const Vector<double> &boundary_zeta)
1338  {
1339  set_coordinates_on_boundary(b,0,boundary_zeta);
1340  }
1341 
1342 
1343 
1344 
1345 
1346 
1347  /// Mark node as obsolete
1348  void set_obsolete() {Obsolete=true;}
1349 
1350  /// Mark node as non-obsolete
1351  void set_non_obsolete() {Obsolete=false;}
1352 
1353  /// Test whether node is obsolete
1354  bool is_obsolete() {return Obsolete;}
1355 
1356  /// \short Return the i-th value stored at the Node. This interface
1357  /// does NOT take the hanging status of the Node into account.
1358  double raw_value(const unsigned &i) const {return Data::value(i);}
1359 
1360  /// \short Return the i-th value at time level t
1361  /// (t=0: present, t>0: previous). This interface does NOT take the
1362  /// hanging status of the Node into account.
1363  double raw_value(const unsigned &t, const unsigned &i) const
1364  {return Data::value(t,i);}
1365 
1366  /// \short Return i-th value (dofs or pinned) at this node
1367  /// either directly or via hanging node representation.
1368  /// Note that this REDFINES the interface in Data
1369  /// Thus, the present function will be called
1370  /// provided that it is accessed through a pointer to a node
1371  /// i.e. Node* node_pt->value()
1372  /// will take hanging information into account.
1373  /// If a pointer to a Node has been explicitly down-cast to a pointer to
1374  /// Data then the "wrong" (Data) version of the function will be called.
1375  double value(const unsigned &i) const;
1376 
1377  /// \short Return i-th value at time level t (t=0: present, t>0: previous)
1378  /// either directly or via hanging node representation.
1379  /// Note that this REDEFINES the interface in Data
1380  /// Thus, the present function will be called
1381  /// provided that it is accessed through a pointer to a node
1382  /// i.e. Node* node_pt->value()
1383  /// will take hanging information into account.
1384  /// If a pointer to a Node has been explicitly down-cast to a pointer to
1385  /// Data then the "wrong" (Data) version of the function will be called.
1386  double value(const unsigned &t, const unsigned &i) const;
1387 
1388  /// \short Compute Vector of values for the Data value
1389  /// taking the hanging node status into account.
1390  /// Note that this REDEFINES the interface in Data
1391  /// Thus, the present function will be called
1392  /// provided that it is accessed through a pointer to a node
1393  /// i.e. Node* node_pt->value()
1394  /// will take hanging information into account.
1395  /// If a pointer to a Node has been explicitly down-cast to a pointer to
1396  /// Data then the "wrong" (Data) version of the function will be called.
1397  void value(Vector<double>& values) const;
1398 
1399  /// Return vector of values calculated using value(vector).
1401  {
1402  Vector<double> vals(nvalue(), 0.0);
1403  value(vals);
1404  return vals;
1405  }
1406 
1407  /// \short Compute Vector of values (dofs or pinned) in this data
1408  /// at time level t (t=0: present; t>0: previous). This interface
1409  /// explicitly takes the hanging status into account.
1410  /// Thus, the present function will be called
1411  /// provided that it is accessed through a pointer to a node
1412  /// i.e. Node* node_pt->value()
1413  /// will take hanging information into account.
1414  /// If a pointer to a Node has been explicitly down-cast to a pointer to
1415  /// Data then the "wrong" (Data) version of the function will be called.
1416  void value(const unsigned& t, Vector<double>& values) const;
1417 
1418  /// \short Compute Vector of nodal positions
1419  /// either directly or via hanging node representation
1420  void position(Vector<double>& pos) const;
1421 
1422  /// Return vector of position of node at current time.
1424  {
1425  Vector<double> pos(ndim(), 0.0);
1426  position(pos);
1427  return pos;
1428  }
1429 
1430  /// \short Compute Vector of nodal position at time level t
1431  /// (t=0: current; t>0: previous timestep),
1432  /// either directly or via hanging node representation.
1433  void position(const unsigned &t, Vector<double>& pos) const;
1434 
1435  /// \short Return i-th nodal coordinate
1436  /// either directly or via hanging node representation.
1437  double position(const unsigned &i) const;
1438 
1439  /// \short Return i-th nodal coordinate at time level t
1440  /// (t=0: current; t>0: previous time level),
1441  /// either directly or via hanging node representation.
1442  double position(const unsigned &t, const unsigned &i) const;
1443 
1444  /// \short Return generalised nodal coordinate
1445  /// either directly or via hanging node representation.
1446  double position_gen(const unsigned &k, const unsigned &i) const;
1447 
1448  /// \short Return generalised nodal coordinate at time level t
1449  /// (t=0: current; t>0: previous time level),
1450  /// either directly or via hanging node representation.
1451  double position_gen(const unsigned &t, const unsigned &k,
1452  const unsigned &i) const;
1453 
1454  /// \short Return the i-th component of nodal velocity: dx/dt,
1455  /// either directly or via hanging node representation.
1456  double dposition_dt(const unsigned &i) const;
1457 
1458  /// \short Return the i-th component of j-th derivative of nodal position:
1459  /// d^jx/dt^j either directly or via hanging node representation
1460  double dposition_dt(const unsigned &j, const unsigned &i) const;
1461 
1462  /// \short i-th component of time derivative (velocity) of the
1463  /// generalised position, dx(k,i)/dt. `Type': k; Coordinate direction: i.
1464  /// This function uses the hanging node representation if necessary.
1465  double dposition_gen_dt(const unsigned &k, const unsigned &i) const;
1466 
1467 
1468  /// \short i-th component of j-th time derivative (velocity) of the
1469  /// generalised position, d^jx(k,i)/dt^j. `Type': k; Coordinate direction: i.
1470  /// This function uses the hanging node representation if necessary
1471  double dposition_gen_dt(const unsigned &j, const unsigned &k,
1472  const unsigned &i) const;
1473 
1474  /// \short Interface for functions that update the nodal
1475  /// position using algebraic remeshing strategies. The
1476  /// interface is common to SpineNodes, AlgebraicNodes and
1477  /// MacroElementNodeUpdateNodes.
1478  /// The default is that the node does not "update itself"
1479  /// i.e. it is fixed in space. When implemented, this
1480  /// function should also execute the Node's auxiliary
1481  /// node update function (if any).
1482  virtual void node_update(const bool&
1483  update_all_time_levels_for_new_node=false) { }
1484 
1485 
1486  /// \short Set pointer to auxiliary update function -- this
1487  /// can be used to update any nodal values following the update
1488  /// of the nodal position. This is needed e.g. to update the no-slip
1489  /// condition on moving boundaries.
1490  void set_auxiliary_node_update_fct_pt(AuxNodeUpdateFctPt
1491  aux_node_update_fct_pt)
1492  {
1493  // Set pointer (by default it's set to NULL)
1494  Aux_node_update_fct_pt=aux_node_update_fct_pt;
1495  }
1496 
1497 
1498 
1499  /// \short Boolean to indicate if node has a pointer to
1500  /// and auxiliary update function.
1502  {
1503  return (Aux_node_update_fct_pt!=0);
1504  }
1505 
1506  /// \short Execute auxiliary update function (if any) -- this
1507  /// can be used to update any nodal values following the update
1508  /// of the nodal position. This is needed e.g. to update the no-slip
1509  /// condition on moving boundaries.
1511  {
1512  if (Aux_node_update_fct_pt!=0)
1513  {
1514  Aux_node_update_fct_pt(this);
1515  }
1516  }
1517 
1518  /// \short Return the number of geometric data that affect the nodal
1519  /// position. The default value is zero (node is stationary)
1520  virtual inline unsigned ngeom_data() const {return 0;}
1521 
1522  /// \short Return a pointer to an array of all (geometric) data that affect
1523  /// the nodal position. The default value is zero (node is stationary)
1524  virtual inline Data** all_geom_data_pt() {return 0;}
1525 
1526  /// \short Return the number of geometric objects that affect the nodal
1527  /// position. The default value is zero (node is stationary)
1528  virtual inline unsigned ngeom_object() const {return 0;}
1529 
1530  /// \short Return a pointer to an array of all (geometric) objects that affect
1531  /// the nodal position. The default value is zero (node is stationary)
1532  virtual inline GeomObject** all_geom_object_pt() {return 0;}
1533 
1534  ///Output nodal position
1535  void output(std::ostream &outfile);
1536 
1537 
1538 #ifdef OOMPH_HAS_MPI
1539 
1540  /// \short Add all data and time history values to the vector.
1541  /// Overloaded to add the position information as well.
1542  void add_values_to_vector(Vector<double> &vector_of_values);
1543 
1544  /// \short Read all data and time history values from the vector
1545  /// starting from index. On return the index will be
1546  /// set the value at the end of the data that has been read in
1547  /// Overload to also read the position information.
1548  void read_values_from_vector(const Vector<double> & vector_of_values,
1549  unsigned &index);
1550 
1551 #endif
1552 
1553 
1554 };
1555 
1556 //=====================================================================
1557 /// \short A Class for nodes that deform elastically (i.e. position is an
1558 /// unknown in the problem). The idea is that the Eulerian positions are
1559 /// stored in a Data object and the Lagrangian coordinates are stored in
1560 /// addition. The pointer that addresses the Eulerian positions is
1561 /// set to the pointer to Value in the Data object. Hence,
1562 /// SolidNode uses knowledge of the internal structure of Data and
1563 /// must be a friend of the Data class.
1564 /// In order to allow a mesh to deform via an elastic-style
1565 /// equation in deforming-domain problems, the positions are stored
1566 /// separately from the values, so that elastic problems may be
1567 /// combined with any other type of problem.
1568 //=====================================================================
1569 class SolidNode : public Node
1570 {
1571  private:
1572 
1573  /// \short Private function to check that the arguments to the position
1574  /// functions are in range
1575  void xi_gen_range_check(const unsigned &k, const unsigned &i) const;
1576 
1577  protected:
1578 
1579  /// Number of Lagrangian coordinates of the node
1580  unsigned Nlagrangian;
1581 
1582  /// \short Number of types of Lagrangian coordinates used to interpolate
1583  /// the Lagrangian coordinates within the element
1585 
1586  /// Pointer to data that will hold variable positions in elastic nodes
1588 
1589  /// \short Storage for the Lagrangian positions
1590  double *Xi_position;
1591 
1592 public:
1593 
1594  /// \short Default Constructor
1595  SolidNode() : Node() {}
1596 
1597  /// \short Steady constructor. The node has n_lagrangian Lagrangian
1598  /// coordinates of n_lagrangian_type types (1 for Lagrange elements,
1599  /// 2 for 1D Hermite etc.).
1600  /// The Eulerian dimension of the Node is n_dim and we have n_position_type
1601  /// (generalised) Eulerian coordinates. There are
1602  /// initial_n_value values stored at
1603  /// this node.
1604  SolidNode(const unsigned &n_lagrangian,
1605  const unsigned &n_lagrangian_type,
1606  const unsigned &n_dim,
1607  const unsigned &n_position_type,
1608  const unsigned &initial_n_value);
1609 
1610  /// \short Unsteady constructor.
1611  /// Allocates storage for initial_n_value nodal values with history values
1612  /// as required by timestepper.
1613  /// The node has n_lagrangian Lagrangian coordinates of
1614  /// n_lagrangian_type types (1 for Lagrange elements, 2 for 1D Hermite etc.)/
1615  /// The Eulerian dimension of the Node is n_dim and we have n_position_type
1616  /// generalised Eulerian coordinates.
1618  const unsigned &n_lagrangian,
1619  const unsigned &n_lagrangian_type,
1620  const unsigned &n_dim,
1621  const unsigned &Nposition_type,
1622  const unsigned &initial_n_value);
1623 
1624  ///Destructor that cleans up the additional memory allocated in SolidNodes
1625  virtual ~SolidNode();
1626 
1627  /// Broken copy constructor
1628  SolidNode(const SolidNode& solid_node) : Node()
1629  {
1630  BrokenCopy::broken_copy("SolidNode");
1631  }
1632 
1633  /// Broken assignment operator
1634  void operator=(const SolidNode&)
1635  {
1636  BrokenCopy::broken_assign("SolidNode");
1637  }
1638 
1639  /// \short Copy nodal positions and associated data from specified
1640  /// node object
1641  void copy(SolidNode* orig_node_pt);
1642 
1643  /// \short Dump nodal positions (variable and fixed) and associated
1644  /// data to file for restart
1645  void dump(std::ostream& dump_file) const;
1646 
1647  /// \short Read nodal positions (variable and fixed) and associated
1648  /// data from file for restart
1649  void read(std::ifstream& restart_file);
1650 
1651  ///Return the variable_position data (const version)
1652  const Data &variable_position() const {return *Variable_position_pt;}
1653 
1654  ///Pointer to variable_position data (const version)
1655  Data* const &variable_position_pt() const {return Variable_position_pt;}
1656 
1657  ///Set the variable position data from an external data object
1658  void set_external_variable_position_pt(Data* const &data_pt);
1659 
1660  /// \short Set a new position timestepper be resizing the appropriate storage
1661  /// Overloaded from the basic implementation to take into account the
1662  /// fact that position is now Data
1663  void set_position_time_stepper(TimeStepper*
1664  const &position_time_stepper_pt,
1665  const bool &preserve_existing_data);
1666 
1667  /// \short Overload the check whether the pointer parameter_pt addresses
1668  /// position data values
1669  bool does_pointer_correspond_to_position_data(double* const &parameter_pt);
1670 
1671  ///Return whether any position component has been copied
1672  bool position_is_a_copy() const {return Variable_position_pt->is_a_copy();}
1673 
1674  ///Return whether the position coordinate i has been copied
1675  bool position_is_a_copy(const unsigned &i) const
1676  {return Variable_position_pt->is_a_copy(Nposition_type*i);}
1677 
1678  /// \short Return the equation number for generalised Eulerian coordinate:
1679  /// type of coordinate: k, coordinate direction: i.
1680  const long &position_eqn_number(const unsigned &k,
1681  const unsigned &i) const
1682  {return Variable_position_pt->eqn_number(Nposition_type*i+k);}
1683 
1684  /// Test whether the i-th coordinate is pinned, 0: false; 1: true
1685  bool position_is_pinned(const unsigned &i)
1686  {return Variable_position_pt->is_pinned(Nposition_type*i);}
1687 
1688  /// \short Test whether the k-th type of the i-th coordinate is pinned
1689  /// 0: false; 1: true
1690  bool position_is_pinned(const unsigned &k, const unsigned &i)
1691  {return Variable_position_pt->is_pinned(Nposition_type*i+k);}
1692 
1693  /// Pin the nodal position
1694  void pin_position(const unsigned &i)
1695  {return Variable_position_pt->pin(Nposition_type*i);}
1696 
1697  /// \short Pin the generalised nodal position.
1698  /// `Type': k; Coordinate direction: i.
1699  void pin_position(const unsigned &k, const unsigned &i)
1700  {return Variable_position_pt->pin(Nposition_type*i+k);}
1701 
1702  /// Unpin the nodal position
1703  void unpin_position(const unsigned &i)
1704  {return Variable_position_pt->unpin(Nposition_type*i);}
1705 
1706  /// \short Unpin the generalised nodal position.
1707  /// `Type': k; Coordinate direction: i.
1708  void unpin_position(const unsigned &k, const unsigned &i)
1709  {return Variable_position_pt->unpin(Nposition_type*i+k);}
1710 
1711  /// Pin all the stored variables (Overloaded)
1712  void pin_all()
1713  {
1714  Node::pin_all();
1715  Variable_position_pt->pin_all();
1716  }
1717 
1718  /// Unpin all the stored variables (Overloaded)
1719  void unpin_all()
1720  {
1721  Node::unpin_all();
1722  Variable_position_pt->unpin_all();
1723  }
1724 
1725  /// \short Overload the constrain positions function to constrain all position
1726  /// values
1727  inline void constrain_positions() {Variable_position_pt->constrain_all();}
1728 
1729  /// \short Overload the unconstrain positions function to unconstrain all
1730  /// position values
1731  inline void unconstrain_positions() {Variable_position_pt->unconstrain_all();}
1732 
1733  ///Return number of lagrangian coordinates
1734  unsigned nlagrangian() const {return Nlagrangian;}
1735 
1736  ///\short Number of types of Lagrangian coordinates used to interpolate
1737  /// the Lagrangian coordinates within the element
1738  unsigned nlagrangian_type() const {return Nlagrangian_type;}
1739 
1740  /// Reference to i-th Lagrangian position
1741  double &xi(const unsigned &i)
1742  {
1743 #ifdef RANGE_CHECKING
1744  xi_gen_range_check(0,i);
1745 #endif
1746  return Xi_position[Nlagrangian_type*i];
1747  }
1748 
1749  /// Reference to i-th Lagrangian position (const version)
1750  const double &xi(const unsigned &i) const
1751  {
1752 #ifdef RANGE_CHECKING
1753  xi_gen_range_check(0,i);
1754 #endif
1755  return Xi_position[Nlagrangian_type*i];
1756  }
1757 
1758  /// \short Reference to the generalised Lagrangian position.
1759  /// `Type': k; 'Coordinate direction: i.
1760  double &xi_gen(const unsigned &k, const unsigned &i)
1761  {
1762 #ifdef RANGE_CHECKING
1763  xi_gen_range_check(k,i);
1764 #endif
1765  return Xi_position[Nlagrangian_type*i + k];
1766  }
1767 
1768  /// \short Reference to the generalised Lagrangian position.
1769  /// `Type': k; 'Coordinate direction: i. (const version
1770  const double &xi_gen(const unsigned &k, const unsigned &i) const
1771  {
1772 #ifdef RANGE_CHECKING
1773  xi_gen_range_check(k,i);
1774 #endif
1775  return Xi_position[Nlagrangian_type*i + k];
1776  }
1777 
1778  ///\short Return lagrangian coordinate either directly or via
1779  ///hanging node representation
1780  double lagrangian_position(const unsigned &i) const;
1781 
1782  ///\short Return generalised lagrangian coordinate either directly or via
1783  ///hanging node representation
1784  double lagrangian_position_gen(const unsigned &k, const unsigned &i)
1785  const;
1786 
1787  ///Overload the assign equation numbers routine
1788  void assign_eqn_numbers(unsigned long &global_number,
1789  Vector<double *> &dof_pt);
1790 
1791  /// \short Function to describe the dofs of the Node. The ostream
1792  /// specifies the output stream to which the description
1793  /// is written; the string stores the currently
1794  /// assembled output that is ultimately written to the
1795  /// output stream by Data::describe_dofs(...); it is typically
1796  /// built up incrementally as we descend through the
1797  /// call hierarchy of this function when called from
1798  /// Problem::describe_dofs(...)
1799  void describe_dofs(std::ostream& out,const std::string& current_string) const;
1800 
1801  ///\short Overload the function add_values_to_map so that it also adds
1802  /// the variable position data
1803  void add_value_pt_to_map(std::map<unsigned,double*> &map_of_value_pt);
1804 
1805 #ifdef OOMPH_HAS_MPI
1806 
1807  /// \short Add all data, position and time history values to the vector
1808  /// Overload to add the Lagrangian coordinates to the vector
1809  void add_values_to_vector(Vector<double> &vector_of_values);
1810 
1811  /// \short Read all data and time history values from the vector
1812  /// starting from index. On return the index will be
1813  /// set the value at the end of the data that has been read in
1814  /// Overload to add the position information and Lagrangian coordinates
1815  void read_values_from_vector(const Vector<double> & vector_of_values,
1816  unsigned &index);
1817 
1818 
1819  /// \short Add all equation numbers to the vector in
1820  /// the internal storage order. Overload to add equation numbers
1821  /// associated with the positional dofs
1822  void add_eqn_numbers_to_vector(Vector<long> &vector_of_eqn_numbers);
1823 
1824  /// \short Read all equation numbers from the vector
1825  /// starting from index. On return the index will be
1826  /// set to the value at the end of the data that has been read in
1827  /// Overload to include the equation numbrs associated with the
1828  /// positional dofs
1830  const Vector<long> & vector_of_eqn_numbers, unsigned &index);
1831 
1832 #endif
1833 
1834 
1835  /// \short Overload node update function: Since the position
1836  /// of SolidNodes is determined by unknowns, there's nothing
1837  /// to be done apart from performing the auxiliary node
1838  /// update function (if any)
1839  void node_update(const bool& update_all_time_levels_for_new_node=false)
1840  {
1841  perform_auxiliary_node_update_fct();
1842  }
1843 
1844 };
1845 
1846 
1847 
1848 //======================================================================
1849 /// \short A class that contains the information required by Nodes that
1850 /// are located on Mesh boundaries. A BoundaryNode of a particular type
1851 /// is obtained by combining a given Node with this class.
1852 /// By differentiating between Nodes and BoundaryNodes we avoid a lot
1853 /// of un-necessary storage in the bulk Nodes.
1854 //======================================================================
1856 {
1857  private:
1858 
1859  /// \short Pointer to a map of pointers to
1860  /// intrinsic boundary coordinates of the Node,
1861  /// indexed by the boundary number. If the Node does not lie
1862  /// on a boundary this map should never be queried because
1863  /// unnecessary storage will then be allocated. Hence, it
1864  /// can only be accessed via the appropriate set and get functions.
1865  std::map<unsigned, DenseMatrix<double>*>* Boundary_coordinates_pt;
1866 
1867  /// \short Pointer to set of mesh boundaries occupied by the Node;
1868  /// NULL if the Node is not on any boundaries
1869  std::set<unsigned>* Boundaries_pt;
1870 
1871  protected:
1872 
1873 
1874  /// \short Pointer to a map,
1875  /// indexed by the face element identifier it returns
1876  /// the position of the first face element value.
1877  /// If the Node does not lie on a face element
1878  /// this map should never be queried.
1880 
1881  /// \short If the BoundaryNode is periodic, this pointer is set to
1882  /// the BoundaryNode whose data it shares
1884 
1885  /// \short Helper function that is used to turn BoundaryNodes into
1886  /// peridic boundary nodes by setting the data values of
1887  /// copied_node_pt to those of original_node_pt.
1888  void make_node_periodic(Node* const &node_pt,
1889  Node* const &original_node_pt);
1890 
1891  /// \short Helper function that is used to turn BoundaryNodes into
1892  /// periodic boundary nodes by setting the data values of the nodes
1893  /// in the vector periodic_copies_pt to be the same as those
1894  /// in node_pt.
1895  void make_nodes_periodic(Node* const &node_pt,
1896  Vector<Node*> const &periodic_copies_pt);
1897 
1898  public:
1899 
1900  /// \short Member function that allocates storage for a given
1901  /// number of additional degrees of freedom, n_additional_value,
1902  /// associated with a particular face_id to the Node
1903  /// node_pt
1904  virtual void assign_additional_values_with_face_id(
1905  const unsigned &n_additional_value, const unsigned &face_id=0)=0;
1906 
1907  /// \short Return pointer to the map giving
1908  /// the index of the first face element value.
1909  std::map<unsigned, unsigned>*
1911  {
1912  return Index_of_first_value_assigned_by_face_element_pt;
1913  }
1914 
1915  /// \short Return the index of the first value associated with
1916  /// the i-th face element value. If no argument is specified
1917  /// we return the index associated with the first (and assumed to be only)
1918  /// face element attached to this node. Throws error only in paranoid mode
1919  /// if no values have been set by any FaceElements. If you want to
1920  /// catch such cases gracefully in all circumstances (there are examples
1921  /// with complex unstructured 3D meshes where it's not clear a priori
1922  /// if a node has been resized by FaceElements) use alternative
1923  /// version (with leading bool arguments) that always checks and throws
1924  /// so exceptions can be caught gracefully. Returns UINT_MAX if error.
1926  const unsigned& face_id=0) const
1927  {
1928 #ifdef PARANOID
1929  if (Index_of_first_value_assigned_by_face_element_pt==0)
1930  {
1931  std::ostringstream error_message;
1932  error_message
1933  << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
1934  << "Pointer must be set via call to: \n\n"
1935  << " BoundaryNode::assign_additional_values_with_face_id(...), \n\n"
1936  << "typically from FaceElement::add_additional_values(...).";
1937  throw OomphLibError(error_message.str(),
1938  OOMPH_CURRENT_FUNCTION,
1939  OOMPH_EXCEPTION_LOCATION);
1940  return UINT_MAX;
1941  }
1942 #endif
1943  return (*Index_of_first_value_assigned_by_face_element_pt)[face_id];
1944  }
1945 
1946 
1947 
1948  /// \short Return the index of the first value associated with
1949  /// the i-th face element value. If no argument id is specified
1950  /// we return the index associated with the first (and assumed to be only)
1951  /// face element attached to this node.
1952  /// If no values have been set by any FaceElements and
1953  /// throw_if_no_value_assigned_by_face_element is set to true, this
1954  /// is caught gracefully in all circumstances (there are examples
1955  /// with complex unstructured 3D meshes where it's not clear a priori
1956  /// if a node has been resized by FaceElements) by throwing an OomphLibError
1957  /// that can be caught gracefully. If throw_quietly is set to true
1958  /// we throw an OomphLibQuietException instead. You can catch either
1959  /// by catching the underlying std::runtime_error. In PARANOID mode
1960  /// we check regardless of the setting of
1961  /// throw_if_no_value_assigned_by_face_element (but respect the
1962  /// request for quietness). Returns UINT_MAX if error.
1964  const bool& throw_if_no_value_assigned_by_face_element,
1965  const bool& throw_quietly,
1966  const unsigned& face_id=0) const
1967  {
1968 
1969  // Over-rule if paranoia rules
1970  bool local_throw_if_no_value_assigned_by_face_element=
1971  throw_if_no_value_assigned_by_face_element;
1972 #ifdef PARANOID
1973  local_throw_if_no_value_assigned_by_face_element=true;
1974 #endif
1975 
1976  if (local_throw_if_no_value_assigned_by_face_element)
1977  {
1978  if (Index_of_first_value_assigned_by_face_element_pt==0)
1979  {
1980  std::ostringstream error_message;
1981  error_message
1982  << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
1983  << "Pointer must be set via call to: \n\n"
1984  << " BoundaryNode::assign_additional_values_with_face_id(...), \n\n"
1985  << "typically from FaceElement::add_additional_values(...).";
1986 
1987  if (throw_quietly)
1988  {
1989  throw OomphLibQuietException();
1990  }
1991  else
1992  {
1993  throw OomphLibError(
1994  error_message.str(),
1995  OOMPH_CURRENT_FUNCTION,
1996  OOMPH_EXCEPTION_LOCATION);
1997  }
1998  return UINT_MAX;
1999  }
2000  }
2001  return (*Index_of_first_value_assigned_by_face_element_pt)[face_id];
2002  }
2003 
2004  /// \short Return the number of values associated with
2005  /// the i-th face element field. If no argument is specified
2006  /// we return the value associated with the first (and assumed to be only)
2007  /// face element attached to this node. Throws error only in paranoid mode
2008  /// if no values have been set by any FaceElements. If you want to
2009  /// catch such cases gracefully in all circumstances (there are examples
2010  /// with complex unstructured 3D meshes where it's not clear a priori
2011  /// if a node has been resized by FaceElements) use alternative
2012  /// version (with leading bool arguments) that always checks and throws
2013  /// so exceptions can be caught gracefully. Returns UINT_MAX if error.
2014  virtual unsigned nvalue_assigned_by_face_element(const unsigned& face_id=0)
2015  const=0;
2016 
2017  /// \short Default constructor, set the pointers to the storage to NULL
2019  Boundary_coordinates_pt(0),
2020  Boundaries_pt(0),
2021  Index_of_first_value_assigned_by_face_element_pt(0),
2022  Copied_node_pt(0){}
2023 
2024  /// \short Destructor, clean up any allocated storage for the boundaries
2025  virtual ~BoundaryNodeBase();
2026 
2027  /// Broken copy constructor
2028  BoundaryNodeBase(const BoundaryNodeBase& boundary_node_base)
2029  { BrokenCopy::broken_copy("BoundaryNodeBase");}
2030 
2031  /// Broken assignment operator
2033  {BrokenCopy::broken_assign("BoundaryNodeBase");}
2034 
2035  /// Have boundary coordinates been set up?
2037  {
2038  return (Boundary_coordinates_pt!=0);
2039  }
2040 
2041  /// \short Access to pointer to set of mesh boundaries that this
2042  /// node occupies; NULL if the node is not on any boundary
2043  void get_boundaries_pt(std::set<unsigned>* &boundaries_pt)
2044  {boundaries_pt = Boundaries_pt;}
2045 
2046  /// \short Add the node to the mesh boundary b
2047  void add_to_boundary(const unsigned &b);
2048 
2049  /// \short Remove the node from the mesh boundary b
2050  void remove_from_boundary(const unsigned &b);
2051 
2052  /// \short Test whether the node lies on a boundary
2053  bool is_on_boundary() const {return !(Boundaries_pt==0);}
2054 
2055  /// \short Test whether the node lies on mesh boundary b
2056  bool is_on_boundary(const unsigned &b) const;
2057 
2058  /// \short Get the number of boundary coordinates on mesh boundary b
2059  unsigned ncoordinates_on_boundary(const unsigned &b);
2060 
2061  /// \short Return the vector of boundary coordinates on mesh boundary b
2062  void get_coordinates_on_boundary(const unsigned &b,
2063  Vector<double> &boundary_zeta)
2064  {
2065  // Just return the zero-th one
2066  get_coordinates_on_boundary(b,0,boundary_zeta);
2067  }
2068 
2069 
2070  /// \short Set the vector of boundary coordinates on mesh boundary b
2071  void set_coordinates_on_boundary(const unsigned &b,
2072  const Vector<double> &boundary_zeta)
2073  {
2074  // Just do the zero-th one
2075  set_coordinates_on_boundary(b,0,boundary_zeta);
2076  }
2077 
2078  /// \short Return the vector of the k-th generalised boundary coordinates
2079  /// on mesh boundary b.
2080  void get_coordinates_on_boundary(const unsigned &b, const unsigned& k,
2081  Vector<double> &boundary_zeta);
2082 
2083  /// \short Set the vector of the k-th generalised boundary coordinates on
2084  /// mesh boundary b.
2085  void set_coordinates_on_boundary(const unsigned &b, const unsigned& k,
2086  const Vector<double> &boundary_zeta);
2087 
2088 };
2089 
2090 
2091 //====================================================================
2092 /// \short A template Class for BoundaryNodes; that is Nodes that MAY live
2093 /// on the boundary of a Mesh. The class is formed by a simple
2094 /// composition of the template parameter NODE_TYPE, which must be
2095 /// a Node class and the BoundaryNodeBase class.
2096 /// Final overloading of functions is always in favour of the
2097 /// BoundaryNodeBase implementation; i.e. these nodes can live on
2098 /// boundaries.
2099 //===================================================================
2100 template<class NODE_TYPE>
2101 class BoundaryNode: public NODE_TYPE, public BoundaryNodeBase
2102 {
2103  private:
2104 
2105  /// \short Set pointers to the copied data used when we have periodic nodes
2107  {
2108 #ifdef PARANOID
2109  if(Copied_node_pt==0)
2110  {
2111  throw OomphLibError("BoundaryNode has not been copied",
2112  OOMPH_CURRENT_FUNCTION,
2113  OOMPH_EXCEPTION_LOCATION);
2114  }
2115 #endif
2116 
2117  //Set the number of values
2118  this->Nvalue = Copied_node_pt->nvalue();
2119  this->Value = Copied_node_pt->Value;
2120  this->Eqn_number = Copied_node_pt->Eqn_number;
2121  //We won't ever need to worry about updating position pointers
2122  //because periodic solid problems are handled using lagrange multipliers.
2123 
2124  // Cast Copied_node_pt to BoundaryNode
2125  BoundaryNode<NODE_TYPE>* cast_copied_node_pt =
2126  dynamic_cast<BoundaryNode<NODE_TYPE>*>(Copied_node_pt);
2127 
2128  // Check that dynamic cast has worked
2129  if(cast_copied_node_pt)
2130  {
2131  this->index_of_first_value_assigned_by_face_element_pt() =
2132  cast_copied_node_pt->index_of_first_value_assigned_by_face_element_pt();
2133  }
2134  else
2135  {
2136  std::ostringstream error_stream;
2137  error_stream
2138  << "Copied_node_pt is not of type BoundaryNode*"
2139  << std::endl;
2140  throw OomphLibError(error_stream.str(),
2141  OOMPH_CURRENT_FUNCTION,
2142  OOMPH_EXCEPTION_LOCATION);
2143  }
2144  }
2145 
2146  /// \short Copy over additional information so that if the node
2147  /// is periodic it can remain active if the node that holds the periodic
2148  /// data is deleted
2150  {
2151  //Only worry about the face index if it has been assigned
2152  if(this->index_of_first_value_assigned_by_face_element_pt()!=0)
2153  {
2154  // Allocate storage for the index of first value assigned by face element
2155  this->index_of_first_value_assigned_by_face_element_pt() =
2156  new std::map<unsigned,unsigned>;
2157 
2158  // Cast copied_node_pt to BoundaryNode
2159  // This will never work because when this is called the node is
2160  // no longer a boundary node
2161  BoundaryNode<NODE_TYPE>* cast_copied_node_pt =
2162  dynamic_cast<BoundaryNode<NODE_TYPE>*>(Copied_node_pt);
2163 
2164  // Check that dynamic cast has worked
2165  if(cast_copied_node_pt)
2166  {
2167  // Initialise the values in the map to be those of the original data
2168  //std::map<unsigned,unsigned>::const_iterator it =
2169  // (*(cast_copied_node_pt->
2170  // index_of_first_value_assigned_by_face_element_pt())).begin();
2171  std::map<unsigned,unsigned>::const_iterator end =
2172  (*(cast_copied_node_pt->
2173  index_of_first_value_assigned_by_face_element_pt())).end();
2174  for(std::map<unsigned,unsigned>::const_iterator it =
2175  (*(cast_copied_node_pt->
2176  index_of_first_value_assigned_by_face_element_pt())).begin();
2177  it!=end;it++)
2178  {
2179  (*(this->
2180  index_of_first_value_assigned_by_face_element_pt()))[it->first] =
2181  it->second;
2182  }
2183  }
2184  }
2185  }
2186 
2187 public:
2188 
2189 
2190  /// \short Clear pointers to the copied data used when we have periodic nodes.
2191  /// The shallow (pointer) copy is turned into a deep copy by allocating
2192  /// new data and copying the actual values across.
2194  {
2195 #ifdef PARANOID
2196  if(Copied_node_pt==0)
2197  {
2198  throw OomphLibError("BoundaryNode has not been copied",
2199  OOMPH_CURRENT_FUNCTION,
2200  OOMPH_EXCEPTION_LOCATION);
2201  }
2202 #endif
2203 
2204  //Simply zeroing these will cause problems during unrefinement because the
2205  //original could be deleted, but the "copy" remain.
2206  //Instead we allocate new storage and copy values over from the original.
2207 
2208  //Get the number of values and time storage
2209  //(must be the same as the original)
2210  const unsigned n_value = this->nvalue();
2211  const unsigned n_tstorage = this->ntstorage();
2212 
2213  //Allocate storage for equation numbers
2214  this->Eqn_number = new long[n_value];
2215 
2216  //Allocate storage for the values
2217  this->Value = new double*[n_value];
2218 
2219  //Allocate all data values in one big array
2220  double *values = new double[n_value*n_tstorage];
2221 
2222  //Set the pointers to the data values and equation numbers
2223  for(unsigned i=0;i<n_value;++i)
2224  {
2225  //Set the pointers
2226  this->Value[i] = &values[i*n_tstorage];
2227  //Initialise all the values to be those of the original data
2228  for(unsigned t=0;t<n_tstorage;++t)
2229  {this->Value[i][t] = Copied_node_pt->value(t,i);}
2230 
2231  //Copy over the values of the equation numbers
2232  this->Eqn_number[i] = Copied_node_pt->eqn_number(i);
2233  }
2234 
2235  //The node is no longer a copy
2236  Copied_node_pt=0;
2237  }
2238 
2239 
2240  /// \short Default Constructor
2241  BoundaryNode() : NODE_TYPE(), BoundaryNodeBase() { }
2242 
2243  /// \short Steady constructor, for a BoundaryNode of spatial dimension n_dim.
2244  /// Simply passes all arguments through to the underlying Node constructor
2245  /// which allocates storage for initial_n_value values.
2246  /// NPosition_type is the number of coordinate types
2247  /// needed in the mapping between local and global coordinates
2248  /// (e.g. 1 for Lagrange-type elements; 2 for 1D Hermite elements; 4 for
2249  /// 2D Hermite elements, etc).
2250  BoundaryNode(const unsigned &n_dim, const unsigned &n_position_type,
2251  const unsigned &initial_n_value) :
2252  NODE_TYPE(n_dim,n_position_type,initial_n_value), BoundaryNodeBase() { }
2253 
2254  /// \short Unsteady constructor for a BoundaryNode
2255  /// of spatial dimension n_dim. Simply passes all arguments through to
2256  /// the underlygin Node constructor which
2257  /// allocates storage for initial_n_value values with
2258  /// history values as required by the timestepper.
2259  /// n_position_type: # of coordinate
2260  /// types needed in the mapping between local and global coordinates
2261  /// (e.g. 1 for Lagrange-type elements; 2 for 1D Hermite elements; 4 for
2262  /// 2D Hermite elements).
2263  BoundaryNode(TimeStepper* const &time_stepper_pt, const unsigned &n_dim,
2264  const unsigned &n_position_type,
2265  const unsigned &initial_n_value) :
2266  NODE_TYPE(time_stepper_pt,n_dim,n_position_type,initial_n_value),
2267  BoundaryNodeBase() { }
2268 
2269  /// \short Steady constructor for Solid-type boundary nodes.
2270  /// The node has n_lagrangian Lagrangian
2271  /// coordinates of n_lagrangian_type types (1 for Lagrange elements,
2272  /// 2 for 1D Hermite etc.).
2273  /// The Eulerian dimension of the Node is n_dim and we have n_position_type
2274  /// (generalised) Eulerian coordinates. There are
2275  /// initial_n_value values stored at
2276  /// this node.
2277  BoundaryNode(const unsigned &n_lagrangian,
2278  const unsigned &n_lagrangian_type,
2279  const unsigned &n_dim,
2280  const unsigned &n_position_type,
2281  const unsigned &initial_n_value) :
2282  NODE_TYPE(n_lagrangian,n_lagrangian_type,n_dim,n_position_type,
2283  initial_n_value), BoundaryNodeBase() {}
2284 
2285  /// \short Unsteady constructor for Solid-type boundary nodes
2286  /// Allocates storage for initial_n_value nodal values with history values
2287  /// as required by timestepper.
2288  /// The node has n_lagrangian Lagrangian coordinates of
2289  /// n_lagrangian_type types (1 for Lagrange elements, 2 for 1D Hermite etc.)/
2290  /// The Eulerian dimension of the Node is n_dim and we have n_position_type
2291  /// generalised Eulerian coordinates.
2293  const unsigned &n_lagrangian,
2294  const unsigned &n_lagrangian_type,
2295  const unsigned &n_dim,
2296  const unsigned &n_position_type,
2297  const unsigned &initial_n_value)
2298  : NODE_TYPE(time_stepper_pt,n_lagrangian,n_lagrangian_type,n_dim,
2299  n_position_type,initial_n_value),
2300  BoundaryNodeBase() {}
2301 
2302  /// \short Destructor resets pointers if
2304  {
2305  //If there are any copies of this Node
2306  //then we need to clear their pointers to information stored in
2307  //this BoundaryNode
2308  //at this level because once we are down to the Node's destructor
2309  //the information no longer exists.
2310  for(unsigned i=0;i<this->Ncopies;i++)
2311  {
2312  //Is the copied node a boundary node (it should be)
2313  BoundaryNode<NODE_TYPE>* cast_node_pt =
2314  dynamic_cast<BoundaryNode<NODE_TYPE>*>(this->Copy_of_data_pt[i]);
2315  //We can only do this if the node is a boundary node
2316  if(cast_node_pt!=0)
2317  {
2318  cast_node_pt->clear_additional_copied_pointers();
2319  }
2320  //Otherwise there is a problem if it's not Hijacked Data
2321 #ifdef PARANOID
2322  else
2323  {
2324  if(dynamic_cast<HijackedData*>(this->Copy_of_data_pt[i])==0)
2325  {
2326 
2327  OomphLibError(
2328  "Copy of a BoundaryNode is not a BoundaryNode or HijackedData",
2329  "BoundaryNode::~BoundaryNode",
2330  OOMPH_EXCEPTION_LOCATION);
2331  }
2332  }
2333 #endif
2334  }
2335 
2336  //If the node was periodic then clear the pointers before deleting
2337  if(Copied_node_pt)
2338  {
2339  //Inform the node that the copy is being deleted
2340  //If the original has been deleted Copied_node_pt will be NULL
2341  Copied_node_pt->remove_copy(this);
2342  Copied_node_pt=0;
2343  this->Value=0;
2344  this->Eqn_number=0;
2345  }
2346  }
2347 
2348  /// Broken copy constructor
2350  {
2351  BrokenCopy::broken_copy("BouandryNode");
2352  }
2353 
2354  /// Broken assignment operator
2356  {
2357  BrokenCopy::broken_assign("BoundaryNode");
2358  }
2359 
2360  /// Have boundary coordinates been set up?
2362  {
2364  }
2365 
2366  /// \short Access to pointer to set of mesh boundaries that this
2367  /// node occupies; NULL if the node is not on any boundary
2368  /// Final overload
2369  void get_boundaries_pt(std::set<unsigned>* &boundaries_pt)
2370  {BoundaryNodeBase::get_boundaries_pt(boundaries_pt);}
2371 
2372  /// \short Test whether the node lies on a boundary
2373  /// Final overload
2375 
2376  /// \short Test whether the node lies on mesh boundary b
2377  /// Final overload
2378  bool is_on_boundary(const unsigned &b) const
2380 
2381  /// \short Add the node to mesh boundary b, final overload
2382  void add_to_boundary(const unsigned &b)
2384 
2385  /// \short Remover the node from mesh boundary b, final overload
2386  void remove_from_boundary(const unsigned &b)
2388 
2389 
2390  /// \short Get the number of boundary coordinates on mesh boundary b.
2391  unsigned ncoordinates_on_boundary(const unsigned &b)
2392  {
2394  }
2395 
2396 
2397  /// \short Return the vector of coordinates on mesh boundary b
2398  /// Final overload
2399  void get_coordinates_on_boundary(const unsigned &b,
2400  Vector<double> &boundary_zeta)
2402 
2403  /// \short Set the vector of coordinates on mesh boundary b
2404  /// Final overload
2405  void set_coordinates_on_boundary(const unsigned &b,
2406  const Vector<double> &boundary_zeta)
2408 
2409 
2410  /// \short Return the vector of k-th generalised boundary coordinates
2411  /// on mesh boundary b Final overload
2412  void get_coordinates_on_boundary(const unsigned &b, const unsigned& k,
2413  Vector<double> &boundary_zeta)
2414  {BoundaryNodeBase::get_coordinates_on_boundary(b,k,boundary_zeta);}
2415 
2416  /// \short Set the vector of k-th generalised boundary coordinates
2417  /// on mesh boundary b. Final overload
2418  void set_coordinates_on_boundary(const unsigned &b, const unsigned& k,
2419  const Vector<double> &boundary_zeta)
2420  {BoundaryNodeBase::set_coordinates_on_boundary(b,k,boundary_zeta);}
2421 
2422 
2423 
2424  /// \short Return the number of values associated with
2425  /// the i-th face element field. If no argument is specified
2426  /// we return the value associated with the first (and assumed to be only)
2427  /// face element attached to this node. Throws error only in paranoid mode
2428  /// if no values have been set by any FaceElements. If you want to
2429  /// catch such cases gracefully in all circumstances (there are examples
2430  /// with complex unstructured 3D meshes where it's not clear a priori
2431  /// if a node has been resized by FaceElements) use alternative
2432  /// version (with leading bool arguments) that always checks and throws
2433  /// so exceptions can be caught gracefully. Returns UINT_MAX if error.
2434  unsigned nvalue_assigned_by_face_element(const unsigned& face_id=0) const
2435  {
2436 #ifdef PARANOID
2437  if (Index_of_first_value_assigned_by_face_element_pt==0)
2438  {
2439  std::ostringstream error_message;
2440  error_message
2441  << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
2442  << "Pointer must be set via call to: \n\n"
2443  << " BoundaryNode::assign_additional_values_with_face_id(), \n\n"
2444  << "typically from FaceElement::add_additional_values(...).";
2445  throw OomphLibError(error_message.str(),
2446  OOMPH_CURRENT_FUNCTION,
2447  OOMPH_EXCEPTION_LOCATION);
2448  return UINT_MAX;
2449  }
2450 #endif
2451 
2452  // How many values are there in total?
2453  unsigned nval=this->nvalue();
2454 
2455  //If ID is not present in the map then return 0
2456  if(Index_of_first_value_assigned_by_face_element_pt->find(face_id)==
2457  Index_of_first_value_assigned_by_face_element_pt->end())
2458  {
2459  return 0;
2460  }
2461 
2462  //Otherwise the entry is present in the map
2463 
2464  // Single entry: Number of values is the difference between
2465  // number of values and first index
2466  else if ((*Index_of_first_value_assigned_by_face_element_pt).size()==1)
2467  {
2468  return nval-
2469  (*Index_of_first_value_assigned_by_face_element_pt)[face_id];
2470  }
2471  else
2472  {
2473  // Find the next first index: Default: nvalue()
2474  unsigned next_first_index=nval;
2475  unsigned my_first_index=
2476  (*Index_of_first_value_assigned_by_face_element_pt)[face_id];
2477  for (std::map<unsigned, unsigned>::iterator it=
2478  (*Index_of_first_value_assigned_by_face_element_pt).begin();
2479  it!=(*Index_of_first_value_assigned_by_face_element_pt).end();
2480  it++)
2481  {
2482  unsigned first_index=(*it).second;
2483  if ((first_index>my_first_index)&&(first_index<next_first_index))
2484  {
2485  next_first_index=first_index;
2486  }
2487  }
2488  return next_first_index-my_first_index;
2489  }
2490  }
2491 
2492 
2493 //=====================================================================
2494 /// Member function to allocates storage for a given
2495 /// number of additional degrees of freedom, n_additional_value,
2496 /// associated with a particular face_id to the Node node_pt. Needs
2497 /// to be filled in here so that access to the nodal values is
2498 /// available.
2499 //=====================================================================
2501  const unsigned &n_additional_value, const unsigned &face_id=0)
2502  {
2503 #ifdef PARANOID
2504  //If nothing is being added warn the user
2505  if(n_additional_value == 0)
2506  {
2507  std::ostringstream warn_message;
2508  warn_message
2509  << "No additional data values are being added to the boundary node "
2510  << this << "\n"
2511  << "by face id " << face_id << ".\n"
2512  << "This means that the function \n"
2513  << "BoundaryNode::index_of_first_value_assigned_by_face_element(id) \n"
2514  << "will return a value that is equal to the number of values stored at the Node.\n"
2515  << "Calling Node::value(...) with this index will lead to an out-of-range error.\n"
2516  << "The anticpated usage of a loop from the index over the number of values.\n"
2517  << "will not cause any problems, but if you try to do anything else, you may be surprised.\n"
2518  << "You have been warned!\n";
2519  OomphLibWarning(warn_message.str(),
2520  OOMPH_CURRENT_FUNCTION,
2521  OOMPH_EXCEPTION_LOCATION);
2522 
2523  }
2524 #endif
2525 
2526  //Allocate storage if not already assigned
2527  if(this->Index_of_first_value_assigned_by_face_element_pt==0)
2528  {
2529  this->Index_of_first_value_assigned_by_face_element_pt =
2530  new std::map<unsigned, unsigned>;
2531  }
2532 
2533  //Find the number of values already stored in the node
2534  const unsigned n_value = this->nvalue();
2535 
2536  //If this ID hasn't already been used
2537  if(this->Index_of_first_value_assigned_by_face_element_pt->find(face_id)
2538  ==this->Index_of_first_value_assigned_by_face_element_pt->end())
2539  {
2540  //Set the first index to by number of values
2541  (*Index_of_first_value_assigned_by_face_element_pt)[face_id] =
2542  n_value;
2543  }
2544  //Otherwise this ID has been used previously
2545  else
2546  {
2547  //Find the number of values associated with this id
2548  const unsigned n_value_for_id =
2549  this->nvalue_assigned_by_face_element(face_id);
2550 
2551  //If the number of current values is equal to the desired values
2552  // do nothing and return
2553  if(n_value_for_id==n_additional_value)
2554  {
2555  return;
2556  }
2557  //Otherwise
2558  else
2559  {
2560  //Safety check, are the value associated with this id
2561  //all at the end
2562  if(((*this->Index_of_first_value_assigned_by_face_element_pt)[face_id]
2563  + n_value_for_id) != n_value)
2564  {
2565 #ifdef PARANOID
2566  std::ostringstream warn_message;
2567  warn_message
2568  << "Trying to (resize) number of unknowns associated with face id " << face_id << "\n"
2569  << "but previous storage for this data is not at the end of the nodal values.\n"
2570  << "The anticipated usage here is within constructors that add additional equations\n"
2571  << "to existing FaceElements in which case we will always be at the end.\n"
2572  << "If you are trying to do something else, then try using a different id.\n"
2573  << " FaceElement::add_additional_values(...)."
2574  << " For consistency with earlier versions, this will do nothing!\n";
2575  OomphLibWarning(warn_message.str(),
2576  OOMPH_CURRENT_FUNCTION,
2577  OOMPH_EXCEPTION_LOCATION);
2578 #endif
2579  //Just return without doing anything
2580  return;
2581  }
2582  } //Case when we are actually requesting additional values
2583  } //End case when ID has already been touched
2584 
2585  //Now finally resize the storage
2586  this->resize(n_value + n_additional_value);
2587  }
2588 
2589 
2590  /// \short Make the node periodic
2591  void make_periodic(Node* const &node_pt)
2592  {BoundaryNodeBase::make_node_periodic(this,node_pt);}
2593 
2594  /// \short Make the nodes passed in periodic_nodes periodic from
2595  /// this node
2596  void make_periodic_nodes(const Vector<Node*> &periodic_nodes_pt)
2597  {BoundaryNodeBase::make_nodes_periodic(this,periodic_nodes_pt);}
2598 
2599  /// \short Return a boolean to indicate whether the data contains
2600  /// any copied values. If the node is periodic all values are copied
2601  bool is_a_copy() const
2602  {if(Copied_node_pt) {return true;} else{return false;}}
2603 
2604  /// \short Return a boolean to indicate whether
2605  /// the i-th value is a copied value.
2606  /// If the node is periodic all values are copies
2607  bool is_a_copy(const unsigned &i) const
2608  {if(Copied_node_pt) {return true;} else{return false;}}
2609 
2610 
2611  /// \short Return pointer to copied node (null if the
2612  /// current node is not a copy)
2614  {
2615  return Copied_node_pt;
2616  }
2617 
2618  /// \short Overload the equation assignment operation
2619  void assign_eqn_numbers(unsigned long &global_ndof,
2620  Vector<double *> &dof_pt)
2621  {
2622  //If the boundary node is not periodic call the ususal
2623  //assign equation numbers
2624  if(Copied_node_pt==0)
2625  {NODE_TYPE::assign_eqn_numbers(global_ndof,dof_pt);}
2626  //Otherwise make sure that we assign equation numbers for
2627  //the variable position pointer of the solid node
2628  else
2629  {
2630  //Is it a solid node?
2631  SolidNode* solid_node_pt = dynamic_cast<SolidNode*>(this);
2632  if(solid_node_pt)
2633  {
2634  //If so we must let the variable position pointer take care of
2635  //itself
2636  solid_node_pt->variable_position_pt()
2637  ->assign_eqn_numbers(global_ndof,dof_pt);
2638  }
2639  }
2640  }
2641 
2642 
2643  /// \short Resize the number of equations
2644  void resize(const unsigned &n_value)
2645  {
2646  //If the node is periodic, warn, but do nothing
2647  if(Copied_node_pt)
2648  {
2649 #ifdef PARANOID
2650  unsigned n_value_new = Copied_node_pt->nvalue();
2651  //Check that we have already resized the original
2652  if(n_value_new != n_value)
2653  {
2654  std::ostringstream error_stream;
2655  error_stream
2656  << "Call to resize copied node before original has been resized!"
2657  << std::endl;
2658  throw OomphLibError(error_stream.str(),
2659  OOMPH_CURRENT_FUNCTION,
2660  OOMPH_EXCEPTION_LOCATION);
2661  }
2662 #endif
2663  }
2664  //Otherwise call the underlying function
2665  else
2666  {
2667  NODE_TYPE::resize(n_value);
2668  }
2669  }
2670 
2671 
2672 
2673 };
2674 
2675 
2676 
2677 }
2678 
2679 #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&#39;: k; Coordinate direction: i.
Definition: nodes.h:1076
double * Xi_position
Storage for the Lagrangian positions.
Definition: nodes.h:1590
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:1358
void add_to_boundary(const unsigned &b)
Add the node to mesh boundary b, final overload.
Definition: nodes.h:2382
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:1690
TimeStepper *const & time_stepper_pt() const
Return the pointer to the timestepper (const version).
Definition: nodes.h:249
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
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
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:1865
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:1363
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
bool Obsolete
Flag to indicate that the Node has become obsolete — usually during mesh refinement process...
Definition: nodes.h:904
TimeStepper *const & position_time_stepper_pt() const
Return a pointer to the position timestepper (const version).
Definition: nodes.h:972
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
const double & xi(const unsigned &i) const
Reference to i-th Lagrangian position (const version)
Definition: nodes.h:1750
void remove_from_boundary(const unsigned &b)
Remove the node from the mesh boundary b.
Definition: nodes.cc:2962
bool is_on_boundary(const unsigned &b) const
Test whether the node lies on mesh boundary b Final overload.
Definition: nodes.h:2378
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:2399
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:2412
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:1268
void resize(const unsigned &n_value)
Resize the number of equations.
Definition: nodes.h:2644
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:1703
bool is_on_boundary() const
Test whether the node lies on a boundary.
Definition: nodes.h:2053
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:1524
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
Vector< double > position() const
Return vector of position of node at current time.
Definition: nodes.h:1423
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 add_to_boundary(const unsigned &b)
Add the node to the mesh boundary b.
Definition: nodes.cc:2933
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
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
bool is_on_boundary() const
Test whether the node lies on a boundary Final overload.
Definition: nodes.h:2374
void make_periodic_nodes(const Vector< Node *> &periodic_nodes_pt)
Make the nodes passed in periodic_nodes periodic from this node.
Definition: nodes.h:2596
unsigned Nvalue
Number of values stored in the data object.
Definition: nodes.h:141
~HangInfo()
Delete the storage.
Definition: nodes.h:707
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:2193
int Non_halo_proc_ID
Non-halo processor ID for Data; -1 if it&#39;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 t...
Definition: nodes.h:1510
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
BoundaryNodeBase()
Default constructor, set the pointers to the storage to NULL.
Definition: nodes.h:2018
void operator=(const SolidNode &)
Broken assignment operator.
Definition: nodes.h:1634
virtual void constrain_positions()
Constrain the positions when the node is made hanging Empty virtual function that is overloaded in So...
Definition: nodes.h:1264
void unpin_position(const unsigned &k, const unsigned &i)
Unpin the generalised nodal position. `Type&#39;: k; Coordinate direction: i.
Definition: nodes.h:1708
void unpin_all()
Unpin all the stored variables.
Definition: nodes.h:396
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 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:1520
Data * Variable_position_pt
Pointer to data that will hold variable positions in elastic nodes.
Definition: nodes.h:1587
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&#39;: k; Coordinate direction: i. (const version)
Definition: nodes.h:1088
BoundaryNode(const BoundaryNode< NODE_TYPE > &node)
Broken copy constructor.
Definition: nodes.h:2349
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
void pin_position(const unsigned &k, const unsigned &i)
Pin the generalised nodal position. `Type&#39;: k; Coordinate direction: i.
Definition: nodes.h:1699
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 const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
Definition: nodes.h:753
bool is_hanging(const int &i) const
Test whether the i-th value is hanging.
Definition: nodes.h:1220
friend class CopiedData
Definition: nodes.h:99
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
unsigned nmaster() const
Return the number of master nodes.
Definition: nodes.h:733
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
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:2792
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
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
BoundaryNode()
Default Constructor.
Definition: nodes.h:2241
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1207
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:2043
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:448
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 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:2149
unsigned ncoordinates_on_boundary(const unsigned &b)
Get the number of boundary coordinates on mesh boundary b.
Definition: nodes.h:2391
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:2607
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:2369
AuxNodeUpdateFctPt Aux_node_update_fct_pt
Pointer to auxiliary update function – this can be used to update any nodal values following the upd...
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:1727
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
const double & xi_gen(const unsigned &k, const unsigned &i) const
Reference to the generalised Lagrangian position. `Type&#39;: k; &#39;Coordinate direction: i...
Definition: nodes.h:1770
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
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:1490
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:1532
void set_obsolete()
Mark node as obsolete.
Definition: nodes.h:1348
bool has_auxiliary_node_update_fct_pt()
Boolean to indicate if node has a pointer to and auxiliary update function.
Definition: nodes.h:1501
Vector< double > value() const
Return vector of values calculated using value(vector).
Definition: nodes.h:1400
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:1528
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:992
long eqn_number(const unsigned &i) const
Return the equation number of the i-th stored variable.
Definition: nodes.h:374
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:2062
HangInfo *const & hanging_pt(const int &i) const
Return pointer to hanging node data for value i (const version)
Definition: nodes.h:1163
~BoundaryNode()
Destructor resets pointers if.
Definition: nodes.h:2303
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:1963
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
unsigned Nlagrangian_type
Number of types of Lagrangian coordinates used to interpolate the Lagrangian coordinates within the e...
Definition: nodes.h:1584
SolidNode(const SolidNode &solid_node)
Broken copy constructor.
Definition: nodes.h:1628
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:1284
void pin_position(const unsigned &i)
Pin the nodal position.
Definition: nodes.h:1694
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
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:1741
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:1855
friend std::ostream & operator<<(std::ostream &out, const Data &d)
double & xi_gen(const unsigned &k, const unsigned &i)
Reference to the generalised Lagrangian position. `Type&#39;: k; &#39;Coordinate direction: i...
Definition: nodes.h:1760
bool boundary_coordinates_have_been_set_up()
Have boundary coordinates been set up?
Definition: nodes.h:2036
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:2071
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:2601
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
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:2292
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
unsigned Ncopies
Number of Data that contain copies of this Data object&#39;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:2500
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&#39;s nothing to be done apart from performing the auxiliary node update function (if any)
Definition: nodes.h:1839
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
A template Class for BoundaryNodes; that is Nodes that MAY live on the boundary of a Mesh...
Definition: nodes.h:67
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
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:2405
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:2619
unsigned nposition_type() const
Number of coordinate types needed in the mapping between local and global coordinates.
Definition: nodes.h:966
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:2591
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:2851
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
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:2434
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
const double & x(const unsigned &i) const
Return the i-th nodal coordinate (const version).
Definition: nodes.h:1004
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 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
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
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
Definition: nodes.h:1655
void read(std::ifstream &restart_file)
Read data object from a file.
Definition: nodes.cc:635
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:2277
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Definition: nodes.h:736
void operator=(const BoundaryNodeBase &)
Broken assignment operator.
Definition: nodes.h:2032
friend class HijackedData
Definition: nodes.h:98
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&#39;s set to NULL if the node isn&#39;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 nlagrangian_type() const
Number of types of Lagrangian coordinates used to interpolate the Lagrangian coordinates within the e...
Definition: nodes.h:1738
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 output(std::ostream &outfile)
Output with default number of plot points.
void dump(std::ostream &dump_file) const
Dump the data object to a file.
Definition: nodes.cc:608
Data ** Copy_of_data_pt
C-style array of any Data objects that contain copies of the current Data object&#39;s data values...
Definition: nodes.h:132
void operator=(const Node &)
Broken assignment operator.
Definition: nodes.h:955
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:3017
const double & x_gen(const unsigned &k, const unsigned &i) const
Reference to the generalised position x(k,i). `Type&#39;: k; Coordinate direction: i (const version)...
Definition: nodes.h:1065
void operator=(const HijackedData &)
Broken assignment operator.
Definition: nodes.h:555
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:1925
void pin_all()
Pin all the stored variables (Overloaded)
Definition: nodes.h:1712
void operator=(const BoundaryNode< NODE_TYPE > &)
Broken assignment operator.
Definition: nodes.h:2355
bool position_is_a_copy(const unsigned &i) const
Return whether the position coordinate i has been copied.
Definition: nodes.h:1675
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:1295
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
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
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:1879
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 remove_from_boundary(const unsigned &b)
Remover the node from mesh boundary b, final overload.
Definition: nodes.h:2386
friend class SolidNode
Definition: nodes.h:106
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:1680
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:2263
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 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 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:1731
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:1569
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:1595
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&#39;s o...
Definition: nodes.h:1042
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
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&#39;s auxiliary node update function (if any).
Definition: nodes.h:1482
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&#39;t been defined.
static long Is_unclassified
Static "Magic number" used in place of the equation number to denote a value that hasn&#39;t been classif...
Definition: nodes.h:201
bool is_pinned(const unsigned &i) const
Test whether the i-th variable is pinned (1: true; 0: false).
Definition: nodes.h:403
const Data & variable_position() const
Return the variable_position data (const version)
Definition: nodes.h:1652
Node * Copied_node_pt
If the BoundaryNode is periodic, this pointer is set to the BoundaryNode whose data it shares...
Definition: nodes.h:1883
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
virtual bool position_is_a_copy() const
Return whether any position coordinate has been copied (always false)
Definition: nodes.h:1048
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
HangInfo(const HangInfo &)
Broken copy constructor.
Definition: nodes.h:721
Node * copied_node_pt() const
Return pointer to copied node (null if the current node is not a copy)
Definition: nodes.h:2613
unsigned Nlagrangian
Number of Lagrangian coordinates of the node.
Definition: nodes.h:1580
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:1290
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
bool is_halo() const
Is this Data a halo?
Definition: nodes.h:490
double * x_position_pt(const unsigned &i)
Direct access to the pointer to the i-th stored coordinate data.
Definition: nodes.h:907
bool position_is_a_copy() const
Return whether any position component has been copied.
Definition: nodes.h:1672
bool position_is_pinned(const unsigned &i)
Test whether the i-th coordinate is pinned, 0: false; 1: true.
Definition: nodes.h:1685
void unpin_all()
Unpin all the stored variables (Overloaded)
Definition: nodes.h:1719
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:1869
HijackedData(const Data &data)
(Shallow) copy constructor
Definition: nodes.h:552
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
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
BoundaryNodeBase(const BoundaryNodeBase &boundary_node_base)
Broken copy constructor.
Definition: nodes.h:2028
unsigned nlagrangian() const
Return number of lagrangian coordinates.
Definition: nodes.h:1734
bool boundary_coordinates_have_been_set_up()
Have boundary coordinates been set up?
Definition: nodes.h:2361
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:1910
Data()
Default: Just set pointer to (steady) timestepper. No storage for values is allocated.
Definition: nodes.cc:235
void set_non_obsolete()
Mark node as non-obsolete.
Definition: nodes.h:1351
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
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
unsigned hang_code()
Code that encapsulates the hanging status of the node (incl. the geometric hanging status) as ...
Definition: nodes.h:1133
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:1328
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
Definition: timesteppers.h:219
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
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:2106
bool is_obsolete()
Test whether node is obsolete.
Definition: nodes.h:1354
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 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
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:2250
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:1336
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:2418