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
multi_physics
boussinesq_convection
boussinesq_convection.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 a multi-physics problem that couples the Navier--Stokes
27
//equations to the advection diffusion equations,
28
//giving Boussinesq convection
29
30
//Oomph-lib headers, we require the generic, advection-diffusion
31
//and navier-stokes elements.
32
#include "generic.h"
33
#include "advection_diffusion.h"
34
#include "navier_stokes.h"
35
#include "multi_physics.h"
36
37
// The mesh is our standard rectangular quadmesh
38
#include "meshes/rectangular_quadmesh.h"
39
40
// Use the oomph and std namespaces
41
using namespace
oomph
;
42
using namespace
std;
43
44
45
//======start_of_namespace============================================
46
/// Namespace for the physical parameters in the problem
47
//====================================================================
48
namespace
Global_Physical_Variables
49
{
50
/// Peclet number (identically one from our non-dimensionalisation)
51
double
Peclet
=1.0;
52
53
/// 1/Prandtl number
54
double
Inverse_Prandtl
=1.0;
55
56
/// Rayleigh number, set to be greater than
57
/// the threshold for linear instability
58
double
Rayleigh
= 1800.0;
59
60
/// Gravity vector
61
Vector<double>
Direction_of_gravity
(2);
62
63
}
// end_of_namespace
64
65
//////////////////////////////////////////////////////////////////////
66
//////////////////////////////////////////////////////////////////////
67
//////////////////////////////////////////////////////////////////////
68
69
//====== start_of_problem_class=======================================
70
/// 2D Convection problem on rectangular domain, discretised
71
/// with refineable elements. The specific type
72
/// of element is specified via the template parameter.
73
//====================================================================
74
template
<
class
ELEMENT>
75
class
ConvectionProblem
:
public
Problem
76
{
77
78
public
:
79
80
/// Constructor
81
ConvectionProblem
();
82
83
/// Destructor. Empty
84
~ConvectionProblem
() {}
85
86
/// Update the problem specs before solve (empty)
87
void
actions_before_newton_solve
() {}
88
89
/// Update the problem after solve (empty)
90
void
actions_after_newton_solve
(){}
91
92
/// Actions before adapt:(empty)
93
void
actions_before_adapt
(){}
94
95
/// Actions before the timestep (update the the time-dependent
96
/// boundary conditions)
97
void
actions_before_implicit_timestep
()
98
{
99
set_boundary_conditions
(time_pt()->time());
100
}
101
102
/// Fix pressure in element e at pressure dof pdof and set to pvalue
103
void
fix_pressure
(
const
unsigned
&e,
const
unsigned
&pdof,
104
const
double
&pvalue)
105
{
106
//Cast to specific element and fix pressure
107
dynamic_cast<
ELEMENT*
>
(
mesh_pt
()->element_pt(e))->
108
fix_pressure
(pdof,pvalue);
109
}
// end_of_fix_pressure
110
111
/// Doc the solution.
112
void
doc_solution
();
113
114
/// Set the boundary conditions
115
void
set_boundary_conditions
(
const
double
&time);
116
117
/// Overloaded version of the problem's access function to
118
/// the mesh. Recasts the pointer to the base Mesh object to
119
/// the actual mesh type.
120
RectangularQuadMesh<ELEMENT>*
mesh_pt
()
121
{
122
return
dynamic_cast<
RectangularQuadMesh<ELEMENT>*
>
(
123
Problem::mesh_pt());
124
}
125
126
private
:
127
128
/// DocInfo object
129
DocInfo
Doc_info
;
130
131
};
// end of problem class
132
133
//===========start_of_constructor=========================================
134
/// Constructor for convection problem
135
//========================================================================
136
template
<
class
ELEMENT>
137
ConvectionProblem<ELEMENT>::ConvectionProblem
()
138
{
139
//Allocate a timestepper
140
add_time_stepper_pt(
new
BDF<2>);
141
142
// Set output directory
143
Doc_info.set_directory(
"RESLT"
);
144
145
// # of elements in x-direction
146
unsigned
n_x=8;
147
148
// # of elements in y-direction
149
unsigned
n_y=8;
150
151
// Domain length in x-direction
152
double
l_x=3.0;
153
154
// Domain length in y-direction
155
double
l_y=1.0;
156
157
// Build a standard rectangular quadmesh
158
Problem::mesh_pt() =
159
new
RectangularQuadMesh<ELEMENT>(n_x,n_y,l_x,l_y,time_stepper_pt());
160
161
// Set the boundary conditions for this problem: All nodes are
162
// free by default -- only need to pin the ones that have Dirichlet
163
// conditions here
164
165
//Loop over the boundaries
166
unsigned
num_bound = mesh_pt()->nboundary();
167
for
(
unsigned
ibound=0;ibound<num_bound;ibound++)
168
{
169
//Set the maximum index to be pinned (all values by default)
170
unsigned
val_max=3;
171
//If we are on the side-walls, the v-velocity and temperature
172
//satisfy natural boundary conditions, so we only pin the
173
//first value
174
if
((ibound==1) || (ibound==3)) {val_max=1;}
175
176
//Loop over the number of nodes on the boundry
177
unsigned
num_nod= mesh_pt()->nboundary_node(ibound);
178
for
(
unsigned
inod=0;inod<num_nod;inod++)
179
{
180
//Loop over the desired values stored at the nodes and pin
181
for
(
unsigned
j=0;j<val_max;j++)
182
{
183
mesh_pt()->boundary_node_pt(ibound,inod)->pin(j);
184
}
185
}
186
}
187
188
//Pin the zero-th pressure dof in element 0 and set its value to
189
//zero:
190
fix_pressure(0,0,0.0);
191
192
// Complete the build of all elements so they are fully functional
193
194
// Loop over the elements to set up element-specific
195
// things that cannot be handled by the (argument-free!) ELEMENT
196
// constructor.
197
unsigned
n_element = mesh_pt()->nelement();
198
for
(
unsigned
i=0;i<n_element;i++)
199
{
200
// Upcast from GeneralsedElement to the present element
201
ELEMENT *el_pt =
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(i));
202
203
// Set the Peclet number
204
el_pt->pe_pt() = &
Global_Physical_Variables::Peclet
;
205
206
// Set the Peclet number multiplied by the Strouhal number
207
el_pt->pe_st_pt() =&
Global_Physical_Variables::Peclet
;
208
209
// Set the Reynolds number (1/Pr in our non-dimensionalisation)
210
el_pt->re_pt() = &
Global_Physical_Variables::Inverse_Prandtl
;
211
212
// Set ReSt (also 1/Pr in our non-dimensionalisation)
213
el_pt->re_st_pt() = &
Global_Physical_Variables::Inverse_Prandtl
;
214
215
// Set the Rayleigh number
216
el_pt->ra_pt() = &
Global_Physical_Variables::Rayleigh
;
217
218
//Set Gravity vector
219
el_pt->g_pt() = &
Global_Physical_Variables::Direction_of_gravity
;
220
221
//The mesh is fixed, so we can disable ALE
222
el_pt->disable_ALE();
223
}
224
225
// Setup equation numbering scheme
226
cout <<
"Number of equations: "
<< assign_eqn_numbers() << endl;
227
228
}
// end of constructor
229
230
231
232
//===========start_of_set_boundary_conditions================
233
/// Set the boundary conditions as a function of continuous
234
/// time
235
//===========================================================
236
template
<
class
ELEMENT>
237
void
ConvectionProblem<ELEMENT>::set_boundary_conditions
(
238
const
double
&time)
239
{
240
// Loop over the boundaries
241
unsigned
num_bound = mesh_pt()->nboundary();
242
for
(
unsigned
ibound=0;ibound<num_bound;ibound++)
243
{
244
// Loop over the nodes on boundary
245
unsigned
num_nod=mesh_pt()->nboundary_node(ibound);
246
for
(
unsigned
inod=0;inod<num_nod;inod++)
247
{
248
// Get pointer to node
249
Node* nod_pt=mesh_pt()->boundary_node_pt(ibound,inod);
250
251
//Set the number of velocity components
252
unsigned
vel_max=2;
253
254
//If we are on the side walls we only set the x-velocity.
255
if
((ibound==1) || (ibound==3)) {vel_max = 1;}
256
257
//Set the pinned velocities to zero
258
for
(
unsigned
j=0;j<vel_max;j++) {nod_pt->set_value(j,0.0);}
259
260
//If we are on the top boundary
261
if
(ibound==2)
262
{
263
//Set the temperature to -0.5 (cooled)
264
nod_pt->set_value(2,-0.5);
265
266
//Add small velocity imperfection if desired
267
double
epsilon = 0.01;
268
269
//Read out the x position
270
double
x = nod_pt->x(0);
271
272
//Set a sinusoidal perturbation in the vertical velocity
273
//This perturbation is mass conserving
274
double
value = sin(2.0*MathematicalConstants::Pi*x/3.0)*
275
epsilon*time*exp(-time);
276
nod_pt->set_value(1,value);
277
}
278
279
//If we are on the bottom boundary, set the temperature
280
//to 0.5 (heated)
281
if
(ibound==0) {nod_pt->set_value(2,0.5);}
282
}
283
}
284
}
// end_of_set_boundary_conditions
285
286
//===============start_doc_solution=======================================
287
/// Doc the solution
288
//========================================================================
289
template
<
class
ELEMENT>
290
void
ConvectionProblem<ELEMENT>::doc_solution
()
291
{
292
//Declare an output stream and filename
293
ofstream some_file;
294
char
filename[100];
295
296
// Number of plot points: npts x npts
297
unsigned
npts=5;
298
299
// Output solution
300
//-----------------
301
snprintf(filename,
sizeof
(filename),
"%s/soln%i.dat"
,Doc_info.directory().c_str(),
302
Doc_info.number());
303
some_file.open(filename);
304
mesh_pt()->output(some_file,npts);
305
some_file.close();
306
307
Doc_info.number()++;
308
}
// end of doc
309
310
311
//=======start_of_main================================================
312
/// Driver code for 2D Boussinesq convection problem
313
//====================================================================
314
int
main
(
int
argc,
char
**argv)
315
{
316
317
// Set the direction of gravity
318
Global_Physical_Variables::Direction_of_gravity
[0] = 0.0;
319
Global_Physical_Variables::Direction_of_gravity
[1] = -1.0;
320
321
//Construct our problem
322
ConvectionProblem<BuoyantQCrouzeixRaviartElement<2>
> problem;
323
324
// Apply the boundary condition at time zero
325
problem.
set_boundary_conditions
(0.0);
326
327
//Perform a single steady Newton solve
328
problem.steady_newton_solve();
329
330
//Document the solution
331
problem.
doc_solution
();
332
333
//Set the timestep
334
double
dt = 0.1;
335
336
//Initialise the value of the timestep and set an impulsive start
337
problem.assign_initial_values_impulsive(dt);
338
339
//Set the number of timesteps to our default value
340
unsigned
n_steps = 200;
341
342
//If we have a command line argument, perform fewer steps
343
//(used for self-test runs)
344
if
(argc > 1) {n_steps = 5;}
345
346
//Perform n_steps timesteps
347
for
(
unsigned
i=0;i<n_steps;++i)
348
{
349
problem.unsteady_newton_solve(dt);
350
problem.
doc_solution
();
351
}
352
353
}
// end of main
354
355
356
357
358
359
360
361
362
ConvectionProblem
2D Convection problem on rectangular domain, discretised with refineable elements....
Definition
boussinesq_convection.cc:76
ConvectionProblem::ConvectionProblem
ConvectionProblem()
Constructor.
Definition
boussinesq_convection.cc:137
ConvectionProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update the problem specs before solve (empty)
Definition
boussinesq_convection.cc:87
ConvectionProblem::actions_before_implicit_timestep
void actions_before_implicit_timestep()
Actions before the timestep (update the the time-dependent boundary conditions)
Definition
boussinesq_convection.cc:97
ConvectionProblem::fix_pressure
void fix_pressure(const unsigned &e, const unsigned &pdof, const double &pvalue)
Fix pressure in element e at pressure dof pdof and set to pvalue.
Definition
boussinesq_convection.cc:103
ConvectionProblem::set_boundary_conditions
void set_boundary_conditions(const double &time)
Set the boundary conditions.
Definition
boussinesq_convection.cc:237
ConvectionProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update the problem after solve (empty)
Definition
boussinesq_convection.cc:90
ConvectionProblem::~ConvectionProblem
~ConvectionProblem()
Destructor. Empty.
Definition
boussinesq_convection.cc:84
ConvectionProblem::doc_solution
void doc_solution()
Doc the solution.
Definition
boussinesq_convection.cc:290
ConvectionProblem::actions_before_adapt
void actions_before_adapt()
Actions before adapt:(empty)
Definition
boussinesq_convection.cc:93
ConvectionProblem::mesh_pt
RectangularQuadMesh< ELEMENT > * mesh_pt()
Overloaded version of the problem's access function to the mesh. Recasts the pointer to the base Mesh...
Definition
boussinesq_convection.cc:120
ConvectionProblem::Doc_info
DocInfo Doc_info
DocInfo object.
Definition
boussinesq_convection.cc:129
main
int main()
Driver code for 2D Boussinesq convection problem with adaptivity.
Definition
multi_domain_ref_b_convection.cc:464
Global_Physical_Variables
Namespace for the physical parameters in the problem.
Definition
boussinesq_convection.cc:49
Global_Physical_Variables::Direction_of_gravity
Vector< double > Direction_of_gravity(2)
Gravity vector.
Global_Physical_Variables::Rayleigh
double Rayleigh
Rayleigh number, set to be greater than the threshold for linear instability.
Definition
boussinesq_convection.cc:58
Global_Physical_Variables::Inverse_Prandtl
double Inverse_Prandtl
1/Prandtl number
Definition
boussinesq_convection.cc:54
Global_Physical_Variables::Peclet
double Peclet
Peclet number (identically one from our non-dimensionalisation)
Definition
boussinesq_convection.cc:51
oomph
Definition
boussinesq_elements.h:41