spines.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 // Header file for spine nodes, elements and meshes
27 
28 // Include guards to prevent multiple inclusion of the header
29 #ifndef OOMPH_SPINES_HEADER
30 #define OOMPH_SPINES_HEADER
31 
32 
33 #include <string>
34 
35 // oomph-lib headers
36 #include "nodes.h"
37 #include "elements.h"
38 #include "mesh.h"
39 #include "geom_objects.h"
41 
42 namespace oomph
43 {
44  //=================================================================
62  //=================================================================
63  class Spine
64  {
65  public:
69  {
70  Geom_data_pt.resize(1);
71  // Create Data for height. By default it's free
72  Geom_data_pt[0] = new Data(1);
73  }
74 
77  Spine(const double& height)
78  {
79  Geom_data_pt.resize(1);
80  // Create Data for height. By default it's free
81  Geom_data_pt[0] = new Data(1);
82  // Set value
83  Geom_data_pt[0]->set_value(0, height);
84  }
85 
90  Spine(const double& height, const Vector<Data*>& geom_data_pt)
91  {
92  // Find the number of geometric data passed
93  const unsigned n_geom_data = geom_data_pt.size();
94  // Now allocate enough storage for the spine height and additional
95  // geometric data
96  Geom_data_pt.resize(n_geom_data + 1);
97 
98  // Create Data for height. By default it's free
99  Geom_data_pt[0] = new Data(1);
100  // Set value
101  Geom_data_pt[0]->set_value(0, height);
102  // Add the additional geometric data
103  for (unsigned i = 0; i < n_geom_data; i++)
104  {
105  Geom_data_pt[i + 1] = geom_data_pt[i];
106  }
107  }
108 
115  Spine(const double& height,
119  {
120  // Find the number of geometric data passed
121  const unsigned n_geom_data = geom_data_pt.size();
122  // Now allocate enough storage for the spine height and additional
123  // geometric data
124  Geom_data_pt.resize(n_geom_data + 1);
125 
126  // Create Data for height. By default it's free
127  Geom_data_pt[0] = new Data(1);
128  // Set value
129  Geom_data_pt[0]->set_value(0, height);
130  // Add the additional geometric data
131  for (unsigned i = 0; i < n_geom_data; i++)
132  {
133  Geom_data_pt[i + 1] = geom_data_pt[i];
134  }
135  }
136 
137 
143  {
144  // Kill spine height
145  delete Geom_data_pt[0];
146  }
147 
148 
150  double& height()
151  {
152  return *(Geom_data_pt[0]->value_pt(0));
153  }
154 
157  {
158  return Geom_data_pt[0];
159  }
160 
164  {
165  return Geom_data_pt[0];
166  }
167 
168 
171  unsigned ngeom_data()
172  {
173  return Geom_data_pt.size();
174  }
175 
180  {
181  unsigned n_geom_data = geom_data_pt.size();
182  Geom_data_pt.resize(n_geom_data + 1);
183  for (unsigned i = 1; i < n_geom_data; i++)
184  {
185  Geom_data_pt[i + 1] = geom_data_pt[i];
186  }
187  }
188 
192  {
193  Geom_data_pt.push_back(geom_data_pt);
194  }
195 
198  Data*& geom_data_pt(const unsigned& i)
199  {
200  return Geom_data_pt[i];
201  }
202 
205  Data* geom_data_pt(const unsigned& i) const
206  {
207  return Geom_data_pt[i];
208  }
209 
212  {
213  return Geom_data_pt;
214  }
215 
218  unsigned ngeom_object()
219  {
220  return Geom_object_pt.size();
221  }
222 
226  {
227  unsigned n_geom_object = geom_object_pt.size();
228  Geom_object_pt.resize(n_geom_object);
229  for (unsigned i = 0; i < n_geom_object; i++)
230  {
232  }
233  }
234 
238  {
239  Geom_object_pt.push_back(geom_object_pt);
240  }
241 
244  GeomObject*& geom_object_pt(const unsigned& i)
245  {
246  return Geom_object_pt[i];
247  }
248 
251  GeomObject* geom_object_pt(const unsigned& i) const
252  {
253  return Geom_object_pt[i];
254  }
255 
259  {
260  return Geom_object_pt;
261  }
262 
265  unsigned ngeom_parameter()
266  {
267  return Geom_parameter.size();
268  }
269 
274  {
276  }
277 
280  void add_geom_parameter(const double& geom_parameter)
281  {
282  Geom_parameter.push_back(geom_parameter);
283  }
284 
287  double& geom_parameter(const unsigned& i)
288  {
289  return Geom_parameter[i];
290  }
291 
294  const double& geom_parameter(const unsigned& i) const
295  {
296  return Geom_parameter[i];
297  }
298 
299 
300  private:
302  // Data* Spine_height_pt;
303 
306 
310 
313  };
314 
315 
316  // Forward declaration
317  class SpineMesh;
318 
319 
320  //=====================================================================
326  //=====================================================================
327  class SpineNode : public Node
328  {
329  private:
332 
334  double Fraction;
335 
339 
343 
344 
345  public:
347  SpineNode(const unsigned& n_dim,
348  const unsigned& n_position_type,
349  const unsigned& initial_nvalue)
350  : Node(n_dim, n_position_type, initial_nvalue),
351  Spine_pt(0),
352  Fraction(0),
353  Spine_mesh_pt(0),
355  {
356  }
357 
360  const unsigned& n_dim,
361  const unsigned& n_position_type,
362  const unsigned& initial_nvalue)
363  : Node(time_stepper_pt, n_dim, n_position_type, initial_nvalue),
364  Spine_pt(0),
365  Fraction(0),
366  Spine_mesh_pt(0),
368  {
369  }
370 
373  {
374  return Spine_pt;
375  }
376 
378  double& fraction()
379  {
380  return Fraction;
381  }
382 
384  unsigned& node_update_fct_id()
385  {
386  return Node_update_fct_id;
387  }
388 
392  {
393  return Spine_mesh_pt;
394  }
395 
397  double& h()
398  {
399  return Spine_pt->height();
400  }
401 
404  void node_update(const bool& update_all_time_levels_for_new_node = false);
405 
407  unsigned ngeom_data() const
408  {
409  if (Spine_pt)
410  {
411  return Spine_pt->ngeom_data();
412  }
413  else
414  {
415  return 0;
416  }
417  }
418 
420  unsigned ngeom_object() const
421  {
422  if (Spine_pt)
423  {
424  return Spine_pt->ngeom_object();
425  }
426  else
427  {
428  return 0;
429  }
430  }
431 
434  {
435  return &(Spine_pt->geom_data_pt(0));
436  }
437 
440  {
441  return &(Spine_pt->geom_object_pt(0));
442  }
443  };
444 
445 
449 
450 
451  //=======================================================================
454  //=======================================================================
456  {
457  public:
460 
462  virtual ~SpineFiniteElement() {}
463  };
464 
465 
466  //========================================================================
472  //========================================================================
473  template<class ELEMENT>
475  : public ElementWithSpecificMovingNodes<ELEMENT, SpineNode>,
476  public SpineFiniteElement
477  {
478  private:
482 
490 
491 
492  public:
498  {
499  }
500 
502  SpineElement(FiniteElement* const& element_pt, const int& face_index)
503  : ElementWithSpecificMovingNodes<ELEMENT, SpineNode>(element_pt,
504  face_index),
507  {
508  }
509 
512  {
514  {
515  delete[] Spine_geometric_index;
516  }
517  }
518 
521  inline int spine_local_eqn(const unsigned& n)
522  {
523 #ifdef RANGE_CHECKING
524  const unsigned n_node = this->nnode();
525  if (n >= n_node)
526  {
527  std::ostringstream error_message;
528  error_message << "Range Error: Node number " << n
529  << " is not in the range (0," << n_node - 1 << ")";
530  throw OomphLibError(error_message.str(),
533  }
534 #endif
535 
536 #ifdef PARANOID
537  // If there is no spine then you can't get the local equation
538  if (Spine_geometric_index[n] == this->ngeom_data())
539  {
540  std::ostringstream error_stream;
541  error_stream << "SpineNode " << n
542  << " does not have a Spine attached,\n"
543  << "so you can't get its local equation number.\n"
544  << "Check that the Mesh is correctly associating Spines "
545  "with is Nodes\n";
546  throw OomphLibError(
547  error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
548  }
549 #endif
550  return this->geometric_data_local_eqn(Spine_geometric_index[n], 0);
551  }
552  };
553 
554  //=======================================================================
557  //=======================================================================
558  template<class ELEMENT>
559  class FaceGeometry<SpineElement<ELEMENT>>
560  : public virtual FaceGeometry<ELEMENT>
561  {
562  public:
564  FaceGeometry() : FaceGeometry<ELEMENT>() {}
565 
566  protected:
567  };
568 
569  //=====================================================================
572  //=======================================================================
573  template<class ELEMENT>
575  : public virtual FaceGeometry<FaceGeometry<ELEMENT>>
576  {
577  public:
580 
581  protected:
582  };
583 
584  //=====================================================================
587  //=======================================================================
588  template<class ELEMENT>
590  : public virtual FaceGeometry<FaceGeometry<ELEMENT>>
591  {
592  public:
595 
596  protected:
597  };
598 
599 
603 
604 
605  //========================================================================
611  //========================================================================
612  class SpineMesh : public virtual Mesh
613  {
614  protected:
617 
618  public:
620  virtual ~SpineMesh();
621 
623  Spine*& spine_pt(const unsigned long& i)
624  {
625  return Spine_pt[i];
626  }
627 
629  const Spine* spine_pt(const unsigned long& i) const
630  {
631  return Spine_pt[i];
632  }
633 
635  unsigned long nspine() const
636  {
637  return Spine_pt.size();
638  }
639 
642  {
643  Spine_pt.push_back(spine_pt);
644  }
645 
647  // Can safely cast the nodes to SpineNodes
648  SpineNode* node_pt(const unsigned long& n)
649  {
650 #ifdef PARANOID
651  if (!dynamic_cast<SpineNode*>(Node_pt[n]))
652  {
653  std::ostringstream error_message;
654  error_message << "Node " << n << "is a " << typeid(Node_pt[n]).name()
655  << ", not a SpineNode" << std::endl;
656 
657  throw OomphLibError(error_message.str(),
660  }
661 #endif
662  // Return a cast to the pointer to the node
663  return (dynamic_cast<SpineNode*>(Node_pt[n]));
664  }
665 
669  SpineNode* element_node_pt(const unsigned long& e, const unsigned& n)
670  {
671 #ifdef PARANOID
672  // Try to cast to FiniteElement
673  FiniteElement* el_pt = dynamic_cast<FiniteElement*>(Element_pt[e]);
674  if (el_pt == 0)
675  {
676  throw OomphLibError(
677  "Can't execute element_node_pt(...) for non FiniteElements",
680  }
681  if (!dynamic_cast<SpineNode*>(el_pt->node_pt(n)))
682  {
683  std::ostringstream error_message;
684  error_message << "Node " << n << "is a "
685  << typeid(el_pt->node_pt(n)).name() << ", not a SpineNode"
686  << std::endl;
687 
688  throw OomphLibError(error_message.str(),
691  }
692 #endif
693  // Return a cast to the node pointer
694  return (dynamic_cast<SpineNode*>(
695  dynamic_cast<FiniteElement*>(Element_pt[e])->node_pt(n)));
696  }
697 
699  // N.B.: Since SpineElement<ELEMENT>'s are templated, we need the template
700  // in this function so that we can do the dynamic cast to a
701  // SpineElement<ELEMENT> template<class ELEMENT> void
702  // add_spine_to_element(const unsigned long &e, Spine* spine)
703  // {dynamic_cast<ELEMENT*>(Element_pt[e])->add_spine(spine);}
704 
706  unsigned long assign_global_spine_eqn_numbers(Vector<double*>& Dof_pt);
707 
716  void describe_spine_dofs(std::ostream& out,
717  const std::string& current_string) const;
718 
721  void set_mesh_level_time_stepper(TimeStepper* const& time_stepper_pt,
722  const bool& preserve_existing_data)
723  {
724  this->set_spine_time_stepper(time_stepper_pt, preserve_existing_data);
725  }
726 
729  void set_spine_time_stepper(TimeStepper* const& time_stepper_pt,
730  const bool& preserve_existing_data);
731 
735  ContinuationStorageScheme* const& continuation_stepper_pt);
736 
737 
740  bool does_pointer_correspond_to_spine_data(double* const& parameter_pt);
741 
746  void node_update(const bool& update_all_solid_nodes = false);
747 
750  virtual void spine_node_update(SpineNode* spine_node_pt) = 0;
751 
752 #ifdef __clang__
753 #pragma clang diagnostic push
754 #pragma clang diagnostic ignored "-Woverloaded-virtual"
755 #endif
756 
758  void dump(std::ofstream& dump_file) const;
759 
760 #ifdef __clang__
761 #pragma clang diagnostic pop
762 #endif
763 
766  void read(std::ifstream& restart_file);
767  };
768 
769 
772  // Functions for the SpineElement class
775 
776 
777  //=================================================================
779  //=================================================================
780  template<class ELEMENT>
782  {
783  // Call function of underlying element
785  SpineNode>::complete_setup_of_dependencies();
786 
787  // Sort out the spine index stuff
788  // Find the data that correspond to spine heights
789  {
790  const unsigned n_node = this->nnode();
791  // Allocate memory
792  if (Spine_geometric_index)
793  {
794  delete[] Spine_geometric_index;
795  }
796  Spine_geometric_index = new unsigned[n_node];
797 
798  // Now loop over data and find out where it fits
799  for (unsigned n = 0; n < n_node; n++)
800  {
801  // Find pointer to the spine
802  Spine* const spine_pt =
803  static_cast<SpineNode*>(this->node_pt(n))->spine_pt();
804 
805  // If there is a spine then find the pointer to the data
806  if (spine_pt)
807  {
808  // Find the pointer to the data
809  Data* spine_height_data_pt = spine_pt->spine_height_pt();
810 
811  // Now find the index of the corresponding spine
812  const unsigned n_node_update_data = this->ngeom_data();
813  for (unsigned i = 0; i < n_node_update_data; i++)
814  {
815  if (this->Geom_data_pt[i] == spine_height_data_pt)
816  {
817  Spine_geometric_index[n] = i;
818  break;
819  }
820  }
821  }
822  // Otherwise issue a warning
823  else
824  {
825  // Set the spine_geometric_index out of range,
826  // which will cause the spine_local_eqn to return a pinned value
827  Spine_geometric_index[n] = this->ngeom_data();
828  }
829  }
830  }
831  }
832 
833 } // namespace oomph
834 
835 #endif
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Definition: generalised_timesteppers.h:101
Definition: nodes.h:86
TimeStepper *& time_stepper_pt()
Return the pointer to the timestepper.
Definition: nodes.h:238
int geometric_data_local_eqn(const unsigned &n, const unsigned &i)
Definition: element_with_moving_nodes.h:126
unsigned ngeom_data() const
Definition: element_with_moving_nodes.h:345
Definition: element_with_moving_nodes.h:382
FaceGeometry()
Constructor.
Definition: spines.h:564
Definition: elements.h:4998
Definition: elements.h:1313
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2175
unsigned nnode() const
Return the number of nodes.
Definition: elements.h:2210
Definition: geom_objects.h:101
Definition: mesh.h:67
Vector< Node * > Node_pt
Vector of pointers to nodes.
Definition: mesh.h:183
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
Definition: mesh.h:186
Definition: nodes.h:906
Definition: oomph_definitions.h:222
Definition: spines.h:477
unsigned * Spine_geometric_index
Definition: spines.h:481
~SpineElement()
Destructor, clean up the storage allocated to the local equation numbers.
Definition: spines.h:511
void complete_setup_of_dependencies()
Construct and fill the node_update_data vector.
Definition: spines.h:781
int spine_local_eqn(const unsigned &n)
Definition: spines.h:521
SpineElement(FiniteElement *const &element_pt, const int &face_index)
Constructor used for spine face elements.
Definition: spines.h:502
SpineElement()
Constructor, call the constructor of the base element.
Definition: spines.h:494
Definition: spines.h:456
SpineFiniteElement()
Empty constructor.
Definition: spines.h:459
virtual ~SpineFiniteElement()
Emtpty virtual destructor.
Definition: spines.h:462
Definition: spines.h:613
const Spine * spine_pt(const unsigned long &i) const
Return the i-th spine in the mesh (const version)
Definition: spines.h:629
void add_spine_pt(Spine *const &spine_pt)
Add a spine to the mesh.
Definition: spines.h:641
void dump(std::ofstream &dump_file) const
Overload the dump function so that the spine data is dumped.
Definition: spines.cc:229
Vector< Spine * > Spine_pt
A Spine mesh contains a Vector of pointers to spines.
Definition: spines.h:616
SpineNode * node_pt(const unsigned long &n)
Return a pointer to the n-th global SpineNode.
Definition: spines.h:648
void describe_spine_dofs(std::ostream &out, const std::string &current_string) const
Definition: spines.cc:154
unsigned long nspine() const
Return the number of spines in the mesh.
Definition: spines.h:635
unsigned long assign_global_spine_eqn_numbers(Vector< double * > &Dof_pt)
Assign spines to Spine_pt vector of element.
Definition: spines.cc:124
bool does_pointer_correspond_to_spine_data(double *const &parameter_pt)
Definition: spines.cc:207
virtual void spine_node_update(SpineNode *spine_node_pt)=0
Spine *& spine_pt(const unsigned long &i)
Return the i-th spine in the mesh.
Definition: spines.h:623
void node_update(const bool &update_all_solid_nodes=false)
Definition: spines.cc:84
void read(std::ifstream &restart_file)
Overload the read function so that the spine data is also read.
Definition: spines.cc:253
void set_spine_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Assign time stepper to spines data.
Definition: spines.cc:171
void set_mesh_level_time_stepper(TimeStepper *const &time_stepper_pt, const bool &preserve_existing_data)
Definition: spines.h:721
virtual ~SpineMesh()
Destructor to clean up the memory allocated to the spines.
Definition: spines.cc:66
SpineNode * element_node_pt(const unsigned long &e, const unsigned &n)
Definition: spines.h:669
void set_consistent_pinned_spine_values_for_continuation(ContinuationStorageScheme *const &continuation_stepper_pt)
Definition: spines.cc:189
Definition: spines.h:328
Data ** all_geom_data_pt()
Return the vector of all geometric data.
Definition: spines.h:433
SpineNode(TimeStepper *const &time_stepper_pt, const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_nvalue)
Unsteady Constructor, initialise pointers to zero.
Definition: spines.h:359
GeomObject ** all_geom_object_pt()
Return the vector of all geometric objects.
Definition: spines.h:439
unsigned ngeom_data() const
Return the number of geometric data, zero if no spine.
Definition: spines.h:407
double & h()
Access function to spine height.
Definition: spines.h:397
SpineMesh *& spine_mesh_pt()
Definition: spines.h:391
SpineMesh * Spine_mesh_pt
Definition: spines.h:338
double Fraction
Private double that represents the fixed fraction along the spine.
Definition: spines.h:334
Spine * Spine_pt
Private internal data pointer to a spine.
Definition: spines.h:331
unsigned Node_update_fct_id
Definition: spines.h:342
Spine *& spine_pt()
Access function to spine.
Definition: spines.h:372
unsigned & node_update_fct_id()
Access function to ID of node update function (within specific mesh)
Definition: spines.h:384
double & fraction()
Set reference to fraction along spine.
Definition: spines.h:378
SpineNode(const unsigned &n_dim, const unsigned &n_position_type, const unsigned &initial_nvalue)
Steady Constructor, initialise pointers to zero.
Definition: spines.h:347
unsigned ngeom_object() const
Return the number of geometric objects, zero if no spine.
Definition: spines.h:420
void node_update(const bool &update_all_time_levels_for_new_node=false)
Update function, call the update function in the Node's SpineMesh.
Definition: spines.cc:44
Definition: spines.h:64
~Spine()
Definition: spines.h:142
Spine(const double &height, const Vector< Data * > &geom_data_pt, const Vector< GeomObject * > &geom_object_pt)
Definition: spines.h:115
Data * spine_height_pt() const
Definition: spines.h:163
GeomObject * geom_object_pt(const unsigned &i) const
Definition: spines.h:251
void set_geom_data_pt(const Vector< Data * > &geom_data_pt)
Definition: spines.h:179
void add_geom_data_pt(Data *geom_data_pt)
Definition: spines.h:191
unsigned ngeom_object()
Definition: spines.h:218
Vector< Data * > Geom_data_pt
Data that stores the spine height.
Definition: spines.h:305
void set_geom_object_pt(const Vector< GeomObject * > &geom_object_pt)
Definition: spines.h:225
void add_geom_parameter(const double &geom_parameter)
Definition: spines.h:280
GeomObject *& geom_object_pt(const unsigned &i)
Definition: spines.h:244
unsigned ngeom_data()
Definition: spines.h:171
void set_geom_parameter(const Vector< double > &geom_parameter)
Definition: spines.h:273
double & height()
Access function to spine height.
Definition: spines.h:150
Spine(const double &height)
Definition: spines.h:77
unsigned ngeom_parameter()
Definition: spines.h:265
Data * geom_data_pt(const unsigned &i) const
Definition: spines.h:205
double & geom_parameter(const unsigned &i)
Definition: spines.h:287
Vector< Data * > & vector_geom_data_pt()
Return the vector of geometric data.
Definition: spines.h:211
Spine()
Definition: spines.h:68
Vector< double > Geom_parameter
Vector that stores doubles that are used in the geometric updates.
Definition: spines.h:312
Vector< GeomObject * > Geom_object_pt
Definition: spines.h:309
Data *& geom_data_pt(const unsigned &i)
Definition: spines.h:198
Data *& spine_height_pt()
Access function to Data object that stores the spine height.
Definition: spines.h:156
Vector< GeomObject * > & vector_geom_object_pt()
Definition: spines.h:258
const double & geom_parameter(const unsigned &i) const
Definition: spines.h:294
void add_geom_object_pt(GeomObject *geom_object_pt)
Definition: spines.h:237
Spine(const double &height, const Vector< Data * > &geom_data_pt)
Definition: spines.h:90
Definition: timesteppers.h:231
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
string name
Definition: plotDoE.py:33
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ofstream out("Result.txt")