nodes.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2022 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 // This header contains class and function prototypes for Data, Node
27 // and associated objects
28 
29 // Include guard to prevent multiple inclusions of the header
30 #ifndef OOMPH_NODES_HEADER
31 #define OOMPH_NODES_HEADER
32 
33 // Config header generated by autoconfig
34 #ifdef HAVE_CONFIG_H
35 #include <oomph-lib-config.h>
36 #endif
37 
38 #ifdef OOMPH_HAS_MPI
39 #include "mpi.h"
40 #endif
41 
42 // C++ headers
43 #include <map>
44 #include <set>
45 #include <climits>
46 #include <string>
47 
48 // oomph-lib headers
49 #include "Vector.h"
50 #include "matrices.h"
51 #include "oomph_utilities.h"
52 
53 namespace oomph
54 {
55  // The following classes are used in the Data class,
56  // so we provide forward references here
57  class TimeStepper;
58  class SolidNode;
59  class HijackedData;
60  class CopiedData;
61  class BoundaryNodeBase;
62  template<class NODE_TYPE>
63  class BoundaryNode;
64 
65  //=====================================================================
84  //=====================================================================
85  class Data
86  {
87  private:
88  // We wish certain classes to have access to the internal data
89  // storage model so that the pointers to the values and equations can be
90  // used for efficiency reasons. In particular, any derived classes
91  // that contains shallow copies of Data values
92  //(BoundaryNodeBase, CopiedData and HijackedData) must have pointer-access.
93  friend class HijackedData;
94  friend class CopiedData;
95  friend class BoundaryNodeBase;
96  template<class NODE_TYPE>
97  friend class BoundaryNode;
98 
99  // SolidNodes use their knowledge of
100  // the internal storage of the data values to efficiently implement
101  // the use of positions as variables for solid mechanics problems.
102  friend class SolidNode;
103 
112  double** Value;
113 
116  long* Eqn_number;
117 
123 
124  protected:
128 
131  unsigned Ncopies;
132 
133  private:
135  unsigned Nvalue;
136 
137 #ifdef OOMPH_HAS_MPI
138 
140  int Non_halo_proc_ID;
141 
142 #endif
143 
146  void range_check(const unsigned& t, const unsigned& i) const;
147 
150  void delete_value_storage();
151 
154  void add_copy(Data* const& data_pt);
155 
158  void remove_copy(Data* const& data_pt);
159 
160  protected:
163 
170  virtual void reset_copied_pointers();
171 
172  public:
179  virtual void clear_copied_pointers();
180 
183  static long Is_pinned;
184 
189 
192  static long Is_unclassified;
193 
198  static long Is_constrained;
199 
202  Data();
203 
206  Data(const unsigned& initial_n_value);
207 
211  // ALH: Note the "awkward" C++ syntax for passing a constant reference to
212  // a pointer. N.B. We cannot change the pointer, but we can change
213  // what it points to. We could use a const pointer, to prevent change of the
214  // object, but that brings in a whole additional layer of complexity.
216  const unsigned& initial_n_value,
217  const bool& allocate_storage = true);
218 
220  Data(const Data& data) = delete;
221 
223  void operator=(const Data&) = delete;
224 
227  friend std::ostream& operator<<(std::ostream& out, const Data& d);
228 
230  virtual ~Data();
231 
235  const bool& preserve_existing_data);
236 
239  {
240  return Time_stepper_pt;
241  }
242 
244  TimeStepper* const& time_stepper_pt() const
245  {
246  return Time_stepper_pt;
247  }
248 
253  virtual bool is_a_copy() const
254  {
255  return false;
256  }
257 
261  virtual bool is_a_copy(const unsigned& i) const
262  {
263  return false;
264  }
265 
271  void set_value(const unsigned& i, const double& value_)
272  {
273 #ifdef RANGE_CHECKING
274  range_check(0, i);
275 #endif
276  Value[i][0] = value_;
277  }
278 
281  void set_value(const unsigned& t, const unsigned& i, const double& value_)
282  {
283 #ifdef RANGE_CHECKING
284  range_check(t, i);
285 #endif
286  Value[i][t] = value_;
287  }
288 
293  double value(const unsigned& i) const
294  {
295 #ifdef RANGE_CHECKING
296  range_check(0, i);
297 #endif
298  return Value[i][0];
299  }
300 
305  double value(const unsigned& t, const unsigned& i) const
306  {
307 #ifdef RANGE_CHECKING
308  range_check(t, i);
309 #endif
310  return Value[i][t];
311  }
312 
314  void value(Vector<double>& values) const;
315 
318  void value(const unsigned& t, Vector<double>& values) const;
319 
324  double* value_pt(const unsigned& i) const
325  {
326 #ifdef RANGE_CHECKING
327  range_check(0, i);
328 #endif
329  return Value[i];
330  }
331 
337  double* value_pt(const unsigned& t, const unsigned& i) const
338  {
339 #ifdef RANGE_CHECKING
340  range_check(t, i);
341 #endif
342  return &Value[i][t];
343  }
344 
346  bool does_pointer_correspond_to_value(double* const& parameter_pt);
347 
349  void copy(Data* orig_data_pt);
350 
352  void dump(std::ostream& dump_file) const;
353 
355  void read(std::ifstream& restart_file);
356 
358  long* eqn_number_pt(const unsigned& i)
359  {
360 #ifdef RANGE_CHECKING
361  range_check(0, i);
362 #endif
363  return &Eqn_number[i];
364  }
365 
367  inline long& eqn_number(const unsigned& i)
368  {
369 #ifdef RANGE_CHECKING
370  range_check(0, i);
371 #endif
372  return Eqn_number[i];
373  }
374 
376  inline long eqn_number(const unsigned& i) const
377  {
378 #ifdef RANGE_CHECKING
379  range_check(0, i);
380 #endif
381  return Eqn_number[i];
382  }
383 
385  inline void pin(const unsigned& i)
386  {
388  }
389 
391  inline void unpin(const unsigned& i)
392  {
394  }
395 
397  void pin_all()
398  {
399  const unsigned n_value = Nvalue;
400  for (unsigned i = 0; i < n_value; i++)
401  {
403  }
404  }
405 
407  void unpin_all()
408  {
409  const unsigned n_value = Nvalue;
410  for (unsigned i = 0; i < n_value; i++)
411  {
413  }
414  }
415 
417  bool is_pinned(const unsigned& i) const
418  {
419  return (Eqn_number[i] == Is_pinned);
420  }
421 
424  bool is_segregated_solve_pinned(const unsigned& i)
425  {
427  }
428 
432  inline void constrain(const unsigned& i)
433  {
434  if (eqn_number(i) != Is_pinned)
435  {
437  }
438  }
439 
442  inline void unconstrain(const unsigned& i)
443  {
444  if (eqn_number(i) == Is_constrained)
445  {
447  }
448  }
449 
452  {
453  const unsigned n_value = Nvalue;
454  for (unsigned i = 0; i < n_value; i++)
455  {
456  constrain(i);
457  }
458  }
459 
462  {
463  const unsigned n_value = Nvalue;
464  for (unsigned i = 0; i < n_value; i++)
465  {
466  unconstrain(i);
467  }
468  }
469 
472  bool is_constrained(const unsigned& i)
473  {
474  return (Eqn_number[i] == Is_constrained);
475  }
476 
477 
480  unsigned self_test();
481 
483  unsigned nvalue() const
484  {
485  return Nvalue;
486  }
487 
490  unsigned ntstorage() const;
491 
494  virtual void assign_eqn_numbers(unsigned long& global_ndof,
495  Vector<double*>& dof_pt);
496 
505  virtual void describe_dofs(std::ostream& out,
506  const std::string& current_string) const;
507 
509  virtual void resize(const unsigned& n_value);
510 
513  virtual void add_value_pt_to_map(
514  std::map<unsigned, double*>& map_of_value_pt);
515 
516 #ifdef OOMPH_HAS_MPI
517 
520  void set_halo(const unsigned& non_halo_proc_ID)
521  {
522  Non_halo_proc_ID = non_halo_proc_ID;
523  }
524 
526  void set_nonhalo()
527  {
528  Non_halo_proc_ID = -1;
529  }
530 
532  bool is_halo() const
533  {
534  return (Non_halo_proc_ID != -1);
535  }
536 
539  int non_halo_proc_ID()
540  {
541  return Non_halo_proc_ID;
542  }
543 
546  virtual void add_values_to_vector(Vector<double>& vector_of_values);
547 
551  virtual void read_values_from_vector(const Vector<double>& vector_of_values,
552  unsigned& index);
553 
554 
557  virtual void add_eqn_numbers_to_vector(Vector<long>& vector_of_eqn_numbers);
558 
562  virtual void read_eqn_numbers_from_vector(
563  const Vector<long>& vector_of_eqn_numbers, unsigned& index);
564 
565 
566 #endif
567  };
568 
569  //=========================================================================
573  //=========================================================================
574  class HijackedData : public Data
575  {
576  private:
579 
581  unsigned Copied_index;
582 
584  void reset_copied_pointers();
585 
586  public:
588  void clear_copied_pointers();
589 
591  HijackedData(const unsigned& copied_value, Data* const& data_pt);
592 
594  HijackedData(const Data& data) = delete;
595 
597  void operator=(const HijackedData&) = delete;
598 
602  {
603  // Inform the Copied data that this copy is being deleted
604  // If the original has already been deleted
605  // Copied_data_pt will be set to NULL and this will not be
606  // necessary
607  if (Copied_data_pt)
608  {
610  }
611  // Now null out the storage
612  Copied_data_pt = 0;
613  Value = 0;
614  Eqn_number = 0;
615  }
616 
619  bool is_a_copy() const
620  {
621  return true;
622  }
623 
627  bool is_a_copy(const unsigned& i) const
628  {
629  return true;
630  }
631 
634  void assign_eqn_numbers(unsigned long& global_ndof, Vector<double*>& dof_pt)
635  {
636  return;
637  }
638 
639 
642  void resize(const unsigned& n_value);
643  };
644 
645 
646  //=========================================================================
650  //=========================================================================
651  class CopiedData : public Data
652  {
653  private:
656 
658  void reset_copied_pointers();
659 
660  public:
662  void clear_copied_pointers();
663 
665  CopiedData(Data* const& data_pt);
666 
668  CopiedData(const Data& data) = delete;
669 
671  void operator=(const CopiedData&) = delete;
672 
676  {
677  // Inform the Copied data that this copy is being deleted
678  // If the original has already been deleted
679  // Copied_data_pt will be set to NULL and this will not be
680  // necessary
681  if (Copied_data_pt)
682  {
684  }
685  // Now null out the storage
686  Copied_data_pt = 0;
687  Value = 0;
688  Eqn_number = 0;
689  }
690 
693  bool is_a_copy() const
694  {
695  return true;
696  }
697 
701  bool is_a_copy(const unsigned& i) const
702  {
703  return true;
704  }
705 
708  void assign_eqn_numbers(unsigned long& global_ndof, Vector<double*>& dof_pt)
709  {
710  return;
711  }
712 
713 
716  void resize(const unsigned& n_value);
717  };
718 
719 
720  // Nodes are required in the HangInfo class, so we need a forward reference
721  class Node;
722 
723 
724  //=====================================================================
740  //=====================================================================
741  class HangInfo
742  {
743  public:
746  {
747 #ifdef LEAK_CHECK
748  LeakCheckNames::HangInfo_build += 1;
749 #endif
750  }
751 
753  HangInfo(const unsigned& n_master) : Nmaster(n_master)
754  {
755 #ifdef LEAK_CHECK
756  LeakCheckNames::HangInfo_build += 1;
757 #endif
758  Master_nodes_pt = new Node*[n_master];
759  Master_weights = new double[n_master];
760  }
761 
764  {
765 #ifdef LEAK_CHECK
766  LeakCheckNames::HangInfo_build -= 1;
767 #endif
768  // If there is any storage, then delete it
769  if (Nmaster > 0)
770  {
771  delete[] Master_nodes_pt;
772  Master_nodes_pt = 0;
773  delete[] Master_weights;
774  Master_weights = 0;
775  }
776  }
777 
779  HangInfo(const HangInfo&) = delete;
780 
782  void operator=(const HangInfo&) = delete;
783 
785  unsigned nmaster() const
786  {
787  return Nmaster;
788  }
789 
791  Node* const& master_node_pt(const unsigned& i) const
792  {
793 #ifdef PARANOID
794  if (Nmaster == 0)
795  {
796  throw OomphLibError("Hanging node data hasn't been setup yet \n",
799  }
800 #endif
801 #ifdef RANGE_CHECKING
802  range_check(i);
803 #endif
804  return Master_nodes_pt[i];
805  }
806 
808  double const& master_weight(const unsigned& i) const
809  {
810 #ifdef PARANOID
811  if (Nmaster == 0)
812  {
813  throw OomphLibError("Hanging node data hasn't been setup yet \n",
816  }
817 #endif
818 #ifdef RANGE_CHECKING
819  range_check(i);
820 #endif
821  return Master_weights[i];
822  }
823 
825  void set_master_node_pt(const unsigned& i,
826  Node* const& master_node_pt,
827  const double& weight);
828 
831  void add_master_node_pt(Node* const& master_node_pt, const double& weight);
832 
833  private:
836  void range_check(const unsigned& i) const;
837 
840 
842  double* Master_weights;
843 
845  unsigned Nmaster;
846  };
847 
848  // Geometric objects are (now) required in the Node class, so we
849  // put a forward reference here
850  class GeomObject;
851 
852 
853  //=====================================================================
904  //=====================================================================
905  class Node : public Data
906  {
907  public:
909  typedef void (*AuxNodeUpdateFctPt)(Node*);
910 
911  // The BoundaryNodeBase class must use knowledge of the internal data
912  // storage
914  friend class BoundaryNodeBase;
915 
916  protected:
919  void x_gen_range_check(const unsigned& t,
920  const unsigned& k,
921  const unsigned& i) const;
922 
929  double** X_position;
930 
933 
943 
945  unsigned Ndim;
946 
951  unsigned Nposition_type;
952 
955  bool Obsolete;
956 
958  double* x_position_pt(const unsigned& i)
959  {
960  return X_position[i];
961  }
962 
968 
969  public:
972  static unsigned No_independent_position;
973 
975  Node();
976 
983  Node(const unsigned& n_dim,
984  const unsigned& n_position_type,
985  const unsigned& initial_n_value,
986  const bool& allocate_x_position = true);
987 
996  const unsigned& n_dim,
997  const unsigned& n_position_type,
998  const unsigned& initial_n_value,
999  const bool& allocate_x_position = true);
1000 
1002  virtual ~Node();
1003 
1005  Node(const Node& node) = delete;
1006 
1008  void operator=(const Node&) = delete;
1009 
1012  friend std::ostream& operator<<(std::ostream& out, const Node& d);
1013 
1016  unsigned nposition_type() const
1017  {
1018  return Nposition_type;
1019  }
1020 
1023  {
1024  return Position_time_stepper_pt;
1025  }
1026 
1029  {
1030  return Position_time_stepper_pt;
1031  }
1032 
1035  virtual void set_position_time_stepper(
1037  const bool& preserve_existing_data);
1038 
1043  double* const& parameter_pt)
1044  {
1045  return false;
1046  }
1047 
1050  virtual void assign_eqn_numbers(unsigned long& global_ndof,
1051  Vector<double*>& dof_pt);
1052 
1054  unsigned ndim() const
1055  {
1056  return Ndim;
1057  }
1058 
1060  double& x(const unsigned& i)
1061  {
1062 #ifdef RANGE_CHECKING
1063  x_gen_range_check(0, 0, i);
1064 #endif
1065  return X_position[Nposition_type * i][0];
1066  }
1067 
1069  const double& x(const unsigned& i) const
1070  {
1071 #ifdef RANGE_CHECKING
1072  x_gen_range_check(0, 0, i);
1073 #endif
1074  return X_position[Nposition_type * i][0];
1075  }
1076 
1079  double& x(const unsigned& t, const unsigned& i)
1080  {
1081 #ifdef RANGE_CHECKING
1082  x_gen_range_check(t, 0, i);
1083 #endif
1084  return X_position[Nposition_type * i][t];
1085  }
1086 
1089  const double& x(const unsigned& t, const unsigned& i) const
1090  {
1091 #ifdef RANGE_CHECKING
1092  x_gen_range_check(t, 0, i);
1093 #endif
1094  return X_position[Nposition_type * i][t];
1095  }
1096 
1098  double dx_dt(const unsigned& i) const;
1099 
1102  double dx_dt(const unsigned& j, const unsigned& i) const;
1103 
1107  virtual Node* copied_node_pt() const
1108  {
1109  return 0;
1110  }
1111 
1113  virtual bool position_is_a_copy() const
1114  {
1115  return false;
1116  }
1117 
1119  virtual bool position_is_a_copy(const unsigned& i) const
1120  {
1121  return false;
1122  }
1123 
1126  double& x_gen(const unsigned& k, const unsigned& i)
1127  {
1128 #ifdef RANGE_CHECKING
1129  x_gen_range_check(0, k, i);
1130 #endif
1131  return X_position[Nposition_type * i + k][0];
1132  }
1133 
1136  const double& x_gen(const unsigned& k, const unsigned& i) const
1137  {
1138 #ifdef RANGE_CHECKING
1139  x_gen_range_check(0, k, i);
1140 #endif
1141  return X_position[Nposition_type * i + k][0];
1142  }
1143 
1146  double& x_gen(const unsigned& t, const unsigned& k, const unsigned& i)
1147  {
1148 #ifdef RANGE_CHECKING
1149  x_gen_range_check(t, k, i);
1150 #endif
1151  return X_position[Nposition_type * i + k][t];
1152  }
1153 
1157  const double& x_gen(const unsigned& t,
1158  const unsigned& k,
1159  const unsigned& i) const
1160  {
1161 #ifdef RANGE_CHECKING
1162  x_gen_range_check(t, k, i);
1163 #endif
1164  return X_position[Nposition_type * i + k][t];
1165  }
1166 
1169  double dx_gen_dt(const unsigned& k, const unsigned& i) const;
1170 
1171 
1175  double dx_gen_dt(const unsigned& j,
1176  const unsigned& k,
1177  const unsigned& i) const;
1178 
1181  double* x_pt(const unsigned& t, const unsigned& i)
1182  {
1183  return &X_position[Nposition_type * i][t];
1184  }
1185 
1187  void copy(Node* orig_node_pt);
1188 
1190  virtual void dump(std::ostream& dump_file) const;
1191 
1193  void read(std::ifstream& restart_file);
1194 
1197  virtual void pin_all()
1198  {
1199  Data::pin_all();
1200  }
1201 
1204  virtual void unpin_all()
1205  {
1206  Data::unpin_all();
1207  }
1208 
1209 
1213  unsigned hang_code()
1214  {
1215  unsigned hang_code = 0;
1216  int nval = nvalue();
1217  for (int i = -1; i < nval; i++)
1218  {
1220  unsigned(std::pow(2.0, double(i + 1)));
1221  }
1222  return hang_code;
1223  }
1224 
1225 
1228  HangInfo* const& hanging_pt() const
1229  {
1230 #ifdef PARANOID
1231  if (Hanging_pt == 0)
1232  {
1233  throw OomphLibError(
1234  "Vector of pointers to hanging data is not setup yet\n",
1237  }
1238 #endif
1239  return Hanging_pt[0];
1240  }
1241 
1243  HangInfo* const& hanging_pt(const int& i) const
1244  {
1245 #ifdef PARANOID
1246  if (Hanging_pt == 0)
1247  {
1248  std::ostringstream error_message;
1249  error_message << "Vector of pointers to hanging data is not setup yet\n"
1250 #ifdef OOMPH_HAS_MPI
1251  << "I'm on processor "
1252  << MPI_Helpers::communicator_pt()->my_rank() << "\n"
1253 #endif
1254  << "Coordinates: \n";
1255 
1256  unsigned n_dim = ndim();
1257  for (unsigned i = 0; i < n_dim; i++)
1258  {
1259  error_message << this->x(i) << " ";
1260  }
1261  throw OomphLibError(error_message.str(),
1264  }
1265 #endif
1266 #ifdef RANGE_CHECKING
1267  // Range checking code.
1268  // Need to make sure that this is an int otherwise the test
1269  // fails when it shouldn't
1270  const int n_value = static_cast<int>(this->nvalue());
1271  if ((i < -1) || (i > n_value))
1272  {
1273  std::ostringstream error_message;
1274  error_message << "Range Error: Value " << i
1275  << " is not in the range (-1," << n_value << ")";
1276  throw OomphLibError(error_message.str(),
1279  }
1280 #endif
1281  return Hanging_pt[i + 1];
1282  }
1283 
1285  bool is_hanging() const
1286  {
1287  if (Hanging_pt == 0)
1288  {
1289  return false;
1290  }
1291  else
1292  {
1293  return (Hanging_pt[0] != 0);
1294  }
1295  }
1296 
1298  bool is_hanging(const int& i) const
1299  {
1300 #ifdef RANGE_CHECKING
1301  // Need to make sure that this is an int otherwise the test
1302  // fails when it shouldn't
1303  const int n_value = static_cast<int>(this->nvalue());
1304  if ((i < -1) || (i > n_value))
1305  {
1306  std::ostringstream error_message;
1307  error_message << "Range Error: Value " << i
1308  << " is not in the range (-1," << n_value << ")";
1309  throw OomphLibError(error_message.str(),
1312  }
1313 #endif
1314 
1315  // Test whether the node is geometrically hanging
1316  if (i == -1)
1317  {
1318  return is_hanging();
1319  }
1320  // Otherwise, is the i-th value hanging
1321  else
1322  {
1323  if (Hanging_pt == 0)
1324  {
1325  return false;
1326  }
1327  else
1328  {
1329  return (Hanging_pt[i + 1] != 0);
1330  }
1331  }
1332  }
1333 
1335  void set_hanging_pt(HangInfo* const& hang_pt, const int& i);
1336 
1338  void set_nonhanging();
1339 
1341  void resize(const unsigned& n_value);
1342 
1345  virtual void constrain_positions() {}
1346 
1349  virtual void unconstrain_positions() {}
1350 
1355  virtual void make_periodic(Node* const& node_pt);
1356 
1359  virtual void make_periodic_nodes(const Vector<Node*>& periodic_nodes_pt);
1360 
1365  virtual void get_boundaries_pt(std::set<unsigned>*& boundaries_pt)
1366  {
1367  boundaries_pt = 0;
1368  }
1369 
1373  virtual bool is_on_boundary() const
1374  {
1375  return false;
1376  }
1377 
1381  virtual bool is_on_boundary(const unsigned& b) const
1382  {
1383  return false;
1384  }
1385 
1388  virtual void add_to_boundary(const unsigned& b);
1389 
1392  virtual void remove_from_boundary(const unsigned& b);
1393 
1397  virtual unsigned ncoordinates_on_boundary(const unsigned& b);
1398 
1402 
1406  virtual void get_coordinates_on_boundary(const unsigned& b,
1407  const unsigned& k,
1408  Vector<double>& boundary_zeta);
1409 
1413  virtual void set_coordinates_on_boundary(
1414  const unsigned& b,
1415  const unsigned& k,
1416  const Vector<double>& boundary_zeta);
1417 
1420  virtual void get_coordinates_on_boundary(const unsigned& b,
1421  Vector<double>& boundary_zeta)
1422  {
1423  get_coordinates_on_boundary(b, 0, boundary_zeta);
1424  }
1425 
1429  const unsigned& b, const Vector<double>& boundary_zeta)
1430  {
1431  set_coordinates_on_boundary(b, 0, boundary_zeta);
1432  }
1433 
1434 
1437  {
1438  Obsolete = true;
1439  }
1440 
1443  {
1444  Obsolete = false;
1445  }
1446 
1449  {
1450  return Obsolete;
1451  }
1452 
1455  double raw_value(const unsigned& i) const
1456  {
1457  return Data::value(i);
1458  }
1459 
1463  double raw_value(const unsigned& t, const unsigned& i) const
1464  {
1465  return Data::value(t, i);
1466  }
1467 
1477  double value(const unsigned& i) const;
1478 
1488  double value(const unsigned& t, const unsigned& i) const;
1489 
1499  void value(Vector<double>& values) const;
1500 
1503  {
1504  Vector<double> vals(nvalue(), 0.0);
1505  value(vals);
1506  return vals;
1507  }
1508 
1518  void value(const unsigned& t, Vector<double>& values) const;
1519 
1522  void position(Vector<double>& pos) const;
1523 
1526  {
1527  Vector<double> pos(ndim(), 0.0);
1528  position(pos);
1529  return pos;
1530  }
1531 
1535  void position(const unsigned& t, Vector<double>& pos) const;
1536 
1539  double position(const unsigned& i) const;
1540 
1544  double position(const unsigned& t, const unsigned& i) const;
1545 
1548  double position_gen(const unsigned& k, const unsigned& i) const;
1549 
1553  double position_gen(const unsigned& t,
1554  const unsigned& k,
1555  const unsigned& i) const;
1556 
1559  double dposition_dt(const unsigned& i) const;
1560 
1563  double dposition_dt(const unsigned& j, const unsigned& i) const;
1564 
1568  double dposition_gen_dt(const unsigned& k, const unsigned& i) const;
1569 
1570 
1574  double dposition_gen_dt(const unsigned& j,
1575  const unsigned& k,
1576  const unsigned& i) const;
1577 
1586  virtual void node_update(
1587  const bool& update_all_time_levels_for_new_node = false)
1588  {
1589  }
1590 
1591 
1597  AuxNodeUpdateFctPt aux_node_update_fct_pt)
1598  {
1599  // Set pointer (by default it's set to NULL)
1600  Aux_node_update_fct_pt = aux_node_update_fct_pt;
1601  }
1602 
1603 
1607  {
1608  return (Aux_node_update_fct_pt != 0);
1609  }
1610 
1616  {
1617  if (Aux_node_update_fct_pt != 0)
1618  {
1619  Aux_node_update_fct_pt(this);
1620  }
1621  }
1622 
1625  virtual inline unsigned ngeom_data() const
1626  {
1627  return 0;
1628  }
1629 
1632  virtual inline Data** all_geom_data_pt()
1633  {
1634  return 0;
1635  }
1636 
1639  virtual inline unsigned ngeom_object() const
1640  {
1641  return 0;
1642  }
1643 
1647  virtual inline GeomObject** all_geom_object_pt()
1648  {
1649  return 0;
1650  }
1651 
1653  void output(std::ostream& outfile);
1654 
1655 
1656 #ifdef OOMPH_HAS_MPI
1657 
1660  void add_values_to_vector(Vector<double>& vector_of_values);
1661 
1666  void read_values_from_vector(const Vector<double>& vector_of_values,
1667  unsigned& index);
1668 
1669 #endif
1670  };
1671 
1672  //=====================================================================
1684  //=====================================================================
1685  class SolidNode : public Node
1686  {
1687  private:
1690  void xi_gen_range_check(const unsigned& k, const unsigned& i) const;
1691 
1692  protected:
1694  unsigned Nlagrangian;
1695 
1699 
1702 
1704  double* Xi_position;
1705 
1706  public:
1708  SolidNode() : Node() {}
1709 
1717  SolidNode(const unsigned& n_lagrangian,
1718  const unsigned& n_lagrangian_type,
1719  const unsigned& n_dim,
1720  const unsigned& n_position_type,
1721  const unsigned& initial_n_value);
1722 
1731  const unsigned& n_lagrangian,
1732  const unsigned& n_lagrangian_type,
1733  const unsigned& n_dim,
1734  const unsigned& Nposition_type,
1735  const unsigned& initial_n_value);
1736 
1738  virtual ~SolidNode();
1739 
1741  SolidNode(const SolidNode& solid_node) = delete;
1742 
1744  void operator=(const SolidNode&) = delete;
1745 
1748  void copy(SolidNode* orig_node_pt);
1749 
1752  void dump(std::ostream& dump_file) const;
1753 
1756  void read(std::ifstream& restart_file);
1757 
1759  const Data& variable_position() const
1760  {
1761  return *Variable_position_pt;
1762  }
1763 
1765  Data* const& variable_position_pt() const
1766  {
1767  return Variable_position_pt;
1768  }
1769 
1771  void set_external_variable_position_pt(Data* const& data_pt);
1772 
1777  const bool& preserve_existing_data);
1778 
1781  bool does_pointer_correspond_to_position_data(double* const& parameter_pt);
1782 
1784  bool position_is_a_copy() const
1785  {
1786  return Variable_position_pt->is_a_copy();
1787  }
1788 
1790  bool position_is_a_copy(const unsigned& i) const
1791  {
1793  }
1794 
1797  const long& position_eqn_number(const unsigned& k, const unsigned& i) const
1798  {
1800  }
1801 
1803  bool position_is_pinned(const unsigned& i)
1804  {
1806  }
1807 
1810  bool position_is_pinned(const unsigned& k, const unsigned& i)
1811  {
1813  }
1814 
1816  void pin_position(const unsigned& i)
1817  {
1819  }
1820 
1823  void pin_position(const unsigned& k, const unsigned& i)
1824  {
1825  return Variable_position_pt->pin(Nposition_type * i + k);
1826  }
1827 
1829  void unpin_position(const unsigned& i)
1830  {
1832  }
1833 
1836  void unpin_position(const unsigned& k, const unsigned& i)
1837  {
1839  }
1840 
1842  void pin_all()
1843  {
1844  Node::pin_all();
1846  }
1847 
1849  void unpin_all()
1850  {
1851  Node::unpin_all();
1853  }
1854 
1857  inline void constrain_positions()
1858  {
1860  }
1861 
1865  {
1867  }
1868 
1870  unsigned nlagrangian() const
1871  {
1872  return Nlagrangian;
1873  }
1874 
1877  unsigned nlagrangian_type() const
1878  {
1879  return Nlagrangian_type;
1880  }
1881 
1883  double& xi(const unsigned& i)
1884  {
1885 #ifdef RANGE_CHECKING
1886  xi_gen_range_check(0, i);
1887 #endif
1888  return Xi_position[Nlagrangian_type * i];
1889  }
1890 
1892  const double& xi(const unsigned& i) const
1893  {
1894 #ifdef RANGE_CHECKING
1895  xi_gen_range_check(0, i);
1896 #endif
1897  return Xi_position[Nlagrangian_type * i];
1898  }
1899 
1902  double& xi_gen(const unsigned& k, const unsigned& i)
1903  {
1904 #ifdef RANGE_CHECKING
1906 #endif
1907  return Xi_position[Nlagrangian_type * i + k];
1908  }
1909 
1912  const double& xi_gen(const unsigned& k, const unsigned& i) const
1913  {
1914 #ifdef RANGE_CHECKING
1916 #endif
1917  return Xi_position[Nlagrangian_type * i + k];
1918  }
1919 
1922  double lagrangian_position(const unsigned& i) const;
1923 
1926  double lagrangian_position_gen(const unsigned& k, const unsigned& i) const;
1927 
1929  void assign_eqn_numbers(unsigned long& global_number,
1930  Vector<double*>& dof_pt);
1931 
1940  void describe_dofs(std::ostream& out,
1941  const std::string& current_string) const;
1942 
1945  void add_value_pt_to_map(std::map<unsigned, double*>& map_of_value_pt);
1946 
1947 #ifdef OOMPH_HAS_MPI
1948 
1951  void add_values_to_vector(Vector<double>& vector_of_values);
1952 
1957  void read_values_from_vector(const Vector<double>& vector_of_values,
1958  unsigned& index);
1959 
1960 
1964  void add_eqn_numbers_to_vector(Vector<long>& vector_of_eqn_numbers);
1965 
1971  void read_eqn_numbers_from_vector(const Vector<long>& vector_of_eqn_numbers,
1972  unsigned& index);
1973 
1974 #endif
1975 
1976 
1981  void node_update(const bool& update_all_time_levels_for_new_node = false)
1982  {
1984  }
1985  };
1986 
1987 
1988  //======================================================================
1994  //======================================================================
1996  {
1997  private:
2004  std::map<unsigned, DenseMatrix<double>*>* Boundary_coordinates_pt;
2005 
2008  std::set<unsigned>* Boundaries_pt;
2009 
2010  protected:
2016  std::map<unsigned, unsigned>*
2018 
2022 
2026  void make_node_periodic(Node* const& node_pt,
2027  Node* const& original_node_pt);
2028 
2033  void make_nodes_periodic(Node* const& node_pt,
2034  Vector<Node*> const& periodic_copies_pt);
2035 
2036  public:
2042  const unsigned& n_additional_value, const unsigned& face_id = 0) = 0;
2043 
2046  std::map<unsigned, unsigned>*& index_of_first_value_assigned_by_face_element_pt()
2047  {
2049  }
2050 
2062  const unsigned& face_id = 0) const
2063  {
2064 #ifdef PARANOID
2066  {
2067  std::ostringstream error_message;
2068  error_message
2069  << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
2070  << "Pointer must be set via call to: \n\n"
2071  << " BoundaryNode::assign_additional_values_with_face_id(...), \n\n"
2072  << "typically from FaceElement::add_additional_values(...).";
2073  throw OomphLibError(error_message.str(),
2076  return UINT_MAX;
2077  }
2078 #endif
2080  }
2081 
2082 
2099  const bool& throw_if_no_value_assigned_by_face_element,
2100  const bool& throw_quietly,
2101  const unsigned& face_id = 0) const
2102  {
2103  // Over-rule if paranoia rules
2104  bool local_throw_if_no_value_assigned_by_face_element =
2105  throw_if_no_value_assigned_by_face_element;
2106 #ifdef PARANOID
2107  local_throw_if_no_value_assigned_by_face_element = true;
2108 #endif
2109 
2110  if (local_throw_if_no_value_assigned_by_face_element)
2111  {
2113  {
2114  std::ostringstream error_message;
2115  error_message
2116  << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
2117  << "Pointer must be set via call to: \n\n"
2118  << " BoundaryNode::assign_additional_values_with_face_id(...), "
2119  "\n\n"
2120  << "typically from FaceElement::add_additional_values(...).";
2121 
2122  if (throw_quietly)
2123  {
2124  throw OomphLibQuietException();
2125  }
2126  else
2127  {
2128  throw OomphLibError(error_message.str(),
2131  }
2132  return UINT_MAX;
2133  }
2134  }
2136  }
2137 
2149  const unsigned& face_id = 0) const = 0;
2150 
2154  Boundaries_pt(0),
2156  Copied_node_pt(0)
2157  {
2158  }
2159 
2161  virtual ~BoundaryNodeBase();
2162 
2164  BoundaryNodeBase(const BoundaryNodeBase& boundary_node_base) = delete;
2165 
2167  void operator=(const BoundaryNodeBase&) = delete;
2168 
2171  {
2172  return (Boundary_coordinates_pt != 0);
2173  }
2174 
2177  void get_boundaries_pt(std::set<unsigned>*& boundaries_pt)
2178  {
2179  boundaries_pt = Boundaries_pt;
2180  }
2181 
2183  void add_to_boundary(const unsigned& b);
2184 
2186  void remove_from_boundary(const unsigned& b);
2187 
2189  bool is_on_boundary() const
2190  {
2191  return !(Boundaries_pt == 0);
2192  }
2193 
2195  bool is_on_boundary(const unsigned& b) const;
2196 
2198  unsigned ncoordinates_on_boundary(const unsigned& b);
2199 
2201  void get_coordinates_on_boundary(const unsigned& b,
2202  Vector<double>& boundary_zeta)
2203  {
2204  // Just return the zero-th one
2205  get_coordinates_on_boundary(b, 0, boundary_zeta);
2206  }
2207 
2208 
2210  void set_coordinates_on_boundary(const unsigned& b,
2211  const Vector<double>& boundary_zeta)
2212  {
2213  // Just do the zero-th one
2214  set_coordinates_on_boundary(b, 0, boundary_zeta);
2215  }
2216 
2219  void get_coordinates_on_boundary(const unsigned& b,
2220  const unsigned& k,
2221  Vector<double>& boundary_zeta);
2222 
2225  void set_coordinates_on_boundary(const unsigned& b,
2226  const unsigned& k,
2227  const Vector<double>& boundary_zeta);
2228  };
2229 
2230 
2231  //====================================================================
2239  //===================================================================
2240  template<class NODE_TYPE>
2241  class BoundaryNode : public NODE_TYPE, public BoundaryNodeBase
2242  {
2243  private:
2246  {
2247 #ifdef PARANOID
2248  if (Copied_node_pt == 0)
2249  {
2250  throw OomphLibError("BoundaryNode has not been copied",
2253  }
2254 #endif
2255 
2256  // Set the number of values
2257  this->Nvalue = Copied_node_pt->nvalue();
2258  this->Value = Copied_node_pt->Value;
2259  this->Eqn_number = Copied_node_pt->Eqn_number;
2260  // We won't ever need to worry about updating position pointers
2261  // because periodic solid problems are handled using lagrange multipliers.
2262 
2263  // Cast Copied_node_pt to BoundaryNode to copy over the
2264  // Face index pointer
2265  BoundaryNode<NODE_TYPE>* cast_copied_node_pt =
2266  dynamic_cast<BoundaryNode<NODE_TYPE>*>(Copied_node_pt);
2267 
2268  // Check that dynamic cast has worked
2269  if (cast_copied_node_pt)
2270  {
2272  cast_copied_node_pt
2274  }
2275  else
2276  {
2277  std::ostringstream error_stream;
2278  error_stream << "Copied_node_pt is not of type BoundaryNode*"
2279  << std::endl;
2280  throw OomphLibError(
2281  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2282  }
2283  }
2284 
2289  {
2290  // Only worry about the face index if it has been assigned
2291  // which it will have been
2293  {
2294  // Allocate new storage for the index of first value assigned by face
2295  // element The other storage will be deleted
2297  new std::map<unsigned, unsigned>;
2298 
2299  // Cast copied_node_pt to BoundaryNode so that we can reset the index
2300  BoundaryNode<NODE_TYPE>* cast_copied_node_pt =
2301  dynamic_cast<BoundaryNode<NODE_TYPE>*>(Copied_node_pt);
2302 
2303  // Check that dynamic cast has worked
2304  if (cast_copied_node_pt)
2305  {
2306  // Initialise the values in the map to be those of the original data
2307  // std::map<unsigned,unsigned>::const_iterator it =
2308  // (*(cast_copied_node_pt->
2309  // index_of_first_value_assigned_by_face_element_pt())).begin();
2310  std::map<unsigned, unsigned>::const_iterator end =
2311  (*(cast_copied_node_pt
2313  .end();
2314  for (std::map<unsigned, unsigned>::const_iterator it =
2315  (*(cast_copied_node_pt
2317  .begin();
2318  it != end;
2319  it++)
2320  {
2322  [it->first] = it->second;
2323  }
2324  }
2325  }
2326  }
2327 
2328  public:
2333  {
2334 #ifdef PARANOID
2335  if (Copied_node_pt == 0)
2336  {
2337  throw OomphLibError("BoundaryNode has not been copied",
2340  }
2341 #endif
2342 
2343  // Simply zeroing these will cause problems during unrefinement because
2344  // the original could be deleted, but the "copy" remain. Instead we
2345  // allocate new storage and copy values over from the original.
2346 
2347  // Get the number of values and time storage
2348  //(must be the same as the original)
2349  const unsigned n_value = this->nvalue();
2350  const unsigned n_tstorage = this->ntstorage();
2351 
2352  // Allocate storage for equation numbers
2353  this->Eqn_number = new long[n_value];
2354 
2355  // Allocate storage for the values
2356  this->Value = new double*[n_value];
2357 
2358  // Allocate all data values in one big array
2359  double* values = new double[n_value * n_tstorage];
2360 
2361  // Set the pointers to the data values and equation numbers
2362  for (unsigned i = 0; i < n_value; ++i)
2363  {
2364  // Set the pointers
2365  this->Value[i] = &values[i * n_tstorage];
2366  // Initialise all the values to be those of the original data
2367  for (unsigned t = 0; t < n_tstorage; ++t)
2368  {
2369  this->Value[i][t] = Copied_node_pt->value(t, i);
2370  }
2371 
2372  // Copy over the values of the equation numbers
2373  this->Eqn_number[i] = Copied_node_pt->eqn_number(i);
2374  }
2375 
2376  // The node is no longer a copy
2377  Copied_node_pt = 0;
2378  }
2379 
2380 
2383 
2391  BoundaryNode(const unsigned& n_dim,
2392  const unsigned& n_position_type,
2393  const unsigned& initial_n_value)
2394  : NODE_TYPE(n_dim, n_position_type, initial_n_value), BoundaryNodeBase()
2395  {
2396  }
2397 
2407  BoundaryNode(TimeStepper* const& time_stepper_pt,
2408  const unsigned& n_dim,
2409  const unsigned& n_position_type,
2410  const unsigned& initial_n_value)
2411  : NODE_TYPE(time_stepper_pt, n_dim, n_position_type, initial_n_value),
2413  {
2414  }
2415 
2424  BoundaryNode(const unsigned& n_lagrangian,
2425  const unsigned& n_lagrangian_type,
2426  const unsigned& n_dim,
2427  const unsigned& n_position_type,
2428  const unsigned& initial_n_value)
2429  : NODE_TYPE(n_lagrangian,
2430  n_lagrangian_type,
2431  n_dim,
2432  n_position_type,
2433  initial_n_value),
2435  {
2436  }
2437 
2445  BoundaryNode(TimeStepper* const& time_stepper_pt,
2446  const unsigned& n_lagrangian,
2447  const unsigned& n_lagrangian_type,
2448  const unsigned& n_dim,
2449  const unsigned& n_position_type,
2450  const unsigned& initial_n_value)
2451  : NODE_TYPE(time_stepper_pt,
2452  n_lagrangian,
2453  n_lagrangian_type,
2454  n_dim,
2455  n_position_type,
2456  initial_n_value),
2458  {
2459  }
2460 
2463  {
2464  // If there are any copies of this Node
2465  // then we need to clear their pointers to information stored in
2466  // this BoundaryNode
2467  // at this level because once we are down to the Node's destructor
2468  // the information no longer exists.
2469  for (unsigned i = 0; i < this->Ncopies; i++)
2470  {
2471  // Is the copied node a boundary node (it should be)
2472  BoundaryNode<NODE_TYPE>* cast_node_pt =
2473  dynamic_cast<BoundaryNode<NODE_TYPE>*>(this->Copy_of_data_pt[i]);
2474  // We can only do this if the node is a boundary node
2475  if (cast_node_pt != 0)
2476  {
2477  // This is required to clear out any pointers to the additional
2478  // data assigned by face elements
2479  cast_node_pt->clear_additional_copied_pointers();
2480  }
2481  // Otherwise there is a problem if it's not Hijacked Data
2482 #ifdef PARANOID
2483  else
2484  {
2485  if (dynamic_cast<HijackedData*>(this->Copy_of_data_pt[i]) == 0)
2486  {
2487  OomphLibError(
2488  "Copy of a BoundaryNode is not a BoundaryNode or HijackedData",
2489  "BoundaryNode::~BoundaryNode",
2491  }
2492  }
2493 #endif
2494  }
2495 
2496  // If the node was periodic then clear the pointers before deleting
2497  if (Copied_node_pt)
2498  {
2499  // Inform the node that the copy is being deleted
2500  // If the original has been deleted Copied_node_pt will be NULL
2501  Copied_node_pt->remove_copy(this);
2502  Copied_node_pt = 0;
2503  this->Value = 0;
2504  this->Eqn_number = 0;
2505  // Remove the information about the boundary node storage scheme
2507  }
2508  }
2509 
2511  BoundaryNode(const BoundaryNode<NODE_TYPE>& node) = delete;
2512 
2514  void operator=(const BoundaryNode<NODE_TYPE>&) = delete;
2515 
2518  {
2520  }
2521 
2525  void get_boundaries_pt(std::set<unsigned>*& boundaries_pt)
2526  {
2527  BoundaryNodeBase::get_boundaries_pt(boundaries_pt);
2528  }
2529 
2532  bool is_on_boundary() const
2533  {
2535  }
2536 
2539  bool is_on_boundary(const unsigned& b) const
2540  {
2542  }
2543 
2545  void add_to_boundary(const unsigned& b)
2546  {
2548  }
2549 
2551  void remove_from_boundary(const unsigned& b)
2552  {
2554  }
2555 
2556 
2558  unsigned ncoordinates_on_boundary(const unsigned& b)
2559  {
2561  }
2562 
2563 
2566  void get_coordinates_on_boundary(const unsigned& b,
2567  Vector<double>& boundary_zeta)
2568  {
2570  }
2571 
2574  void set_coordinates_on_boundary(const unsigned& b,
2575  const Vector<double>& boundary_zeta)
2576  {
2578  }
2579 
2580 
2583  void get_coordinates_on_boundary(const unsigned& b,
2584  const unsigned& k,
2585  Vector<double>& boundary_zeta)
2586  {
2588  }
2589 
2592  void set_coordinates_on_boundary(const unsigned& b,
2593  const unsigned& k,
2594  const Vector<double>& boundary_zeta)
2595  {
2597  }
2598 
2599 
2610  unsigned nvalue_assigned_by_face_element(const unsigned& face_id = 0) const
2611  {
2612 #ifdef PARANOID
2614  {
2615  std::ostringstream error_message;
2616  error_message
2617  << "Index_of_first_value_assigned_by_face_element_pt==0;\n"
2618  << "Pointer must be set via call to: \n\n"
2619  << " BoundaryNode::assign_additional_values_with_face_id(), \n\n"
2620  << "typically from FaceElement::add_additional_values(...).";
2621  throw OomphLibError(error_message.str(),
2624  return UINT_MAX;
2625  }
2626 #endif
2627 
2628  // How many values are there in total?
2629  unsigned nval = this->nvalue();
2630 
2631  // If ID is not present in the map then return 0
2634  {
2635  return 0;
2636  }
2637 
2638  // Otherwise the entry is present in the map
2639 
2640  // Single entry: Number of values is the difference between
2641  // number of values and first index
2642  else if ((*Index_of_first_value_assigned_by_face_element_pt).size() == 1)
2643  {
2644  return nval -
2645  (*Index_of_first_value_assigned_by_face_element_pt)[face_id];
2646  }
2647  else
2648  {
2649  // Find the next first index: Default: nvalue()
2650  unsigned next_first_index = nval;
2651  unsigned my_first_index =
2652  (*Index_of_first_value_assigned_by_face_element_pt)[face_id];
2653  for (std::map<unsigned, unsigned>::iterator it =
2654  (*Index_of_first_value_assigned_by_face_element_pt).begin();
2655  it != (*Index_of_first_value_assigned_by_face_element_pt).end();
2656  it++)
2657  {
2658  unsigned first_index = (*it).second;
2659  if ((first_index > my_first_index) &&
2660  (first_index < next_first_index))
2661  {
2662  next_first_index = first_index;
2663  }
2664  }
2665  return next_first_index - my_first_index;
2666  }
2667  }
2668 
2669 
2670  //=====================================================================
2676  //=====================================================================
2678  const unsigned& n_additional_value, const unsigned& face_id = 0)
2679  {
2680 #ifdef PARANOID
2681  // If nothing is being added warn the user
2682  if (n_additional_value == 0)
2683  {
2684  std::ostringstream warn_message;
2685  warn_message
2686  << "No additional data values are being added to the boundary node "
2687  << this << "\n"
2688  << "by face id " << face_id << ".\n"
2689  << "This means that the function \n"
2690  << "BoundaryNode::index_of_first_value_assigned_by_face_element(id) "
2691  "\n"
2692  << "will return a value that is equal to the number of values stored "
2693  "at the Node.\n"
2694  << "Calling Node::value(...) with this index will lead to an "
2695  "out-of-range error.\n"
2696  << "The anticpated usage of a loop from the index over the number of "
2697  "values.\n"
2698  << "will not cause any problems, but if you try to do anything else, "
2699  "you may be surprised.\n"
2700  << "You have been warned!\n";
2702  warn_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2703  }
2704 #endif
2705 
2706  // Allocate storage if not already assigned
2708  {
2710  new std::map<unsigned, unsigned>;
2711  }
2712 
2713  // Find the number of values already stored in the node
2714  const unsigned n_value = this->nvalue();
2715 
2716  // If this ID hasn't already been used
2718  face_id) ==
2719  this->Index_of_first_value_assigned_by_face_element_pt->end())
2720  {
2721  // Set the first index to by number of values
2722  (*Index_of_first_value_assigned_by_face_element_pt)[face_id] = n_value;
2723  }
2724  // Otherwise this ID has been used previously
2725  else
2726  {
2727  // Find the number of values associated with this id
2728  const unsigned n_value_for_id =
2729  this->nvalue_assigned_by_face_element(face_id);
2730 
2731  // If the number of current values is equal to the desired values
2732  // do nothing and return
2733  if (n_value_for_id == n_additional_value)
2734  {
2735  return;
2736  }
2737  // Otherwise
2738  else
2739  {
2740  // Safety check, are the value associated with this id
2741  // all at the end
2743  [face_id] +
2744  n_value_for_id) != n_value)
2745  {
2746 #ifdef PARANOID
2747  std::ostringstream warn_message;
2748  warn_message << "Trying to (resize) number of unknowns associated "
2749  "with face id "
2750  << face_id << "\n"
2751  << "but previous storage for this data is not at the "
2752  "end of the nodal values.\n"
2753  << "The anticipated usage here is within constructors "
2754  "that add additional equations\n"
2755  << "to existing FaceElements in which case we will "
2756  "always be at the end.\n"
2757  << "If you are trying to do something else, then try "
2758  "using a different id.\n"
2759  << " FaceElement::add_additional_values(...)."
2760  << " For consistency with earlier versions, this will "
2761  "do nothing!\n";
2762  OomphLibWarning(warn_message.str(),
2765 #endif
2766  // Just return without doing anything
2767  return;
2768  }
2769  } // Case when we are actually requesting additional values
2770  } // End case when ID has already been touched
2771 
2772  // Now finally resize the storage
2773  this->resize(n_value + n_additional_value);
2774  }
2775 
2776 
2778  void make_periodic(Node* const& node_pt)
2779  {
2780  BoundaryNodeBase::make_node_periodic(this, node_pt);
2781  }
2782 
2785  void make_periodic_nodes(const Vector<Node*>& periodic_nodes_pt)
2786  {
2787  BoundaryNodeBase::make_nodes_periodic(this, periodic_nodes_pt);
2788  }
2789 
2792  bool is_a_copy() const
2793  {
2794  if (Copied_node_pt)
2795  {
2796  return true;
2797  }
2798  else
2799  {
2800  return false;
2801  }
2802  }
2803 
2807  bool is_a_copy(const unsigned& i) const
2808  {
2809  if (Copied_node_pt)
2810  {
2811  return true;
2812  }
2813  else
2814  {
2815  return false;
2816  }
2817  }
2818 
2819 
2823  {
2824  return Copied_node_pt;
2825  }
2826 
2828  void assign_eqn_numbers(unsigned long& global_ndof, Vector<double*>& dof_pt)
2829  {
2830  // If the boundary node is not periodic call the ususal
2831  // assign equation numbers
2832  if (Copied_node_pt == 0)
2833  {
2834  NODE_TYPE::assign_eqn_numbers(global_ndof, dof_pt);
2835  }
2836  // Otherwise make sure that we assign equation numbers for
2837  // the variable position pointer of the solid node
2838  else
2839  {
2840  // Is it a solid node?
2841  SolidNode* solid_node_pt = dynamic_cast<SolidNode*>(this);
2842  if (solid_node_pt)
2843  {
2844  // If so we must let the variable position pointer take care of
2845  // itself
2846  solid_node_pt->variable_position_pt()->assign_eqn_numbers(global_ndof,
2847  dof_pt);
2848  }
2849  }
2850  }
2851 
2852 
2854  void resize(const unsigned& n_value)
2855  {
2856  // If the node is periodic, warn, but do nothing
2857  if (Copied_node_pt)
2858  {
2859 #ifdef PARANOID
2860  unsigned n_value_new = Copied_node_pt->nvalue();
2861  // Check that we have already resized the original
2862  if (n_value_new != n_value)
2863  {
2864  std::ostringstream error_stream;
2865  error_stream
2866  << "Call to resize copied node before original has been resized!"
2867  << std::endl;
2868  throw OomphLibError(error_stream.str(),
2871  }
2872 #endif
2873  }
2874  // Otherwise call the underlying function
2875  else
2876  {
2877  NODE_TYPE::resize(n_value);
2878  }
2879  }
2880  };
2881 
2882 
2884  template<>
2885  inline void BoundaryNode<SolidNode>::make_periodic(Node* const& node_pt)
2886  {
2887 #ifdef PARANOID
2888  std::ostringstream warn_message;
2889  warn_message << "You are trying to make a Solid Node Periodic.\n"
2890  << "This action will reset pointers to stored values and "
2891  << "equation numbers,\n"
2892  << "meaning that all values will be shared by this Node and "
2893  << "its master.\n"
2894  << "Unfortunately, this does not ensure that the variable "
2895  << "nodal coordinates coincide.\n"
2896  << "For matching nodal coordinates the options are:\n"
2897  << "(i) Introduce Lagrange multipliers,\n"
2898  << "(ii) Pin one side and treat the data as dependent,\n"
2899  << "(iii) Hijack the nodal coordinates on one side "
2900  << "and specify an alternative equation.\n\n"
2901  << "If you plan to use refineability, then the easiest\n"
2902  << "option is to use Lagrange multipliers.\n"
2903  << std::endl;
2905  warn_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2906 #endif
2907 
2908  BoundaryNodeBase::make_node_periodic(this, node_pt);
2909  }
2910 
2911 
2912 } // namespace oomph
2913 
2914 #endif
int i
Definition: BiCGSTAB_step_by_step.cpp:9
int data[]
Definition: Map_placement_new.cpp:1
v resize(3)
Scalar * b
Definition: benchVecAdd.cpp:17
Definition: nodes.h:1996
BoundaryNodeBase()
Default constructor, set the pointers to the storage to NULL.
Definition: nodes.h:2152
unsigned ncoordinates_on_boundary(const unsigned &b)
Get the number of boundary coordinates on mesh boundary b.
Definition: nodes.cc:3119
std::set< unsigned > * Boundaries_pt
Definition: nodes.h:2008
unsigned index_of_first_value_assigned_by_face_element(const bool &throw_if_no_value_assigned_by_face_element, const bool &throw_quietly, const unsigned &face_id=0) const
Definition: nodes.h:2098
void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Definition: nodes.h:2177
virtual void assign_additional_values_with_face_id(const unsigned &n_additional_value, const unsigned &face_id=0)=0
void set_coordinates_on_boundary(const unsigned &b, const Vector< double > &boundary_zeta)
Set the vector of boundary coordinates on mesh boundary b.
Definition: nodes.h:2210
void make_node_periodic(Node *const &node_pt, Node *const &original_node_pt)
Definition: nodes.cc:2951
BoundaryNodeBase(const BoundaryNodeBase &boundary_node_base)=delete
Broken copy constructor.
void make_nodes_periodic(Node *const &node_pt, Vector< Node * > const &periodic_copies_pt)
Definition: nodes.cc:2896
void add_to_boundary(const unsigned &b)
Add the node to the mesh boundary b.
Definition: nodes.cc:3028
Node * Copied_node_pt
Definition: nodes.h:2021
void get_coordinates_on_boundary(const unsigned &b, Vector< double > &boundary_zeta)
Return the vector of boundary coordinates on mesh boundary b.
Definition: nodes.h:2201
bool boundary_coordinates_have_been_set_up()
Have boundary coordinates been set up?
Definition: nodes.h:2170
unsigned index_of_first_value_assigned_by_face_element(const unsigned &face_id=0) const
Definition: nodes.h:2061
std::map< unsigned, DenseMatrix< double > * > * Boundary_coordinates_pt
Definition: nodes.h:2004
void operator=(const BoundaryNodeBase &)=delete
Broken assignment operator.
std::map< unsigned, unsigned > * Index_of_first_value_assigned_by_face_element_pt
Definition: nodes.h:2017
bool is_on_boundary() const
Test whether the node lies on a boundary.
Definition: nodes.h:2189
void remove_from_boundary(const unsigned &b)
Remove the node from the mesh boundary b.
Definition: nodes.cc:3062
virtual ~BoundaryNodeBase()
Destructor, clean up any allocated storage for the boundaries.
Definition: nodes.cc:2993
std::map< unsigned, unsigned > *& index_of_first_value_assigned_by_face_element_pt()
Definition: nodes.h:2046
virtual unsigned nvalue_assigned_by_face_element(const unsigned &face_id=0) const =0
Definition: nodes.h:2242
void assign_additional_values_with_face_id(const unsigned &n_additional_value, const unsigned &face_id=0)
Definition: nodes.h:2677
BoundaryNode(TimeStepper *const &time_stepper_pt, const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_n_value)
Definition: nodes.h:2407
unsigned ncoordinates_on_boundary(const unsigned &b)
Get the number of boundary coordinates on mesh boundary b.
Definition: nodes.h:2558
~BoundaryNode()
Destructor resets pointers if.
Definition: nodes.h:2462
void operator=(const BoundaryNode< NODE_TYPE > &)=delete
Broken assignment operator.
void set_coordinates_on_boundary(const unsigned &b, const Vector< double > &boundary_zeta)
Definition: nodes.h:2574
BoundaryNode(const BoundaryNode< NODE_TYPE > &node)=delete
Broken copy constructor.
bool is_a_copy() const
Definition: nodes.h:2792
Node * copied_node_pt() const
Definition: nodes.h:2822
BoundaryNode(const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_n_value)
Definition: nodes.h:2391
void make_periodic_nodes(const Vector< Node * > &periodic_nodes_pt)
Definition: nodes.h:2785
BoundaryNode(const unsigned &n_lagrangian, const unsigned &n_lagrangian_type, const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_n_value)
Definition: nodes.h:2424
bool is_on_boundary() const
Definition: nodes.h:2532
bool is_a_copy(const unsigned &i) const
Definition: nodes.h:2807
void clear_copied_pointers()
Definition: nodes.h:2332
void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
Overload the equation assignment operation.
Definition: nodes.h:2828
void resize(const unsigned &n_value)
Resize the number of equations.
Definition: nodes.h:2854
void remove_from_boundary(const unsigned &b)
Remover the node from mesh boundary b, final overload.
Definition: nodes.h:2551
BoundaryNode(TimeStepper *const &time_stepper_pt, const unsigned &n_lagrangian, const unsigned &n_lagrangian_type, const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_n_value)
Definition: nodes.h:2445
void make_periodic(Node *const &node_pt)
Make the node periodic.
Definition: nodes.h:2778
void add_to_boundary(const unsigned &b)
Add the node to mesh boundary b, final overload.
Definition: nodes.h:2545
BoundaryNode()
Default Constructor.
Definition: nodes.h:2382
void clear_additional_copied_pointers()
Definition: nodes.h:2288
void reset_copied_pointers()
Set pointers to the copied data used when we have periodic nodes.
Definition: nodes.h:2245
bool boundary_coordinates_have_been_set_up()
Have boundary coordinates been set up?
Definition: nodes.h:2517
unsigned nvalue_assigned_by_face_element(const unsigned &face_id=0) const
Definition: nodes.h:2610
void get_coordinates_on_boundary(const unsigned &b, Vector< double > &boundary_zeta)
Definition: nodes.h:2566
void set_coordinates_on_boundary(const unsigned &b, const unsigned &k, const Vector< double > &boundary_zeta)
Definition: nodes.h:2592
void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Definition: nodes.h:2525
void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Definition: nodes.h:2583
bool is_on_boundary(const unsigned &b) const
Definition: nodes.h:2539
Definition: nodes.h:652
void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
Definition: nodes.h:708
~CopiedData()
Definition: nodes.h:675
Data * Copied_data_pt
Pointer to the Data object from which the values are copied.
Definition: nodes.h:655
void clear_copied_pointers()
Clear the pointers to the copied data.
Definition: nodes.cc:1398
void reset_copied_pointers()
Reset the pointers to the copied data.
Definition: nodes.cc:1381
bool is_a_copy(const unsigned &i) const
Definition: nodes.h:701
void resize(const unsigned &n_value)
We do not allow Copied Data to be resized.
Definition: nodes.cc:1438
bool is_a_copy() const
Definition: nodes.h:693
CopiedData(const Data &data)=delete
(Shallow) copy constructor
void operator=(const CopiedData &)=delete
Broken assignment operator.
Definition: nodes.h:86
long eqn_number(const unsigned &i) const
Return the equation number of the i-th stored variable.
Definition: nodes.h:376
static TimeStepper * Default_static_time_stepper_pt
Default (static) timestepper used in steady problems.
Definition: nodes.h:162
void add_copy(Data *const &data_pt)
Definition: nodes.cc:76
long & eqn_number(const unsigned &i)
Return the equation number of the i-th stored variable.
Definition: nodes.h:367
void pin_all()
Pin all the stored variables.
Definition: nodes.h:397
long * Eqn_number
Definition: nodes.h:116
bool does_pointer_correspond_to_value(double *const &parameter_pt)
Check whether the pointer parameter_pt addresses internal data values.
Definition: nodes.cc:568
void constrain(const unsigned &i)
Definition: nodes.h:432
virtual void describe_dofs(std::ostream &out, const std::string &current_string) const
Definition: nodes.cc:939
virtual void add_value_pt_to_map(std::map< unsigned, double * > &map_of_value_pt)
Definition: nodes.cc:1089
long * eqn_number_pt(const unsigned &i)
Return the pointer to the equation number of the i-th stored variable.
Definition: nodes.h:358
unsigned Nvalue
Number of values stored in the data object.
Definition: nodes.h:135
void set_value(const unsigned &t, const unsigned &i, const double &value_)
Definition: nodes.h:281
static long Is_pinned
Static "Magic number" to indicate pinned values.
Definition: nodes.h:183
double value(const unsigned &t, const unsigned &i) const
Definition: nodes.h:305
void range_check(const unsigned &t, const unsigned &i) const
Definition: nodes.cc:47
void remove_copy(Data *const &data_pt)
Definition: nodes.cc:102
virtual void clear_copied_pointers()
Definition: nodes.cc:176
void pin(const unsigned &i)
Pin the i-th stored variable.
Definition: nodes.h:385
friend class HijackedData
Definition: nodes.h:93
bool is_segregated_solve_pinned(const unsigned &i)
Definition: nodes.h:424
Data ** Copy_of_data_pt
Definition: nodes.h:127
void unpin(const unsigned &i)
Unpin the i-th stored variable.
Definition: nodes.h:391
double * value_pt(const unsigned &i) const
Definition: nodes.h:324
void copy(Data *orig_data_pt)
Copy Data values from specified Data object.
Definition: nodes.cc:601
void unpin_all()
Unpin all the stored variables.
Definition: nodes.h:407
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:238
void unconstrain_all()
Unconstrain all the stored variables when the data is made nonhanging.
Definition: nodes.h:461
TimeStepper * Time_stepper_pt
Definition: nodes.h:122
friend class CopiedData
Definition: nodes.h:94
static long Is_constrained
Definition: nodes.h:198
void set_value(const unsigned &i, const double &value_)
Definition: nodes.h:271
virtual bool is_a_copy() const
Definition: nodes.h:253
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:483
unsigned Ncopies
Definition: nodes.h:131
void dump(std::ostream &dump_file) const
Dump the data object to a file.
Definition: nodes.cc:645
virtual ~Data()
Destructor, deallocates memory assigned for data.
Definition: nodes.cc:483
double value(const unsigned &i) const
Definition: nodes.h:293
unsigned ntstorage() const
Definition: nodes.cc:879
virtual void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
Definition: nodes.cc:896
double ** Value
Definition: nodes.h:112
Data(const Data &data)=delete
Broken copy constructor.
void constrain_all()
Constrain all the stored variables when the data is made hanging.
Definition: nodes.h:451
friend std::ostream & operator<<(std::ostream &out, const Data &d)
Definition: nodes.cc:349
bool is_constrained(const unsigned &i)
Definition: nodes.h:472
static long Is_unclassified
Definition: nodes.h:192
void delete_value_storage()
Definition: nodes.cc:187
virtual void resize(const unsigned &n_value)
Change (increase) the number of values that may be stored.
Definition: nodes.cc:1002
Data()
Default constructor.
Definition: nodes.cc:237
void unconstrain(const unsigned &i)
Definition: nodes.h:442
void set_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Definition: nodes.cc:406
TimeStepper *const & time_stepper_pt() const
Return the pointer to the timestepper (const version).
Definition: nodes.h:244
void read(std::ifstream &restart_file)
Read data object from a file.
Definition: nodes.cc:672
static long Is_segregated_solve_pinned
Definition: nodes.h:188
virtual bool is_a_copy(const unsigned &i) const
Definition: nodes.h:261
unsigned self_test()
Definition: nodes.cc:965
double * value_pt(const unsigned &t, const unsigned &i) const
Definition: nodes.h:337
bool is_pinned(const unsigned &i) const
Test whether the i-th variable is pinned (1: true; 0: false).
Definition: nodes.h:417
void operator=(const Data &)=delete
Broken assignment operator.
virtual void reset_copied_pointers()
Definition: nodes.cc:162
Definition: geom_objects.h:101
Definition: nodes.h:742
Node ** Master_nodes_pt
C-style array of pointers to nodes that this hanging node depends on.
Definition: nodes.h:839
~HangInfo()
Delete the storage.
Definition: nodes.h:763
HangInfo()
Default constructor, initialise vectors to have size zero.
Definition: nodes.h:745
double const & master_weight(const unsigned &i) const
Return weight for dofs on i-th master node.
Definition: nodes.h:808
Node *const & master_node_pt(const unsigned &i) const
Return a pointer to the i-th master node.
Definition: nodes.h:791
void operator=(const HangInfo &)=delete
Broken assignment operator.
HangInfo(const unsigned &n_master)
Alternative constructor when the number of master nodes is known.
Definition: nodes.h:753
void range_check(const unsigned &i) const
Definition: nodes.cc:1456
unsigned Nmaster
Number of master nodes required by this hanging node.
Definition: nodes.h:845
unsigned nmaster() const
Return the number of master nodes.
Definition: nodes.h:785
double * Master_weights
C-style array of weights for the dofs on the master nodes.
Definition: nodes.h:842
void add_master_node_pt(Node *const &master_node_pt, const double &weight)
Definition: nodes.cc:1489
HangInfo(const HangInfo &)=delete
Broken copy constructor.
void set_master_node_pt(const unsigned &i, Node *const &master_node_pt, const double &weight)
Set the pointer to the i-th master node and its weight.
Definition: nodes.cc:1474
Definition: nodes.h:575
Data * Copied_data_pt
Pointer to the Data object from which the value is copied.
Definition: nodes.h:578
~HijackedData()
Definition: nodes.h:601
void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
Definition: nodes.h:634
unsigned Copied_index
Index of the value that is copied from within the Data object.
Definition: nodes.h:581
bool is_a_copy(const unsigned &i) const
Definition: nodes.h:627
bool is_a_copy() const
Definition: nodes.h:619
void resize(const unsigned &n_value)
We do not allow Hijacked Data to be resized.
Definition: nodes.cc:1363
void reset_copied_pointers()
Reset the pointers to the copied data.
Definition: nodes.cc:1304
void operator=(const HijackedData &)=delete
Broken assignment operator.
HijackedData(const Data &data)=delete
(Shallow) copy constructor
void clear_copied_pointers()
Clear the pointers to the copied data.
Definition: nodes.cc:1318
static OomphCommunicator * communicator_pt()
access to the global oomph-lib communicator
Definition: oomph_utilities.cc:1046
Definition: nodes.h:906
double dx_gen_dt(const unsigned &k, const unsigned &i) const
Definition: nodes.cc:1865
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
double & x_gen(const unsigned &k, const unsigned &i)
Definition: nodes.h:1126
virtual void set_coordinates_on_boundary(const unsigned &b, const Vector< double > &boundary_zeta)
Definition: nodes.h:1428
HangInfo *const & hanging_pt() const
Definition: nodes.h:1228
HangInfo *const & hanging_pt(const int &i) const
Return pointer to hanging node data for value i (const version)
Definition: nodes.h:1243
virtual bool position_is_a_copy(const unsigned &i) const
Return whether the position coordinate i has been copied (always false)
Definition: nodes.h:1119
void copy(Node *orig_node_pt)
Copy all nodal data from specified Node object.
Definition: nodes.cc:1916
double & x_gen(const unsigned &t, const unsigned &k, const unsigned &i)
Definition: nodes.h:1146
virtual void set_position_time_stepper(TimeStepper *const &position_time_stepper_pt, const bool &preserve_existing_data)
Definition: nodes.cc:1752
void operator=(const Node &)=delete
Broken assignment operator.
virtual unsigned ncoordinates_on_boundary(const unsigned &b)
Definition: nodes.cc:2363
void set_nonhanging()
Label node as non-hanging node by removing all hanging node data.
Definition: nodes.cc:2281
bool is_obsolete()
Test whether node is obsolete.
Definition: nodes.h:1448
virtual unsigned ngeom_object() const
Definition: nodes.h:1639
virtual bool is_on_boundary() const
Definition: nodes.h:1373
virtual GeomObject ** all_geom_object_pt()
Definition: nodes.h:1647
void set_obsolete()
Mark node as obsolete.
Definition: nodes.h:1436
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Definition: nodes.h:1365
virtual void pin_all()
Definition: nodes.h:1197
void read(std::ifstream &restart_file)
Read nodal position and associated data from file for restart.
Definition: nodes.cc:1996
static unsigned No_independent_position
Definition: nodes.h:972
bool is_hanging(const int &i) const
Test whether the i-th value is hanging.
Definition: nodes.h:1298
TimeStepper *const & position_time_stepper_pt() const
Return a pointer to the position timestepper (const version).
Definition: nodes.h:1028
void x_gen_range_check(const unsigned &t, const unsigned &k, const unsigned &i) const
Definition: nodes.cc:1528
virtual void assign_eqn_numbers(unsigned long &global_ndof, Vector< double * > &dof_pt)
Definition: nodes.cc:534
void set_auxiliary_node_update_fct_pt(AuxNodeUpdateFctPt aux_node_update_fct_pt)
Definition: nodes.h:1596
virtual void remove_from_boundary(const unsigned &b)
Definition: nodes.cc:2350
void perform_auxiliary_node_update_fct()
Definition: nodes.h:1615
virtual void get_coordinates_on_boundary(const unsigned &b, Vector< double > &boundary_zeta)
Definition: nodes.h:1420
void set_non_obsolete()
Mark node as non-obsolete.
Definition: nodes.h:1442
virtual Data ** all_geom_data_pt()
Definition: nodes.h:1632
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
virtual void make_periodic_nodes(const Vector< Node * > &periodic_nodes_pt)
Definition: nodes.cc:2270
double & x(const unsigned &t, const unsigned &i)
Definition: nodes.h:1079
virtual bool position_is_a_copy() const
Return whether any position coordinate has been copied (always false)
Definition: nodes.h:1113
const double & x_gen(const unsigned &k, const unsigned &i) const
Definition: nodes.h:1136
double * x_position_pt(const unsigned &i)
Direct access to the pointer to the i-th stored coordinate data.
Definition: nodes.h:958
virtual void constrain_positions()
Definition: nodes.h:1345
void output(std::ostream &outfile)
Output nodal position.
Definition: nodes.cc:2760
AuxNodeUpdateFctPt Aux_node_update_fct_pt
Definition: nodes.h:967
TimeStepper * Position_time_stepper_pt
Pointer to the timestepper associated with the position data.
Definition: nodes.h:932
virtual void unpin_all()
Definition: nodes.h:1204
double ** X_position
Definition: nodes.h:929
virtual void add_to_boundary(const unsigned &b)
Definition: nodes.cc:2336
virtual void set_coordinates_on_boundary(const unsigned &b, const unsigned &k, const Vector< double > &boundary_zeta)
Definition: nodes.cc:2394
HangInfo ** Hanging_pt
Definition: nodes.h:942
void set_hanging_pt(HangInfo *const &hang_pt, const int &i)
Set the hanging data for the i-th value. (hang_pt=0 to make non-hanging)
Definition: nodes.cc:2068
Vector< double > value() const
Return vector of values calculated using value(vector).
Definition: nodes.h:1502
double * x_pt(const unsigned &t, const unsigned &i)
Definition: nodes.h:1181
TimeStepper *& position_time_stepper_pt()
Return a pointer to the position timestepper.
Definition: nodes.h:1022
const double & x(const unsigned &i) const
Return the i-th nodal coordinate (const version).
Definition: nodes.h:1069
const double & x(const unsigned &t, const unsigned &i) const
Definition: nodes.h:1089
unsigned Nposition_type
Definition: nodes.h:951
virtual bool boundary_coordinates_have_been_set_up()
Definition: nodes.cc:2323
double position_gen(const unsigned &k, const unsigned &i) const
Definition: nodes.cc:2592
unsigned Ndim
Eulerian dimension of the node.
Definition: nodes.h:945
unsigned hang_code()
Definition: nodes.h:1213
virtual bool does_pointer_correspond_to_position_data(double *const &parameter_pt)
Definition: nodes.h:1042
virtual void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Definition: nodes.cc:2379
double raw_value(const unsigned &i) const
Definition: nodes.h:1455
virtual void unconstrain_positions()
Definition: nodes.h:1349
Node(const Node &node)=delete
Broken copy constructor.
Vector< double > position() const
Return vector of position of node at current time.
Definition: nodes.h:1525
virtual Node * copied_node_pt() const
Definition: nodes.h:1107
virtual void dump(std::ostream &dump_file) const
Dump nodal position and associated data to file for restart.
Definition: nodes.cc:1969
friend std::ostream & operator<<(std::ostream &out, const Node &d)
Definition: nodes.cc:373
virtual bool is_on_boundary(const unsigned &b) const
Definition: nodes.h:1381
virtual unsigned ngeom_data() const
Definition: nodes.h:1625
const double & x_gen(const unsigned &t, const unsigned &k, const unsigned &i) const
Definition: nodes.h:1157
double dposition_dt(const unsigned &i) const
Definition: nodes.cc:2659
bool has_auxiliary_node_update_fct_pt()
Definition: nodes.h:1606
double dx_dt(const unsigned &i) const
Return the i-th component of nodal velocity: dx/dt.
Definition: nodes.cc:1817
bool Obsolete
Definition: nodes.h:955
void resize(const unsigned &n_value)
Resize the number of equations.
Definition: nodes.cc:2167
virtual void make_periodic(Node *const &node_pt)
Definition: nodes.cc:2257
double raw_value(const unsigned &t, const unsigned &i) const
Definition: nodes.h:1463
virtual void node_update(const bool &update_all_time_levels_for_new_node=false)
Definition: nodes.h:1586
unsigned nposition_type() const
Definition: nodes.h:1016
bool is_hanging() const
Test whether the node is geometrically hanging.
Definition: nodes.h:1285
Node()
Default constructor.
Definition: nodes.cc:1574
double dposition_gen_dt(const unsigned &k, const unsigned &i) const
Definition: nodes.cc:2708
virtual ~Node()
Destructor: Clean up the memory allocated for nodal position.
Definition: nodes.cc:1695
void(* AuxNodeUpdateFctPt)(Node *)
Function pointer to auxiliary node update function.
Definition: nodes.h:909
double value(const unsigned &i) const
Definition: nodes.cc:2408
int my_rank() const
my rank
Definition: communicator.h:176
Definition: oomph_definitions.h:222
Definition: oomph_definitions.h:149
Definition: oomph_definitions.h:267
Definition: nodes.h:1686
void constrain_positions()
Definition: nodes.h:1857
void xi_gen_range_check(const unsigned &k, const unsigned &i) const
Definition: nodes.cc:3312
void unpin_all()
Unpin all the stored variables (Overloaded)
Definition: nodes.h:1849
const double & xi(const unsigned &i) const
Reference to i-th Lagrangian position (const version)
Definition: nodes.h:1892
void set_position_time_stepper(TimeStepper *const &position_time_stepper_pt, const bool &preserve_existing_data)
Definition: nodes.cc:3548
unsigned Nlagrangian
Number of Lagrangian coordinates of the node.
Definition: nodes.h:1694
void unconstrain_positions()
Definition: nodes.h:1864
bool does_pointer_correspond_to_position_data(double *const &parameter_pt)
Check whether the pointer parameter_pt refers to positional data.
Definition: nodes.cc:3573
const double & xi_gen(const unsigned &k, const unsigned &i) const
Definition: nodes.h:1912
unsigned nlagrangian_type() const
Definition: nodes.h:1877
void unpin_position(const unsigned &k, const unsigned &i)
Definition: nodes.h:1836
double & xi_gen(const unsigned &k, const unsigned &i)
Definition: nodes.h:1902
SolidNode(const SolidNode &solid_node)=delete
Broken copy constructor.
const Data & variable_position() const
Return the variable_position data (const version)
Definition: nodes.h:1759
Data * Variable_position_pt
Pointer to data that will hold variable positions in elastic nodes.
Definition: nodes.h:1701
void add_value_pt_to_map(std::map< unsigned, double * > &map_of_value_pt)
Definition: nodes.cc:3693
unsigned Nlagrangian_type
Definition: nodes.h:1698
double lagrangian_position(const unsigned &i) const
Definition: nodes.cc:3586
double lagrangian_position_gen(const unsigned &k, const unsigned &i) const
Definition: nodes.cc:3619
SolidNode()
Default Constructor.
Definition: nodes.h:1708
const long & position_eqn_number(const unsigned &k, const unsigned &i) const
Definition: nodes.h:1797
virtual ~SolidNode()
Destructor that cleans up the additional memory allocated in SolidNodes.
Definition: nodes.cc:3416
void describe_dofs(std::ostream &out, const std::string &current_string) const
Definition: nodes.cc:3671
bool position_is_a_copy(const unsigned &i) const
Return whether the position coordinate i has been copied.
Definition: nodes.h:1790
void pin_position(const unsigned &i)
Pin the nodal position.
Definition: nodes.h:1816
bool position_is_a_copy() const
Return whether any position component has been copied.
Definition: nodes.h:1784
void dump(std::ostream &dump_file) const
Dump nodal positions and associated data to file for restart.
Definition: nodes.cc:3470
void pin_all()
Pin all the stored variables (Overloaded)
Definition: nodes.h:1842
void unpin_position(const unsigned &i)
Unpin the nodal position.
Definition: nodes.h:1829
void set_external_variable_position_pt(Data *const &data_pt)
Set the variable position data from an external data object.
Definition: nodes.cc:3532
void read(std::ifstream &restart_file)
Read nodal positions and associated data to file for restart.
Definition: nodes.cc:3490
double * Xi_position
Storage for the Lagrangian positions.
Definition: nodes.h:1704
double & xi(const unsigned &i)
Reference to i-th Lagrangian position.
Definition: nodes.h:1883
void pin_position(const unsigned &k, const unsigned &i)
Definition: nodes.h:1823
void assign_eqn_numbers(unsigned long &global_number, Vector< double * > &dof_pt)
Overload the assign equation numbers routine.
Definition: nodes.cc:3652
void copy(SolidNode *orig_node_pt)
Definition: nodes.cc:3433
void node_update(const bool &update_all_time_levels_for_new_node=false)
Definition: nodes.h:1981
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
Definition: nodes.h:1765
bool position_is_pinned(const unsigned &k, const unsigned &i)
Definition: nodes.h:1810
unsigned nlagrangian() const
Return number of lagrangian coordinates.
Definition: nodes.h:1870
bool position_is_pinned(const unsigned &i)
Test whether the i-th coordinate is pinned, 0: false; 1: true.
Definition: nodes.h:1803
void operator=(const SolidNode &)=delete
Broken assignment operator.
Definition: timesteppers.h:231
static constexpr lastp1_t end
Definition: IndexedViewHelper.h:79
char char char int int * k
Definition: level2_impl.h:374
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 pow(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:625
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
t
Definition: plotPSD.py:36
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ofstream out("Result.txt")
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2