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
beam
steady_ring
steady_ring.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 function for a simple test ring problem with/without
27
//diplacement control
28
29
//Generic oomph-lib sources
30
#include "generic.h"
31
32
// Beam sources
33
#include "beam.h"
34
35
// The mesh
36
#include "meshes/one_d_lagrangian_mesh.h"
37
38
using namespace
std;
39
40
using namespace
oomph;
41
42
43
//=======start_of_namespace=========================
44
/// Namespace for physical parameters
45
//==================================================
46
namespace
Global_Physical_Variables
47
{
48
49
/// Nondim thickness
50
double
H
=0.05;
51
52
/// Prescribed position (only used for displacement control)
53
double
Xprescr
= 1.0;
54
55
/// Perturbation pressure
56
double
Pcos
=0.0;
57
58
/// Pointer to pressure load (stored in Data so it can
59
/// become an unknown in the problem when displacement control is used
60
Data*
Pext_data_pt
;
61
62
/// Load function: Constant external pressure with cos variation to
63
/// induce buckling in n=2 mode
64
void
press_load
(
const
Vector<double>& xi,
65
const
Vector<double> &x,
66
const
Vector<double>& N,
67
Vector<double>& load)
68
{
69
for
(
unsigned
i=0;i<2;i++)
70
{
71
load[i] = (
Pext_data_pt
->value(0)-
Pcos
*cos(2.0*xi[0]))*N[i];
72
}
73
}
74
75
/// Return a reference to the external pressure
76
/// load on the elastic ring.
77
/// A reference is obtained by de-referencing the pointer to the
78
/// data value that contains the external load
79
double
&
external_pressure
()
80
{
return
*
Pext_data_pt
->value_pt(0);}
81
82
83
}
// end of namespace
84
85
86
87
/////////////////////////////////////////////////////////////////////
88
/////////////////////////////////////////////////////////////////////
89
/////////////////////////////////////////////////////////////////////
90
91
92
93
//========start_of_problem_class========================================
94
/// Ring problem
95
//======================================================================
96
template
<
class
ELEMENT>
97
class
ElasticRingProblem
:
public
Problem
98
{
99
100
public
:
101
102
/// Constructor: Number of elements and flags for displ control
103
/// and displacement control with existing data respectively.
104
ElasticRingProblem
(
const
unsigned
&n_element,
105
bool
& displ_control,
106
bool
& load_data_already_exists);
107
108
/// Access function for the specific mesh
109
OneDLagrangianMesh<ELEMENT>*
mesh_pt
()
110
{
111
return
dynamic_cast<
OneDLagrangianMesh<ELEMENT>*
>
(Problem::mesh_pt());
112
}
113
114
/// Update function is empty
115
void
actions_after_newton_solve
() {}
116
117
/// Update function is empty
118
void
actions_before_newton_solve
() {}
119
120
/// Doc solution
121
void
doc_solution
(DocInfo& doc_info, ofstream& trace_file);
122
123
/// Perform the parameter study
124
void
parameter_study
(DocInfo& doc_info);
125
126
private
:
127
128
/// Use displacement control?
129
bool
Displ_control
;
130
131
/// Pointer to geometric object that represents the undeformed shape
132
GeomObject*
Undef_geom_pt
;
133
134
/// Number of elements in the beam mesh
135
unsigned
Nbeam_element
;
136
137
};
// end of problem class
138
139
140
141
142
143
144
145
//======start_of_constructor============================================
146
/// Constructor for elastic ring problem
147
//======================================================================
148
template
<
class
ELEMENT>
149
ElasticRingProblem<ELEMENT>::ElasticRingProblem
150
(
const
unsigned
& n_element,
bool
& displ_control,
bool
& load_data_already_exists) :
151
Displ_control(displ_control),Nbeam_element(n_element)
152
{
153
154
// Undeformed beam is an elliptical ring
155
Undef_geom_pt
=
new
Ellipse(1.0,1.0);
156
157
// Length of the doamin (in terms of the Lagrangian coordinates)
158
double
length=2.0*atan(1.0);
159
160
//Now create the (Lagrangian!) mesh
161
Problem::mesh_pt() =
162
new
OneDLagrangianMesh<ELEMENT>(n_element,length,
Undef_geom_pt
);
163
164
// Boundary condition:
165
166
// Bottom:
167
unsigned
ibound=0;
168
// No vertical displacement
169
mesh_pt
()->boundary_node_pt(ibound,0)->pin_position(1);
170
// Infinite slope: Pin type 1 (slope) dof for displacement direction 0
171
mesh_pt
()->boundary_node_pt(ibound,0)->pin_position(1,0);
172
173
// Top:
174
ibound=1;
175
// No horizontal displacement
176
mesh_pt
()->boundary_node_pt(ibound,0)->pin_position(0);
177
// Zero slope: Pin type 1 (slope) dof for displacement direction 1
178
mesh_pt
()->boundary_node_pt(ibound,0)->pin_position(1,1);
179
180
181
// Normal load incrementation
182
//===========================
183
if
(!
Displ_control
)
184
{
185
// Create Data object whose one-and-only value contains the
186
// (in principle) adjustable load
187
Global_Physical_Variables::Pext_data_pt
=
new
Data(1);
188
189
//Pin the external pressure because it isn't actually adjustable.
190
Global_Physical_Variables::Pext_data_pt
->pin(0);
191
}
192
// Displacement control
193
//=====================
194
else
195
{
196
// Choose element in which displacement control is applied: the last one
197
SolidFiniteElement* controlled_element_pt=
198
dynamic_cast<
ELEMENT*
>
(
mesh_pt
()->element_pt(
Nbeam_element
-1));
199
200
// Fix the displacement in the vertical (1) direction...
201
unsigned
controlled_direction=1;
202
203
//... at right end of the control element
204
Vector<double> s_displ_control(1);
205
s_displ_control[0]=1.0;
206
207
// Pointer to displacement control element
208
DisplacementControlElement* displ_control_el_pt;
209
210
// Displacement control without previously existing load Data
211
//-----------------------------------------------------------
212
if
(!load_data_already_exists)
213
{
214
// Build displacement control element
215
displ_control_el_pt=
216
new
DisplacementControlElement(controlled_element_pt,
217
s_displ_control,
218
controlled_direction,
219
&
Global_Physical_Variables::Xprescr
);
220
221
// The constructor of the DisplacementControlElement has created
222
// a new Data object whose one-and-only value contains the
223
// adjustable load: Use this Data object in the load function:
224
Global_Physical_Variables::Pext_data_pt
=displ_control_el_pt->
225
displacement_control_load_pt();
226
}
227
// Demonstrate use of displacement control with some existing data
228
//----------------------------------------------------------------
229
else
230
{
231
// Create Data object whose one-and-only value contains the
232
// adjustable load
233
Global_Physical_Variables::Pext_data_pt
=
new
Data(1);
234
235
// Currently, nobody's "in charge of" this Data so it won't
236
// get included in any equation numbering schemes etc.
237
// --> declare it to be "global Data" for the Problem
238
// so the Problem is in charge and will perform such tasks.
239
add_global_data(
Global_Physical_Variables::Pext_data_pt
);
240
241
// Build displacement control element and pass pointer to the
242
// already existing adjustable load Data.
243
displ_control_el_pt=
244
new
DisplacementControlElement(controlled_element_pt,
245
s_displ_control,
246
controlled_direction,
247
&
Global_Physical_Variables::Xprescr
,
248
Global_Physical_Variables::Pext_data_pt
);
249
}
250
251
// Add the displacement-control element to the mesh
252
mesh_pt
()->add_element_pt(displ_control_el_pt);
253
}
254
255
256
257
258
//Loop over the elements to set physical parameters etc.
259
for
(
unsigned
i=0;i<
Nbeam_element
;i++)
260
{
261
//Cast to proper element type
262
ELEMENT *elem_pt =
dynamic_cast<
ELEMENT*
>
(
mesh_pt
()->element_pt(i));
263
264
// Set wall thickness
265
elem_pt->h_pt() = &
Global_Physical_Variables::H
;
266
267
// Function that specifies load Vector
268
elem_pt->load_vector_fct_pt() = &
Global_Physical_Variables::press_load
;
269
270
//Assign the undeformed beam shape
271
elem_pt->undeformed_beam_pt() =
Undef_geom_pt
;
272
273
// Displacement control? If so, the load on *all* elements
274
// is affected by an unknown -- the external pressure, stored
275
// as the one-and-only value in a Data object: Add it to the
276
// elements' external Data.
277
if
(
Displ_control
)
278
{
279
//The external pressure is external data for all elements
280
elem_pt->add_external_data(
Global_Physical_Variables::Pext_data_pt
);
281
}
282
}
283
284
// Do equation numbering
285
cout <<
"# of dofs "
<< assign_eqn_numbers() << std::endl;
286
287
}
// end of constructor
288
289
290
//=======start_of_doc=====================================================
291
/// Document solution
292
//========================================================================
293
template
<
class
ELEMENT>
294
void
ElasticRingProblem<ELEMENT>::doc_solution
(DocInfo& doc_info,
295
ofstream& trace_file)
296
{
297
ofstream some_file;
298
char
filename[100];
299
300
// Number of plot points
301
unsigned
npts=5;
302
303
// Output solution
304
snprintf(filename,
sizeof
(filename),
"%s/ring%i.dat"
,doc_info.directory().c_str(),
305
doc_info.number());
306
some_file.open(filename);
307
mesh_pt()->output(some_file,npts);
308
some_file.close();
309
310
// Local coordinates of plot points at left and right end of domain
311
Vector<double> s_left(1);
312
s_left[0]=-1.0;
313
Vector<double> s_right(1);
314
s_right[0]=1.0;
315
316
// Write trace file: Pressure, two radii
317
trace_file
318
<<
Global_Physical_Variables::Pext_data_pt
->value(0)/
319
(pow(
Global_Physical_Variables::H
,3)/12.0)
320
<<
" "
321
<<
dynamic_cast<
ELEMENT*
>
(mesh_pt()->
322
element_pt(0))->interpolated_x(s_left,0)
323
<<
" "
324
<<
dynamic_cast<
ELEMENT*
>
325
(mesh_pt()->element_pt(Nbeam_element-1))->interpolated_x(s_right,1)
326
<< std::endl;
327
328
329
}
// end of doc
330
331
332
333
//========start_of_run=====================================================
334
/// Solver loop to perform parameter study
335
//=========================================================================
336
template
<
class
ELEMENT>
337
void
ElasticRingProblem<ELEMENT>::parameter_study
(DocInfo& doc_info)
338
{
339
340
//Open a trace file
341
char
filename[100];
342
snprintf(filename,
sizeof
(filename),
"%s/trace.dat"
,doc_info.directory().c_str());
343
ofstream trace_file(filename);
344
trace_file <<
"VARIABLES=\"p_e_x_t\",\"R_1\",\"R_2\""
<< std::endl;
345
trace_file <<
"ZONE"
<< std::endl;
346
347
//Output initial data
348
doc_solution(doc_info,trace_file);
349
350
// Number of steps
351
unsigned
nstep= 11;
//51;
352
353
// Increments
354
double
displ_increment=1.0/double(nstep-1);
355
double
p_buckl=3.00*pow(
Global_Physical_Variables::H
,3)/12.0;
356
double
p_owc =5.22*pow(
Global_Physical_Variables::H
,3)/12.0;
357
double
pext_increment=(p_owc-p_buckl)/
double
(nstep-1);
358
359
// Set initial values for parameters that are to be incremented
360
Global_Physical_Variables::Xprescr
=1.0+displ_increment;
361
Global_Physical_Variables::Pext_data_pt
->set_value(0,p_buckl-pext_increment);
362
363
364
365
// Without displacement control the Newton method converges very slowly
366
// as we approach the axisymmetric state: Allow more iterations before
367
// calling it a day...
368
if
(Displ_control)
369
{
370
Max_newton_iterations=100;
371
}
372
373
374
// Downward loop over parameter incrementation with pcos>0
375
//--------------------------------------------------------
376
377
/// Perturbation pressure
378
Global_Physical_Variables::Pcos
=1.0e-5;
379
380
381
// Downward loop over parameter incrementation
382
//---------------------------------------------
383
for
(
unsigned
i=1;i<=nstep;i++)
384
{
385
386
// Displacement control?
387
if
(!Displ_control)
388
{
389
// Increment pressure
390
Global_Physical_Variables::external_pressure
() += pext_increment;
391
}
392
else
393
{
394
// Increment control displacement
395
Global_Physical_Variables::Xprescr
-=displ_increment;
396
}
397
398
// Solve
399
newton_solve();
400
401
// Doc solution
402
doc_info.number()++;
403
doc_solution(doc_info,trace_file);
404
405
}
// end of downward loop
406
407
// Reset perturbation pressure
408
//----------------------------
409
Global_Physical_Variables::Pcos
=0.0;
410
411
// Set initial values for parameters that are to be incremented
412
Global_Physical_Variables::Xprescr
-=displ_increment;
413
Global_Physical_Variables::external_pressure
() += pext_increment;
414
415
// Start new zone for tecplot
416
trace_file <<
"ZONE"
<< std::endl;
417
418
// Upward loop over parameter incrementation
419
//------------------------------------------
420
for
(
unsigned
i=nstep;i<2*nstep;i++)
421
{
422
423
// Displacement control?
424
if
(!Displ_control)
425
{
426
// Increment pressure
427
Global_Physical_Variables::external_pressure
() -= pext_increment;
428
}
429
else
430
{
431
// Increment control displacement
432
Global_Physical_Variables::Xprescr
+=displ_increment;
433
}
434
435
// Solve
436
newton_solve();
437
438
// Doc solution
439
doc_info.number()++;
440
doc_solution(doc_info,trace_file);
441
442
}
443
444
}
// end of run
445
446
447
448
////////////////////////////////////////////////////////////////////////
449
////////////////////////////////////////////////////////////////////////
450
////////////////////////////////////////////////////////////////////////
451
452
453
//=======start_of_main=================================================
454
/// Driver for ring test problem
455
//=====================================================================
456
int
main
()
457
{
458
// Number of elements
459
unsigned
n_element = 13;
460
461
// Displacement control?
462
bool
displ_control=
true
;
463
464
// Label for output
465
DocInfo doc_info;
466
467
// Demonstrate how to use displacement control with already existing load Data
468
//----------------------------------------------------------------------------
469
{
470
bool
load_data_already_exists=
true
;
471
472
//Set up the problem
473
ElasticRingProblem<HermiteBeamElement>
474
problem(n_element,displ_control,load_data_already_exists);
475
476
// Output directory
477
doc_info.set_directory(
"RESLT_global"
);
478
479
// Do static run
480
problem.
parameter_study
(doc_info);
481
}
482
483
// Demonstrate how to use displacement control without existing load Data
484
//-----------------------------------------------------------------------
485
{
486
bool
load_data_already_exists=
false
;
487
488
//Set up the problem
489
ElasticRingProblem<HermiteBeamElement>
490
problem(n_element,displ_control,load_data_already_exists);
491
492
// Output directory
493
doc_info.set_directory(
"RESLT_no_global"
);
494
495
// Reset counter
496
doc_info.number()=0;
497
498
// Do static run
499
problem.
parameter_study
(doc_info);
500
}
501
502
}
// end of main
503
504
505
506
507
508
ElasticRingProblem
Ring problem.
Definition
steady_ring.cc:98
ElasticRingProblem::Undef_geom_pt
GeomObject * Undef_geom_pt
Pointer to geometric object that represents the undeformed shape.
Definition
steady_ring.cc:132
ElasticRingProblem::mesh_pt
OneDLagrangianMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
Definition
steady_ring.cc:109
ElasticRingProblem::ElasticRingProblem
ElasticRingProblem(const unsigned &n_element, bool &displ_control, bool &load_data_already_exists)
Constructor: Number of elements and flags for displ control and displacement control with existing da...
Definition
steady_ring.cc:150
ElasticRingProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update function is empty.
Definition
steady_ring.cc:115
ElasticRingProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update function is empty.
Definition
steady_ring.cc:118
ElasticRingProblem::Displ_control
bool Displ_control
Use displacement control?
Definition
steady_ring.cc:129
ElasticRingProblem::Nbeam_element
unsigned Nbeam_element
Number of elements in the beam mesh.
Definition
steady_ring.cc:135
ElasticRingProblem::doc_solution
void doc_solution(DocInfo &doc_info, ofstream &trace_file)
Doc solution.
Definition
steady_ring.cc:294
ElasticRingProblem::parameter_study
void parameter_study(DocInfo &doc_info)
Perform the parameter study.
Definition
steady_ring.cc:337
Global_Physical_Variables
Namespace for physical parameters.
Definition
steady_ring.cc:47
Global_Physical_Variables::Xprescr
double Xprescr
Prescribed position (only used for displacement control)
Definition
steady_ring.cc:53
Global_Physical_Variables::press_load
void press_load(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &N, Vector< double > &load)
Load function: Constant external pressure with cos variation to induce buckling in n=2 mode.
Definition
steady_ring.cc:64
Global_Physical_Variables::Pext_data_pt
Data * Pext_data_pt
Pointer to pressure load (stored in Data so it can become an unknown in the problem when displacement...
Definition
steady_ring.cc:60
Global_Physical_Variables::Pcos
double Pcos
Perturbation pressure.
Definition
steady_ring.cc:56
Global_Physical_Variables::external_pressure
double & external_pressure()
Return a reference to the external pressure load on the elastic ring. A reference is obtained by de-r...
Definition
steady_ring.cc:79
Global_Physical_Variables::H
double H
Nondim thickness.
Definition
steady_ring.cc:50
main
int main()
Driver for ring test problem.
Definition
steady_ring.cc:456