clamped_shell_with_arclength_cont.cc
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 //Driver function for a simple test shell problem:
27 //Calculate the deformation of an elastic tube approximated
28 //using Kirchoff--Love shell theory
29 
30 //Standard system includes
31 #include <iostream>
32 #include <fstream>
33 #include <cmath>
34 #include <typeinfo>
35 #include <algorithm>
36 #include <cstdio>
37 
38 //Include files from the finite-element library
39 #include "generic.h"
40 #include "shell.h"
41 #include "meshes/rectangular_quadmesh.h"
42 
43 using namespace std;
44 
45 using namespace oomph;
46 
47 //========================================================================
48 /// Global variables that represent physical properties
49 //========================================================================
51 {
52 
53  /// Prescribed position of control point
54  double Prescribed_y = 1.0;
55 
56  /// Pointer to pressure load (stored in Data so it can
57  /// become an unknown in the problem when displacement control is used
58  Data* Pext_data_pt;
59 
60  /// Return a reference to the external pressure
61  /// load on the elastic tube.
62  double external_pressure()
63  {return (*Pext_data_pt->value_pt(0))*pow(0.05,3)/12.0;}
64 
65 
66  /// Load function, normal pressure loading
67  void press_load(const Vector<double> &xi,
68  const Vector<double> &x,
69  const Vector<double> &N,
70  Vector<double>& load)
71  {
72  for(unsigned i=0;i<3;i++)
73  {
74  load[i] = external_pressure()*N[i];
75  }
76  }
77 
78 }
79 
80 //========================================================================
81 /// A 2D Mesh class. The tube wall is represented by two Lagrangian
82 /// coordinates that correspond to z and theta in cylindrical polars.
83 /// The required mesh is therefore a 2D mesh and is therefore inherited
84 /// from the generic RectangularQuadMesh
85 //=======================================================================
86 template <class ELEMENT>
87 class ShellMesh : public virtual RectangularQuadMesh<ELEMENT>,
88  public virtual SolidMesh
89 {
90 public:
91 
92  /// Constructor for the mesh
93  ShellMesh(const unsigned &nx, const unsigned &ny,
94  const double &lx, const double &ly);
95 
96  /// In all elastic problems, the nodes must be assigned an undeformed,
97  /// or reference, position, corresponding to the stress-free state
98  /// of the elastic body. This function assigns the undeformed position
99  /// for the nodes on the elastic tube
100  void assign_undeformed_positions(GeomObject* const &undeformed_midplane_pt);
101 
102 };
103 
104 
105 
106 
107 
108 //=======================================================================
109 /// Mesh constructor
110 /// Argument list:
111 /// nx : number of elements in the axial direction
112 /// ny : number of elements in the azimuthal direction
113 /// lx : length in the axial direction
114 /// ly : length in theta direction
115 //=======================================================================
116 template <class ELEMENT>
117 ShellMesh<ELEMENT>::ShellMesh(const unsigned &nx,
118  const unsigned &ny,
119  const double &lx,
120  const double &ly) :
121  RectangularQuadMesh<ELEMENT>(nx,ny,lx,ly)
122 {
123  //Find out how many nodes there are
124  unsigned n_node = nnode();
125 
126  //Now in this case it is the Lagrangian coordinates that we want to set,
127  //so we have to loop over all nodes and set them to the Eulerian
128  //coordinates that are set by the generic mesh generator
129  for(unsigned i=0;i<n_node;i++)
130  {
131  node_pt(i)->xi(0) = node_pt(i)->x(0);
132  node_pt(i)->xi(1) = node_pt(i)->x(1);
133  }
134 
135 
136  //Assign gradients, etc for the Lagrangian coordinates of
137  //hermite-type elements
138 
139  //Read out number of position dofs
140  unsigned n_position_type = finite_element_pt(0)->nnodal_position_type();
141 
142  //If this is greater than 1 set the slopes, which are the distances between
143  //nodes. If the spacing were non-uniform, this part would be more difficult
144  if(n_position_type > 1)
145  {
146  double xstep = (this->Xmax - this->Xmin)/((this->Np-1)*this->Nx);
147  double ystep = (this->Ymax - this->Ymin)/((this->Np-1)*this->Ny);
148  for(unsigned n=0;n<n_node;n++)
149  {
150  //The factor 0.5 is because our reference element has length 2.0
151  node_pt(n)->xi_gen(1,0) = 0.5*xstep;
152  node_pt(n)->xi_gen(2,1) = 0.5*ystep;
153  }
154  }
155 }
156 
157 
158 //=======================================================================
159 /// Set the undeformed coordinates of the nodes
160 //=======================================================================
161 template <class ELEMENT>
163  GeomObject* const &undeformed_midplane_pt)
164 {
165  //Find out how many nodes there are
166  unsigned n_node = nnode();
167 
168  //Loop over all the nodes
169  for(unsigned n=0;n<n_node;n++)
170  {
171  //Get the Lagrangian coordinates
172  Vector<double> xi(2);
173  xi[0] = node_pt(n)->xi(0);
174  xi[1] = node_pt(n)->xi(1);
175 
176  //Assign memory for values of derivatives, etc
177  Vector<double> R(3);
178  DenseMatrix<double> a(2,3);
179  RankThreeTensor<double> dadxi(2,2,3);
180 
181  //Get the geometrical information from the geometric object
182  undeformed_midplane_pt->d2position(xi,R,a,dadxi);
183 
184  //Loop over coordinate directions
185  for(unsigned i=0;i<3;i++)
186  {
187  //Set the position
188  node_pt(n)->x_gen(0,i) = R[i];
189 
190  //Set the derivative wrt Lagrangian coordinates
191  //Note that we need to scale by the length of each element here!!
192  node_pt(n)->x_gen(1,i) = 0.5*a(0,i)*((this->Xmax - this->Xmin)/this->Nx);
193  node_pt(n)->x_gen(2,i) = 0.5*a(1,i)*((this->Ymax - this->Ymin)/this->Ny);
194 
195  //Set the mixed derivative
196  //(symmetric so doesn't matter which one we use)
197  node_pt(n)->x_gen(3,i) = 0.25*dadxi(0,1,i);
198  }
199  }
200 }
201 
202 
203 
204 // //========================================================================
205 // /// A 2D mesh class for the problem.
206 // /// The tube is represented by two Lagrangian coordinates that correspond
207 // /// to z and theta in cylindrical polars. The required mesh is therefore a
208 // /// 2D mesh and is therefore inherited from the generic RectangularQuadMesh
209 // //=======================================================================
210 // template <class ELEMENT>
211 // class ShellMesh : public virtual RectangularQuadMesh<ELEMENT>,
212 // public virtual SolidMesh
213 // {
214 // public:
215 // //Constructor for the mesh
216 // ShellMesh(const unsigned &nx, const unsigned &ny,
217 // const double &lx, const double &ly);
218 
219 // //In all elastic problems, the nodes must be assigned an undeformed,
220 // //or reference, position, corresponding to the stress-free state
221 // //of the elastic body. This function assigns the undeformed position
222 // //for the nodes on the elastic tube
223 // void assign_undeformed_positions(GeomObject* const &undeformed_midplane_pt);
224 // };
225 
226 // //Define the mesh constructor
227 // //Argument list:
228 // // nx : number of elements in the axial direction
229 // // ny : number of elements in the azimuthal direction
230 // // lx : length in the axial direction
231 // // ly : length in theta direction
232 // template <class ELEMENT>
233 // ShellMesh<ELEMENT>::ShellMesh(const unsigned &nx,
234 // const unsigned &ny,
235 // const double &lx, const double &ly) :
236 // RectangularQuadMesh<ELEMENT>(nx,ny,lx,ly)
237 // {
238 // //Find out how many nodes there are
239 // unsigned Nnode = nnode();
240 
241 // //Now in this case it is the Lagrangian coordinates that we want to set,
242 // //so we have to loop over all nodes and set them to the Eulerian
243 // //coordinates that are set by the generic mesh generator
244 // for(unsigned i=0;i<Nnode;i++)
245 // {
246 // node_pt(i)->xi(0) = node_pt(i)->x(0);
247 // node_pt(i)->xi(1) = node_pt(i)->x(1);
248 // }
249 
250 // //Assign gradients, etc for the Lagrangian coordinates of
251 // //hermite-type elements
252 
253 // //Read out number of position dofs
254 // unsigned Nposition_type = finite_element_pt(0)->nnodal_position_type();
255 // std::cout << Nposition_type << std::endl;
256 // //If this is greater than 1 set the slopes, which are the distances between
257 // //nodes. If the spacing were non-uniform, this part would be more difficult
258 // if(Nposition_type > 1)
259 // {
260 // double xstep = (this->Xmax - this->Xmin)/((this->Np-1)*this->Nx);
261 // double ystep = (this->Ymax - this->Ymin)/((this->Np-1)*this->Ny);
262 // for(unsigned n=0;n<Nnode;n++)
263 // {
264 // //The factor 0.5 is because our reference element has length 2.0
265 // node_pt(n)->xi_gen(1,0) = 0.5*xstep;
266 // node_pt(n)->xi_gen(2,1) = 0.5*ystep;
267 // }
268 // }
269 // }
270 
271 // //Set the undeformed values of the nodes
272 // template <class ELEMENT>
273 // void ShellMesh<ELEMENT>::
274 // assign_undeformed_positions(GeomObject* const &undeformed_midplane_pt)
275 // {
276 // //Find out how many nodes there are
277 // unsigned n_node = nnode();
278 // //Loop over all the nodes
279 // for(unsigned n=0;n<n_node;n++)
280 // {
281 // //Get the lagrangian coordinates
282 // Vector<double> xi(2);
283 // xi[0] = node_pt(n)->xi(0); xi[1] = node_pt(n)->xi(1);
284 
285 // //Assign memory for values of derivatives, etc
286 // Vector<double> R(3);
287 // DenseMatrix<double> a(2,3);
288 // RankThreeTensor<double> dadxi(2,2,3);
289 
290 // //Get the geometrical information from the geometric object
291 // undeformed_midplane_pt->d2position(xi,R,a,dadxi);
292 
293 // //Loop over coordinate directions
294 // for(unsigned i=0;i<3;i++)
295 // {
296 // //Set the position
297 // node_pt(n)->x_gen(0,i) = R[i];
298 // //Set the derivative wrt Lagrangian coordinates
299 // //Note that we need to scale by the length of each element here!!
300 // node_pt(n)->x_gen(1,i) = 0.5*a(0,i)*((this->Xmax - this->Xmin)/this->Nx);
301 // node_pt(n)->x_gen(2,i) = 0.5*a(1,i)*((this->Ymax - this->Ymin)/this->Ny);
302 // //Set the mixed derivative
303 // //(symmetric so doesn't matter which one we use)
304 // node_pt(n)->x_gen(3,i) = 0.25*dadxi(0,1,i);
305 // }
306 // }
307 // }
308 
309 
310 
311 //======================================================================
312 //Problem class to solve the deformation of an elastic tube
313 //=====================================================================
314 template<class ELEMENT>
315 class ShellProblem : public Problem
316 {
317 
318 public:
319 
320  /// Constructor
321  ShellProblem(const unsigned &nx, const unsigned &ny,
322  const double &lx, const double &ly);
323 
324  /// Destructor: delete mesh, geometric object
326  {
327  delete Problem::mesh_pt();
328  delete Undeformed_midplane_pt;
329  }
330 
331 
332  /// Overload Access function for the mesh
334  {return dynamic_cast<ShellMesh<ELEMENT>*>(Problem::mesh_pt());}
335 
336  /// Actions after solve empty
338 
339  /// Actions before solve empty
341 
342  //A self_test function
343  void solve();
344 
345 private:
346 
347  /// Pointer to GeomObject that specifies the undeformed midplane
348  GeomObject* Undeformed_midplane_pt;
349 
350  /// First trace node
351  Node* Trace_node_pt;
352 
353  /// Second trace node
354  Node* Trace_node2_pt;
355 
356 };
357 
358 
359 
360 //======================================================================
361 /// Constructor
362 //======================================================================
363 template<class ELEMENT>
364 ShellProblem<ELEMENT>::ShellProblem(const unsigned &nx, const unsigned &ny,
365  const double &lx, const double &ly)
366 {
367  //Suppress the warning about empty mesh_level_timestepper_stuff
368  Mesh::Suppress_warning_about_empty_mesh_level_time_stepper_function=true;
369 
370  //Use the continuation timestepper
371  Use_continuation_timestepper = true;
372 
373  //Create the undeformed midplane object
374  Undeformed_midplane_pt = new EllipticalTube(1.0,1.0);
375 
376  //Now create the mesh
377  Problem::mesh_pt() = new ShellMesh<ELEMENT>(nx,ny,lx,ly);
378 
379  //Set the undeformed positions in the mesh
380  mesh_pt()->assign_undeformed_positions(Undeformed_midplane_pt);
381 
382  //Reorder the elements, since I know what's best for them....
383  mesh_pt()->element_reorder();
384 
385  //Apply boundary conditions to the ends of the tube
386  unsigned n_ends = mesh_pt()->nboundary_node(1);
387  //Loop over the node
388  for(unsigned i=0;i<n_ends;i++)
389  {
390  //Pin in the axial direction (prevents rigid body motions)
391  mesh_pt()->boundary_node_pt(1,i)->pin_position(2);
392  mesh_pt()->boundary_node_pt(3,i)->pin_position(2);
393  //Derived conditions
394  mesh_pt()->boundary_node_pt(1,i)->pin_position(2,2);
395  mesh_pt()->boundary_node_pt(3,i)->pin_position(2,2);
396 
397  //------------------CLAMPING CONDITIONS----------------------
398  //------Pin positions in the transverse directions-----------
399  // Comment these out to get the ring case
400  mesh_pt()->boundary_node_pt(1,i)->pin_position(0);
401  mesh_pt()->boundary_node_pt(3,i)->pin_position(0);
402  //Derived conditions
403  mesh_pt()->boundary_node_pt(1,i)->pin_position(2,0);
404  mesh_pt()->boundary_node_pt(3,i)->pin_position(2,0);
405 
406  mesh_pt()->boundary_node_pt(1,i)->pin_position(1);
407  mesh_pt()->boundary_node_pt(3,i)->pin_position(1);
408  //Derived conditions
409  mesh_pt()->boundary_node_pt(1,i)->pin_position(2,1);
410  mesh_pt()->boundary_node_pt(3,i)->pin_position(2,1);
411  //----------------------------------------------------------
412 
413  // Set the axial gradients of the transverse coordinates to be
414  // zero --- need to be enforced for ring or tube buckling
415  //Pin dx/dz and dy/dz
416  mesh_pt()->boundary_node_pt(1,i)->pin_position(1,0);
417  mesh_pt()->boundary_node_pt(1,i)->pin_position(1,1);
418  mesh_pt()->boundary_node_pt(3,i)->pin_position(1,0);
419  mesh_pt()->boundary_node_pt(3,i)->pin_position(1,1);
420  //Derived conditions
421  mesh_pt()->boundary_node_pt(1,i)->pin_position(3,0);
422  mesh_pt()->boundary_node_pt(1,i)->pin_position(3,1);
423  mesh_pt()->boundary_node_pt(3,i)->pin_position(3,0);
424  mesh_pt()->boundary_node_pt(3,i)->pin_position(3,1);
425  }
426 
427  //Now loop over the sides and apply symmetry conditions
428  unsigned n_side = mesh_pt()->nboundary_node(0);
429  for(unsigned i=0;i<n_side;i++)
430  {
431  //At the side where theta is 0, pin in the y direction
432  mesh_pt()->boundary_node_pt(0,i)->pin_position(1);
433  //Derived condition
434  mesh_pt()->boundary_node_pt(0,i)->pin_position(1,1);
435  //Pin dx/dtheta and dz/dtheta
436  mesh_pt()->boundary_node_pt(0,i)->pin_position(2,0);
437  mesh_pt()->boundary_node_pt(0,i)->pin_position(2,2);
438  //Pin the mixed derivative
439  mesh_pt()->boundary_node_pt(0,i)->pin_position(3,0);
440  mesh_pt()->boundary_node_pt(0,i)->pin_position(3,2);
441 
442  //At the side when theta is 0.5pi pin in the x direction
443  mesh_pt()->boundary_node_pt(2,i)->pin_position(0);
444  //Derived condition
445  mesh_pt()->boundary_node_pt(2,i)->pin_position(1,0);
446  //Pin dy/dtheta and dz/dtheta
447  mesh_pt()->boundary_node_pt(2,i)->pin_position(2,1);
448  mesh_pt()->boundary_node_pt(2,i)->pin_position(2,2);
449  //Pin the mixed derivative
450  mesh_pt()->boundary_node_pt(2,i)->pin_position(3,1);
451  mesh_pt()->boundary_node_pt(2,i)->pin_position(3,2);
452 
453  //Set an initial kick to make sure that we hop onto the
454  //non-axisymmetric branch
455  if((i>1) && (i<n_side-1))
456  {
457  mesh_pt()->boundary_node_pt(0,i)->x(0) += 0.05;
458  mesh_pt()->boundary_node_pt(2,i)->x(1) -= 0.1;
459  }
460  }
461 
462 
463  // Setup displacement control
464  //---------------------------
465 
466 
467 
468 // //Setup displacement control
469 // //Fix the displacement at the mid-point of the tube in the "vertical"
470 // //(y) direction.
471 // //Set the displacement control element (located halfway along the tube)
472 // Disp_ctl_element_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(3*Ny-1));
473 // //The midpoint of the tube is located exactly half-way along the element
474 // Vector<double> s(2); s[0] = 1.0; s[1] = 0.0; //s[1] = 0.5
475 // //Fix the displacement at this point in the y (1) direction
476 // Disp_ctl_element_pt->fix_displacement_for_displacement_control(s,1);
477 // //Set the pointer to the prescribed position
478 // Disp_ctl_element_pt->prescribed_position_pt() = &Prescribed_y;
479 
480 
481 
482  // Choose element in which displacement control is applied: This
483  // one is located halfway along the tube)
484  SolidFiniteElement* controlled_element_pt=
485  dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(3*ny-1));
486 
487  // Fix the displacement in the y (1) direction...
488  unsigned controlled_direction=1;
489 
490  // Local coordinate of the control point within the controlled element
491  Vector<double> s_displ_control(2);
492  s_displ_control[0]=1.0;
493  s_displ_control[1]=0.0;
494 
495  // Pointer to displacement control element
496  DisplacementControlElement* displ_control_el_pt;
497 
498  // Build displacement control element
499  displ_control_el_pt=
500  new DisplacementControlElement(controlled_element_pt,
501  s_displ_control,
502  controlled_direction,
504 
505  // The constructor of the DisplacementControlElement has created
506  // a new Data object whose one-and-only value contains the
507  // adjustable load: Use this Data object in the load function:
508  Global_Physical_Variables::Pext_data_pt=displ_control_el_pt->
509  displacement_control_load_pt();
510 
511  // Add the displacement-control element to the mesh
512  mesh_pt()->add_element_pt(displ_control_el_pt);
513 
514 
515 
516  // Complete build of shell elements
517  //---------------------------------
518 
519  //Find number of shell elements in mesh
520  unsigned n_element = nx*ny;
521 
522  //Explicit pointer to first element in the mesh
523  ELEMENT* first_el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(0));
524 
525  //Loop over the elements
526  for(unsigned e=0;e<n_element;e++)
527  {
528  //Cast to a shell element
529  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
530 
531  //Set the load function
532  el_pt->load_vector_fct_pt() = & Global_Physical_Variables::press_load;
533 
534  //Set the undeformed surface
535  el_pt->undeformed_midplane_pt() = Undeformed_midplane_pt;
536 
537  //The external pressure is external data for all elements
538  el_pt->add_external_data(Global_Physical_Variables::Pext_data_pt);
539 
540  //Pre-compute the second derivatives wrt Lagrangian coordinates
541  //for the first element only
542  if(e==0)
543  {
544  el_pt->pre_compute_d2shape_lagrangian_at_knots();
545  }
546 
547  //Otherwise set the values to be the same as those in the first element
548  //this is OK because the Lagrangian mesh is uniform.
549  else
550  {
551  el_pt->set_dshape_lagrangian_stored_from_element(first_el_pt);
552  }
553  }
554 
555  //Set pointers to two trace nodes, used for output
556  Trace_node_pt = mesh_pt()->finite_element_pt(2*ny-1)->node_pt(3);
557  Trace_node2_pt = mesh_pt()->finite_element_pt(ny)->node_pt(1);
558 
559  // Do equation numbering
560  cout << std::endl;
561  cout << "------------------DISPLACEMENT CONTROL--------------------"
562  << std::endl;
563  cout << "# of dofs " << assign_eqn_numbers() << std::endl;
564  cout << "----------------------------------------------------------"
565  << std::endl;
566  cout << std::endl;
567 
568 }
569 
570 
571 //================================================================
572 // /Define the solve function, disp ctl and then continuation
573 //================================================================
574 template<class ELEMENT>
576 {
577 
578  //Increase the maximum number of Newton iterations.
579  //Finding the first buckled solution requires a large(ish) number
580  //of Newton steps -- shells are just a bit twitchy
581  Max_newton_iterations = 40;
582 
583  //Open an output trace file
584  ofstream trace("trace.dat");
585 
586  //Change in displacemenet
587  double disp_incr = 0.05;
588 
589  //Gradually compress the tube by decreasing the value of the prescribed
590  //position from 1 to zero in steps of 0.05 initially and then 0.1
591  for(unsigned i=1;i<13;i++)
592  {
593  //By the time we reach the second time round increase the incremenet
594  if(i==3) {disp_incr = 0.1;}
595  //Reduce prescribed y by our chosen increment
597 
598  cout << std::endl << "Increasing displacement: Prescribed_y is "
600 
601  // Solve
602  newton_solve();
603 
604  //Output the pressure
605  trace << Global_Physical_Variables::external_pressure()/(pow(0.05,3)/12.0)
606  << " "
607  //Position of first trace node
608  << Trace_node_pt->x(0) << " " << Trace_node_pt->x(1) << " "
609  //Position of second trace node
610  << Trace_node2_pt->x(0) << " " << Trace_node2_pt->x(1) << std::endl;
611  }
612 
613  //Close the trace file
614  trace.close();
615 
616  //Output the tube shape in the most strongly collapsed configuration
617  ofstream file("final_shape.dat");
618  mesh_pt()->output(file,5);
619  file.close();
620 
621 
622  //Switch from displacement control to arc-length continuation and
623  //trace back up the solution branch
624 
625  //Now pin the external pressure
627 
628  //Re-assign the equation numbers
629  cout << std::endl;
630  cout << "-----------------ARC-LENGTH CONTINUATION --------------"
631  << std::endl;
632  cout << "# of dofs " << assign_eqn_numbers() << std::endl;
633  cout << "-------------------------------------------------------"
634  << std::endl;
635  cout << std::endl;
636 
637  //Set the maximum number of Newton iterations to something more reasonable
638  Max_newton_iterations=6;
639 
640  //Set the desired number of Newton iterations per arc-length step
641  Desired_newton_iterations_ds=3;
642 
643  //Set the proportion of the arc length
644  Desired_proportion_of_arc_length = 0.2;
645 
646  //Check for any bifurcations using the sign of the determinant of the Jacobian
647  Bifurcation_detection = true;
648 
649  //Set an initial value for the step size
650  double ds = -0.5;
651 
652  //Open a different trace file
653  trace.open("trace_disp.dat");
654  //Take fifteen continuation steps
655  for(unsigned i=0;i<15;i++)
656  {
657  ds = arc_length_step_solve(
659 
660  //Output the pressure
661  trace << Global_Physical_Variables::external_pressure()/(pow(0.05,3)/12.0)
662  << " "
663  //Position of first trace node
664  << Trace_node_pt->x(0) << " " << Trace_node_pt->x(1) << " "
665  //Position of second trace node
666  << Trace_node2_pt->x(0) << " " << Trace_node2_pt->x(1) << std::endl;
667  }
668 
669  //Close the trace file
670  trace.close();
671 
672 }
673 
674 
675 //====================================================================
676 /// Driver
677 //====================================================================
678 int main()
679 {
680 
681  //Length of domain
682  double L = 10.0;
683  double L_phi=0.5*MathematicalConstants::Pi;
684 
685  //Set up the problem
687  problem(5,5,L,L_phi);
688 
689  //Solve the problem
690  problem.solve();
691 }
692 
693 
694 
695 
696 
697 
A 2D Mesh class. The tube wall is represented by two Lagrangian coordinates that correspond to z and ...
void assign_undeformed_positions(GeomObject *const &undeformed_midplane_pt)
In all elastic problems, the nodes must be assigned an undeformed, or reference, position,...
ShellMesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Constructor for the mesh.
ShellMesh< ELEMENT > * mesh_pt()
Overload Access function for the mesh.
Node * Trace_node2_pt
Second trace node.
GeomObject * Undeformed_midplane_pt
Pointer to GeomObject that specifies the undeformed midplane.
ShellProblem(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Constructor.
void actions_before_newton_solve()
Actions before solve empty.
Node * Trace_node_pt
First trace node.
void actions_after_newton_solve()
Actions after solve empty.
~ShellProblem()
Destructor: delete mesh, geometric object.
Global variables that represent physical properties.
double external_pressure()
Return a reference to the external pressure load on the elastic tube.
void press_load(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &N, Vector< double > &load)
Load function, normal pressure loading.
double Prescribed_y
Prescribed position of control point.
Data * Pext_data_pt
Pointer to pressure load (stored in Data so it can become an unknown in the problem when displacement...