Toggle navigation
Documentation
Big picture
The finite element method
The data structure
Not-so-quick guide
Optimisation
Order of action functions
Example codes and tutorials
List of example codes and tutorials
Meshing
Solvers
MPI parallel processing
Post-processing/visualisation
Other
Change log
Creating documentation
Coding conventions
Index
FAQ
About
People
Contact/Get involved
Publications
Acknowledgements
Copyright
Picture show
Go
demo_drivers
solid
compressed_square
compressed_square.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 compressed square
27
28
//Oomph-lib includes
29
#include "generic.h"
30
#include "solid.h"
31
32
//The mesh
33
#include "meshes/rectangular_quadmesh.h"
34
35
using namespace
std;
36
37
using namespace
oomph
;
38
39
namespace
oomph
40
{
41
42
//=================start_wrapper==================================
43
/// Wrapper class for solid element to modify the output
44
//================================================================
45
template
<
class
ELEMENT>
46
class
MySolidElement
:
public
virtual
ELEMENT
47
{
48
49
public
:
50
51
/// Constructor: Call constructor of underlying element
52
MySolidElement
() : ELEMENT() {}
53
54
/// Overload output function
55
void
output
(std::ostream &outfile,
const
unsigned
&n_plot)
56
{
57
Vector<double> s(2);
58
Vector<double> x(2);
59
Vector<double> xi(2);
60
DenseMatrix<double> sigma(2,2);
61
62
//Tecplot header info
63
outfile <<
"ZONE I="
<< n_plot <<
", J="
<< n_plot << std::endl;
64
65
//Loop over plot points
66
for
(
unsigned
l2=0;l2<n_plot;l2++)
67
{
68
s[1] = -1.0 + l2*2.0/(n_plot-1);
69
for
(
unsigned
l1=0;l1<n_plot;l1++)
70
{
71
s[0] = -1.0 + l1*2.0/(n_plot-1);
72
73
// Get Eulerian and Lagrangian coordinates and the stress
74
this->interpolated_x(s,x);
75
this->interpolated_xi(s,xi);
76
this->get_stress(s,sigma);
77
78
//Output the x,y coordinates
79
for
(
unsigned
i=0;i<2;i++)
80
{outfile << x[i] <<
" "
;}
81
82
// Output displacements, the difference between Eulerian and Lagrangian
83
// coordinates
84
for
(
unsigned
i=0;i<2;i++)
85
{outfile << x[i]-xi[i] <<
" "
;}
86
87
//Output stress
88
outfile << sigma(0,0) <<
" "
89
<< sigma(1,0) <<
" "
90
<< sigma(1,1) <<
" "
91
<< std::endl;
92
}
93
}
94
}
95
};
96
97
}
//end namespace extension
98
99
100
101
///////////////////////////////////////////////////////////////////////
102
///////////////////////////////////////////////////////////////////////
103
///////////////////////////////////////////////////////////////////////
104
105
106
107
//=======start_namespace==========================================
108
/// Global variables
109
//================================================================
110
namespace
Global_Physical_Variables
111
{
112
113
/// Pointer to constitutive law
114
ConstitutiveLaw*
Constitutive_law_pt
=0;
115
116
/// Poisson's ratio for Hooke's law
117
double
Nu
=0.45;
118
119
/// Pointer to strain energy function
120
StrainEnergyFunction*
Strain_energy_function_pt
=0;
121
122
/// First "Mooney Rivlin" coefficient for generalised Mooney Rivlin law
123
double
C1
=1.3;
124
125
/// Second "Mooney Rivlin" coefficient for generalised Mooney Rivlin law
126
double
C2
=1.3;
127
128
/// Non-dim gravity
129
double
Gravity
=0.0;
130
131
/// Non-dimensional gravity as body force
132
void
gravity
(
const
double
& time,
133
const
Vector<double> &xi,
134
Vector<double> &b)
135
{
136
b[0]=0.0;
137
b[1]=-
Gravity
;
138
}
139
140
}
//end namespace
141
142
143
144
//=============begin_problem============================================
145
/// Problem class
146
//======================================================================
147
template
<
class
ELEMENT>
148
class
CompressedSquareProblem
:
public
Problem
149
{
150
151
public
:
152
153
/// Constructor: Pass flag that determines if we want to use
154
/// a true incompressible formulation
155
CompressedSquareProblem
(
const
bool
& incompress);
156
157
/// Update function (empty)
158
void
actions_after_newton_solve
() {}
159
160
/// Update function (empty)
161
void
actions_before_newton_solve
() {}
162
163
/// Doc the solution & exact (linear) solution for compressible
164
/// or incompressible materials
165
void
doc_solution
(
const
bool
& incompress);
166
167
/// Run the job -- doc in RESLTi_case
168
void
run_it
(
const
int
& i_case,
const
bool
& incompress);
169
170
private
:
171
172
/// Trace file
173
ofstream
Trace_file
;
174
175
/// Pointers to node whose position we're tracing
176
Node*
Trace_node_pt
;
177
178
/// DocInfo object for output
179
DocInfo
Doc_info
;
180
181
};
182
183
184
//===========start_of_constructor=======================================
185
/// Constructor: Pass flag that determines if we want to enforce
186
/// incompressibility
187
//======================================================================
188
template
<
class
ELEMENT>
189
CompressedSquareProblem<ELEMENT>::CompressedSquareProblem
(
190
const
bool
& incompress)
191
{
192
193
// Create the mesh
194
195
// # of elements in x-direction
196
unsigned
n_x=5;
197
198
// # of elements in y-direction
199
unsigned
n_y=5;
200
201
// Domain length in x-direction
202
double
l_x=1.0;
203
204
// Domain length in y-direction
205
double
l_y=1.0;
206
207
//Now create the mesh
208
mesh_pt() =
new
ElasticRectangularQuadMesh<ELEMENT>(n_x,n_y,l_x,l_y);
209
210
211
//Assign the physical properties to the elements
212
unsigned
n_element=mesh_pt()->nelement();
213
for
(
unsigned
i=0;i<n_element;i++)
214
{
215
//Cast to a solid element
216
ELEMENT *el_pt =
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(i));
217
218
// Set the constitutive law
219
el_pt->constitutive_law_pt() =
220
Global_Physical_Variables::Constitutive_law_pt
;
221
222
//Set the body force
223
el_pt->body_force_fct_pt() =
Global_Physical_Variables::gravity
;
224
225
226
// Is the element based on the pressure/displacement formulation?
227
PVDEquationsWithPressure<2>* test_pt =
228
dynamic_cast<
PVDEquationsWithPressure<2>*
>
(mesh_pt()->element_pt(i));
229
if
(test_pt!=0)
230
{
231
// Do we want true incompressibility (formulation III in the
232
// associated tutorial) or not (formulation II)
233
if
(incompress)
234
{
235
test_pt->set_incompressible();
236
}
237
else
238
{
239
// Note that this assignment isn't strictly necessary as it's the
240
// default setting, but it doesn't do any harm to be explicit.
241
test_pt->set_compressible();
242
}
243
}
244
}
// end compressibility
245
246
247
// Choose a control node: The last node in the solid mesh
248
unsigned
nnod=mesh_pt()->nnode();
249
Trace_node_pt=mesh_pt()->node_pt(nnod-1);
250
251
// Pin the left and right boundaries (1 and 2) in the horizontal directions
252
for
(
unsigned
b=1;b<4;b+=2)
253
{
254
unsigned
nnod = mesh_pt()->nboundary_node(b);
255
for
(
unsigned
i=0;i<nnod;i++)
256
{
257
dynamic_cast<
SolidNode*
>
(
258
mesh_pt()->boundary_node_pt(b,i))->pin_position(0);
259
}
260
}
261
262
// Pin the bottom boundary (0) in the vertical direction
263
unsigned
b=0;
264
{
265
unsigned
nnod= mesh_pt()->nboundary_node(b);
266
for
(
unsigned
i=0;i<nnod;i++)
267
{
268
dynamic_cast<
SolidNode*
>
(
269
mesh_pt()->boundary_node_pt(b,i))->pin_position(1);
270
}
271
}
272
273
//Assign equation numbers
274
assign_eqn_numbers();
275
276
}
//end of constructor
277
278
279
280
//==============start_doc===========================================
281
/// Doc the solution
282
//==================================================================
283
template
<
class
ELEMENT>
284
void
CompressedSquareProblem<ELEMENT>::doc_solution
(
const
bool
& incompress)
285
{
286
ofstream some_file;
287
char
filename[100];
288
289
// Number of plot points
290
unsigned
n_plot = 5;
291
292
// Output shape of and stress in deformed body
293
snprintf(filename,
sizeof
(filename),
"%s/soln%i.dat"
,Doc_info.directory().c_str(),
294
Doc_info.number());
295
some_file.open(filename);
296
mesh_pt()->output(some_file,n_plot);
297
some_file.close();
298
299
// Write trace file: Load/displacement characteristics
300
Trace_file <<
Global_Physical_Variables::Gravity
<<
" "
301
<< Trace_node_pt->x(0) <<
" "
302
<< Trace_node_pt->x(1) <<
" "
303
<< std::endl;
304
305
306
// Output exact solution for linear elasticity
307
// -------------------------------------------
308
snprintf(filename,
sizeof
(filename),
"%s/exact_soln%i.dat"
,Doc_info.directory().c_str(),
309
Doc_info.number());
310
some_file.open(filename);
311
unsigned
nelem=mesh_pt()->nelement();
312
Vector<double> s(2);
313
Vector<double> x(2);
314
DenseMatrix<double> sigma(2,2);
315
316
// Poisson's ratio
317
double
nu=
Global_Physical_Variables::Nu
;
318
if
(incompress) nu=0.5;
319
320
// Loop over all elements
321
for
(
unsigned
e=0;e<nelem;e++)
322
{
323
//Cast to a solid element
324
ELEMENT* el_pt =
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(e));
325
326
//Tecplot header info
327
some_file <<
"ZONE I="
<< n_plot <<
", J="
<< n_plot << std::endl;
328
329
//Loop over plot points
330
for
(
unsigned
l2=0;l2<n_plot;l2++)
331
{
332
s[1] = -1.0 + l2*2.0/(n_plot-1);
333
for
(
unsigned
l1=0;l1<n_plot;l1++)
334
{
335
s[0] = -1.0 + l1*2.0/(n_plot-1);
336
337
// Get Lagrangian coordinates
338
el_pt->interpolated_x(s,x);
339
340
// Output the x,y,..
341
for
(
unsigned
i=0;i<2;i++)
342
{some_file << x[i] <<
" "
;}
343
344
// Exact vertical displacement
345
double
v_exact=
Global_Physical_Variables::Gravity
*
346
(1.0+nu)*(1.0-2*nu)/(1.0-nu)*(0.5*x[1]*x[1]-x[1]);
347
348
// x and y displacement
349
some_file <<
"0.0 "
<< v_exact <<
" "
;
350
351
// Stresses
352
sigma(0,0)=nu/(1.0-nu)*
Global_Physical_Variables::Gravity
*(x[1]-1.0);
353
sigma(1,0)=0.0;
354
sigma(1,1)=
Global_Physical_Variables::Gravity
*(x[1]-1.0);
355
356
// Output linear stress tensor
357
some_file << sigma(0,0) <<
" "
358
<< sigma(1,0) <<
" "
359
<< sigma(1,1) <<
" "
360
<< std::endl;
361
}
362
}
363
}
364
some_file.close();
365
366
// Increment label for output files
367
Doc_info.number()++;
368
369
}
//end doc
370
371
372
373
374
375
//==============start_run_it========================================
376
/// Run it
377
//==================================================================
378
template
<
class
ELEMENT>
379
void
CompressedSquareProblem<ELEMENT>::run_it
(
const
int
& i_case,
380
const
bool
& incompress)
381
{
382
383
// Set output directory
384
char
dirname[100];
385
snprintf(dirname,
sizeof
(dirname),
"RESLT%i"
,i_case);
386
Doc_info.set_directory(dirname);
387
388
// Open trace file
389
char
filename[100];
390
snprintf(filename,
sizeof
(filename),
"%s/trace.dat"
,Doc_info.directory().c_str());
391
Trace_file.open(filename);
392
393
394
// Doc initial configuration
395
doc_solution(incompress);
396
397
// Initial values for parameter values
398
Global_Physical_Variables::Gravity
=0.0;
399
400
//Parameter incrementation
401
unsigned
nstep=1;
402
double
g_increment=1.0e-2;
403
for
(
unsigned
i=0;i<nstep;i++)
404
{
405
// Bump up gravity
406
Global_Physical_Variables::Gravity
+=g_increment;
407
408
// Solve
409
newton_solve();
410
411
// Doc solution
412
doc_solution(incompress);
413
}
414
415
}
416
417
418
//=======start_of_main==================================================
419
/// Driver for compressed square
420
//======================================================================
421
int
main
()
422
{
423
424
//Flag to indicate if we want the material to be incompressible
425
bool
incompress=
false
;
426
427
// Label for different cases
428
int
case_number=-1;
429
430
// Generalised Hookean constitutive equations
431
//===========================================
432
{
433
// Nu values
434
Vector<double> nu_value(3);
435
nu_value[0]=0.45;
436
nu_value[1]=0.499999;
437
nu_value[2]=0.5;
438
439
// Loop over nu values
440
for
(
unsigned
i=0;i<3;i++)
441
{
442
// Set Poisson ratio
443
Global_Physical_Variables::Nu
=nu_value[i];
444
445
std::cout <<
"===========================================\n"
;
446
std::cout <<
"Doing Nu="
<<
Global_Physical_Variables::Nu
447
<< std::endl;
448
std::cout <<
"===========================================\n"
;
449
450
// Create constitutive equation
451
Global_Physical_Variables::Constitutive_law_pt
=
452
new
GeneralisedHookean(&
Global_Physical_Variables::Nu
);
453
454
// Displacement-based formulation
455
//--------------------------------
456
// (not for nu=1/2, obviously)
457
if
(i!=2)
458
{
459
case_number++;
460
std::cout
461
<<
"Doing Generalised Hookean with displacement formulation: Case "
462
<< case_number << std::endl;
463
464
//Set up the problem with pure displacement based elements
465
incompress=
false
;
466
CompressedSquareProblem<MySolidElement<QPVDElement<2,3>
> >
467
problem(incompress);
468
469
// Run it
470
problem.
run_it
(case_number,incompress);
471
}
472
473
474
// Generalised Hookean with continuous pressure, compressible
475
//-----------------------------------------------------------
476
{
477
case_number++;
478
std::cout
479
<<
"Doing Generalised Hookean with displacement/cont pressure "
480
<<
"formulation: Case "
<< case_number << std::endl;
481
482
//Set up the problem with continous pressure/displacement
483
incompress=
false
;
484
CompressedSquareProblem
<
MySolidElement
<
485
QPVDElementWithContinuousPressure<2> > >
486
problem(incompress);
487
488
// Run it
489
problem.run_it(case_number,incompress);
490
}
491
492
493
// Generalised Hookean with discontinuous pressure, compressible
494
//--------------------------------------------------------------
495
{
496
case_number++;
497
std::cout
498
<<
"Doing Generalised Hookean with displacement/discont pressure "
499
<<
"formulation: Case "
<< case_number << std::endl;
500
501
//Set up the problem with discontinous pressure/displacement
502
CompressedSquareProblem
<
MySolidElement
<
503
QPVDElementWithPressure<2> > > problem(incompress);
504
505
// Run it
506
problem.run_it(case_number,incompress);
507
}
508
509
510
511
// Generalised Hookean with continous pressure/displacement;
512
//----------------------------------------------------------
513
// incompressible
514
//---------------
515
{
516
case_number++;
517
std::cout
518
<<
"Doing Generalised Hookean with displacement/cont pressure, "
519
<<
"incompressible formulation: Case "
<< case_number << std::endl;
520
521
//Set up the problem with continous pressure/displacement
522
incompress=
true
;
523
CompressedSquareProblem
<
MySolidElement
<
524
QPVDElementWithContinuousPressure<2> > >
525
problem(incompress);
526
527
// Run it
528
problem.run_it(case_number,incompress);
529
}
530
531
532
// Generalised Hookean with discontinous pressure/displacement;
533
//-------------------------------------------------------------
534
// incompressible
535
//---------------
536
{
537
case_number++;
538
std::cout
539
<<
"Doing Generalised Hookean with displacement/discont pressure, "
540
<<
"incompressible formulation: Case "
<< case_number << std::endl;
541
542
//Set up the problem with discontinous pressure/displacement
543
incompress=
true
;
544
CompressedSquareProblem
<
MySolidElement
<
545
QPVDElementWithPressure<2> > > problem(incompress);
546
547
// Run it
548
problem.run_it(case_number,incompress);
549
}
550
551
// Clean up
552
delete
Global_Physical_Variables::Constitutive_law_pt
;
553
Global_Physical_Variables::Constitutive_law_pt
=0;
554
555
}
556
557
}
// end generalised Hookean
558
559
560
// Incompressible Mooney Rivlin
561
//=============================
562
{
563
564
// Create strain energy function
565
Global_Physical_Variables::Strain_energy_function_pt
=
566
new
MooneyRivlin(&
Global_Physical_Variables::C1
,
567
&
Global_Physical_Variables::C2
);
568
569
// Define a constitutive law (based on strain energy function)
570
Global_Physical_Variables::Constitutive_law_pt
=
571
new
IsotropicStrainEnergyFunctionConstitutiveLaw(
572
Global_Physical_Variables::Strain_energy_function_pt
);
573
574
575
// Mooney-Rivlin with continous pressure/displacement;
576
//----------------------------------------------------
577
// incompressible
578
//---------------
579
{
580
case_number++;
581
std::cout
582
<<
"Doing Mooney Rivlin with cont pressure formulation: Case "
583
<< case_number << std::endl;
584
585
//Set up the problem with continous pressure/displacement
586
incompress=
true
;
587
CompressedSquareProblem
<
MySolidElement
<
588
QPVDElementWithContinuousPressure<2> > >
589
problem(incompress);
590
591
// Run it
592
problem.run_it(case_number,incompress);
593
}
594
595
596
// Mooney-Rivlin with discontinous pressure/displacement;
597
//-------------------------------------------------------
598
// incompressible
599
//---------------
600
{
601
case_number++;
602
std::cout
603
<<
"Doing Mooney Rivlin with discont pressure formulation: Case "
604
<< case_number << std::endl;
605
606
//Set up the problem with discontinous pressure/displacement
607
incompress=
true
;
608
CompressedSquareProblem
<
MySolidElement
<
609
QPVDElementWithPressure<2> > >
610
problem(incompress);
611
612
// Run it
613
problem.run_it(case_number,incompress);
614
}
615
616
617
// Clean up
618
delete
Global_Physical_Variables::Strain_energy_function_pt
;
619
Global_Physical_Variables::Strain_energy_function_pt
=0;
620
621
delete
Global_Physical_Variables::Constitutive_law_pt
;
622
Global_Physical_Variables::Constitutive_law_pt
=0;
623
624
}
625
626
}
//end of main
627
628
629
630
631
632
633
634
CompressedSquareProblem
Problem class.
Definition
compressed_square.cc:149
CompressedSquareProblem::Trace_node_pt
Node * Trace_node_pt
Pointers to node whose position we're tracing.
Definition
compressed_square.cc:176
CompressedSquareProblem::run_it
void run_it(const int &i_case, const bool &incompress)
Run the job – doc in RESLTi_case.
Definition
compressed_square.cc:379
CompressedSquareProblem::Doc_info
DocInfo Doc_info
DocInfo object for output.
Definition
compressed_square.cc:179
CompressedSquareProblem::doc_solution
void doc_solution(const bool &incompress)
Doc the solution & exact (linear) solution for compressible or incompressible materials.
Definition
compressed_square.cc:284
CompressedSquareProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update function (empty)
Definition
compressed_square.cc:161
CompressedSquareProblem::CompressedSquareProblem
CompressedSquareProblem(const bool &incompress)
Constructor: Pass flag that determines if we want to use a true incompressible formulation.
Definition
compressed_square.cc:189
CompressedSquareProblem::Trace_file
ofstream Trace_file
Trace file.
Definition
compressed_square.cc:173
CompressedSquareProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update function (empty)
Definition
compressed_square.cc:158
oomph::MySolidElement
Wrapper class for solid element to modify the output.
Definition
compressed_square.cc:47
oomph::MySolidElement::output
void output(std::ostream &outfile, const unsigned &n_plot)
Overload output function.
Definition
compressed_square.cc:55
oomph::MySolidElement::MySolidElement
MySolidElement()
Constructor: Call constructor of underlying element.
Definition
compressed_square.cc:52
main
int main()
Driver for compressed square.
Definition
compressed_square.cc:421
Global_Physical_Variables
Global variables.
Definition
compressed_square.cc:111
Global_Physical_Variables::gravity
void gravity(const double &time, const Vector< double > &xi, Vector< double > &b)
Non-dimensional gravity as body force.
Definition
compressed_square.cc:132
Global_Physical_Variables::Constitutive_law_pt
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
Definition
compressed_square.cc:114
Global_Physical_Variables::Nu
double Nu
Poisson's ratio for Hooke's law.
Definition
compressed_square.cc:117
Global_Physical_Variables::Strain_energy_function_pt
StrainEnergyFunction * Strain_energy_function_pt
Pointer to strain energy function.
Definition
compressed_square.cc:120
Global_Physical_Variables::C1
double C1
First "Mooney Rivlin" coefficient for generalised Mooney Rivlin law.
Definition
compressed_square.cc:123
Global_Physical_Variables::Gravity
double Gravity
Non-dim gravity.
Definition
compressed_square.cc:129
Global_Physical_Variables::C2
double C2
Second "Mooney Rivlin" coefficient for generalised Mooney Rivlin law.
Definition
compressed_square.cc:126
oomph
Definition
compressed_square.cc:40