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-2025 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.h"
37
38// The mesh
39#include "meshes/quarter_tube_mesh.h"
40
41using namespace std;
42using namespace oomph;
43
44
45///////////////////////////////////////////////////////////////////////
46///////////////////////////////////////////////////////////////////////
47///////////////////////////////////////////////////////////////////////
48
49//======================start_mesh=========================================
50/// Simple quarter tube mesh upgraded to become a solid mesh
51//=========================================================================
52template<class ELEMENT>
54 public virtual RefineableQuarterTubeMesh<ELEMENT>,
55 public virtual SolidMesh
56{
57
58public:
59
60 /// Constructor:
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//=========================================================================
90template<class ELEMENT>
91class ElasticQuarterTubeMesh : public virtual QuarterTubeMesh<ELEMENT>,
92 public virtual SolidMesh
93{
94
95public:
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//======================================================================
181template<class ELEMENT>
182class CantileverProblem : public Problem
183{
184
185public:
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
235private:
236
237 /// DocInfo object for output
238 DocInfo Doc_info;
239
240};
241
242
243//===========start_of_constructor=======================================
244/// Constructor:
245//======================================================================
246template<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>
276
277 // Set error estimator
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>
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!)
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)
340 mesh_pt()->element_pt());
341
342 //Assign equation 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//==================================================================
355template<class ELEMENT>
357{
358
360 char filename[100];
361
362 // Number of plot points
363 unsigned n_plot = 5;
364
365 // Output shape of deformed body
366 snprintf(filename, sizeof(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//==================================================================
383template<class ELEMENT>
385 const bool& incompress,
386 const bool& use_fd)
387{
388
389 // Set output directory
390 char dirname[100];
391
392#ifdef REFINE
393 snprintf(dirname, sizeof(dirname), "RESLT_refine%i",i_case);
394#else
395 snprintf(dirname, sizeof(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 {
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;
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//======================================================================
473int 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
484
485 // Define a constitutive law (based on strain energy function)
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 {
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 {
606
607 // Define a constitutive law (based on strain energy function)
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.
ElasticQuarterTubeMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
void actions_before_newton_solve()
Update function (empty)
DocInfo Doc_info
DocInfo object for output.
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.
RefineableElasticQuarterTubeMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
void run_tests(const unsigned &i_case, const bool &incompress, const bool &use_fd)
Run extended tests – doc in RESLTi_case.
Simple quarter tube mesh upgraded to become a solid mesh.
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:
Simple quarter tube mesh upgraded to become a solid mesh.
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.
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.