three_d_cantilever.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 for 3D Airy cantilever beam problem
27 
28 //#include <fenv.h>
29 
30 //Oomph-lib includes
31 #include "generic.h"
32 #include "solid.h"
33 #include "constitutive.h"
34 
35 // The mesh
36 #include "meshes/simple_cubic_mesh.template.h"
37 
38 // The mesh
39 #include "meshes/quarter_tube_mesh.h"
40 
41 using namespace std;
42 using namespace oomph;
43 
44 
45 /// ////////////////////////////////////////////////////////////////////
46 /// ////////////////////////////////////////////////////////////////////
47 /// ////////////////////////////////////////////////////////////////////
48 
49 //======================start_mesh=========================================
50 /// Simple quarter tube mesh upgraded to become a solid mesh
51 //=========================================================================
52 template<class ELEMENT>
54  public virtual RefineableQuarterTubeMesh<ELEMENT>,
55  public virtual SolidMesh
56 {
57 
58 public:
59 
60  /// Constructor:
61  RefineableElasticQuarterTubeMesh(GeomObject* wall_pt,
62  const Vector<double>& xi_lo,
63  const double& fract_mid,
64  const Vector<double>& xi_hi,
65  const unsigned& nlayer,
66  TimeStepper* time_stepper_pt=
67  &Mesh::Default_TimeStepper) :
68  QuarterTubeMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
69  nlayer,time_stepper_pt),
70  RefineableQuarterTubeMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
71  nlayer,time_stepper_pt)
72  {
73  //Assign the Lagrangian coordinates
74  set_lagrangian_nodal_coordinates();
75  }
76 
77  /// Empty Destructor
79 
80 };
81 
82 /// ////////////////////////////////////////////////////////////////////
83 /// ////////////////////////////////////////////////////////////////////
84 /// ////////////////////////////////////////////////////////////////////
85 
86 
87 //=========================================================================
88 /// Simple quarter tube mesh upgraded to become a solid mesh
89 //=========================================================================
90 template<class ELEMENT>
91 class ElasticQuarterTubeMesh : public virtual QuarterTubeMesh<ELEMENT>,
92  public virtual SolidMesh
93 {
94 
95 public:
96 
97  /// Constructor:
98  ElasticQuarterTubeMesh(GeomObject* wall_pt,
99  const Vector<double>& xi_lo,
100  const double& fract_mid,
101  const Vector<double>& xi_hi,
102  const unsigned& nlayer,
103  TimeStepper* time_stepper_pt=
104  &Mesh::Default_TimeStepper) :
105  QuarterTubeMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
106  nlayer,time_stepper_pt)
107  {
108  //Assign the Lagrangian coordinates
109  set_lagrangian_nodal_coordinates();
110  }
111 
112  /// Empty Destructor
114 
115 };
116 
117 /// ////////////////////////////////////////////////////////////////////
118 /// ////////////////////////////////////////////////////////////////////
119 /// ////////////////////////////////////////////////////////////////////
120 
121 
122 //=======start_namespace==========================================
123 /// Global variables
124 //================================================================
126 {
127 
128  /// Length of beam
129  double L=10.0;
130 
131  /// Pointer to strain energy function
132  StrainEnergyFunction* Strain_energy_function_pt=0;
133 
134  /// First "Mooney Rivlin" coefficient
135  double C1=1.3;
136 
137  /// Second "Mooney Rivlin" coefficient
138  double C2=1.3;
139 
140  /// Pointer to constitutive law
141  ConstitutiveLaw* Constitutive_law_pt=0;
142 
143  /// Non-dim gravity
144  double Gravity=0.0;
145 
146  /// Non-dimensional gravity as body force
147  void gravity(const double& time,
148  const Vector<double> &xi,
149  Vector<double> &b)
150  {
151  b[0]=0.0;
152  b[1]=-Gravity;
153  b[2]=0.0;
154  }
155 
156 } //end namespace
157 
158 
159 
160 
161 
162 //================================================================
163 /// Extension of global variables for self tests
164 //================================================================
166 {
167 
168  /// Elastic modulus
169  double E=1.0;
170 
171  /// Poisson's ratio
172  double Nu=0.3;
173 
174 }
175 
176 
177 
178 //=============begin_problem============================================
179 /// Problem class for the 3D cantilever "beam" structure.
180 //======================================================================
181 template<class ELEMENT>
182 class CantileverProblem : public Problem
183 {
184 
185 public:
186 
187  /// Constructor:
189 
190  /// Update function (empty)
192 
193  /// Update function (empty)
195 
196  /// Actions before adapt. Empty
198 
199  /// Actions after adapt
201  {
202  // Pin the redundant solid pressures (if any)
203  PVDEquationsBase<3>::pin_redundant_nodal_solid_pressures(
204  mesh_pt()->element_pt());
205  }
206 
207  /// Doc the solution
208  void doc_solution();
209 
210 #ifdef REFINE
211 
212  /// Access function for the mesh
214  {
215  return dynamic_cast<RefineableElasticQuarterTubeMesh<ELEMENT>*>(
216  Problem::mesh_pt());
217  }
218 
219 #else
220 
221  /// Access function for the mesh
223  {
224  return dynamic_cast<ElasticQuarterTubeMesh<ELEMENT>*>(
225  Problem::mesh_pt());
226  }
227 
228 #endif
229 
230  /// Run extended tests -- doc in RESLTi_case
231  void run_tests(const unsigned& i_case,
232  const bool& incompress,
233  const bool& use_fd);
234 
235 private:
236 
237  /// DocInfo object for output
238  DocInfo Doc_info;
239 
240 };
241 
242 
243 //===========start_of_constructor=======================================
244 /// Constructor:
245 //======================================================================
246 template<class ELEMENT>
248 {
249 
250  // Create geometric object that defines curvilinear boundary of
251  // beam: Elliptical tube with half axes = radius = 1.0
252  double radius=1.0;
253  GeomObject* wall_pt=new EllipticalTube(radius,radius);
254 
255  // Bounding Lagrangian coordinates
256  Vector<double> xi_lo(2);
257  xi_lo[0]=0.0;
258  xi_lo[1]=0.0;
259 
260  Vector<double> xi_hi(2);
262  xi_hi[1]=2.0*atan(1.0);
263 
264 
265 #ifdef REFINE
266 
267  // # of layers
268  unsigned nlayer=6;
269 
270  //Radial divider is located half-way along the circumference
271  double frac_mid=0.5;
272 
273  //Now create the mesh
274  Problem::mesh_pt() = new RefineableElasticQuarterTubeMesh<ELEMENT>
275  (wall_pt,xi_lo,frac_mid,xi_hi,nlayer);
276 
277  // Set error estimator
279  mesh_pt())->spatial_error_estimator_pt()=new Z2ErrorEstimator;
280 
281  // Error targets for adaptive refinement
282  mesh_pt()->max_permitted_error()=0.05;
283  mesh_pt()->min_permitted_error()=0.005;
284 
285 #else
286 
287  // # of layers
288  unsigned nlayer=6;
289 
290  //Radial divider is located half-way along the circumference
291  double frac_mid=0.5;
292 
293  //Now create the mesh
294  Problem::mesh_pt() = new ElasticQuarterTubeMesh<ELEMENT>
295  (wall_pt,xi_lo,frac_mid,xi_hi,nlayer);
296 
297 #endif
298 
299 
300  // Complete build of elements
301  unsigned n_element=mesh_pt()->nelement();
302  for(unsigned i=0;i<n_element;i++)
303  {
304  // Cast to a solid element
305  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
306 
307  // Set the constitutive law
308  el_pt->constitutive_law_pt() =
310 
311  // Set the body force
312  el_pt->body_force_fct_pt() = Global_Physical_Variables::gravity;
313 
314  // Material is incompressble: Use incompressible displacement/pressure
315  // formulation (if the element is pressure based, that is!)
316  PVDEquationsWithPressure<3>* cast_el_pt =
317  dynamic_cast<PVDEquationsWithPressure<3>*>(mesh_pt()->element_pt(i));
318  if (cast_el_pt!=0)
319  {
320  cast_el_pt->set_incompressible();
321  }
322 
323  } // done build of elements
324 
325 
326  // Pin the left boundary (boundary 0) in all directions
327  unsigned b=0;
328  unsigned n_side = mesh_pt()->nboundary_node(b);
329 
330  //Loop over the nodes
331  for(unsigned i=0;i<n_side;i++)
332  {
333  mesh_pt()->boundary_node_pt(b,i)->pin_position(0);
334  mesh_pt()->boundary_node_pt(b,i)->pin_position(1);
335  mesh_pt()->boundary_node_pt(b,i)->pin_position(2);
336  }
337 
338  // Pin the redundant solid pressures (if any)
339  PVDEquationsBase<3>::pin_redundant_nodal_solid_pressures(
340  mesh_pt()->element_pt());
341 
342  //Assign equation numbers
343  assign_eqn_numbers();
344 
345  // Prepare output directory
346  Doc_info.set_directory("RESLT");
347 
348 } //end of constructor
349 
350 
351 
352 //==============start_doc===========================================
353 /// Doc the solution
354 //==================================================================
355 template<class ELEMENT>
357 {
358 
359  ofstream some_file;
360  char filename[100];
361 
362  // Number of plot points
363  unsigned n_plot = 5;
364 
365  // Output shape of deformed body
366  sprintf(filename,"%s/soln%i.dat",Doc_info.directory().c_str(),
367  Doc_info.number());
368  some_file.open(filename);
369  mesh_pt()->output(some_file,n_plot);
370  some_file.close();
371 
372  // Increment label for output files
373  Doc_info.number()++;
374 
375 } //end doc
376 
377 
378 
379 
380 //==============start_run_tests========================================
381 /// Run tests
382 //==================================================================
383 template<class ELEMENT>
384 void CantileverProblem<ELEMENT>::run_tests(const unsigned& i_case,
385  const bool& incompress,
386  const bool& use_fd)
387 {
388 
389  // Set output directory
390  char dirname[100];
391 
392 #ifdef REFINE
393  sprintf(dirname,"RESLT_refine%i",i_case);
394 #else
395  sprintf(dirname,"RESLT_norefine%i",i_case);
396 #endif
397 
398  // Prepare output
399  Doc_info.set_directory(dirname);
400 
401  //Assign the physical properties to the elements before any refinement
402  //Loop over the elements in the main mesh
403  unsigned n_element=mesh_pt()->nelement();
404  for(unsigned i=0;i<n_element;i++)
405  {
406  //Cast to a solid element
407  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
408 
409  // Get Jacobian by FD?
410  if(use_fd)
411  {
412  el_pt->enable_evaluate_jacobian_by_fd();
413  }
414  else
415  {
416  el_pt->disable_evaluate_jacobian_by_fd();
417  }
418 
419  // Is the material actually not incompressible?
420  if (!incompress)
421  {
422  PVDEquationsWithPressure<3>* cast_el_pt =
423  dynamic_cast<PVDEquationsWithPressure<3>*>(
424  mesh_pt()->element_pt(i));
425  if (cast_el_pt!=0)
426  {
427  cast_el_pt->set_compressible();
428  }
429  }
430  }
431 
432 
433  // Doc solution
434  doc_solution();
435 
436  // Initial values for parameter values
438 
439  //Parameter incrementation
440  unsigned nstep=1;
441 
442  double g_increment=1.0e-5;
443  for(unsigned i=0;i<nstep;i++)
444  {
445  // Increment load
447 
448 #ifdef REFINE
449 
450  // Solve the problem with Newton's method, allowing
451  // up to max_adapt mesh adaptations after every solve.
452  unsigned max_adapt=1;
453  newton_solve(max_adapt);
454 
455 #else
456 
457  // Solve it
458  newton_solve();
459 
460 #endif
461 
462  // Doc solution
463  doc_solution();
464 
465  }
466 
467 }
468 
469 
470 //=======start_of_main==================================================
471 /// Driver for 3D cantilever beam loaded by gravity
472 //======================================================================
473 int main(int argc, char* argv[])
474 {
475 
476  // Run main demo code if no command line arguments are specified
477  if (argc==1)
478  {
479 
480  // Create incompressible Mooney Rivlin strain energy function
482  new MooneyRivlin(&Global_Physical_Variables::C1,
484 
485  // Define a constitutive law (based on strain energy function)
487  new IsotropicStrainEnergyFunctionConstitutiveLaw(
489 
490  //Set up the problem with continous pressure/displacement
492 
493  // Doc solution
494  problem.doc_solution();
495 
496  // Initial values for parameter values
498 
499  //Parameter incrementation
500  unsigned nstep=10;
501 
502  double g_increment=5.0e-4;
503  for(unsigned i=0;i<nstep;i++)
504  {
505  // Increment load
507 
508  // Solve the problem with Newton's method, allowing
509  // up to max_adapt mesh adaptations after every solve.
510  unsigned max_adapt=1;
511  problem.newton_solve(max_adapt);
512 
513  // Doc solution
514  problem.doc_solution();
515  }
516 
517  } // end main demo code
518 
519  // Run self-tests
520  else
521  {
522 
523  // Additional test cases combining adaptive/non-adaptive
524  // elements with displacement/displacement-pressure
525  // discretisation and various constitutive equations
526 
527 
528  // Initialise flag for FD evaluation
529  bool use_fd=false;
530 
531  // Number of cases per implementation
532  unsigned ncase=5;
533 
534  // Is the material incomressible?
535  bool incompress=true;
536 
537  // Loop over fd and analytical implementation
538  for (unsigned i=0;i<2;i++)
539  {
540 
541  // Generalised Hookean constitutive equations
542  //-------------------------------------------
543  {
545  new GeneralisedHookean(&Global_Physical_Variables::Nu,
547 
548  incompress=false;
549 
550 #ifdef REFINE
551  {
552  //Set up the problem with pure displacement based elements
554  problem.run_tests(0+i*ncase,incompress,use_fd);
555  }
556 #else
557  {
558  //Set up the problem with pure displacement based elements
560  problem.run_tests(0+i*ncase,incompress,use_fd);
561  }
562 #endif
563 
564 
565 #ifdef REFINE
566  {
567  //Set up the problem with continous pressure/displacement
569  problem.run_tests(1+i*ncase,incompress,use_fd);
570  }
571 #else
572  {
573  //Set up the problem with continous pressure/displacement
575  problem.run_tests(1+i*ncase,incompress,use_fd);
576  }
577 #endif
578 
579 
580 #ifdef REFINE
581  {
582  //Set up the problem with discontinous pressure/displacement
584  problem.run_tests(2+i*ncase,incompress,use_fd);
585  }
586 #else
587  {
588  //Set up the problem with discontinous pressure/displacement
590  problem.run_tests(2+i*ncase,incompress,use_fd);
591  }
592 #endif
593 
596  }
597 
598 
599 
600  // Incompressible Mooney Rivlin
601  //-----------------------------
602  {
604  new MooneyRivlin(&Global_Physical_Variables::C1,
606 
607  // Define a constitutive law (based on strain energy function)
609  new IsotropicStrainEnergyFunctionConstitutiveLaw(
611 
612  incompress=true;
613 
614 
615 #ifdef REFINE
616  {
617  //Set up the problem with continous pressure/displacement
619  problem.run_tests(3+i*ncase,incompress,use_fd);
620  }
621 #else
622  {
623  //Set up the problem with continous pressure/displacement
625  problem.run_tests(3+i*ncase,incompress,use_fd);
626  }
627 #endif
628 
629 
630 
631 #ifdef REFINE
632  {
633  //Set up the problem with discontinous pressure/displacement
635  problem.run_tests(4+i*ncase,incompress,use_fd);
636  }
637 #else
638  {
639  //Set up the problem with discontinous pressure/displacement
641  problem.run_tests(4+i*ncase,incompress,use_fd);
642  }
643 #endif
644 
647 
650  }
651 
652 
653  use_fd=true;
654  std::cout << "\n\n\n CR Total fill_in... : bla \n\n\n " << std::endl;
655 
656  }
657  }
658 
659 
660 } //end of main
661 
662 
663 
664 
665 
666 
Problem class for the 3D cantilever "beam" structure.
RefineableElasticQuarterTubeMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
void actions_before_newton_solve()
Update function (empty)
DocInfo Doc_info
DocInfo object for output.
ElasticQuarterTubeMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
void actions_after_newton_solve()
Update function (empty)
void actions_before_adapt()
Actions before adapt. Empty.
void doc_solution()
Doc the solution.
CantileverProblem()
Constructor:
void actions_after_adapt()
Actions after adapt.
void run_tests(const unsigned &i_case, const bool &incompress, const bool &use_fd)
Run extended tests – doc in RESLTi_case.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
virtual ~ElasticQuarterTubeMesh()
Empty Destructor.
ElasticQuarterTubeMesh(GeomObject *wall_pt, const Vector< double > &xi_lo, const double &fract_mid, const Vector< double > &xi_hi, const unsigned &nlayer, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor:
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
virtual ~RefineableElasticQuarterTubeMesh()
Empty Destructor.
RefineableElasticQuarterTubeMesh(GeomObject *wall_pt, const Vector< double > &xi_lo, const double &fract_mid, const Vector< double > &xi_hi, const unsigned &nlayer, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor:
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
void gravity(const double &time, const Vector< double > &xi, Vector< double > &b)
Non-dimensional gravity as body force.
double E
Elastic modulus.
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
double Nu
Poisson's ratio.
StrainEnergyFunction * Strain_energy_function_pt
Pointer to strain energy function.
double C1
First "Mooney Rivlin" coefficient.
double Gravity
Non-dim gravity.
double C2
Second "Mooney Rivlin" coefficient.
int main(int argc, char *argv[])
Driver for 3D cantilever beam loaded by gravity.