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
navier_stokes
unstructured_fluid
unstructured_two_d_fluid.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 flow past odd-shaped obstacle -- domain meshed with triangle.
27
// This is a warm-up problem for an unstructured fsi problem.
28
29
//Generic includes
30
#include "generic.h"
31
#include "navier_stokes.h"
32
#include "solid.h"
33
#include "constitutive.h"
34
35
// The mesh
36
#include "meshes/triangle_mesh.h"
37
38
39
using namespace
std;
40
41
using namespace
oomph;
42
43
44
//===========start_mesh====================================================
45
/// Triangle-based mesh upgraded to become a (pseudo-) solid mesh
46
//=========================================================================
47
template
<
class
ELEMENT>
48
class
ElasticTriangleMesh
:
public
virtual
TriangleMesh<ELEMENT>,
49
public
virtual
SolidMesh
50
{
51
52
public
:
53
54
/// Constructor:
55
ElasticTriangleMesh
(
const
std::string& node_file_name,
56
const
std::string& element_file_name,
57
const
std::string& poly_file_name,
58
TimeStepper* time_stepper_pt=
59
&Mesh::Default_TimeStepper) :
60
TriangleMesh<ELEMENT>(node_file_name,element_file_name,
61
poly_file_name, time_stepper_pt)
62
{
63
//Assign the Lagrangian coordinates
64
set_lagrangian_nodal_coordinates();
65
66
//Identify the domain boundaries
67
this->
identify_boundaries
();
68
}
69
70
71
/// Function used to identify the domain boundaries
72
void
identify_boundaries
()
73
{
74
// We will have three boundaries
75
this->set_nboundary(3);
76
77
unsigned
n_node=this->nnode();
78
for
(
unsigned
j=0;j<n_node;j++)
79
{
80
Node* nod_pt=this->node_pt(j);
81
82
// Boundary 1 is left (inflow) boundary
83
if
(nod_pt->x(0)<0.226)
84
{
85
// If it's not on the upper or lower channel walls remove it
86
// from boundary 0
87
if
((nod_pt->x(1)<4.08)&&(nod_pt->x(1)>0.113))
88
{
89
this->remove_boundary_node(0,nod_pt);
90
}
91
this->add_boundary_node(1,nod_pt);
92
}
93
94
// Boundary 2 is right (outflow) boundary
95
if
(nod_pt->x(0)>8.28)
96
{
97
// If it's not on the upper or lower channel walls remove it
98
// from boundary 0
99
if
((nod_pt->x(1)<4.08)&&(nod_pt->x(1)>0.113))
100
{
101
this->remove_boundary_node(0,nod_pt);
102
}
103
this->add_boundary_node(2,nod_pt);
104
}
105
}
106
this->setup_boundary_element_info();
107
}
108
109
/// Empty Destructor
110
virtual
~ElasticTriangleMesh
() { }
111
112
113
};
114
115
116
117
//==start_namespace==============================
118
/// Namespace for physical parameters
119
//==================================================
120
namespace
Global_Physical_Variables
121
{
122
123
/// Reynolds number
124
double
Re
=0.0;
125
126
/// Pseudo-solid Poisson ratio
127
double
Nu
=0.3;
128
129
/// Constitutive law used to determine the mesh deformation
130
ConstitutiveLaw *
Constitutive_law_pt
=0;
131
132
}
// end_of_namespace
133
134
135
136
////////////////////////////////////////////////////////////////////////
137
////////////////////////////////////////////////////////////////////////
138
////////////////////////////////////////////////////////////////////////
139
140
141
142
//==start_of_problem_class============================================
143
/// Unstructured fluid problem
144
//====================================================================
145
template
<
class
ELEMENT>
146
class
UnstructuredFluidProblem
:
public
Problem
147
{
148
149
public
:
150
151
/// Constructor
152
UnstructuredFluidProblem
();
153
154
/// Destructor (empty)
155
~UnstructuredFluidProblem
(){}
156
157
/// Access function for the fluid mesh
158
ElasticTriangleMesh<ELEMENT>
*&
fluid_mesh_pt
()
159
{
160
return
Fluid_mesh_pt
;
161
}
162
163
/// Set the boundary conditions
164
void
set_boundary_conditions
();
165
166
/// Doc the solution
167
void
doc_solution
(DocInfo& doc_info);
168
169
private
:
170
171
/// Fluid mesh
172
ElasticTriangleMesh<ELEMENT>
*
Fluid_mesh_pt
;
173
174
175
};
// end_of_problem_class
176
177
178
//==start_constructor=====================================================
179
/// Constructor
180
//========================================================================
181
template
<
class
ELEMENT>
182
UnstructuredFluidProblem<ELEMENT>::UnstructuredFluidProblem
()
183
{
184
185
//Create fluid mesh
186
string
fluid_node_file_name=
"fluid.fig.1.node"
;
187
string
fluid_element_file_name=
"fluid.fig.1.ele"
;
188
string
fluid_poly_file_name=
"fluid.fig.1.poly"
;
189
Fluid_mesh_pt =
new
ElasticTriangleMesh<ELEMENT>
(
fluid_node_file_name
,
190
fluid_element_file_name
,
191
fluid_poly_file_name
);
192
193
//Set the boundary conditions
194
this->set_boundary_conditions();
195
196
// Add fluid mesh
197
add_sub_mesh
(fluid_mesh_pt());
198
199
// Build global mesh
200
build_global_mesh
();
201
202
// Setup equation numbering scheme
203
cout
<<
"Number of equations: "
<<
assign_eqn_numbers
() << std::endl;
204
205
}
// end_of_constructor
206
207
208
209
//============start_of_set_boundary_conditions=============================
210
/// Set the boundary conditions for the problem and document the boundary
211
/// nodes
212
//==========================================================================
213
template
<
class
ELEMENT>
214
void
UnstructuredFluidProblem<ELEMENT>::set_boundary_conditions
()
215
{
216
// Doc pinned nodes
217
std::ofstream
solid_bc_file
(
"pinned_solid_nodes.dat"
);
218
std::ofstream
u_bc_file
(
"pinned_u_nodes.dat"
);
219
std::ofstream
v_bc_file
(
"pinned_v_nodes.dat"
);
220
221
// Set the boundary conditions for fluid problem: All nodes are
222
// free by default -- just pin the ones that have Dirichlet conditions
223
// here.
224
unsigned
nbound
=Fluid_mesh_pt->nboundary();
225
for
(
unsigned
ibound
=0;
ibound
<
nbound
;
ibound
++)
226
{
227
unsigned
num_nod
=Fluid_mesh_pt->nboundary_node(
ibound
);
228
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
229
{
230
// Get node
231
Node
*
nod_pt
=Fluid_mesh_pt->boundary_node_pt(
ibound
,
inod
);
232
233
// Pin velocity everywhere apart from outlet where we
234
// have parallel outflow
235
if
(
ibound
!=2)
236
{
237
// Pin it
238
nod_pt
->pin(0);
239
// Doc it as pinned
240
u_bc_file
<<
nod_pt
->x(0) <<
" "
<<
nod_pt
->x(1) << std::endl;
241
}
242
// Pin it
243
nod_pt
->pin(1);
244
// Doc it as pinned
245
v_bc_file
<<
nod_pt
->x(0) <<
" "
<<
nod_pt
->x(1) << std::endl;
246
247
// Pin pseudo-solid positions everywhere
248
for
(
unsigned
i
=0;
i
<2;
i
++)
249
{
250
// Pin the node
251
SolidNode
*
nod_pt
=Fluid_mesh_pt->boundary_node_pt(
ibound
,
inod
);
252
nod_pt
->pin_position(
i
);
253
254
// Doc it as pinned
255
solid_bc_file
<<
nod_pt
->x(
i
) <<
" "
;
256
}
257
solid_bc_file
<< std::endl;
258
}
259
}
// end loop over boundaries
260
261
// Close
262
solid_bc_file
.close();
263
264
// Complete the build of all elements so they are fully functional
265
unsigned
n_element
= fluid_mesh_pt()->nelement();
266
for
(
unsigned
e
=0;
e
<
n_element
;
e
++)
267
{
268
// Upcast from GeneralisedElement to the present element
269
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(fluid_mesh_pt()->element_pt(
e
));
270
271
//Set the Reynolds number
272
el_pt
->re_pt() = &
Global_Physical_Variables::Re
;
273
274
// Set the constitutive law
275
el_pt
->constitutive_law_pt() =
276
Global_Physical_Variables::Constitutive_law_pt
;
277
}
278
279
280
// Apply fluid boundary conditions: Poiseuille at inflow
281
//------------------------------------------------------
282
283
// Find max. and min y-coordinate at inflow
284
unsigned
ibound
=1;
285
//Initialise y_min and y_max to y-coordinate of first node on boundary
286
double
y_min
=fluid_mesh_pt()->boundary_node_pt(
ibound
,0)->x(1);
287
double
y_max
=
y_min
;
288
//Loop over the rest of the nodes
289
unsigned
num_nod
= fluid_mesh_pt()->nboundary_node(
ibound
);
290
for
(
unsigned
inod
=1;
inod
<
num_nod
;
inod
++)
291
{
292
double
y
=fluid_mesh_pt()->boundary_node_pt(
ibound
,
inod
)->x(1);
293
if
(
y
>
y_max
)
294
{
295
y_max
=
y
;
296
}
297
if
(
y
<
y_min
)
298
{
299
y_min
=
y
;
300
}
301
}
302
double
y_mid
=0.5*(
y_min
+
y_max
);
303
304
// Loop over all boundaries
305
for
(
unsigned
ibound
=0;
ibound
<fluid_mesh_pt()->nboundary();
ibound
++)
306
{
307
unsigned
num_nod
= fluid_mesh_pt()->nboundary_node(
ibound
);
308
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
309
{
310
// Parabolic inflow at the left boundary (boundary 1)
311
if
(
ibound
==1)
312
{
313
double
y
=fluid_mesh_pt()->boundary_node_pt(
ibound
,
inod
)->x(1);
314
double
veloc
=1.5/(
y_max
-
y_min
)*
315
(
y
-
y_min
)*(
y_max
-
y
)/((
y_mid
-
y_min
)*(
y_max
-
y_mid
));
316
fluid_mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(0,
veloc
);
317
fluid_mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(1,0.0);
318
}
319
// Zero flow elsewhere apart from x-velocity on outflow boundary
320
else
321
{
322
if
(
ibound
!=2)
323
{
324
fluid_mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(0,0.0);
325
}
326
fluid_mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(1,0.0);
327
}
328
}
329
}
330
}
// end_of_set_boundary_conditions
331
332
333
334
335
//==start_of_doc_solution=================================================
336
/// Doc the solution
337
//========================================================================
338
template
<
class
ELEMENT>
339
void
UnstructuredFluidProblem<ELEMENT>::doc_solution
(
DocInfo
&
doc_info
)
340
{
341
ofstream
some_file
;
342
char
filename
[100];
343
344
// Number of plot points
345
unsigned
npts
;
346
npts
=5;
347
348
// Output solution
349
snprintf
(
filename
,
sizeof
(
filename
),
"%s/soln%i.dat"
,
doc_info
.directory().c_str(),
350
doc_info
.number());
351
some_file
.open(
filename
);
352
fluid_mesh_pt()->output(
some_file
,
npts
);
353
some_file
.close();
354
}
//end_of_doc_solution
355
356
357
////////////////////////////////////////////////////////////////////////
358
////////////////////////////////////////////////////////////////////////
359
////////////////////////////////////////////////////////////////////////
360
361
362
363
364
365
366
367
//==start_of_main======================================================
368
/// Driver for unstructured fluid test problem
369
//=====================================================================
370
int
main
()
371
{
372
// Label for output
373
DocInfo
doc_info
;
374
375
//Set the constitutive law for the pseudo-elasticity
376
Global_Physical_Variables::Constitutive_law_pt
=
377
new
GeneralisedHookean
(&
Global_Physical_Variables::Nu
);
378
379
//Taylor--Hood formulation
380
{
381
// Set output directory
382
doc_info
.set_directory(
"RESLT_TH"
);
383
384
// Step number
385
doc_info
.number()=0;
386
387
// Build the problem with TTaylorHoodElements
388
UnstructuredFluidProblem
<
PseudoSolidNodeUpdateElement
<
389
TTaylorHoodElement<2>
,
390
TPVDElement<2,3>
> >
problem
;
391
392
// Output boundaries
393
problem
.fluid_mesh_pt()->output_boundaries(
"RESLT_TH/boundaries.dat"
);
394
395
// Output the initial guess for the solution
396
problem
.doc_solution(
doc_info
);
397
doc_info
.number()++;
398
399
// Parameter study
400
double
re_increment
=5.0;
401
unsigned
nstep
=2;
// 10;
402
for
(
unsigned
i
=0;
i
<
nstep
;
i
++)
403
{
404
// Solve the problem
405
problem
.newton_solve();
406
407
// Output the solution
408
problem
.doc_solution(
doc_info
);
409
doc_info
.number()++;
410
411
// Bump up Re
412
Global_Physical_Variables::Re
+=
re_increment
;
413
}
//end_of_parameter_study
414
}
415
416
417
418
//Crouzeix--Raviart formulation
419
{
420
// Set output directory
421
doc_info
.set_directory(
"RESLT_CR"
);
422
423
// Step number
424
doc_info
.number()=0;
425
426
// Reset Reynolds number
427
Global_Physical_Variables::Re
= 0.0;
428
429
// Build the problem with TCrouzeixRaviartElements
430
UnstructuredFluidProblem
<
PseudoSolidNodeUpdateElement
<
431
TCrouzeixRaviartElement<2>
,
432
TPVDBubbleEnrichedElement<2,3>
> >
problem
;
433
434
// Output boundaries
435
problem
.fluid_mesh_pt()->output_boundaries(
"RESLT_CR/boundaries.dat"
);
436
437
// Output the initial guess for the solution
438
problem
.doc_solution(
doc_info
);
439
doc_info
.number()++;
440
441
// Parameter study
442
double
re_increment
=5.0;
443
unsigned
nstep
=2;
// 10;
444
for
(
unsigned
i
=0;
i
<
nstep
;
i
++)
445
{
446
// Solve the problem
447
problem
.newton_solve();
448
449
// Output the solution
450
problem
.doc_solution(
doc_info
);
451
doc_info
.number()++;
452
453
// Bump up Re
454
Global_Physical_Variables::Re
+=
re_increment
;
455
}
456
}
457
458
459
}
// end_of_main
460
461
462
463
464
465
466
467
468
469
ElasticTriangleMesh
Triangle-based mesh upgraded to become a (pseudo-) solid mesh.
Definition
unstructured_two_d_fluid.cc:50
ElasticTriangleMesh::ElasticTriangleMesh
ElasticTriangleMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &poly_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor:
Definition
unstructured_two_d_fluid.cc:55
ElasticTriangleMesh::identify_boundaries
void identify_boundaries()
Function used to identify the domain boundaries.
Definition
unstructured_two_d_fluid.cc:72
ElasticTriangleMesh::~ElasticTriangleMesh
virtual ~ElasticTriangleMesh()
Empty Destructor.
Definition
unstructured_two_d_fluid.cc:110
UnstructuredFluidProblem
Unstructured fluid problem.
Definition
unstructured_two_d_fluid.cc:147
UnstructuredFluidProblem::~UnstructuredFluidProblem
~UnstructuredFluidProblem()
Destructor (empty)
Definition
unstructured_two_d_fluid.cc:155
UnstructuredFluidProblem::set_boundary_conditions
void set_boundary_conditions()
Set the boundary conditions.
Definition
unstructured_two_d_fluid.cc:214
UnstructuredFluidProblem::UnstructuredFluidProblem
UnstructuredFluidProblem()
Constructor.
Definition
unstructured_two_d_fluid.cc:182
UnstructuredFluidProblem::Fluid_mesh_pt
ElasticTriangleMesh< ELEMENT > * Fluid_mesh_pt
Fluid mesh.
Definition
unstructured_two_d_fluid.cc:172
UnstructuredFluidProblem::doc_solution
void doc_solution(DocInfo &doc_info)
Doc the solution.
Definition
unstructured_two_d_fluid.cc:339
UnstructuredFluidProblem::fluid_mesh_pt
ElasticTriangleMesh< ELEMENT > *& fluid_mesh_pt()
Access function for the fluid mesh.
Definition
unstructured_two_d_fluid.cc:158
Global_Physical_Variables
Namespace for physical parameters.
Definition
unstructured_two_d_fluid.cc:121
Global_Physical_Variables::Constitutive_law_pt
ConstitutiveLaw * Constitutive_law_pt
Constitutive law used to determine the mesh deformation.
Definition
unstructured_two_d_fluid.cc:130
Global_Physical_Variables::Nu
double Nu
Pseudo-solid Poisson ratio.
Definition
unstructured_two_d_fluid.cc:127
Global_Physical_Variables::Re
double Re
Reynolds number.
Definition
unstructured_two_d_fluid.cc:124
main
int main()
Driver for unstructured fluid test problem.
Definition
unstructured_two_d_fluid.cc:370