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
simple_shear
refineable_simple_shear.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 elastic deformation of a cuboidal domain
27
// This version tests refineable elements
28
// The deformation is a simple shear in the x-z plane driven by
29
// motion of the top boundary, which has an exact solution see Green & Zerna.
30
31
32
// Generic oomph-lib headers
33
#include "generic.h"
34
35
// Solid mechanics
36
#include "solid.h"
37
38
// The fish mesh
39
#include "meshes/simple_cubic_mesh.h"
40
41
using namespace
std;
42
43
using namespace
oomph;
44
45
46
///////////////////////////////////////////////////////////////////////
47
///////////////////////////////////////////////////////////////////////
48
///////////////////////////////////////////////////////////////////////
49
50
//=========================================================================
51
/// Simple cubic mesh upgraded to become a solid mesh
52
//=========================================================================
53
template
<
class
ELEMENT>
54
class
RefineableElasticCubicMesh
:
public
virtual
SimpleCubicMesh<ELEMENT>,
55
public
virtual
RefineableBrickMesh<ELEMENT>,
56
public
virtual
SolidMesh
57
{
58
59
public
:
60
61
/// Constructor:
62
RefineableElasticCubicMesh
(
const
unsigned
&nx,
const
unsigned
&ny,
63
const
unsigned
&nz,
64
const
double
&a,
const
double
&b,
65
const
double
&c,
66
TimeStepper* time_stepper_pt =
67
&Mesh::Default_TimeStepper) :
68
SimpleCubicMesh<ELEMENT>(nx,ny,nz,-a,a,-b,b,-c,c,time_stepper_pt),
69
RefineableBrickMesh<ELEMENT>(), SolidMesh()
70
{
71
72
this->setup_octree_forest();
73
//Assign the initial lagrangian coordinates
74
set_lagrangian_nodal_coordinates();
75
}
76
77
/// Empty Destructor
78
virtual
~RefineableElasticCubicMesh
() { }
79
80
};
81
82
83
84
85
///////////////////////////////////////////////////////////////////////
86
///////////////////////////////////////////////////////////////////////
87
///////////////////////////////////////////////////////////////////////
88
89
90
91
92
//================================================================
93
/// Global variables
94
//================================================================
95
namespace
Global_Physical_Variables
96
{
97
/// Pointer to strain energy function
98
StrainEnergyFunction*
Strain_energy_function_pt
;
99
100
/// Pointer to constitutive law
101
ConstitutiveLaw*
Constitutive_law_pt
;
102
103
/// Elastic modulus
104
double
E
=1.0;
105
106
/// Poisson's ratio
107
double
Nu
=0.3;
108
109
/// "Mooney Rivlin" coefficient for generalised Mooney Rivlin law
110
double
C1
=1.3;
111
112
/// Body force
113
double
Gravity
=0.0;
114
115
/// Body force vector: Vertically downwards with magnitude Gravity
116
void
body_force
(
const
Vector<double>& xi,
117
const
double
& t,
118
Vector<double>& b)
119
{
120
b[0]=0.0;
121
b[1]=-
Gravity
;
122
}
123
124
}
125
126
127
///////////////////////////////////////////////////////////////////////
128
///////////////////////////////////////////////////////////////////////
129
///////////////////////////////////////////////////////////////////////
130
131
132
133
//======================================================================
134
/// Boundary-driven elastic deformation of fish-shaped domain.
135
//======================================================================
136
template
<
class
ELEMENT>
137
class
SimpleShearProblem
:
public
Problem
138
{
139
double
Shear
;
140
141
void
set_incompressible
(ELEMENT *el_pt,
const
bool
&incompressible);
142
143
public
:
144
145
/// Constructor:
146
SimpleShearProblem
(
const
bool
&incompressible);
147
148
/// Run simulation.
149
void
run
(
const
std::string &dirname);
150
151
/// Access function for the mesh
152
RefineableElasticCubicMesh<ELEMENT>
*
mesh_pt
()
153
{
return
dynamic_cast<
RefineableElasticCubicMesh<ELEMENT>
*
>
154
(Problem::mesh_pt());}
155
156
/// Doc the solution
157
void
doc_solution
(DocInfo& doc_info);
158
159
/// Update function (empty)
160
void
actions_after_newton_solve
() {}
161
162
void
setup_boundary_conditions
()
163
{
164
//Loop over all boundaries
165
for
(
unsigned
b=0;b<6;b++)
166
{
167
//Loop over nodes in the boundary
168
unsigned
n_node =
mesh_pt
()->nboundary_node(b);
169
for
(
unsigned
n=0;n<n_node;n++)
170
{
171
//Pin all nodes in the y and z directions to keep the motion in plane
172
for
(
unsigned
i=1;i<3;i++)
173
{
174
mesh_pt
()->boundary_node_pt(b,n)->pin_position(i);
175
}
176
//On the top and bottom pin the positions in x
177
if
((b==0) || (b==5))
178
{
179
mesh_pt
()->boundary_node_pt(b,n)->pin_position(0);
180
}
181
}
182
}
183
184
// Pin the redundant solid pressures
185
PVDEquationsBase<3>::pin_redundant_nodal_solid_pressures(
186
mesh_pt
()->element_pt());
187
}
188
189
/// Need to pin the redundent solid pressures after adaptation
190
void
actions_after_adapt
()
191
{
192
//Re-pin the boundaries
193
//This is required because there is now the possibility that
194
//Nodes that were hanging on boundaries have become free and
195
//we can't do this automatically at the moment.
196
//setup_boundary_conditions();
197
198
// Pin the redundant solid pressures
199
PVDEquationsBase<3>::pin_redundant_nodal_solid_pressures(
200
mesh_pt
()->element_pt());
201
}
202
203
/// Update before solve: We're dealing with a static problem so
204
/// the nodal positions before the next solve merely serve as
205
/// initial conditions. For meshes that are very strongly refined
206
/// near the boundary, the update of the displacement boundary
207
/// conditions (which only moves the SolidNodes *on* the boundary),
208
/// can lead to strongly distorted meshes. This can cause the
209
/// Newton method to fail --> the overall method is actually more robust
210
/// if we use the nodal positions as determined by the Domain/MacroElement-
211
/// based mesh update as initial guesses.
212
void
actions_before_newton_solve
()
213
{
214
apply_boundary_conditions
();
215
bool
update_all_solid_nodes=
true
;
216
mesh_pt
()->node_update(update_all_solid_nodes);
217
}
218
219
/// Shear the top
220
void
apply_boundary_conditions
()
221
{
222
unsigned
ibound = 5;
223
unsigned
num_nod=
mesh_pt
()->nboundary_node(ibound);
224
for
(
unsigned
inod=0;inod<num_nod;inod++)
225
{
226
SolidNode *solid_nod_pt =
static_cast<
SolidNode*
>
(
227
mesh_pt
()->boundary_node_pt(ibound,inod));
228
229
solid_nod_pt->x(0) = solid_nod_pt->xi(0) +
Shear
*
230
solid_nod_pt->xi(2);
231
}
232
}
233
234
};
235
236
//======================================================================
237
/// Constructor:
238
//======================================================================
239
template
<
class
ELEMENT>
240
SimpleShearProblem<ELEMENT>::SimpleShearProblem
(
const
bool
&incompressible)
241
: Shear(0.0)
242
{
243
double
a = 1.0, b = 1.0, c = 1.0;
244
unsigned
nx = 2, ny = 2, nz = 2;
245
246
// Build fish mesh with geometric objects that specify the deformable
247
// and undeformed fish back
248
Problem::mesh_pt()=
new
RefineableElasticCubicMesh<ELEMENT>
(nx,ny,nz,a,b,c);
249
250
mesh_pt
()->spatial_error_estimator_pt() =
new
Z2ErrorEstimator;
251
252
253
//Loop over the elements in the mesh to set parameters/function pointers
254
unsigned
n_element =
mesh_pt
()->nelement();
255
for
(
unsigned
i=0;i<n_element;i++)
256
{
257
//Cast to a solid element
258
ELEMENT *el_pt =
dynamic_cast<
ELEMENT*
>
(
mesh_pt
()->element_pt(i));
259
260
// Set the constitutive law
261
el_pt->constitutive_law_pt() =
262
Global_Physical_Variables::Constitutive_law_pt
;
263
264
set_incompressible
(el_pt,incompressible);
265
266
// Set the body force
267
//el_pt->body_force_fct_pt()=Global_Physical_Variables::body_force;
268
}
269
270
setup_boundary_conditions
();
271
272
//Attach the boundary conditions to the mesh
273
cout << assign_eqn_numbers() << std::endl;
274
}
275
276
277
//==================================================================
278
/// Doc the solution
279
//==================================================================
280
template
<
class
ELEMENT>
281
void
SimpleShearProblem<ELEMENT>::doc_solution
(DocInfo& doc_info)
282
{
283
284
ofstream some_file;
285
char
filename[100];
286
287
// Number of plot points
288
unsigned
npts = 5;
289
290
// Output shape of deformed body
291
snprintf(filename,
sizeof
(filename),
"%s/soln%i.dat"
,doc_info.directory().c_str(),
292
doc_info.number());
293
some_file.open(filename);
294
mesh_pt()->output(some_file,npts);
295
some_file.close();
296
297
snprintf(filename,
sizeof
(filename),
"%s/stress%i.dat"
, doc_info.directory().c_str(),
298
doc_info.number());
299
some_file.open(filename);
300
//Output the appropriate stress at the centre of each element
301
Vector<double> s(3,0.0);
302
Vector<double> x(3);
303
DenseMatrix<double> sigma(3,3);
304
305
unsigned
n_element = mesh_pt()->nelement();
306
for
(
unsigned
e=0;e<n_element;e++)
307
{
308
ELEMENT* el_pt =
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(e));
309
el_pt->interpolated_x(s,x);
310
el_pt->get_stress(s,sigma);
311
312
//Output
313
for
(
unsigned
i=0;i<3;i++)
314
{
315
some_file << x[i] <<
" "
;
316
}
317
for
(
unsigned
i=0;i<3;i++)
318
{
319
for
(
unsigned
j=0;j<3;j++)
320
{
321
some_file << sigma(i,j) <<
" "
;
322
}
323
}
324
some_file << std::endl;
325
}
326
some_file.close();
327
328
}
329
330
331
//==================================================================
332
/// Run the problem
333
//==================================================================
334
template
<
class
ELEMENT>
335
void
SimpleShearProblem<ELEMENT>::run
(
const
std::string &dirname)
336
{
337
338
// Output
339
DocInfo doc_info;
340
341
// Set output directory
342
doc_info.set_directory(dirname);
343
344
// Step number
345
doc_info.number()=0;
346
347
// Initial parameter values
348
349
// Gravity:
350
Global_Physical_Variables::Gravity
=0.1;
351
352
353
354
//Parameter incrementation
355
unsigned
nstep=2;
356
for
(
unsigned
i=0;i<nstep;i++)
357
{
358
//Solve the problem with Newton's method, allowing for up to one
359
//rounds of adaptation
360
//newton_solve(1);
361
362
//Refine according to a pattern
363
Vector<unsigned> refine_pattern(2);
364
refine_pattern[0] = 0; refine_pattern[1] = 7;
365
refine_selected_elements(refine_pattern);
366
367
//Solve it
368
newton_solve();
369
// Doc solution
370
doc_solution(doc_info);
371
doc_info.number()++;
372
//Increase the shear
373
Shear += 0.25;
374
}
375
376
}
377
378
template
<
class
ELEMENT>
379
void
SimpleShearProblem<ELEMENT>::set_incompressible
(
380
ELEMENT *el_pt,
const
bool
&incompressible)
381
{
382
//Does nothing
383
}
384
385
386
template
<>
387
void
SimpleShearProblem<QPVDElementWithPressure<3>
>::set_incompressible(
388
QPVDElementWithPressure<3> *el_pt,
const
bool
&incompressible)
389
{
390
if
(incompressible) {el_pt->
set_incompressible
();}
391
else
{el_pt->set_compressible();}
392
}
393
394
template
<>
395
void
SimpleShearProblem<QPVDElementWithContinuousPressure<3>
>::
396
set_incompressible(
397
QPVDElementWithContinuousPressure<3> *el_pt,
const
bool
&incompressible)
398
{
399
if
(incompressible) {el_pt->
set_incompressible
();}
400
else
{el_pt->set_compressible();}
401
}
402
403
404
//======================================================================
405
/// Driver for simple elastic problem
406
//======================================================================
407
int
main
()
408
{
409
410
//Initialise physical parameters
411
Global_Physical_Variables::E
= 2.1;
412
Global_Physical_Variables::Nu
= 0.4;
413
Global_Physical_Variables::C1
= 1.3;
414
415
416
// Define a strain energy function: Generalised Mooney Rivlin
417
Global_Physical_Variables::Strain_energy_function_pt
=
418
new
GeneralisedMooneyRivlin(&
Global_Physical_Variables::Nu
,
419
&
Global_Physical_Variables::C1
,
420
&
Global_Physical_Variables::E
);
421
422
// Define a constitutive law (based on strain energy function)
423
Global_Physical_Variables::Constitutive_law_pt
=
424
new
IsotropicStrainEnergyFunctionConstitutiveLaw(
425
Global_Physical_Variables::Strain_energy_function_pt
);
426
427
{
428
//Set up the problem with pure displacement formulation
429
SimpleShearProblem<RefineableQPVDElement<3,3>
> problem(
false
);
430
problem.
run
(
"RESLT_ref"
);
431
}
432
433
{
434
//Set up the problem with displacement and pressure
435
SimpleShearProblem<RefineableQPVDElementWithPressure<3>
> problem(
false
);
436
problem.
run
(
"RESLT_pres_ref"
);
437
}
438
439
{
440
//Set up the problem with displacement and continuous pressure
441
SimpleShearProblem<RefineableQPVDElementWithContinuousPressure<3>
>
442
problem(
false
);
443
problem.
run
(
"RESLT_cont_pres_ref"
);
444
}
445
446
447
448
}
449
450
451
452
453
RefineableElasticCubicMesh
Simple cubic mesh upgraded to become a solid mesh.
Definition
refineable_simple_shear.cc:57
RefineableElasticCubicMesh::~RefineableElasticCubicMesh
virtual ~RefineableElasticCubicMesh()
Empty Destructor.
Definition
refineable_simple_shear.cc:78
RefineableElasticCubicMesh::RefineableElasticCubicMesh
RefineableElasticCubicMesh(const unsigned &nx, const unsigned &ny, const unsigned &nz, const double &a, const double &b, const double &c, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor:
Definition
refineable_simple_shear.cc:62
SimpleShearProblem
Boundary-driven elastic deformation of fish-shaped domain.
Definition
refineable_simple_shear.cc:138
SimpleShearProblem::apply_boundary_conditions
void apply_boundary_conditions()
Shear the top.
Definition
refineable_simple_shear.cc:220
SimpleShearProblem::setup_boundary_conditions
void setup_boundary_conditions()
Definition
refineable_simple_shear.cc:162
SimpleShearProblem::doc_solution
void doc_solution(DocInfo &doc_info)
Doc the solution.
Definition
refineable_simple_shear.cc:281
SimpleShearProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update before solve: We're dealing with a static problem so the nodal positions before the next solve...
Definition
refineable_simple_shear.cc:212
SimpleShearProblem::Shear
double Shear
Definition
refineable_simple_shear.cc:139
SimpleShearProblem::set_incompressible
void set_incompressible(ELEMENT *el_pt, const bool &incompressible)
Definition
refineable_simple_shear.cc:379
SimpleShearProblem::mesh_pt
RefineableElasticCubicMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
Definition
refineable_simple_shear.cc:152
SimpleShearProblem::actions_after_adapt
void actions_after_adapt()
Need to pin the redundent solid pressures after adaptation.
Definition
refineable_simple_shear.cc:190
SimpleShearProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update function (empty)
Definition
refineable_simple_shear.cc:160
SimpleShearProblem::run
void run(const std::string &dirname)
Run simulation.
Definition
refineable_simple_shear.cc:335
SimpleShearProblem::SimpleShearProblem
SimpleShearProblem(const bool &incompressible)
Constructor:
Definition
refineable_simple_shear.cc:240
Global_Physical_Variables
Global variables.
Definition
refineable_simple_shear.cc:96
Global_Physical_Variables::body_force
void body_force(const Vector< double > &xi, const double &t, Vector< double > &b)
Body force vector: Vertically downwards with magnitude Gravity.
Definition
refineable_simple_shear.cc:116
Global_Physical_Variables::E
double E
Elastic modulus.
Definition
refineable_simple_shear.cc:104
Global_Physical_Variables::Nu
double Nu
Poisson's ratio.
Definition
refineable_simple_shear.cc:107
Global_Physical_Variables::Constitutive_law_pt
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
Definition
refineable_simple_shear.cc:101
Global_Physical_Variables::C1
double C1
"Mooney Rivlin" coefficient for generalised Mooney Rivlin law
Definition
refineable_simple_shear.cc:110
Global_Physical_Variables::Gravity
double Gravity
Body force.
Definition
refineable_simple_shear.cc:113
Global_Physical_Variables::Strain_energy_function_pt
StrainEnergyFunction * Strain_energy_function_pt
Pointer to strain energy function.
Definition
refineable_simple_shear.cc:98
main
int main()
Driver for simple elastic problem.
Definition
refineable_simple_shear.cc:407