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
interaction
free_boundary_poisson
elastic_mesh_update.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
// Solve Poisson equation in deformable fish-shaped domain.
27
// Mesh deformation is driven by pseudo-elasticity approach.
28
29
// Generic oomph-lib headers
30
#include "generic.h"
31
32
// Poisson equations
33
#include "poisson.h"
34
35
// Solid mechanics
36
#include "solid.h"
37
38
// The fish mesh
39
#include "meshes/fish_mesh.h"
40
41
using namespace
std;
42
43
using namespace
oomph
;
44
45
///////////////////////////////////////////////////////////////////////
46
///////////////////////////////////////////////////////////////////////
47
///////////////////////////////////////////////////////////////////////
48
49
50
51
//====================================================================
52
/// Namespace for const source term in Poisson equation
53
//====================================================================
54
namespace
ConstSourceForPoisson
55
{
56
/// Strength of source function: default value 1.0
57
double
Strength
=1.0;
58
59
/// Const source function
60
void
get_source
(
const
Vector<double>
&
x
,
double
&
source
)
61
{
62
source
= -
Strength
;
63
}
64
65
}
66
67
///////////////////////////////////////////////////////////////////////
68
///////////////////////////////////////////////////////////////////////
69
///////////////////////////////////////////////////////////////////////
70
71
//=========================================================================
72
/// Refineable fish mesh upgraded to become a solid mesh
73
//=========================================================================
74
template
<
class
ELEMENT>
75
class
ElasticFishMesh
:
public
virtual
RefineableFishMesh<ELEMENT>,
76
public
virtual
SolidMesh
77
{
78
79
public
:
80
81
/// Constructor: Build underlying adaptive fish mesh and then
82
/// set current Eulerian coordinates to be the Lagrangian ones.
83
/// Pass pointer to geometric objects that specify the
84
/// fish's back in the "current" and "undeformed" configurations,
85
/// and pointer to timestepper (defaults to Static)
86
// Note: FishMesh is virtual base and its constructor is automatically
87
// called first! --> this is where we need to build the mesh;
88
// the constructors of the derived meshes don't call the
89
// base constructor again and simply add the extra functionality.
90
ElasticFishMesh
(GeomObject*
back_pt
, GeomObject*
undeformed_back_pt
,
91
TimeStepper
*
time_stepper_pt
=&Mesh::Default_TimeStepper) :
92
FishMesh<
ELEMENT
>(
back_pt
,
time_stepper_pt
),
93
RefineableFishMesh<
ELEMENT
>(
back_pt
,
time_stepper_pt
)
94
{
95
// Mesh has been built, adaptivity etc has been set up -->
96
// assign the Lagrangian coordinates so that the current
97
// configuration becomes the stress-free initial configuration
98
set_lagrangian_nodal_coordinates
();
99
100
// Build "undeformed" domain: This is a "deep" copy of the
101
// Domain that we used to create set the Eulerian coordinates
102
// in the initial mesh -- the original domain (accessible via
103
// the private member data Domain_pt) will be used to update
104
// the position of boundary nodes; the copy that we're
105
// creating here will be used to determine the Lagrangian coordinates
106
// of any newly created SolidNodes during mesh refinement
107
double
xi_nose
= this->
Domain_pt
->xi_nose();
108
double
xi_tail
= this->
Domain_pt
->xi_tail();
109
Undeformed_domain_pt
=
new
FishDomain
(undeformed_back_pt,
xi_nose
,
xi_tail
);
110
111
// Loop over all elements and set the undeformed macro element pointer
112
unsigned
n_element
=this->
nelement
();
113
for
(
unsigned
e
=0;
e
<
n_element
;
e
++)
114
{
115
// Get pointer to full element type
116
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(this->
element_pt
(
e
));
117
118
// Set pointer to macro element so the curvlinear boundaries
119
// of the undeformed mesh/domain get picked up during adaptive
120
// mesh refinement
121
el_pt->set_undeformed_macro_elem_pt(
122
Undeformed_domain_pt
->macro_element_pt(
e
));
123
}
124
125
}
126
127
/// Destructor: Kill "undeformed" Domain
128
virtual
~ElasticFishMesh
()
129
{
130
delete
Undeformed_domain_pt
;
131
}
132
133
private
:
134
135
/// Pointer to "undeformed" Domain -- used to determine the
136
/// Lagrangian coordinates of any newly created SolidNodes during
137
/// Mesh refinement
138
Domain
*
Undeformed_domain_pt
;
139
140
};
141
142
143
144
145
///////////////////////////////////////////////////////////////////////
146
///////////////////////////////////////////////////////////////////////
147
///////////////////////////////////////////////////////////////////////
148
149
150
151
152
//================================================================
153
/// Global variables
154
//================================================================
155
namespace
Global_Physical_Variables
156
{
157
/// Pointer to constitutive law
158
ConstitutiveLaw
*
Constitutive_law_pt
;
159
160
/// Poisson's ratio
161
double
Nu
=0.3;
162
163
}
164
165
166
///////////////////////////////////////////////////////////////////////
167
///////////////////////////////////////////////////////////////////////
168
///////////////////////////////////////////////////////////////////////
169
170
171
172
//======================================================================
173
/// Solve Poisson equation on deforming fish-shaped domain.
174
/// Mesh update via pseudo-elasticity.
175
//======================================================================
176
template
<
class
ELEMENT>
177
class
DeformableFishPoissonProblem
:
public
Problem
178
{
179
180
public
:
181
182
/// Constructor:
183
DeformableFishPoissonProblem
();
184
185
/// Run simulation
186
void
run
();
187
188
/// Access function for the specific mesh
189
ElasticFishMesh<ELEMENT>
*
mesh_pt
()
190
{
return
dynamic_cast<
ElasticFishMesh<ELEMENT>
*
>
(Problem::mesh_pt());}
191
192
/// Doc the solution
193
void
doc_solution
(
DocInfo
& doc_info);
194
195
/// Update function (empty)
196
void
actions_after_newton_solve
() {}
197
198
/// Update before solve: We're dealing with a static problem so
199
/// the nodal positions before the next solve merely serve as
200
/// initial conditions. For meshes that are very strongly refined
201
/// near the boundary, the update of the displacement boundary
202
/// conditions (which only moves the SolidNodes *on* the boundary),
203
/// can lead to strongly distorted meshes. This can cause the
204
/// Newton method to fail --> the overall method is actually more robust
205
/// if we use the nodal positions as determined by the Domain/MacroElement-
206
/// based mesh update as initial guesses.
207
void
actions_before_newton_solve
()
208
{
209
bool
update_all_solid_nodes
=
true
;
210
mesh_pt
()->node_update(
update_all_solid_nodes
);
211
212
// Now set the Eulerian equal to the Lagrangian coordinates
213
mesh_pt
()->set_lagrangian_nodal_coordinates();
214
215
}
216
217
/// Update after adapt: Pin all redundant solid pressure nodes (if required)
218
void
actions_after_adapt
()
219
{
220
// Pin the redundant solid pressures (if any)
221
PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
222
mesh_pt
()->
element_pt
());
223
}
224
225
private
:
226
227
228
/// Node at which the solution of the Poisson equation is documented
229
Node
*
Doc_node_pt
;
230
231
/// Trace file
232
ofstream
Trace_file
;
233
234
// Geometric object that represents the deformable fish back
235
Circle
*
Fish_back_pt
;
236
237
};
238
239
//======================================================================
240
/// Constructor:
241
//======================================================================
242
template
<
class
ELEMENT>
243
DeformableFishPoissonProblem<ELEMENT>::DeformableFishPoissonProblem
()
244
{
245
246
// Set coordinates and radius for the circle that will become the fish back
247
double
x_c=0.5;
248
double
y_c=0.0;
249
double
r_back
=1.0;
250
251
// Build geometric object that will become the deformable fish back
252
//GeomObject* fish_back_pt=new ElasticFishBackElement(x_c,y_c,r_back);
253
Fish_back_pt=
new
Circle
(x_c,y_c,
r_back
);
254
255
// Build geometric object that specifies the fish back in the
256
// undeformed configuration (basically a deep copy of the previous one)
257
GeomObject*
undeformed_fish_back_pt
=
new
Circle
(x_c,y_c,
r_back
);
258
259
// Build fish mesh with geometric object that specifies the deformable
260
// and undeformed fish back
261
Problem::mesh_pt()=
new
ElasticFishMesh<ELEMENT>
(Fish_back_pt,
262
undeformed_fish_back_pt
);
263
264
265
// Choose a node at which the solution is documented: Choose
266
// the central node that is shared by all four elements in
267
// the base mesh because it exists at all refinement levels.
268
269
// How many nodes does element 0 have?
270
unsigned
nnod
=mesh_pt()->finite_element_pt(0)->nnode();
271
272
// The central node is the last node in element 0:
273
Doc_node_pt=mesh_pt()->finite_element_pt(0)->node_pt(
nnod
-1);
274
275
// Doc
276
cout
<< std::endl <<
"Control node is located at: "
277
<< Doc_node_pt->x(0) <<
" "
<< Doc_node_pt->x(1) << std::endl << std::endl;
278
279
280
// Set error estimator
281
Z2ErrorEstimator
*
error_estimator_pt
=
new
Z2ErrorEstimator
;
282
mesh_pt()->spatial_error_estimator_pt()=
error_estimator_pt
;
283
284
// Change/doc targets for mesh adaptation
285
if
(CommandLineArgs::Argc>1)
286
{
287
mesh_pt()->max_permitted_error()=0.05;
288
mesh_pt()->min_permitted_error()=0.005;
289
}
290
mesh_pt()->doc_adaptivity_targets(
cout
);
291
292
293
// Specify BC/source fct for Poisson problem:
294
//-------------------------------------------
295
296
// Set the Poisson boundary conditions for this problem: All nodes are
297
// free by default -- just pin the ones that have Dirichlet conditions
298
// here.
299
unsigned
num_bound
= mesh_pt()->nboundary();
300
for
(
unsigned
ibound
=0;
ibound
<
num_bound
;
ibound
++)
301
{
302
unsigned
num_nod
=mesh_pt()->nboundary_node(
ibound
);
303
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
304
{
305
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->pin(0);
306
}
307
}
308
309
// Set homogeneous boundary conditions for the Poisson equation
310
// on all boundaries
311
for
(
unsigned
ibound
=0;
ibound
<
num_bound
;
ibound
++)
312
{
313
// Loop over the nodes on boundary
314
unsigned
num_nod
=mesh_pt()->nboundary_node(
ibound
);
315
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
316
{
317
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(0,0.0);
318
}
319
}
320
321
/// Loop over elements and set pointers to source function
322
unsigned
n_element
= mesh_pt()->nelement();
323
for
(
unsigned
i
=0;
i
<
n_element
;
i
++)
324
{
325
// Upcast from FiniteElement to the present element
326
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(mesh_pt()->element_pt(
i
));
327
328
//Set the source function pointer
329
el_pt
->source_fct_pt() = &
ConstSourceForPoisson::get_source
;
330
}
331
332
333
// Specify BC/source fct etc for (pseudo-)Solid problem
334
//-----------------------------------------------------
335
336
// Pin all nodal positions
337
for
(
unsigned
ibound
=0;
ibound
<
num_bound
;
ibound
++)
338
{
339
unsigned
num_nod
=mesh_pt()->nboundary_node(
ibound
);
340
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
341
{
342
for
(
unsigned
i
=0;
i
<2;
i
++)
343
{
344
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->pin_position(
i
);
345
}
346
}
347
}
348
349
//Loop over the elements in the mesh to set Solid parameters/function pointers
350
for
(
unsigned
i
=0;
i
<
n_element
;
i
++)
351
{
352
//Cast to a solid element
353
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(mesh_pt()->element_pt(
i
));
354
355
// Set the constitutive law
356
el_pt
->constitutive_law_pt() =
357
Global_Physical_Variables::Constitutive_law_pt
;
358
}
359
360
// Pin the redundant solid pressures (if any)
361
PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
362
mesh_pt()->
element_pt
());
363
364
365
//Attach the boundary conditions to the mesh
366
cout
<<
assign_eqn_numbers
() << std::endl;
367
368
// Refine the problem uniformly (this automatically passes the
369
// function pointers/parameters to the finer elements
370
refine_uniformly
();
371
372
// The non-pinned positions of the newly SolidNodes will have been
373
// determined by interpolation. Update all solid nodes based on
374
// the Mesh's Domain/MacroElement representation.
375
bool
update_all_solid_nodes
=
true
;
376
mesh_pt()->node_update(
update_all_solid_nodes
);
377
378
// Now set the Eulerian equal to the Lagrangian coordinates
379
mesh_pt()->set_lagrangian_nodal_coordinates();
380
381
}
382
383
384
//==================================================================
385
/// Doc the solution
386
//==================================================================
387
template
<
class
ELEMENT>
388
void
DeformableFishPoissonProblem<ELEMENT>::doc_solution
(
DocInfo
& doc_info)
389
{
390
ofstream
some_file
;
391
char
filename
[100];
392
393
// Number of plot points
394
unsigned
npts
= 5;
395
396
// Call output function for all elements
397
snprintf
(
filename
,
sizeof
(
filename
),
"%s/soln%i.dat"
,doc_info.directory().c_str(),
398
doc_info.number());
399
some_file
.open(
filename
);
400
mesh_pt()->output(
some_file
,
npts
);
401
some_file
.close();
402
403
404
// Write vertical position of the fish back, and solution at
405
// control node to trace file
406
Trace_file
407
<<
static_cast<
Circle
*
>
(mesh_pt()->fish_back_pt())->y_c()
408
<<
" "
<< Doc_node_pt->value(0) << std::endl;
409
410
}
411
412
413
//==================================================================
414
/// Run the problem
415
//==================================================================
416
template
<
class
ELEMENT>
417
void
DeformableFishPoissonProblem<ELEMENT>::run
()
418
{
419
420
// Output
421
DocInfo
doc_info;
422
423
// Set output directory
424
doc_info.set_directory(
"RESLT"
);
425
426
// Step number
427
doc_info.number()=0;
428
429
// Open trace file
430
char
filename
[100];
431
snprintf
(
filename
,
sizeof
(
filename
),
"%s/trace.dat"
,doc_info.directory().c_str());
432
Trace_file.open(
filename
);
433
434
Trace_file <<
"VARIABLES=\"y<sub>circle</sub>\",\"u<sub>control</sub>\""
435
<< std::endl;
436
437
//Parameter incrementation
438
unsigned
nstep
=5;
439
for
(
unsigned
i
=0;
i
<
nstep
;
i
++)
440
{
441
//Solve the problem with Newton's method, allowing for up to 2
442
//rounds of adaptation
443
newton_solve
(2);
444
445
// Doc solution
446
doc_solution(doc_info);
447
doc_info.number()++;
448
449
// Increment width of fish domain
450
Fish_back_pt->y_c()+=0.3;
451
}
452
453
}
454
455
//======================================================================
456
/// Driver for simple elastic problem.
457
/// If there are any command line arguments, we regard this as a
458
/// validation run and perform only a single step.
459
//======================================================================
460
int
main
(
int
argc
,
char
*
argv
[])
461
{
462
463
// Store command line arguments
464
CommandLineArgs::setup(
argc
,
argv
);
465
466
//Set physical parameters
467
Global_Physical_Variables::Nu
= 0.4;
468
469
// Define a constitutive law (based on strain energy function)
470
Global_Physical_Variables::Constitutive_law_pt
=
471
new
GeneralisedHookean
(&
Global_Physical_Variables::Nu
);
472
473
// Set up the problem: Choose a hybrid element that combines the
474
// 3x3 node refineable quad Poisson element with a displacement-based
475
// solid-mechanics element (for the pseudo-elastic mesh update in response
476
// to changes in the boundary shape)
477
DeformableFishPoissonProblem
<
478
RefineablePseudoSolidNodeUpdateElement<RefineableQPoissonElement<2,3>
,
479
RefineableQPVDElement<2,3>
>
480
>
problem
;
481
482
problem
.
run
();
483
484
485
}
486
487
488
489
490
491
demo_fish_poisson
void demo_fish_poisson(const string &directory_name)
Demonstrate how to solve 2D Poisson problem in deformable fish-shaped domain with mesh adaptation.
Definition
algebraic_free_boundary_poisson.cc:460
main
int main()
Driver.
Definition
circle.cc:40
DeformableFishPoissonProblem
Solve Poisson equation on deforming fish-shaped domain. Mesh update via pseudo-elasticity.
Definition
elastic_mesh_update.cc:178
DeformableFishPoissonProblem::run
void run()
Run simulation.
Definition
elastic_mesh_update.cc:417
DeformableFishPoissonProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update function (empty)
Definition
elastic_mesh_update.cc:196
DeformableFishPoissonProblem::DeformableFishPoissonProblem
DeformableFishPoissonProblem()
Constructor:
Definition
elastic_mesh_update.cc:243
DeformableFishPoissonProblem::mesh_pt
ElasticFishMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
Definition
elastic_mesh_update.cc:189
DeformableFishPoissonProblem::Fish_back_pt
Circle * Fish_back_pt
Definition
elastic_mesh_update.cc:235
DeformableFishPoissonProblem::Trace_file
ofstream Trace_file
Trace file.
Definition
elastic_mesh_update.cc:232
DeformableFishPoissonProblem::Doc_node_pt
Node * Doc_node_pt
Node at which the solution of the Poisson equation is documented.
Definition
elastic_mesh_update.cc:229
DeformableFishPoissonProblem::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
elastic_mesh_update.cc:207
DeformableFishPoissonProblem::actions_after_adapt
void actions_after_adapt()
Update after adapt: Pin all redundant solid pressure nodes (if required)
Definition
elastic_mesh_update.cc:218
DeformableFishPoissonProblem::doc_solution
void doc_solution(DocInfo &doc_info)
Doc the solution.
Definition
elastic_mesh_update.cc:388
ElasticFishMesh
Refineable fish mesh upgraded to become a solid mesh.
Definition
elastic_mesh_update.cc:77
ElasticFishMesh::ElasticFishMesh
ElasticFishMesh(GeomObject *back_pt, GeomObject *undeformed_back_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Build underlying adaptive fish mesh and then set current Eulerian coordinates to be the ...
Definition
elastic_mesh_update.cc:90
ElasticFishMesh::~ElasticFishMesh
virtual ~ElasticFishMesh()
Destructor: Kill "undeformed" Domain.
Definition
elastic_mesh_update.cc:128
ElasticFishMesh::Undeformed_domain_pt
Domain * Undeformed_domain_pt
Pointer to "undeformed" Domain – used to determine the Lagrangian coordinates of any newly created So...
Definition
elastic_mesh_update.cc:138
ConstSourceForPoisson
Namespace for const source term in Poisson equation.
Definition
algebraic_free_boundary_poisson.cc:56
ConstSourceForPoisson::get_source
void get_source(const Vector< double > &x, double &source)
Const source function.
Definition
algebraic_free_boundary_poisson.cc:61
ConstSourceForPoisson::Strength
double Strength
Strength of source function: default value 1.0.
Definition
algebraic_free_boundary_poisson.cc:58
Global_Physical_Variables
Global variables.
Definition
elastic_mesh_update.cc:156
Global_Physical_Variables::Nu
double Nu
Poisson's ratio.
Definition
elastic_mesh_update.cc:161
Global_Physical_Variables::Constitutive_law_pt
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
Definition
elastic_mesh_update.cc:158
oomph
Definition
circle.h:34