steady_ring.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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 //Driver function for a simple test ring problem with/without
31 //diplacement control
32 
33 //Generic oomph-lib sources
34 #include "generic.h"
35 
36 // Beam sources
37 #include "beam.h"
38 
39 // The mesh
40 #include "meshes/one_d_lagrangian_mesh.h"
41 
42 using namespace std;
43 
44 using namespace oomph;
45 
46 
47 //=======start_of_namespace=========================
48 /// Namespace for physical parameters
49 //==================================================
51 {
52 
53  /// Nondim thickness
54  double H=0.05;
55 
56  /// Prescribed position (only used for displacement control)
57  double Xprescr = 1.0;
58 
59  /// Perturbation pressure
60  double Pcos=0.0;
61 
62  /// \short Pointer to pressure load (stored in Data so it can
63  /// become an unknown in the problem when displacement control is used
64  Data* Pext_data_pt;
65 
66  /// \short Load function: Constant external pressure with cos variation to
67  /// induce buckling in n=2 mode
68  void press_load(const Vector<double>& xi,
69  const Vector<double> &x,
70  const Vector<double>& N,
71  Vector<double>& load)
72  {
73  for(unsigned i=0;i<2;i++)
74  {
75  load[i] = (Pext_data_pt->value(0)-Pcos*cos(2.0*xi[0]))*N[i];
76  }
77  }
78 
79  /// \short Return a reference to the external pressure
80  /// load on the elastic ring.
81  /// A reference is obtained by de-referencing the pointer to the
82  /// data value that contains the external load
83  double &external_pressure()
84  {return *Pext_data_pt->value_pt(0);}
85 
86 
87 } // end of namespace
88 
89 
90 
91 /////////////////////////////////////////////////////////////////////
92 /////////////////////////////////////////////////////////////////////
93 /////////////////////////////////////////////////////////////////////
94 
95 
96 
97 //========start_of_problem_class========================================
98 /// Ring problem
99 //======================================================================
100 template<class ELEMENT>
101 class ElasticRingProblem : public Problem
102 {
103 
104 public:
105 
106  /// Constructor: Number of elements and flags for displ control
107  /// and displacement control with existing data respectively.
108  ElasticRingProblem(const unsigned &n_element,
109  bool& displ_control,
110  bool& load_data_already_exists);
111 
112  /// Access function for the specific mesh
113  OneDLagrangianMesh<ELEMENT>* mesh_pt()
114  {
115  return dynamic_cast<OneDLagrangianMesh<ELEMENT>*>(Problem::mesh_pt());
116  }
117 
118  /// Update function is empty
120 
121  /// Update function is empty
123 
124  /// Doc solution
125  void doc_solution(DocInfo& doc_info, ofstream& trace_file);
126 
127  /// Perform the parameter study
128  void parameter_study(DocInfo& doc_info);
129 
130 private:
131 
132  /// Use displacement control?
134 
135  /// Pointer to geometric object that represents the undeformed shape
136  GeomObject* Undef_geom_pt;
137 
138  /// Number of elements in the beam mesh
139  unsigned Nbeam_element;
140 
141 }; // end of problem class
142 
143 
144 
145 
146 
147 
148 
149 //======start_of_constructor============================================
150 /// Constructor for elastic ring problem
151 //======================================================================
152 template<class ELEMENT>
154 (const unsigned& n_element, bool& displ_control, bool& load_data_already_exists) :
155  Displ_control(displ_control),Nbeam_element(n_element)
156 {
157 
158  // Undeformed beam is an elliptical ring
159  Undef_geom_pt=new Ellipse(1.0,1.0);
160 
161  // Length of the doamin (in terms of the Lagrangian coordinates)
162  double length=2.0*atan(1.0);
163 
164  //Now create the (Lagrangian!) mesh
165  Problem::mesh_pt() =
166  new OneDLagrangianMesh<ELEMENT>(n_element,length,Undef_geom_pt);
167 
168  // Boundary condition:
169 
170  // Bottom:
171  unsigned ibound=0;
172  // No vertical displacement
173  mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1);
174  // Infinite slope: Pin type 1 (slope) dof for displacement direction 0
175  mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1,0);
176 
177  // Top:
178  ibound=1;
179  // No horizontal displacement
180  mesh_pt()->boundary_node_pt(ibound,0)->pin_position(0);
181  // Zero slope: Pin type 1 (slope) dof for displacement direction 1
182  mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1,1);
183 
184 
185  // Normal load incrementation
186  //===========================
187  if (!Displ_control)
188  {
189  // Create Data object whose one-and-only value contains the
190  // (in principle) adjustable load
192 
193  //Pin the external pressure because it isn't actually adjustable.
195  }
196  // Displacement control
197  //=====================
198  else
199  {
200  // Choose element in which displacement control is applied: the last one
201  SolidFiniteElement* controlled_element_pt=
202  dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(Nbeam_element-1));
203 
204  // Fix the displacement in the vertical (1) direction...
205  unsigned controlled_direction=1;
206 
207  //... at right end of the control element
208  Vector<double> s_displ_control(1);
209  s_displ_control[0]=1.0;
210 
211  // Pointer to displacement control element
212  DisplacementControlElement* displ_control_el_pt;
213 
214  // Displacement control without previously existing load Data
215  //-----------------------------------------------------------
216  if (!load_data_already_exists)
217  {
218  // Build displacement control element
219  displ_control_el_pt=
220  new DisplacementControlElement(controlled_element_pt,
221  s_displ_control,
222  controlled_direction,
224 
225  // The constructor of the DisplacementControlElement has created
226  // a new Data object whose one-and-only value contains the
227  // adjustable load: Use this Data object in the load function:
228  Global_Physical_Variables::Pext_data_pt=displ_control_el_pt->
229  displacement_control_load_pt();
230  }
231  // Demonstrate use of displacement control with some existing data
232  //----------------------------------------------------------------
233  else
234  {
235  // Create Data object whose one-and-only value contains the
236  // adjustable load
238 
239  // Currently, nobody's "in charge of" this Data so it won't
240  // get included in any equation numbering schemes etc.
241  // --> declare it to be "global Data" for the Problem
242  // so the Problem is in charge and will perform such tasks.
244 
245  // Build displacement control element and pass pointer to the
246  // already existing adjustable load Data.
247  displ_control_el_pt=
248  new DisplacementControlElement(controlled_element_pt,
249  s_displ_control,
250  controlled_direction,
253  }
254 
255  // Add the displacement-control element to the mesh
256  mesh_pt()->add_element_pt(displ_control_el_pt);
257  }
258 
259 
260 
261 
262  //Loop over the elements to set physical parameters etc.
263  for(unsigned i=0;i<Nbeam_element;i++)
264  {
265  //Cast to proper element type
266  ELEMENT *elem_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
267 
268  // Set wall thickness
269  elem_pt->h_pt() = &Global_Physical_Variables::H;
270 
271  // Function that specifies load Vector
272  elem_pt->load_vector_fct_pt() = &Global_Physical_Variables::press_load;
273 
274  //Assign the undeformed beam shape
275  elem_pt->undeformed_beam_pt() = Undef_geom_pt;
276 
277  // Displacement control? If so, the load on *all* elements
278  // is affected by an unknown -- the external pressure, stored
279  // as the one-and-only value in a Data object: Add it to the
280  // elements' external Data.
281  if (Displ_control)
282  {
283  //The external pressure is external data for all elements
284  elem_pt->add_external_data(Global_Physical_Variables::Pext_data_pt);
285  }
286  }
287 
288  // Do equation numbering
289  cout << "# of dofs " << assign_eqn_numbers() << std::endl;
290 
291 } // end of constructor
292 
293 
294 //=======start_of_doc=====================================================
295 /// Document solution
296 //========================================================================
297 template<class ELEMENT>
299  ofstream& trace_file)
300 {
301  ofstream some_file;
302  char filename[100];
303 
304  // Number of plot points
305  unsigned npts=5;
306 
307  // Output solution
308  sprintf(filename,"%s/ring%i.dat",doc_info.directory().c_str(),
309  doc_info.number());
310  some_file.open(filename);
311  mesh_pt()->output(some_file,npts);
312  some_file.close();
313 
314  // Local coordinates of plot points at left and right end of domain
315  Vector<double> s_left(1);
316  s_left[0]=-1.0;
317  Vector<double> s_right(1);
318  s_right[0]=1.0;
319 
320  // Write trace file: Pressure, two radii
321  trace_file
323  (pow(Global_Physical_Variables::H,3)/12.0)
324  << " "
325  << dynamic_cast<ELEMENT*>(mesh_pt()->
326  element_pt(0))->interpolated_x(s_left,0)
327  << " "
328  << dynamic_cast<ELEMENT*>
329  (mesh_pt()->element_pt(Nbeam_element-1))->interpolated_x(s_right,1)
330  << std::endl;
331 
332 
333 } // end of doc
334 
335 
336 
337 //========start_of_run=====================================================
338 /// Solver loop to perform parameter study
339 //=========================================================================
340 template<class ELEMENT>
342 {
343 
344  //Open a trace file
345  char filename[100];
346  sprintf(filename,"%s/trace.dat",doc_info.directory().c_str());
347  ofstream trace_file(filename);
348  trace_file << "VARIABLES=\"p_e_x_t\",\"R_1\",\"R_2\"" << std::endl;
349  trace_file << "ZONE" << std::endl;
350 
351  //Output initial data
352  doc_solution(doc_info,trace_file);
353 
354  // Number of steps
355  unsigned nstep= 11; //51;
356 
357  // Increments
358  double displ_increment=1.0/double(nstep-1);
359  double p_buckl=3.00*pow(Global_Physical_Variables::H,3)/12.0;
360  double p_owc =5.22*pow(Global_Physical_Variables::H,3)/12.0;
361  double pext_increment=(p_owc-p_buckl)/double(nstep-1);
362 
363  // Set initial values for parameters that are to be incremented
364  Global_Physical_Variables::Xprescr=1.0+displ_increment;
365  Global_Physical_Variables::Pext_data_pt->set_value(0,p_buckl-pext_increment);
366 
367 
368 
369  // Without displacement control the Newton method converges very slowly
370  // as we approach the axisymmetric state: Allow more iterations before
371  // calling it a day...
372  if (Displ_control)
373  {
374  Max_newton_iterations=100;
375  }
376 
377 
378  // Downward loop over parameter incrementation with pcos>0
379  //--------------------------------------------------------
380 
381  /// Perturbation pressure
383 
384 
385  // Downward loop over parameter incrementation
386  //---------------------------------------------
387  for(unsigned i=1;i<=nstep;i++)
388  {
389 
390  // Displacement control?
391  if (!Displ_control)
392  {
393  // Increment pressure
395  }
396  else
397  {
398  // Increment control displacement
399  Global_Physical_Variables::Xprescr-=displ_increment;
400  }
401 
402  // Solve
403  newton_solve();
404 
405  // Doc solution
406  doc_info.number()++;
407  doc_solution(doc_info,trace_file);
408 
409  } // end of downward loop
410 
411  // Reset perturbation pressure
412  //----------------------------
414 
415  // Set initial values for parameters that are to be incremented
416  Global_Physical_Variables::Xprescr-=displ_increment;
418 
419  // Start new zone for tecplot
420  trace_file << "ZONE" << std::endl;
421 
422  // Upward loop over parameter incrementation
423  //------------------------------------------
424  for(unsigned i=nstep;i<2*nstep;i++)
425  {
426 
427  // Displacement control?
428  if (!Displ_control)
429  {
430  // Increment pressure
432  }
433  else
434  {
435  // Increment control displacement
436  Global_Physical_Variables::Xprescr+=displ_increment;
437  }
438 
439  // Solve
440  newton_solve();
441 
442  // Doc solution
443  doc_info.number()++;
444  doc_solution(doc_info,trace_file);
445 
446  }
447 
448 } // end of run
449 
450 
451 
452 ////////////////////////////////////////////////////////////////////////
453 ////////////////////////////////////////////////////////////////////////
454 ////////////////////////////////////////////////////////////////////////
455 
456 
457 //=======start_of_main=================================================
458 /// Driver for ring test problem
459 //=====================================================================
460 int main()
461 {
462  // Number of elements
463  unsigned n_element = 13;
464 
465  // Displacement control?
466  bool displ_control=true;
467 
468  // Label for output
469  DocInfo doc_info;
470 
471  // Demonstrate how to use displacement control with already existing load Data
472  //----------------------------------------------------------------------------
473  {
474  bool load_data_already_exists=true;
475 
476  //Set up the problem
478  problem(n_element,displ_control,load_data_already_exists);
479 
480  // Output directory
481  doc_info.set_directory("RESLT_global");
482 
483  // Do static run
484  problem.parameter_study(doc_info);
485  }
486 
487  // Demonstrate how to use displacement control without existing load Data
488  //-----------------------------------------------------------------------
489  {
490  bool load_data_already_exists=false;
491 
492  //Set up the problem
494  problem(n_element,displ_control,load_data_already_exists);
495 
496  // Output directory
497  doc_info.set_directory("RESLT_no_global");
498 
499  // Reset counter
500  doc_info.number()=0;
501 
502  // Do static run
503  problem.parameter_study(doc_info);
504  }
505 
506 } // end of main
507 
508 
509 
510 
511 
512 
Ring problem.
Definition: steady_ring.cc:101
double Pcos
Perturbation pressure.
Definition: steady_ring.cc:60
bool Displ_control
Use displacement control?
Definition: steady_ring.cc:133
int main()
Driver for ring test problem.
Definition: steady_ring.cc:460
GeomObject * Undef_geom_pt
Pointer to geometric object that represents the undeformed shape.
Definition: steady_ring.cc:136
double & external_pressure()
Return a reference to the external pressure load on the elastic ring. A reference is obtained by de-r...
Definition: steady_ring.cc:83
void actions_before_newton_solve()
Update function is empty.
Definition: steady_ring.cc:122
unsigned Nbeam_element
Number of elements in the beam mesh.
Definition: steady_ring.cc:139
void press_load(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &N, Vector< double > &load)
Load function: Constant external pressure with cos variation to induce buckling in n=2 mode...
Definition: steady_ring.cc:68
OneDLagrangianMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
Definition: steady_ring.cc:113
Data * Pext_data_pt
Pointer to pressure load (stored in Data so it can become an unknown in the problem when displacement...
Definition: steady_ring.cc:64
void actions_after_newton_solve()
Update function is empty.
Definition: steady_ring.cc:119
Namespace for physical parameters.
Definition: steady_ring.cc:50
double H
Nondim thickness.
Definition: steady_ring.cc:54
void parameter_study(DocInfo &doc_info)
Perform the parameter study.
Definition: steady_ring.cc:341
void doc_solution(DocInfo &doc_info, ofstream &trace_file)
Doc solution.
Definition: steady_ring.cc:298
ElasticRingProblem(const unsigned &n_element, bool &displ_control, bool &load_data_already_exists)
Constructor for elastic ring problem.
Definition: steady_ring.cc:154
double Xprescr
Prescribed position (only used for displacement control)
Definition: steady_ring.cc:57