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
meshing
mesh_from_triangle
mesh_from_triangle_navier_stokes.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 rectangular box -- meshed with triangle
27
28
//Generic includes
29
#include "generic.h"
30
#include "navier_stokes.h"
31
32
// The mesh
33
#include "
meshes/triangle_mesh.h
"
34
35
using namespace
std;
36
37
using namespace
oomph
;
38
39
//==start_of_namespace==============================
40
/// Namespace for physical parameters
41
//==================================================
42
namespace
Global_Physical_Variables
43
{
44
45
/// Reynolds number
46
double
Re
=10.0;
47
48
}
// end_of_namespace
49
50
51
52
////////////////////////////////////////////////////////////////////////
53
////////////////////////////////////////////////////////////////////////
54
////////////////////////////////////////////////////////////////////////
55
56
57
58
//==start_of_problem_class============================================
59
/// Flow past a box in a channel
60
//====================================================================
61
template
<
class
ELEMENT>
62
class
FlowPastBoxProblem
:
public
Problem
63
{
64
65
public
:
66
67
68
/// Constructor: Pass filenames for mesh
69
FlowPastBoxProblem
(
const
string
& node_file_name,
70
const
string
& element_file_name,
71
const
string
& poly_file_name);
72
73
/// Destructor (empty)
74
~FlowPastBoxProblem
(){}
75
76
/// Update the after solve (empty)
77
void
actions_after_newton_solve
(){}
78
79
/// Update the problem specs before solve.
80
/// Re-set velocity boundary conditions just to be on the safe side...
81
void
actions_before_newton_solve
()
82
{
83
// Find max. and min y-coordinate at inflow
84
double
y_min=1.0e20;
85
double
y_max=-1.0e20;
86
unsigned
ibound=0;
87
unsigned
num_nod=
mesh_pt
()->nboundary_node(ibound);
88
for
(
unsigned
inod=0;inod<num_nod;inod++)
89
{
90
double
y=
mesh_pt
()->boundary_node_pt(ibound,inod)->x(1);
91
if
(y>y_max)
92
{
93
y_max=y;
94
}
95
if
(y<y_min)
96
{
97
y_min=y;
98
}
99
}
100
101
// Loop over all boundaries
102
for
(
unsigned
ibound=0;ibound<
mesh_pt
()->nboundary();ibound++)
103
{
104
unsigned
num_nod=
mesh_pt
()->nboundary_node(ibound);
105
for
(
unsigned
inod=0;inod<num_nod;inod++)
106
{
107
// Parabolic horizontal flow at inflow
108
if
(ibound==0)
109
{
110
double
y=
mesh_pt
()->boundary_node_pt(ibound,inod)->x(1);
111
double
veloc=(y-y_min)*(y_max-y);
112
mesh_pt
()->boundary_node_pt(ibound,inod)->set_value(0,veloc);
113
}
114
// Zero horizontal flow elsewhere (either as IC or otherwise)
115
else
116
{
117
mesh_pt
()->boundary_node_pt(ibound,inod)->set_value(0,0.0);
118
}
119
// Zero vertical flow on all boundaries
120
mesh_pt
()->boundary_node_pt(ibound,inod)->set_value(1,0.0);
121
}
122
}
123
}
// end_of_actions_before_newton_solve
124
125
#ifdef ADAPT
126
// Perform actions after mesh adaptation
127
void
actions_after_adapt
();
128
#endif
129
130
#ifdef ADAPT
131
/// Access function for the specific mesh
132
RefineableTriangleMesh<ELEMENT>
*
mesh_pt
()
133
{
134
return
dynamic_cast<
RefineableTriangleMesh<ELEMENT>
*
>
(Problem::mesh_pt());
135
}
136
#else
137
/// Access function for the specific mesh
138
TriangleMesh<ELEMENT>
*
mesh_pt
()
139
{
140
return
dynamic_cast<
TriangleMesh<ELEMENT>
*
>
(Problem::mesh_pt());
141
}
142
#endif
143
144
/// Doc the solution
145
void
doc_solution
(DocInfo& doc_info);
146
147
#ifdef ADAPT
148
private
:
149
/// Pointer to the bulk mesh
150
RefineableTriangleMesh<ELEMENT>
*
Bulk_mesh_pt
;
151
152
/// Error estimator
153
Z2ErrorEstimator*
error_estimator_pt
;
154
155
#endif
156
157
};
// end_of_problem_class
158
159
160
//==start_of_constructor==================================================
161
/// Constructor for FlowPastBox problem. Pass filenames for mesh
162
//========================================================================
163
template
<
class
ELEMENT>
164
FlowPastBoxProblem<ELEMENT>::FlowPastBoxProblem
(
165
const
string
& node_file_name,
166
const
string
& element_file_name,
167
const
string
& poly_file_name)
168
{
169
170
Problem::Max_residuals=1000.0;
171
172
#ifdef ADAPT
173
//Create mesh
174
Bulk_mesh_pt =
new
RefineableTriangleMesh<ELEMENT>
(
node_file_name
,
175
element_file_name
,
176
poly_file_name
);
177
178
// Set error estimator for bulk mesh
179
Z2ErrorEstimator
* error_estimator_pt=
new
Z2ErrorEstimator
;
180
Bulk_mesh_pt->spatial_error_estimator_pt() = error_estimator_pt;
181
182
// Set the problem mesh pointer to the bulk mesh
183
Problem::mesh_pt() = Bulk_mesh_pt;
184
185
#else
186
//Create mesh
187
Problem::mesh_pt() =
new
TriangleMesh<ELEMENT>
(
node_file_name
,
188
element_file_name
,
189
poly_file_name
);
190
#endif
191
192
// Set the boundary conditions for this problem: All nodes are
193
// free by default -- just pin the ones that have Dirichlet conditions
194
// here.
195
unsigned
num_bound
= mesh_pt()->nboundary();
196
for
(
unsigned
ibound
=0;
ibound
<
num_bound
;
ibound
++)
197
{
198
unsigned
num_nod
= mesh_pt()->nboundary_node(
ibound
);
199
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
200
{
201
// Pin horizontal velocity everywhere apart from pure outflow
202
if
((
ibound
!=2))
203
{
204
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->pin(0);
205
}
206
207
// Pin vertical velocity everywhere
208
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->pin(1);
209
}
210
}
// end loop over boundaries
211
212
// Complete the build of all elements so they are fully functional
213
214
//Find number of elements in mesh
215
unsigned
n_element
= mesh_pt()->nelement();
216
217
// Loop over the elements to set up element-specific
218
// things that cannot be handled by constructor
219
for
(
unsigned
e
=0;
e
<
n_element
;
e
++)
220
{
221
// Upcast from GeneralisedElement to the present element
222
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(mesh_pt()->element_pt(
e
));
223
224
//Set the Reynolds number
225
el_pt
->re_pt() = &
Global_Physical_Variables::Re
;
226
}
// end loop over elements
227
228
229
// Setup equation numbering scheme
230
cout
<<
"Number of equations: "
<<
assign_eqn_numbers
() << std::endl;
231
232
}
// end_of_constructor
233
234
#ifdef ADAPT
235
//========================================================================
236
// Perform actions after mesh adaptation
237
//========================================================================
238
template
<
class
ELEMENT>
239
void
FlowPastBoxProblem<ELEMENT>::actions_after_adapt
()
240
{
241
242
// Pin the nodes and make all the element fully functional since the
243
// mesh adaptation generated a new mesh
244
245
// Set the boundary conditions for this problem: All nodes are
246
// free by default -- just pin the ones that have Dirichlet conditions
247
// here.
248
unsigned
num_bound
= mesh_pt()->nboundary();
249
for
(
unsigned
ibound
=0;
ibound
<
num_bound
;
ibound
++)
250
{
251
unsigned
num_nod
= mesh_pt()->nboundary_node(
ibound
);
252
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
253
{
254
// Pin horizontal velocity everywhere apart from pure outflow
255
if
((
ibound
!=2))
256
{
257
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->pin(0);
258
}
259
260
// Pin vertical velocity everywhere
261
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->pin(1);
262
}
263
}
// end loop over boundaries
264
265
// Complete the build of all elements so they are fully functional
266
267
//Find number of elements in mesh
268
unsigned
n_element
= mesh_pt()->nelement();
269
270
// Loop over the elements to set up element-specific
271
// things that cannot be handled by constructor
272
for
(
unsigned
e
=0;
e
<
n_element
;
e
++)
273
{
274
// Upcast from GeneralisedElement to the present element
275
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(mesh_pt()->element_pt(
e
));
276
277
//Set the Reynolds number
278
el_pt
->re_pt() = &
Global_Physical_Variables::Re
;
279
}
// end loop over elements
280
281
282
// Setup equation numbering scheme
283
cout
<<
"Number of equations: "
<<
assign_eqn_numbers
() << std::endl;
284
285
}
286
#endif
287
288
289
//==start_of_doc_solution=================================================
290
/// Doc the solution
291
//========================================================================
292
template
<
class
ELEMENT>
293
void
FlowPastBoxProblem<ELEMENT>::doc_solution
(
DocInfo
&
doc_info
)
294
{
295
ofstream
some_file
;
296
char
filename
[100];
297
298
// Number of plot points
299
unsigned
npts
;
300
npts
=5;
301
302
// Output solution
303
snprintf
(
filename
,
sizeof
(
filename
),
"%s/soln%i.dat"
,
doc_info
.directory().c_str(),
304
doc_info
.number());
305
some_file
.open(
filename
);
306
mesh_pt()->output(
some_file
,
npts
);
307
some_file
.close();
308
309
// Get norm of solution
310
snprintf
(
filename
,
sizeof
(
filename
),
"%s/norm%i.dat"
,
doc_info
.directory().c_str(),
311
doc_info
.number());
312
some_file
.open(
filename
);
313
double
norm_soln
=0.0;
314
mesh_pt()->compute_norm(
norm_soln
);
315
some_file
<<
sqrt
(
norm_soln
) << std::endl;
316
cout
<<
"Norm of computed solution: "
<<
sqrt
(
norm_soln
) <<
endl
;
317
some_file
.close();
318
319
320
}
// end_of_doc_solution
321
322
323
324
325
326
////////////////////////////////////////////////////////////////////////
327
////////////////////////////////////////////////////////////////////////
328
////////////////////////////////////////////////////////////////////////
329
330
331
332
333
334
335
336
//==start_of_main======================================================
337
/// Driver for FlowPastBox test problem
338
//=====================================================================
339
int
main
(
int
argc
,
char
*
argv
[])
340
{
341
342
// Store command line arguments
343
CommandLineArgs::setup(
argc
,
argv
);
344
345
346
// Check number of command line arguments: Need exactly two.
347
if
(
argc
!=4)
348
{
349
std::string
error_message
=
350
"Wrong number of command line arguments.\n"
;
351
error_message
+=
352
"Must specify the following file names \n"
;
353
error_message
+=
354
"filename.node then filename.ele then filename.poly\n"
;
355
356
throw
OomphLibError
(
error_message
,
357
OOMPH_CURRENT_FUNCTION
,
358
OOMPH_EXCEPTION_LOCATION
);
359
}
360
361
362
// Convert arguments to strings that specify the input file names
363
string
node_file_name
(
argv
[1]);
364
string
element_file_name
(
argv
[2]);
365
string
poly_file_name
(
argv
[3]);
366
367
368
// Set up doc info
369
// ---------------
370
371
// Label for output
372
DocInfo
doc_info
;
373
374
// Set output directory
375
doc_info
.set_directory(
"RESLT"
);
376
377
// Step number
378
doc_info
.number()=0;
379
380
#ifdef ADAPT
381
const
unsigned
max_adapt
= 3;
382
#endif
383
384
// Doing TTaylorHoodElements
385
{
386
#ifdef ADAPT
387
// Build the problem with TTaylorHoodElements
388
FlowPastBoxProblem<ProjectableTaylorHoodElement<TTaylorHoodElement<2>
> >
389
problem
(
node_file_name
,
element_file_name
,
poly_file_name
);
390
#else
391
// Build the problem with TTaylorHoodElements
392
FlowPastBoxProblem<TTaylorHoodElement<2>
>
393
problem
(
node_file_name
,
element_file_name
,
poly_file_name
);
394
#endif
395
// Output boundaries
396
problem
.mesh_pt()->output_boundaries(
"RESLT/boundaries.dat"
);
397
398
// Outpt the solution
399
problem
.doc_solution(
doc_info
);
400
401
// Step number
402
doc_info
.number()++;
403
404
#ifdef ADAPT
405
// Solve the problem
406
problem
.newton_solve(
max_adapt
);
407
#else
408
// Solve the problem
409
problem
.newton_solve();
410
#endif
411
412
// Outpt the solution
413
problem
.doc_solution(
doc_info
);
414
415
// Step number
416
doc_info
.number()++;
417
418
}
// end of QTaylorHoodElements
419
420
421
}
// end_of_main
422
423
424
425
426
427
428
429
430
431
FlowPastBoxProblem
Flow past a box in a channel.
Definition
mesh_from_triangle_navier_stokes.cc:63
FlowPastBoxProblem::mesh_pt
RefineableTriangleMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
Definition
mesh_from_triangle_navier_stokes.cc:132
FlowPastBoxProblem::error_estimator_pt
Z2ErrorEstimator * error_estimator_pt
Error estimator.
Definition
mesh_from_triangle_navier_stokes.cc:153
FlowPastBoxProblem::~FlowPastBoxProblem
~FlowPastBoxProblem()
Destructor (empty)
Definition
mesh_from_triangle_navier_stokes.cc:74
FlowPastBoxProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update the after solve (empty)
Definition
mesh_from_triangle_navier_stokes.cc:77
FlowPastBoxProblem::Bulk_mesh_pt
RefineableTriangleMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the bulk mesh.
Definition
mesh_from_triangle_navier_stokes.cc:150
FlowPastBoxProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update the problem specs before solve. Re-set velocity boundary conditions just to be on the safe sid...
Definition
mesh_from_triangle_navier_stokes.cc:81
FlowPastBoxProblem::FlowPastBoxProblem
FlowPastBoxProblem(const string &node_file_name, const string &element_file_name, const string &poly_file_name)
Constructor: Pass filenames for mesh.
Definition
mesh_from_triangle_navier_stokes.cc:164
FlowPastBoxProblem::actions_after_adapt
void actions_after_adapt()
Definition
mesh_from_triangle_navier_stokes.cc:239
FlowPastBoxProblem::doc_solution
void doc_solution(DocInfo &doc_info)
Doc the solution.
Definition
mesh_from_triangle_navier_stokes.cc:293
FlowPastBoxProblem::mesh_pt
TriangleMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
Definition
mesh_from_triangle_navier_stokes.cc:138
oomph::RefineableTriangleMesh
Unstructured refineable Triangle Mesh.
Definition
triangle_mesh.h:2225
oomph::TriangleMesh
Triangle mesh build with the help of the scaffold mesh coming from the triangle mesh generator Triang...
Definition
triangle_mesh.h:408
main
int main(int argc, char *argv[])
Driver for FlowPastBox test problem.
Definition
mesh_from_triangle_navier_stokes.cc:339
Global_Physical_Variables
Namespace for physical parameters.
Definition
mesh_from_triangle_navier_stokes.cc:43
Global_Physical_Variables::Re
double Re
Reynolds number.
Definition
mesh_from_triangle_navier_stokes.cc:46
oomph
Definition
annular_domain.h:35
triangle_mesh.h