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