pseudo_buckling_ring.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-2023 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 #ifndef OOMPH_PSEUDO_BUCKLING_RING_HEADER
27 #define OOMPH_PSEUDO_BUCKLING_RING_HEADER
28 
29 
30 // Config header generated by autoconfig
31 #ifdef HAVE_CONFIG_H
32 #include <oomph-lib-config.h>
33 #endif
34 
35 // oomph-lib headers
36 #include "elements.h"
37 #include "nodes.h"
38 #include "quadtree.h"
39 #include "mesh.h"
40 #include "timesteppers.h"
41 #include "geom_objects.h"
42 
43 namespace oomph
44 {
45  //=========================================================================
46  /// Pseudo buckling ring: Circular ring deformed by the
47  /// N-th buckling mode of a thin-wall elastic ring.
48  /// \f[ x = R_0 \cos(\zeta) + \epsilon \left( \cos(N \zeta) \cos(\zeta) - A \sin(N \zeta) \sin(\zeta) \right) sin(2 \pi t/T) \f]
49  /// \f[ y = R_0 \sin(\zeta) + \epsilon \left( \cos(N \zeta) \sin(\zeta) + A \sin(N \zeta) \cos(\zeta) \right) sin(2 \pi t/T) \f]
50  /// where A is the ratio of the aziumuthal to the radial buckling
51  /// amplitude (A=-1/N for statically buckling rings) and epsilon
52  /// is the buckling amplitude.
53  ///
54  //=========================================================================
56  {
57  public:
58  /// Default constructor (empty and broken)
60  {
61  throw OomphLibError(
62  "Don't call empty constructor for PseudoBucklingRing!",
63  OOMPH_CURRENT_FUNCTION,
64  OOMPH_EXCEPTION_LOCATION);
65  }
66 
67  /// Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass
68  /// buckling amplitude, ratio of of buckling amplitudes, buckling
69  /// wavenumber (as a double), undeformed ring radius (all as Data)
70  /// and pointer to global timestepper.
71  /// \code
72  /// Geom_data_pt[0]->value(0) = Eps_buckl;
73  /// Geom_data_pt[0]->value(1) = Ampl_ratio;
74  /// Geom_data_pt[0]->value(2) = Double_N_buckl;
75  /// Geom_data_pt[0]->value(3) = R_0;
76  /// Geom_data_pt[0]->value(4) = T;
77  /// \endcode
81  {
82 #ifdef PARANOID
83  if (geom_data_pt.size() != 1)
84  {
85  std::ostringstream error_message;
86  error_message << "geom_data_pt should be of size 1, but is of size"
87  << geom_data_pt.size() << std::endl;
88 
89  throw OomphLibError(error_message.str(),
90  OOMPH_CURRENT_FUNCTION,
91  OOMPH_EXCEPTION_LOCATION);
92  }
93  if (geom_data_pt[0]->nvalue() != 5)
94  {
95  std::ostringstream error_message;
96  error_message << "geom_data_pt[0] should have 5 values, but has"
97  << geom_data_pt[0]->nvalue() << std::endl;
98 
99  throw OomphLibError(error_message.str(),
100  OOMPH_CURRENT_FUNCTION,
101  OOMPH_EXCEPTION_LOCATION);
102  }
103 #endif
104  Geom_data_pt.resize(1);
105  Geom_data_pt[0] = geom_data_pt[0];
106 
107  // Data has been created externally: Must not clean up
108  Must_clean_up = false;
109  }
110 
111 
112  /// Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass
113  /// buckling amplitude, ratio of of buckling amplitudes, buckling
114  /// wavenumber, undeformed ring radius, period of osc and pointer
115  /// to global timestepper. All geometric data is pinned by default.
117  const double& ampl_ratio,
118  const unsigned n_buckl,
119  const double& r_0,
120  const double& T,
122  : GeomObject(1, 2, time_stepper_pt)
123  {
124  // Number of previous timesteps that need to be stored
125  unsigned n_time = time_stepper_pt->nprev_values();
126 
127  // Setup geometric data for element: Five items of data live in
128  // in the one and only geometric data. Also store time history
129  Geom_data_pt.resize(1);
130  Geom_data_pt[0] = new Data(time_stepper_pt, 5);
131 
132  // I've created the data, I need to clean up
133  Must_clean_up = true;
134 
135  for (unsigned itime = 0; itime <= n_time; itime++)
136  {
137  // Buckling amplitude
138  Geom_data_pt[0]->set_value(itime, 0, eps_buckl);
139  Geom_data_pt[0]->pin(0);
140 
141  // Ratio of buckling amplitudes
142  Geom_data_pt[0]->set_value(itime, 1, ampl_ratio);
143  Geom_data_pt[0]->pin(1);
144 
145  // Buckling wavenumber (as double)
146  Geom_data_pt[0]->set_value(itime, 2, double(n_buckl));
147  Geom_data_pt[0]->pin(2);
148 
149  // Radius of undeformed ring
150  Geom_data_pt[0]->set_value(itime, 3, r_0);
151  Geom_data_pt[0]->pin(3);
152 
153  // Period of oscillation
154  Geom_data_pt[0]->set_value(itime, 4, T);
155  Geom_data_pt[0]->pin(4);
156  }
157  }
158 
159 
160  /// Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass
161  /// buckling amplitude, h/R, buckling wavenumbe and pointer
162  /// to global timestepper. Other parameters get set up to represent
163  /// oscillating ring with mode imode (1 or 2). All geometric data is
164  /// pinned by default.
166  const double& HoR,
167  const unsigned& n_buckl,
168  const unsigned& imode,
170  : GeomObject(1, 2, time_stepper_pt)
171  {
172  // Constants in Soedel solution:
173  double K1 = (pow(double(n_buckl), 2) + 1.0) *
174  (1.0 / 12.0 * pow(double(n_buckl), 2) * pow(HoR, 2) + 1.0);
175 
176  double K2oK1sq =
177  1.0 / 12.0 * pow(HoR, 2) * pow(double(n_buckl), 2) *
178  pow((pow(double(n_buckl), 2) - 1.0), 2) /
179  (pow((pow(double(n_buckl), 2) + 1.0), 2) *
180  pow((1.0 / 12.0 * pow(double(n_buckl), 2) * pow(HoR, 2) + 1.0), 2));
181 
182  // The two fundamental frequencies:
183  double omega1 = sqrt(0.5 * K1 * (1.0 + sqrt(1.0 - 4 * K2oK1sq)));
184  double omega2 = sqrt(0.5 * K1 * (1.0 - sqrt(1.0 - 4 * K2oK1sq)));
185 
186  // The two amplitude ratios:
187  double ampl_ratio1 =
188  (double(n_buckl) *
189  (1.0 / 12.0 * pow(double(n_buckl), 2) * pow(HoR, 2) + 1.0)) /
190  (pow(omega1, 2) -
191  pow(double(n_buckl), 2) * (1.0 / 12.0 * pow(HoR, 2) + 1.0));
192 
193  double ampl_ratio2 =
194  double(n_buckl) *
195  (1.0 / 12.0 * pow(double(n_buckl), 2) * pow(HoR, 2) + 1.0) /
196  (pow(omega2, 2) -
197  pow(double(n_buckl), 2) * (1.0 / 12.0 * pow(HoR, 2) + 1.0));
198 
199  double T;
200  double ampl_ratio;
201 
202  if (n_buckl > 1)
203  {
204  T = 2.0 * MathematicalConstants::Pi / omega2;
205  ampl_ratio = ampl_ratio2;
206  if (imode == 1)
207  {
208  T = 2.0 * MathematicalConstants::Pi / omega1;
209  ampl_ratio = ampl_ratio1;
210  }
211  else if (imode == 2)
212  {
213  T = 2.0 * MathematicalConstants::Pi / omega2;
214  ampl_ratio = ampl_ratio2;
215  }
216  else
217  {
218  oomph_info << "wrong imode " << imode << std::endl;
219  }
220  }
221  else
222  {
223  T = 2.0 * MathematicalConstants::Pi / omega1;
224  ampl_ratio = ampl_ratio1;
225  }
226 
227  // Number of previous timesteps that need to be stored
228  unsigned n_time = time_stepper_pt->nprev_values();
229 
230  // Setup geometric data for element: Five items of data live in
231  // in the one and only geometric data. Also store time history
232  Geom_data_pt.resize(1);
233  Geom_data_pt[0] = new Data(time_stepper_pt, 5);
234 
235  // I've created the data, I need to clean up
236  Must_clean_up = true;
237 
238  for (unsigned itime = 0; itime <= n_time; itime++)
239  {
240  // Buckling amplitude
241  Geom_data_pt[0]->set_value(itime, 0, eps_buckl);
242  Geom_data_pt[0]->pin(0);
243 
244  // Ratio of buckling amplitudes
245  Geom_data_pt[0]->set_value(itime, 1, ampl_ratio);
246  Geom_data_pt[0]->pin(1);
247 
248  // Buckling wavenumber (as double)
249  Geom_data_pt[0]->set_value(itime, 2, double(n_buckl));
250  Geom_data_pt[0]->pin(2);
251 
252  // Radius of undeformed ring
253  Geom_data_pt[0]->set_value(itime, 3, 1.0);
254  Geom_data_pt[0]->pin(3);
255 
256  // Period of oscillation
257  Geom_data_pt[0]->set_value(itime, 4, T);
258  Geom_data_pt[0]->pin(4);
259  }
260  }
261 
262  /// Broken copy constructor
263  PseudoBucklingRing(const PseudoBucklingRing& node) = delete;
264 
265  /// Broken assignment operator
266  void operator=(const PseudoBucklingRing&) = delete;
267 
268  /// Destructor: Clean up if necessary
270  {
271  // Do I need to clean up?
272  if (Must_clean_up)
273  {
274  delete Geom_data_pt[0];
275  Geom_data_pt[0] = 0;
276  }
277  }
278 
279 
280  /// Access function for buckling amplitude
281  double eps_buckl()
282  {
283  return Geom_data_pt[0]->value(0);
284  }
285 
286  /// Access function for amplitude ratio
287  double ampl_ratio()
288  {
289  return Geom_data_pt[0]->value(1);
290  }
291 
292  /// Access function for undeformed radius
293  double r_0()
294  {
295  return Geom_data_pt[0]->value(3);
296  }
297 
298  /// Access function for period of oscillation
299  double T()
300  {
301  return Geom_data_pt[0]->value(4);
302  }
303 
304  /// Access function for buckling wavenumber (as float)
305  double n_buckl_float()
306  {
307  return Geom_data_pt[0]->value(2);
308  }
309 
310  /// Set buckling amplitude
311  void set_eps_buckl(const double& eps_buckl)
312  {
313  Geom_data_pt[0]->set_value(0, eps_buckl);
314  }
315 
316  /// Set amplitude ratio between radial and azimuthal
317  /// buckling displacements
318  void set_ampl_ratio(const double& ampl_ratio)
319  {
320  Geom_data_pt[0]->set_value(1, ampl_ratio);
321  }
322 
323  /// Set buckling wavenumber
324  void set_n_buckl(const unsigned& n_buckl)
325  {
326  Geom_data_pt[0]->set_value(2, double(n_buckl));
327  }
328 
329  /// Set undeformed radius of ring
330  void set_R_0(const double& r_0)
331  {
332  Geom_data_pt[0]->set_value(3, r_0);
333  }
334 
335  /// Set period of oscillation
336  void set_T(const double& T)
337  {
338  Geom_data_pt[0]->set_value(4, T);
339  }
340 
341 
342  /// Position Vector at Lagrangian coordinate zeta at present
343  /// time
344  void position(const Vector<double>& zeta, Vector<double>& r) const
345  {
346 #ifdef PARANOID
347  if (r.size() != Ndim)
348  {
349  throw OomphLibError("The position vector r has the wrong dimension",
350  OOMPH_CURRENT_FUNCTION,
351  OOMPH_EXCEPTION_LOCATION);
352  }
353 #endif
354 
355  // Parameter values at present time
356  double time = Geom_object_time_stepper_pt->time_pt()->time();
357  double Eps_buckl = Geom_data_pt[0]->value(0);
358  double Ampl_ratio = Geom_data_pt[0]->value(1);
359  double double_N_buckl = Geom_data_pt[0]->value(2);
360  double R_0 = Geom_data_pt[0]->value(3);
361  double T = Geom_data_pt[0]->value(4);
362 
363 
364  // Position Vector
365  r[0] = R_0 * cos(zeta[0]) +
366  Eps_buckl *
367  (cos(double_N_buckl * zeta[0]) * cos(zeta[0]) -
368  Ampl_ratio * sin(double_N_buckl * zeta[0]) * sin(zeta[0])) *
369  sin(2.0 * MathematicalConstants::Pi * time / T);
370 
371  r[1] = R_0 * sin(zeta[0]) +
372  Eps_buckl *
373  (cos(double_N_buckl * zeta[0]) * sin(zeta[0]) +
374  Ampl_ratio * sin(double_N_buckl * zeta[0]) * cos(zeta[0])) *
375  sin(2.0 * MathematicalConstants::Pi * time / T);
376  }
377 
378 
379  /// Parametrised velocity on object at current time: veloc = d
380  /// r(zeta)/dt.
381  void veloc(const Vector<double>& zeta, Vector<double>& veloc) // const
382  {
383 #ifdef PARANOID
384  if (veloc.size() != Ndim)
385  {
386  throw OomphLibError("The vector veloc has the wrong size",
387  OOMPH_CURRENT_FUNCTION,
388  OOMPH_EXCEPTION_LOCATION);
389  }
390 #endif
391 
392  // Parameter values at present time
393  double time = Geom_object_time_stepper_pt->time_pt()->time();
394  double Eps_buckl = Geom_data_pt[0]->value(0);
395  double Ampl_ratio = Geom_data_pt[0]->value(1);
396  double double_N_buckl = Geom_data_pt[0]->value(2);
397  // Unused double R_0 = Geom_data_pt[0]->value(3);
398  double T = Geom_data_pt[0]->value(4);
399 
400  // Veloc
401  veloc[0] = Eps_buckl *
402  (cos(double_N_buckl * zeta[0]) * cos(zeta[0]) -
403  Ampl_ratio * sin(double_N_buckl * zeta[0]) * sin(zeta[0])) *
404  cos(2.0 * MathematicalConstants::Pi * time / T) * 2.0 *
406  veloc[1] = Eps_buckl *
407  (cos(double_N_buckl * zeta[0]) * sin(zeta[0]) +
408  Ampl_ratio * sin(double_N_buckl * zeta[0]) * cos(zeta[0])) *
409  cos(2.0 * MathematicalConstants::Pi * time / T) * 2.0 *
411  }
412 
413 
414  /// Parametrised acceleration on object at current time:
415  /// accel = d^2 r(zeta)/dt^2.
416  void accel(const Vector<double>& zeta, Vector<double>& accel) // const
417  {
418 #ifdef PARANOID
419  if (accel.size() != Ndim)
420  {
421  throw OomphLibError("The vector accel has the wrong dimension",
422  OOMPH_CURRENT_FUNCTION,
423  OOMPH_EXCEPTION_LOCATION);
424  }
425 #endif
426 
427  // Parameter values at present time
428  double time = Geom_object_time_stepper_pt->time_pt()->time();
429  double Eps_buckl = Geom_data_pt[0]->value(0);
430  double Ampl_ratio = Geom_data_pt[0]->value(1);
431  double double_N_buckl = Geom_data_pt[0]->value(2);
432  // Unused double R_0 = Geom_data_pt[0]->value(3);
433  double T = Geom_data_pt[0]->value(4);
434 
435  // Accel
436  accel[0] = -Eps_buckl *
437  (cos(double_N_buckl * zeta[0]) * cos(zeta[0]) -
438  Ampl_ratio * sin(double_N_buckl * zeta[0]) * sin(zeta[0])) *
439  sin(2.0 * MathematicalConstants::Pi * time / T) * 4.0 *
441 
442  accel[1] = -Eps_buckl *
443  (cos(double_N_buckl * zeta[0]) * sin(zeta[0]) +
444  Ampl_ratio * sin(double_N_buckl * zeta[0]) * cos(zeta[0])) *
445  sin(2.0 * MathematicalConstants::Pi * time / T) * 4.0 *
447  }
448 
449 
450  /// Position Vector at Lagrangian coordinate zeta at discrete
451  /// previous time (t=0: present time; t>0: previous time)
452  void position(const unsigned& t,
453  const Vector<double>& zeta,
454  Vector<double>& r) const
455  {
456 #ifdef PARANOID
457  if (r.size() != Ndim)
458  {
459  throw OomphLibError("The position vector r has the wrong dimension",
460  OOMPH_CURRENT_FUNCTION,
461  OOMPH_EXCEPTION_LOCATION);
462  }
464  {
465  throw OomphLibError(
466  "The time value t is greater than the number of previous steps",
467  OOMPH_CURRENT_FUNCTION,
468  OOMPH_EXCEPTION_LOCATION);
469  }
470 #endif
471 
472  // Parameter values at previous time
473  double Eps_buckl = Geom_data_pt[0]->value(t, 0);
474  double Ampl_ratio = Geom_data_pt[0]->value(t, 1);
475  double double_N_buckl = Geom_data_pt[0]->value(t, 2);
476  double R_0 = Geom_data_pt[0]->value(t, 3);
477  double T = Geom_data_pt[0]->value(4);
478 
479  // Present time
480  double time = Geom_object_time_stepper_pt->time_pt()->time();
481 
482  // Recover time at previous timestep
483  for (unsigned i = 0; i < t; i++)
484  {
486  }
487 
488  // Position Vector
489  r[0] = R_0 * cos(zeta[0]) +
490  Eps_buckl *
491  (cos(double_N_buckl * zeta[0]) * cos(zeta[0]) -
492  Ampl_ratio * sin(double_N_buckl * zeta[0]) * sin(zeta[0])) *
493  sin(2.0 * MathematicalConstants::Pi * time / T);
494 
495  r[1] = R_0 * sin(zeta[0]) +
496  Eps_buckl *
497  (cos(double_N_buckl * zeta[0]) * sin(zeta[0]) +
498  Ampl_ratio * sin(double_N_buckl * zeta[0]) * cos(zeta[0])) *
499  sin(2.0 * MathematicalConstants::Pi * time / T);
500  }
501 
502 
503  /// j-th time-derivative on object at current time:
504  /// \f$ \frac{d^{j} r(\zeta)}{dt^j} \f$.
505  void dposition_dt(const Vector<double>& zeta,
506  const unsigned& j,
507  Vector<double>& drdt)
508  {
509  switch (j)
510  {
511  // Current position
512  case 0:
513  position(zeta, drdt);
514  break;
515 
516  // Velocity:
517  case 1:
518  veloc(zeta, drdt);
519  break;
520 
521  // Acceleration:
522  case 2:
523  accel(zeta, drdt);
524  break;
525 
526  default:
527  std::ostringstream error_message;
528  error_message << j << "th derivative not implemented\n";
529 
530  throw OomphLibError(error_message.str(),
531  OOMPH_CURRENT_FUNCTION,
532  OOMPH_EXCEPTION_LOCATION);
533  }
534  }
535 
536 
537  /// How many items of Data does the shape of the object depend on?
538  unsigned ngeom_data() const
539  {
540  return Geom_data_pt.size();
541  }
542 
543  /// Return pointer to the j-th Data item that the object's
544  /// shape depends on
545  Data* geom_data_pt(const unsigned& j)
546  {
547  return Geom_data_pt[j];
548  }
549 
550 
551  protected:
552  /// Vector of pointers to Data items that affects the object's shape
554 
555  /// Do I need to clean up?
557  };
558 
559 
560  /// ////////////////////////////////////////////////////////////////////
561  /// ////////////////////////////////////////////////////////////////////
562  // Pseudo buckling ring as element
563  /// ////////////////////////////////////////////////////////////////////
564  /// ////////////////////////////////////////////////////////////////////
565 
566 
567  //=========================================================================
568  /// Pseudo buckling ring: Circular ring deformed by the
569  /// N-th buckling mode of a thin-wall elastic ring.
570  /// \f[ x = R_0 \cos(\zeta) + \epsilon \left( \cos(N \zeta) \cos(\zeta) - A \sin(N \zeta) \sin(\zeta) \right) sin(2 \pi t/T) \f]
571  /// \f[ y = R_0 \sin(\zeta) + \epsilon \left( \cos(N \zeta) \sin(\zeta) + A \sin(N \zeta) \cos(\zeta) \right) sin(2 \pi t/T) \f]
572  /// where A is the ratio of the aziumuthal to the radial buckling
573  /// amplitude (A=-1/N for statically buckling rings) and epsilon
574  /// is the buckling amplitude.
575  /// Scale R_0 is adjusted to ensure conservation of (computational)
576  /// volume/area. This is implemented by a
577  /// pseudo-elasticity approach: The governing equation for \f$ R_0 \f$ is:
578  /// \f[ p_{ref} = R_0 - 1.0 \f]
579  /// The pointer to the reference pressure needs to be set with
580  /// reference_pressure_pt().
581  //=========================================================================
583  public PseudoBucklingRing
584  {
585  private:
586  /// Index of the value stored in the single geometric object that has
587  /// become an unknown
589 
590  /// The Data object that represents the reference pressure is stored
591  /// at the location indexed by this integer in the external data storage.
593 
594  /// Pointer to the data object that represents the external reference
595  /// pressure
597 
598  /// Return the local equation number of the internal geometric variable
599  inline int geometric_local_eqn()
600  {
602  }
603 
604  /// Return the local equation number of the reference pressure variable
606  {
608  }
609 
610 
611  public:
612  /// Constructor: Build pseudo buckling ring
613  /// from doubles that describe the geometry.
615  const double& ampl_ratio,
616  const unsigned n_buckl,
617  const double& r_0,
618  const double& T,
621  eps_buckl, ampl_ratio, n_buckl, r_0, T, time_stepper_pt),
623  {
624  // Geom data for geom object has been setup (and pinned) in
625  // constructor for geometric object. Now free the scale for the half axes
626  // because we want to determine it as an unknown
627  Geom_data_pt[0]->unpin(3);
628 
629  // Record that the geometric variable is value 3 in the geometric data
631 
632  // The geometric data is internal to the element -- this
633  // ensures that any unknown pieces of geom_data get global equation
634  // numbers. There should only be one piece of internal data
635  unsigned n_geom_data = Geom_data_pt.size();
636  for (unsigned i = 0; i < n_geom_data; i++)
637  {
639  }
640  }
641 
642 
643  /// Constructor: Pass
644  /// buckling amplitude, h/R, buckling wavenumbe and pointer
645  /// to global timestepper. Other parameters get set up to represent
646  /// oscillating ring with mode imode (1 or 2). All geometric data is
647  /// pinned by default.
649  const double& HoR,
650  const unsigned& n_buckl,
651  const unsigned& imode,
653  : PseudoBucklingRing(eps_buckl, HoR, n_buckl, imode, time_stepper_pt),
655  {
656  // Geom data for geom object has been setup (and pinned) in
657  // constructor for geometric object. Now free the scale for the half axes
658  // because we want to determine it as an unknown
659  Geom_data_pt[0]->unpin(3);
660 
661  // Record that the geometric variable is value 3 in the geometric data
663 
664  // The geometric data is internal to the element -- this
665  // ensures that any unknown pieces of geom_data get global equation
666  // numbers. There should only be one piece of internal data
667  unsigned n_geom_data = Geom_data_pt.size();
668  for (unsigned i = 0; i < n_geom_data; i++)
669  {
671  }
672  }
673 
674 
675  /// Broken copy constructor
677 
678  /// Broken assignment operator
679  void operator=(const PseudoBucklingRingElement&) = delete;
680 
681  /// Destructor: Kill internal data and set to NULL
683  {
684  // The GeomElement's GeomData is mirrored in the element's
685  // Internal Data and therefore gets wiped in the
686  // destructor of GeneralisedElement --> No need to
687  // kill it in PseudoBucklingRing()
688  Must_clean_up = false;
689  }
690 
691 
692  /// Compute element residual Vector (wrapper)
693  inline virtual void get_residuals(Vector<double>& residuals)
694  {
695  // Create a dummy matrix
696  DenseMatrix<double> dummy(1);
697 
698  // Call the generic residuals function with flag set to 0
699  get_residuals_generic(residuals, dummy, 0);
700  }
701 
702 
703  /// Compute element residual Vector and element Jacobian matrix (wrapper)
704  inline virtual void get_jacobian(Vector<double>& residuals,
705  DenseMatrix<double>& jacobian)
706  {
707  // Call the generic routine with the flag set to 1
708  get_residuals_generic(residuals, jacobian, 1);
709  }
710 
711  /// Pointer to pressure data that is used as reference pressure
712  Data* const& reference_pressure_pt() const
713  {
714  return external_data_pt(0);
715  }
716 
717  /// Return the reference pressure
718  double reference_pressure() const
719  {
720  // If there is no external pressure, return 0.0
722  {
723  return 0.0;
724  }
725  else
726  {
728  }
729  }
730 
731  /// Set the pressure data that is used as reference pressure
732  void set_reference_pressure_pt(Data* const& data_pt)
733  {
734  // Clear the existing external data, if there is any
736  // Set the new External reference pointer
738  // Add it to the external data
740  }
741 
742  protected:
743  /// Compute element residual Vector (only if flag=0) and also
744  /// element Jacobian matrix (if flag=1)
745  virtual void get_residuals_generic(Vector<double>& residuals,
746  DenseMatrix<double>& jacobian,
747  unsigned flag)
748  {
749  // Initialise the residuals to zero
750  residuals.initialise(0.0);
751  // If computing the Jacobian initialise to zero
752  if (flag)
753  {
754  jacobian.initialise(0.0);
755  }
756 
757  // There is only one equation, which is due to the internal degree
758  // of freedom
759  int local_eqn = geometric_local_eqn();
760 
761  // If it's not a boundary condition
762  if (local_eqn >= 0)
763  {
764  // Pseudo force balance
765  residuals[local_eqn] = reference_pressure() - (r_0() - 1.0);
766 
767  // Work out jacobian: d residual[0]/d r_0
768  if (flag)
769  {
770  // The derivative wrt the internal unknown is
771  // Derivative residual w.r.t. scale
772  jacobian(local_eqn, local_eqn) = -1.0;
773 
774  int local_unknown = reference_pressure_local_eqn();
775  if (local_unknown >= 0)
776  {
777  jacobian(local_eqn, local_unknown) = 1.0;
778  }
779  }
780  }
781  }
782  };
783 
784 } // namespace oomph
785 
786 #endif
cstr elem_len * i
Definition: cfortran.h:603
char t
Definition: cfortran.h:568
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:86
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:483
double value(const unsigned &i) const
Return i-th stored value. This function is not virtual so that it can be inlined. This means that if ...
Definition: nodes.h:293
void initialise(const T &val)
Initialize all values in the matrix to val.
Definition: matrices.h:514
A Generalised Element class.
Definition: elements.h:73
unsigned add_internal_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) internal data object to the element and return the index required to obtain it ...
Definition: elements.cc:62
Data *& external_data_pt(const unsigned &i)
Return a pointer to i-th external data object.
Definition: elements.h:659
int internal_local_eqn(const unsigned &i, const unsigned &j) const
Return the local equation number corresponding to the j-th value stored at the i-th internal data.
Definition: elements.h:267
int external_local_eqn(const unsigned &i, const unsigned &j)
Return the local equation number corresponding to the j-th value stored at the i-th external data.
Definition: elements.h:311
void flush_external_data()
Flush all external data.
Definition: elements.cc:387
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) external data object to the element and return its index (i....
Definition: elements.cc:307
/////////////////////////////////////////////////////////////////////
Definition: geom_objects.h:101
TimeStepper * Geom_object_time_stepper_pt
Timestepper (used to handle access to geometry at previous timesteps)
Definition: geom_objects.h:435
TimeStepper *& time_stepper_pt()
Access function for pointer to time stepper: Null if object is not time-dependent.
Definition: geom_objects.h:192
unsigned Ndim
Number of Eulerian coordinates.
Definition: geom_objects.h:431
An OomphLibError object which should be thrown when an run-time error is encountered....
////////////////////////////////////////////////////////////////////
Data * External_reference_pressure_pt
Pointer to the data object that represents the external reference pressure.
int reference_pressure_local_eqn()
Return the local equation number of the reference pressure variable.
unsigned External_reference_pressure_index
The Data object that represents the reference pressure is stored at the location indexed by this inte...
virtual void get_residuals_generic(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Compute element residual Vector (only if flag=0) and also element Jacobian matrix (if flag=1)
int geometric_local_eqn()
Return the local equation number of the internal geometric variable.
void set_reference_pressure_pt(Data *const &data_pt)
Set the pressure data that is used as reference pressure.
virtual ~PseudoBucklingRingElement()
Destructor: Kill internal data and set to NULL.
PseudoBucklingRingElement(const double &eps_buckl, const double &HoR, const unsigned &n_buckl, const unsigned &imode, TimeStepper *time_stepper_pt)
Constructor: Pass buckling amplitude, h/R, buckling wavenumbe and pointer to global timestepper....
unsigned Internal_geometric_variable_index
Index of the value stored in the single geometric object that has become an unknown.
PseudoBucklingRingElement(const PseudoBucklingRingElement &dummy)=delete
Broken copy constructor.
virtual void get_residuals(Vector< double > &residuals)
Compute element residual Vector (wrapper)
PseudoBucklingRingElement(const double &eps_buckl, const double &ampl_ratio, const unsigned n_buckl, const double &r_0, const double &T, TimeStepper *time_stepper_pt)
Constructor: Build pseudo buckling ring from doubles that describe the geometry.
Data *const & reference_pressure_pt() const
Pointer to pressure data that is used as reference pressure.
void operator=(const PseudoBucklingRingElement &)=delete
Broken assignment operator.
virtual void get_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Compute element residual Vector and element Jacobian matrix (wrapper)
double reference_pressure() const
Return the reference pressure.
Pseudo buckling ring: Circular ring deformed by the N-th buckling mode of a thin-wall elastic ring.
void position(const unsigned &t, const Vector< double > &zeta, Vector< double > &r) const
Position Vector at Lagrangian coordinate zeta at discrete previous time (t=0: present time; t>0: prev...
~PseudoBucklingRing()
Destructor: Clean up if necessary.
void position(const Vector< double > &zeta, Vector< double > &r) const
Position Vector at Lagrangian coordinate zeta at present time.
void set_R_0(const double &r_0)
Set undeformed radius of ring.
bool Must_clean_up
Do I need to clean up?
void set_T(const double &T)
Set period of oscillation.
void set_ampl_ratio(const double &ampl_ratio)
Set amplitude ratio between radial and azimuthal buckling displacements.
PseudoBucklingRing(const double &eps_buckl, const double &ampl_ratio, const unsigned n_buckl, const double &r_0, const double &T, TimeStepper *time_stepper_pt)
Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass buckling amplitude, ratio of of bucklin...
Data * geom_data_pt(const unsigned &j)
Return pointer to the j-th Data item that the object's shape depends on.
double n_buckl_float()
Access function for buckling wavenumber (as float)
PseudoBucklingRing(const double &eps_buckl, const double &HoR, const unsigned &n_buckl, const unsigned &imode, TimeStepper *time_stepper_pt)
Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass buckling amplitude, h/R,...
Vector< Data * > Geom_data_pt
Vector of pointers to Data items that affects the object's shape.
PseudoBucklingRing()
Default constructor (empty and broken)
void veloc(const Vector< double > &zeta, Vector< double > &veloc)
Parametrised velocity on object at current time: veloc = d r(zeta)/dt.
unsigned ngeom_data() const
How many items of Data does the shape of the object depend on?
void dposition_dt(const Vector< double > &zeta, const unsigned &j, Vector< double > &drdt)
j-th time-derivative on object at current time: .
PseudoBucklingRing(const Vector< Data * > &geom_data_pt, TimeStepper *time_stepper_pt)
Constructor: 1 Lagrangian coordinate, 2 Eulerian coords. Pass buckling amplitude, ratio of of bucklin...
PseudoBucklingRing(const PseudoBucklingRing &node)=delete
Broken copy constructor.
void set_n_buckl(const unsigned &n_buckl)
Set buckling wavenumber.
double r_0()
Access function for undeformed radius.
double eps_buckl()
Access function for buckling amplitude.
void operator=(const PseudoBucklingRing &)=delete
Broken assignment operator.
void set_eps_buckl(const double &eps_buckl)
Set buckling amplitude.
double ampl_ratio()
Access function for amplitude ratio.
void accel(const Vector< double > &zeta, Vector< double > &accel)
Parametrised acceleration on object at current time: accel = d^2 r(zeta)/dt^2.
double T()
Access function for period of oscillation.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
Definition: timesteppers.h:231
virtual unsigned nprev_values() const =0
Number of previous values available: 0 for static, 1 for BDF<1>,...
Time *const & time_pt() const
Access function for the pointer to time (const version)
Definition: timesteppers.h:572
double & dt(const unsigned &t=0)
Return the value of the t-th stored timestep (t=0: present; t>0: previous).
Definition: timesteppers.h:136
double & time()
Return the current value of the continuous time.
Definition: timesteppers.h:123
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition: Vector.h:58
void initialise(const _Tp &__value)
Iterate over all values and set to the desired value.
Definition: Vector.h:167
const double Pi
50 digits from maple
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...