disk_compression.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 elasticity problem: the
31 //compression of an axisymmetric disk. We also demonstrate how
32 //to incorporate isotropic growth into the model and how to
33 //switch between different constitutive equations.
34 #include <iostream>
35 #include <fstream>
36 #include <cmath>
37 
38 //My own includes
39 #include "generic.h"
40 #include "solid.h"
41 
42 //Need to instantiate templated mesh
43 #include "meshes/quarter_circle_sector_mesh.h"
44 
45 using namespace std;
46 
47 using namespace oomph;
48 
49 
50 //============namespace_for_problem_parameters=====================
51 /// Global variables
52 //=================================================================
54 {
55  /// Pointer to strain energy function
56  StrainEnergyFunction* Strain_energy_function_pt;
57 
58  /// Pointer to constitutive law
59  ConstitutiveLaw* Constitutive_law_pt;
60 
61  /// Elastic modulus
62  double E=1.0;
63 
64  /// Poisson's ratio
65  double Nu=0.3;
66 
67  /// "Mooney Rivlin" coefficient for generalised Mooney Rivlin law
68  double C1=1.3;
69 
70  /// Uniform pressure
71  double P = 0.0;
72 
73  /// Constant pressure load
74  void constant_pressure(const Vector<double> &xi,const Vector<double> &x,
75  const Vector<double> &n, Vector<double> &traction)
76  {
77  unsigned dim = traction.size();
78  for(unsigned i=0;i<dim;i++)
79  {
80  traction[i] = -P*n[i];
81  }
82  } // end of pressure load
83 
84 
85  /// Uniform volumetric expansion
86  double Uniform_gamma=1.1;
87 
88  /// Growth function
89  void growth_function(const Vector<double>& xi, double& gamma)
90  {
91  gamma = Uniform_gamma;
92  }
93 
94 } // end namespace
95 
96 
97 ///////////////////////////////////////////////////////////////////////
98 ///////////////////////////////////////////////////////////////////////
99 ///////////////////////////////////////////////////////////////////////
100 
101 
102 
103 //==========start_mesh=================================================
104 /// Elastic quarter circle sector mesh with functionality to
105 /// attach traction elements to the curved surface. We "upgrade"
106 /// the RefineableQuarterCircleSectorMesh to become an
107 /// SolidMesh and equate the Eulerian and Lagrangian coordinates,
108 /// thus making the domain represented by the mesh the stress-free
109 /// configuration.
110 /// \n\n
111 /// The member function \c make_traction_element_mesh() creates
112 /// a separate mesh of SolidTractionElements that are attached to the
113 /// mesh's curved boundary (boundary 1).
114 //=====================================================================
115 template <class ELEMENT>
117  public virtual RefineableQuarterCircleSectorMesh<ELEMENT>,
118  public virtual SolidMesh
119 {
120 
121 
122 public:
123 
124  /// \short Constructor: Build mesh and copy Eulerian coords to Lagrangian
125  /// ones so that the initial configuration is the stress-free one.
127  const double& xi_lo,
128  const double& fract_mid,
129  const double& xi_hi,
130  TimeStepper* time_stepper_pt=
131  &Mesh::Default_TimeStepper) :
132  RefineableQuarterCircleSectorMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
133  time_stepper_pt)
134  {
135  /// Make the current configuration the undeformed one by
136  /// setting the nodal Lagrangian coordinates to their current
137  /// Eulerian ones
138  set_lagrangian_nodal_coordinates();
139  }
140 
141 
142  /// Function to create mesh made of traction elements
143  void make_traction_element_mesh(SolidMesh*& traction_mesh_pt)
144  {
145 
146  // Make new mesh
147  traction_mesh_pt = new SolidMesh;
148 
149  // Loop over all elements on boundary 1:
150  unsigned b=1;
151  unsigned n_element = this->nboundary_element(b);
152  for (unsigned e=0;e<n_element;e++)
153  {
154  // The element itself:
155  FiniteElement* fe_pt = this->boundary_element_pt(b,e);
156 
157  // Find the index of the face of element e along boundary b
158  int face_index = this->face_index_at_boundary(b,e);
159 
160  // Create new element
161  traction_mesh_pt->add_element_pt(new SolidTractionElement<ELEMENT>
162  (fe_pt,face_index));
163  }
164  }
165 
166 };
167 
168 
169 //======================================================================
170 /// Uniform compression of a circular disk in a state of plane strain,
171 /// subject to uniform growth.
172 //======================================================================
173 template<class ELEMENT>
174 class StaticDiskCompressionProblem : public Problem
175 {
176 
177 public:
178 
179  /// Constructor:
181 
182  /// Run simulation: Pass case number to label output files
183  void parameter_study(const unsigned& case_number);
184 
185  /// Doc the solution
186  void doc_solution(DocInfo& doc_info);
187 
188  /// Update function (empty)
190 
191  /// Update function (empty)
193 
194 private:
195 
196  /// Trace file
197  ofstream Trace_file;
198 
199  /// Vector of pointers to nodes whose position we're tracing
200  Vector<Node*> Trace_node_pt;
201 
202  /// Pointer to solid mesh
204 
205  /// Pointer to mesh of traction elements
206  SolidMesh* Traction_mesh_pt;
207 
208 };
209 
210 //======================================================================
211 /// Constructor:
212 //======================================================================
213 template<class ELEMENT>
215 {
216  // Build the geometric object that describes the curvilinear
217  // boundary of the quarter circle domain
218  Ellipse* curved_boundary_pt = new Ellipse(1.0,1.0);
219 
220  // The curved boundary of the mesh is defined by the geometric object
221  // What follows are the start and end coordinates on the geometric object:
222  double xi_lo=0.0;
223  double xi_hi=2.0*atan(1.0);
224 
225  // Fraction along geometric object at which the radial dividing line
226  // is placed
227  double fract_mid=0.5;
228 
229  //Now create the mesh using the geometric object
231  curved_boundary_pt,xi_lo,fract_mid,xi_hi);
232 
233  // Setup trace nodes as the nodes on boundary 1 (=curved boundary)
234  // in the original mesh.
235  unsigned n_boundary_node = Solid_mesh_pt->nboundary_node(1);
236  Trace_node_pt.resize(n_boundary_node);
237  for(unsigned j=0;j<n_boundary_node;j++)
238  {Trace_node_pt[j]=Solid_mesh_pt->boundary_node_pt(1,j);}
239 
240  // Refine the mesh uniformly
241  Solid_mesh_pt->refine_uniformly();
242 
243  // Now construct the traction element mesh
244  Solid_mesh_pt->make_traction_element_mesh(Traction_mesh_pt);
245 
246  // Solid mesh is first sub-mesh
247  add_sub_mesh(Solid_mesh_pt);
248 
249  // Traction mesh is second sub-mesh
250  add_sub_mesh(Traction_mesh_pt);
251 
252  // Build combined "global" mesh
253  build_global_mesh();
254 
255 
256  // Pin the left edge in the horizontal direction
257  unsigned n_side = mesh_pt()->nboundary_node(2);
258  for(unsigned i=0;i<n_side;i++)
259  {Solid_mesh_pt->boundary_node_pt(2,i)->pin_position(0);}
260 
261  // Pin the bottom in the vertical direction
262  unsigned n_bottom = mesh_pt()->nboundary_node(0);
263  for(unsigned i=0;i<n_bottom;i++)
264  {Solid_mesh_pt->boundary_node_pt(0,i)->pin_position(1);}
265 
266  // Pin the redundant solid pressures (if any)
267  PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
268  Solid_mesh_pt->element_pt());
269 
270  //Complete the build process for elements in "bulk" solid mesh
271  unsigned n_element =Solid_mesh_pt->nelement();
272  for(unsigned i=0;i<n_element;i++)
273  {
274  //Cast to a solid element
275  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(Solid_mesh_pt->element_pt(i));
276 
277  // Set the constitutive law
278  el_pt->constitutive_law_pt() =
280 
281  // Set the isotropic growth function pointer
282  el_pt->isotropic_growth_fct_pt()=Global_Physical_Variables::growth_function;
283  }
284 
285  // Complete build process for SolidTractionElements
286  n_element=Traction_mesh_pt->nelement();
287  for(unsigned i=0;i<n_element;i++)
288  {
289  //Cast to a solid traction element
290  SolidTractionElement<ELEMENT> *el_pt =
291  dynamic_cast<SolidTractionElement<ELEMENT>*>
292  (Traction_mesh_pt->element_pt(i));
293 
294  //Set the traction function
295  el_pt->traction_fct_pt() = Global_Physical_Variables::constant_pressure;
296  }
297 
298  //Set up equation numbering scheme
299  cout << "Number of equations: " << assign_eqn_numbers() << std::endl;
300 }
301 
302 
303 //==================================================================
304 /// Doc the solution
305 //==================================================================
306 template<class ELEMENT>
308 {
309 
310  ofstream some_file;
311  char filename[100];
312 
313  // Number of plot points
314  unsigned npts = 5;
315 
316  // Output shape of deformed body
317  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
318  doc_info.number());
319  some_file.open(filename);
320  Solid_mesh_pt->output(some_file,npts);
321  some_file.close();
322 
323  //Find number of solid elements
324  unsigned nelement = Solid_mesh_pt->nelement();
325 
326  // Work out volume
327  double volume = 0.0;
328  for(unsigned e=0;e<nelement;e++)
329  {volume+= Solid_mesh_pt->finite_element_pt(e)->size();}
330 
331  // Exact outer radius for linear elasticity
333  double exact_r=sqrt(Global_Physical_Variables::Uniform_gamma)*
335  *((1.0+nu)*(1.0-2.0*nu)));
336 
337 
338  // Write trace file: Problem parameters
339  Trace_file << Global_Physical_Variables::P << " "
341  << volume << " "
342  << exact_r << " ";
343 
344  // Write radii of trace nodes
345  unsigned ntrace_node=Trace_node_pt.size();
346  for (unsigned j=0;j<ntrace_node;j++)
347  {
348  Trace_file << sqrt(pow(Trace_node_pt[j]->x(0),2)+
349  pow(Trace_node_pt[j]->x(1),2)) << " ";
350  }
351  Trace_file << std::endl;
352 
353 } // end of doc_solution
354 
355 
356 //==================================================================
357 /// Run the paramter study
358 //==================================================================
359 template<class ELEMENT>
361  const unsigned& case_number)
362 {
363  // Output
364  DocInfo doc_info;
365 
366  char dirname[100];
367  sprintf(dirname,"RESLT%i",case_number);
368 
369  // Set output directory
370  doc_info.set_directory(dirname);
371 
372  // Step number
373  doc_info.number()=0;
374 
375  // Open trace file
376  char filename[100];
377  sprintf(filename,"%s/trace.dat",doc_info.directory().c_str());
378  Trace_file.open(filename);
379 
380  //Parameter incrementation
381  double delta_p=0.0125;
382  unsigned nstep=21;
383 
384  // Perform fewer steps if run as self-test (indicated by nonzero number
385  // of command line arguments)
386  if (CommandLineArgs::Argc!=1)
387  {
388  nstep=3;
389  }
390 
391  // Offset external pressure so that the computation sweeps
392  // over a range of positive and negative pressures
393  Global_Physical_Variables::P =-delta_p*double(nstep-1)*0.5;
394 
395  // Do the parameter study
396  for(unsigned i=0;i<nstep;i++)
397  {
398  //Solve the problem for current load
399  newton_solve();
400 
401  // Doc solution
402  doc_solution(doc_info);
403  doc_info.number()++;
404 
405  // Increment pressure load
406  Global_Physical_Variables::P += delta_p;
407  }
408 
409 } // end of parameter study
410 
411 
412 //=====start_of_main====================================================
413 /// Driver code for disk-compression
414 //======================================================================
415 int main(int argc, char* argv[])
416 {
417 
418  // Store command line arguments
419  CommandLineArgs::setup(argc,argv);
420 
421  // Define a strain energy function: Generalised Mooney Rivlin
423  new GeneralisedMooneyRivlin(&Global_Physical_Variables::Nu,
426 
427  // Define a constitutive law (based on strain energy function)
429  new IsotropicStrainEnergyFunctionConstitutiveLaw(
431 
432  // Case 0: No pressure, generalised Mooney Rivlin
433  //-----------------------------------------------
434  {
435  //Set up the problem
437 
438  cout << "gen. M.R.: RefineableQPVDElement<2,3>" << std::endl;
439 
440  //Run the simulation
441  problem.parameter_study(0);
442 
443  } // done case 0
444 
445 
446  // Case 1: Continuous pressure formulation with generalised Mooney Rivlin
447  //------------------------------------------------------------------------
448  {
449  //Set up the problem
451  RefineableQPVDElementWithContinuousPressure<2> > problem;
452 
453  cout << "gen. M.R.: RefineableQPVDElementWithContinuousPressure<2> "
454  << std::endl;
455 
456  //Run the simulation
457  problem.parameter_study(1);
458 
459  } // done case 1
460 
461 
462 
463  // Case 2: Discontinuous pressure formulation with generalised Mooney Rivlin
464  //--------------------------------------------------------------------------
465  {
466  //Set up the problem
468  problem;
469 
470  cout << "gen. M.R.: RefineableQPVDElementWithPressure<2>" << std::endl;
471 
472  //Run the simulation
473  problem.parameter_study(2);
474 
475  } // done case 2
476 
477 
478  // Change the consitutive law: Delete the old one
480 
481  // Create oomph-lib's generalised Hooke's law constitutive equation
483  new GeneralisedHookean(&Global_Physical_Variables::Nu,
485 
486  // Case 3: No pressure, generalised Hooke's law
487  //----------------------------------------------
488  {
489  //Set up the problem
491 
492  cout << "gen. Hooke: RefineableQPVDElement<2,3> " << std::endl;
493 
494  //Run the simulation
495  problem.parameter_study(3);
496 
497  } // done case 3
498 
499  // Case 4: Continuous pressure formulation with generalised Hooke's law
500  //---------------------------------------------------------------------
501  {
502 
503  //Set up the problem
505  RefineableQPVDElementWithContinuousPressure<2> > problem;
506 
507  cout << "gen. Hooke: RefineableQPVDElementWithContinuousPressure<2> "
508  << std::endl;
509 
510  //Run the simulation
511  problem.parameter_study(4);
512 
513  } // done case 4
514 
515 
516  // Case 5: Discontinous pressure formulation with generalised Hooke's law
517  //------------------------------------------------------------------------
518  {
519 
520  //Set up the problem
522 
523  cout << "gen. Hooke: RefineableQPVDElementWithPressure<2> " << std::endl;
524 
525  //Run the simulation
526  problem.parameter_study(5);
527 
528  } // done case 5
529 
530  // Clean up
533 
534 } // end of main
535 
536 
537 
538 
539 
540 
541 
542 
void growth_function(const Vector< double > &xi, double &gamma)
Growth function.
ofstream Trace_file
Trace file.
ElasticRefineableQuarterCircleSectorMesh< ELEMENT > * Solid_mesh_pt
Pointer to solid mesh.
void parameter_study(const unsigned &case_number)
Run simulation: Pass case number to label output files.
double P
Uniform pressure.
SolidMesh * Traction_mesh_pt
Pointer to mesh of traction elements.
void doc_solution(DocInfo &doc_info)
Doc the solution.
Vector< Node * > Trace_node_pt
Vector of pointers to nodes whose position we&#39;re tracing.
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
StaticDiskCompressionProblem()
Constructor:
double Uniform_gamma
Uniform volumetric expansion.
void actions_before_newton_solve()
Update function (empty)
void constant_pressure(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Constant pressure load.
void make_traction_element_mesh(SolidMesh *&traction_mesh_pt)
Function to create mesh made of traction elements.
double C1
"Mooney Rivlin" coefficient for generalised Mooney Rivlin law
StrainEnergyFunction * Strain_energy_function_pt
Pointer to strain energy function.
void actions_after_newton_solve()
Update function (empty)
int main(int argc, char *argv[])
Driver code for disk-compression.
double Nu
Poisson&#39;s ratio.
double E
Elastic modulus.