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
spine_channel
spine_channel.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 2-D Channel with changing width, using Taylor Hood
27
// and Crouzeix Raviart elements.
28
29
// Generic oomph-lib header
30
#include "generic.h"
31
32
// Navier Stokes headers
33
#include "navier_stokes.h"
34
35
// The mesh
36
#include "meshes/channel_spine_mesh.h"
37
38
using namespace
std;
39
40
using namespace
oomph;
41
42
//==start_of_namespace===================================================
43
/// Namespace for physical parameters
44
//=======================================================================
45
namespace
Global_Physical_Variables
46
{
47
48
/// Reynolds number
49
double
Re
=100;
50
51
}
// end_of_namespace
52
53
54
55
56
57
///////////////////////////////////////////////////////////////////////
58
///////////////////////////////////////////////////////////////////////
59
// Sinusoidal wall as geometric object
60
///////////////////////////////////////////////////////////////////////
61
///////////////////////////////////////////////////////////////////////
62
63
64
65
//=========================================================================
66
/// Geometric object representing a sinusoidal wall, parametrised by
67
/// \f[ x = \zeta \f]
68
/// \f[ y = H + A \sin\left(\frac{2\pi \left(\zeta-\zeta_{\mbox{min}}\right)}
69
/// {\zeta_{\mbox{max}}-\zeta_{\mbox{min}}}
70
/// \right)\f]
71
//=========================================================================
72
class
SinusoidalWall
:
public
GeomObject
73
{
74
75
public
:
76
77
/// Constructor: Pass height, amplitude, zeta min and zeta max
78
/// (all are pinned by default)
79
SinusoidalWall
(
const
double
& height,
const
double
&
amplitude
,
80
const
double
&
zeta_min
,
const
double
&
zeta_max
)
81
: GeomObject(1,2)
82
{
83
// Make space for the geometric data
84
Geom_data_pt
.resize(1);
85
86
// Create data: Four value, no time dependence, free by default
87
Geom_data_pt
[0] =
new
Data
(4);
88
89
// I've created the data, I have to clean up
90
Must_clean_up
=
true
;
91
92
// Pin the data
93
for
(
unsigned
i
=0;
i
<4;
i
++) {
Geom_data_pt
[0]->pin(
i
);}
94
95
// Give it a value: Initial height
96
Geom_data_pt
[0]->set_value(0,height);
97
Geom_data_pt
[0]->set_value(1,
amplitude
);
98
Geom_data_pt
[0]->set_value(2,
zeta_min
);
99
Geom_data_pt
[0]->set_value(3,
zeta_max
);
100
}
101
102
103
/// Constructor: One item of geometric data, containing
104
/// four values:
105
/// \code
106
/// Geom_data_pt[0]->value(0) = height
107
/// Geom_data_pt[0]->value(1) = amplitude
108
/// Geom_data_pt[0]->value(2) = zeta_min
109
/// Geom_data_pt[0]->value(3) = zeta_max
110
/// \endcode
111
SinusoidalWall
(
const
Vector<Data*>
&
geom_data_pt
) : GeomObject(1,2)
112
{
113
#ifdef PARANOID
114
if
(
geom_data_pt
.size()!=1)
115
{
116
std::ostringstream
error_stream
;
117
error_stream
118
<<
"Wrong size for geom_data_pt "
<<
geom_data_pt
.size() << std::endl;
119
if
(
geom_data_pt
[0]->
nvalue
()!=1)
120
{
121
error_stream
<<
"Wrong geom_data_pt[0]->nvalue() "
122
<<
geom_data_pt
[0]->nvalue() << std::endl;
123
}
124
125
throw
OomphLibError
(
error_stream
.str(),
126
OOMPH_CURRENT_FUNCTION
,
127
OOMPH_EXCEPTION_LOCATION
);
128
}
129
#endif
130
Geom_data_pt
.resize(1);
131
Geom_data_pt
[0]=
geom_data_pt
[0];
132
133
// Data has been created externally: Must not clean up
134
Must_clean_up
=
false
;
135
}
136
137
138
139
/// Destructor: Clean up if necessary
140
~SinusoidalWall
()
141
{
142
// Do I need to clean up?
143
if
(
Must_clean_up
)
144
{
145
delete
Geom_data_pt
[0];
146
Geom_data_pt
[0]=0;
147
}
148
}
149
150
/// Access function for horizontal half axis
151
double
&
height
(){
return
*
Geom_data_pt
[0]->value_pt(0);}
152
153
/// Access function for vertical half axis
154
double
&
amplitude
(){
return
*
Geom_data_pt
[0]->value_pt(1);}
155
156
157
/// Position vector at Lagrangian coordinate zeta
158
void
position(
const
Vector<double>
&
zeta
,
Vector<double>
&
r
)
const
159
{
160
#ifdef PARANOID
161
if
(
r
.size()!=
Ndim
)
162
{
163
throw
OomphLibError
(
"The vector r has the wrong dimension\n"
,
164
OOMPH_CURRENT_FUNCTION
,
165
OOMPH_EXCEPTION_LOCATION
);
166
}
167
#endif
168
// Get parameters
169
double
H
=
Geom_data_pt
[0]->value(0);
170
double
A
=
Geom_data_pt
[0]->value(1);
171
double
zeta_min
=
Geom_data_pt
[0]->value(2);
172
double
zeta_max
=
Geom_data_pt
[0]->value(3);
173
double
Lz
=
zeta_max
-
zeta_min
;
174
175
// Position Vector
176
r
[0] =
zeta
[0];
177
r
[1] =
H
+
A
*
sin
(
MathematicalConstants::Pi
*(
zeta
[0]-
zeta_min
)/
Lz
);
178
}
179
180
181
/// Parametrised position on object: r(zeta). Evaluated at
182
/// previous timestep. t=0: current time; t>0: previous
183
/// timestep.
184
void
position(
const
unsigned
&
t
,
const
Vector<double>
&
zeta
,
185
Vector<double>
&
r
)
const
186
{
187
#ifdef PARANOID
188
if
(
t
>
Geom_data_pt
[0]->
time_stepper_pt
()->
nprev_values
())
189
{
190
std::ostringstream
error_stream
;
191
error_stream
192
<<
"t > nprev_values() in SpikedLine: "
<<
t
<<
" "
193
<<
Geom_data_pt
[0]->time_stepper_pt()->nprev_values() << std::endl;
194
195
throw
OomphLibError
(
error_stream
.str(),
196
OOMPH_CURRENT_FUNCTION
,
197
OOMPH_EXCEPTION_LOCATION
);
198
}
199
#endif
200
201
// Get parameters
202
double
H
=
Geom_data_pt
[0]->value(
t
,0);
203
double
A
=
Geom_data_pt
[0]->value(
t
,1);
204
double
zeta_min
=
Geom_data_pt
[0]->value(
t
,2);
205
double
zeta_max
=
Geom_data_pt
[0]->value(
t
,3);
206
double
Lz
=
zeta_max
-
zeta_min
;
207
208
// Position Vector at time level t
209
r
[0] =
zeta
[0];
210
r
[1] =
H
+
A
*
sin
(
MathematicalConstants::Pi
*(
zeta
[0]-
zeta_min
)/
Lz
);
211
}
212
213
214
215
/// Derivative of position Vector w.r.t. to coordinates:
216
/// \f$ \frac{dR_i}{d \zeta_\alpha}\f$ = drdzeta(alpha,i).
217
/// Evaluated at current time.
218
virtual
void
dposition
(
const
Vector<double>
&
zeta
,
219
DenseMatrix<double>
&
drdzeta
)
const
220
{
221
// Get parametres
222
double
A
=
Geom_data_pt
[0]->value(1);
223
double
zeta_min
=
Geom_data_pt
[0]->value(2);
224
double
zeta_max
=
Geom_data_pt
[0]->value(3);
225
double
Lz
=
zeta_max
-
zeta_min
;
226
227
// Tangent vector
228
drdzeta
(0,0)=1.0;
229
drdzeta
(0,1)=
MathematicalConstants::Pi
*
A
*
230
cos
(
MathematicalConstants::Pi
*(
zeta
[0]-
zeta_min
)/
Lz
)/
Lz
;
231
}
232
233
234
/// 2nd derivative of position Vector w.r.t. to coordinates:
235
/// \f$ \frac{d^2R_i}{d \zeta_\alpha d \zeta_\beta}\f$ = ddrdzeta(alpha,beta,i).
236
/// Evaluated at current time.
237
virtual
void
d2position
(
const
Vector<double>
&
zeta
,
238
RankThreeTensor<double>
&
ddrdzeta
)
const
239
{
240
// Get parametres
241
double
A
=
Geom_data_pt
[0]->value(1);
242
double
zeta_min
=
Geom_data_pt
[0]->value(2);
243
double
zeta_max
=
Geom_data_pt
[0]->value(3);
244
double
Lz
=
zeta_max
-
zeta_min
;
245
246
// Derivative of tangent vector
247
ddrdzeta
(0,0,0)=0.0;
248
ddrdzeta
(0,0,1)=-
MathematicalConstants::Pi
*
MathematicalConstants::Pi
*
249
A
*
sin
(
MathematicalConstants::Pi
*(
zeta
[0]-
zeta_min
)/
Lz
)/(
Lz
*
Lz
);
250
}
251
252
253
/// Posn Vector and its 1st & 2nd derivatives
254
/// w.r.t. to coordinates:
255
/// \f$ \frac{dR_i}{d \zeta_\alpha}\f$ = drdzeta(alpha,i).
256
/// \f$ \frac{d^2R_i}{d \zeta_\alpha d \zeta_\beta}\f$ = ddrdzeta(alpha,beta,i).
257
/// Evaluated at current time.
258
virtual
void
d2position
(
const
Vector<double>
&
zeta
,
Vector<double>
&
r
,
259
DenseMatrix<double>
&
drdzeta
,
260
RankThreeTensor<double>
&
ddrdzeta
)
const
261
{
262
// Get parametres
263
double
H
=
Geom_data_pt
[0]->value(0);
264
double
A
=
Geom_data_pt
[0]->value(1);
265
double
zeta_min
=
Geom_data_pt
[0]->value(2);
266
double
zeta_max
=
Geom_data_pt
[0]->value(3);
267
double
Lz
=
zeta_max
-
zeta_min
;
268
269
// Position Vector
270
r
[0] =
zeta
[0];
271
r
[1] =
H
+
A
*
sin
(
MathematicalConstants::Pi
*(
zeta
[0]-
zeta_min
)/
Lz
);
272
273
// Tangent vector
274
drdzeta
(0,0)=1.0;
275
drdzeta
(0,1)=
MathematicalConstants::Pi
*
A
*
276
cos
(
MathematicalConstants::Pi
*(
zeta
[0]-
zeta_min
)/
Lz
)/
Lz
;
277
278
// Derivative of tangent vector
279
ddrdzeta
(0,0,0)=0.0;
280
ddrdzeta
(0,0,1)=-
MathematicalConstants::Pi
*
MathematicalConstants::Pi
*
281
A
*
sin
(
MathematicalConstants::Pi
*(
zeta
[0]-
zeta_min
)/
Lz
)/(
Lz
*
Lz
);
282
}
283
284
/// How many items of Data does the shape of the object depend on?
285
unsigned
ngeom_data
()
const
{
return
Geom_data_pt
.size();}
286
287
/// Return pointer to the j-th Data item that the object's
288
/// shape depends on
289
Data
*
geom_data_pt
(
const
unsigned
&
j
) {
return
Geom_data_pt
[
j
];}
290
291
292
private
:
293
294
/// Vector of pointers to Data items that affects the object's shape
295
Vector<Data*>
Geom_data_pt
;
296
297
/// Do I need to clean up?
298
bool
Must_clean_up
;
299
300
};
301
302
///////////////////////////////////////////////////////////////////////
303
///////////////////////////////////////////////////////////////////////
304
///////////////////////////////////////////////////////////////////////
305
306
307
308
//==start_of_problem_class============================================
309
/// Channel flow through a non-uniform channel whose geometry is defined
310
/// by a spine mesh.
311
//====================================================================
312
template
<
class
ELEMENT>
313
class
ChannelSpineFlowProblem
:
public
Problem
314
{
315
316
public
:
317
318
/// Constructor
319
ChannelSpineFlowProblem
();
320
321
/// Destructor: (empty)
322
~ChannelSpineFlowProblem
(){}
323
324
/// Update the problem specs before solve.
325
/// Set velocity boundary conditions just to be on the safe side...
326
void
actions_before_newton_solve
()
327
{
328
// Update the mesh
329
mesh_pt
()->node_update();
330
331
}
// end_of_actions_before_newton_solve
332
333
334
/// Update the after solve (empty)
335
void
actions_after_newton_solve
(){}
336
337
/// Doc the solution
338
void
doc_solution
(
DocInfo
&
doc_info
);
339
340
private
:
341
342
/// Width of channel
343
double
Ly
;
344
345
346
};
// end_of_problem_class
347
348
349
350
//==start_of_constructor==================================================
351
/// Constructor for ChannelSpineFlow problem
352
//========================================================================
353
template
<
class
ELEMENT>
354
ChannelSpineFlowProblem<ELEMENT>::ChannelSpineFlowProblem
()
355
{
356
357
// Setup mesh
358
359
// # of elements in x-direction in left region
360
unsigned
Nx0
=3;
361
// # of elements in x-direction in centre region
362
unsigned
Nx1
=12;
363
// # of elements in x-direction in right region
364
unsigned
Nx2
=8;
365
366
// # of elements in y-direction
367
unsigned
Ny
=10;
368
369
// Domain length in x-direction in left region
370
double
Lx0
=0.5;
371
// Domain length in x-direction in centre region
372
double
Lx1
=0.7;
373
// Domain length in x-direction in right region
374
double
Lx2
=1.5;
375
376
// Domain length in y-direction
377
Ly=1.0;
378
379
// Build geometric object that represents the sinusoidal bump on
380
// the upper wall:
381
382
// 40% indendentation
383
double
amplitude_upper
= -0.4*Ly;
384
// Minimum and maximum coordinates of bump
385
double
zeta_min
=
Lx0
;
386
double
zeta_max
=
Lx0
+
Lx1
;
387
GeomObject*
UpperWall
=
388
new
SinusoidalWall
(Ly,
amplitude_upper
,
zeta_min
,
zeta_max
);
389
390
// Build and assign mesh -- pass pointer to geometric object
391
// that represents the sinusoidal bump on the upper wall
392
Problem::mesh_pt() =
new
ChannelSpineMesh<ELEMENT>
(
Nx0
,
Nx1
,
Nx2
,
Ny
,
393
Lx0
,
Lx1
,
Lx2
,Ly,
394
UpperWall
);
395
396
397
// Set the boundary conditions for this problem: All nodes are
398
// free by default -- just pin the ones that have Dirichlet conditions
399
// here: All boundaries are Dirichlet boundaries, except on boundary 1
400
unsigned
num_bound
= mesh_pt()->nboundary();
401
for
(
unsigned
ibound
=0;
ibound
<
num_bound
;
ibound
++)
402
{
403
unsigned
num_nod
= mesh_pt()->nboundary_node(
ibound
);
404
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
405
{
406
if
(
ibound
!=1)
407
{
408
// Loop over values (u and v velocities)
409
for
(
unsigned
i
=0;
i
<2;
i
++)
410
{
411
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->pin(
i
);
412
}
413
}
414
else
415
{
416
// Parallel outflow ==> no-slip
417
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->pin(1);
418
}
419
}
420
}
// end loop over boundaries
421
422
423
// No slip on stationary upper and lower walls (boundaries 0 and 2)
424
// and parallel outflow (boundary 1)
425
for
(
unsigned
ibound
=0;
ibound
<
num_bound
-1;
ibound
++)
426
{
427
unsigned
num_nod
= mesh_pt()->nboundary_node(
ibound
);
428
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
429
{
430
if
(
ibound
!=1)
431
{
432
for
(
unsigned
i
=0;
i
<2;
i
++)
433
{
434
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(
i
,0.0);
435
}
436
}
437
else
438
{
439
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(1,0.0);
440
}
441
}
442
}
443
444
445
// Setup parabolic inflow along boundary 3:
446
unsigned
ibound
=3;
447
unsigned
num_nod
= mesh_pt()->nboundary_node(
ibound
);
448
for
(
unsigned
inod
=0;
inod
<
num_nod
;
inod
++)
449
{
450
double
y
=mesh_pt()->boundary_node_pt(
ibound
,
inod
)->x(1);
451
// Parallel, parabolic inflow
452
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(0,
y
*(Ly-
y
));
453
mesh_pt()->boundary_node_pt(
ibound
,
inod
)->set_value(1,0.0);
454
}
455
456
// Find number of elements in mesh
457
unsigned
n_element
= mesh_pt()->nelement();
458
459
// Loop over the elements to set up element-specific
460
// things that cannot be handled by constructor: Pass
461
// pointer to Reynolds number
462
for
(
unsigned
e
=0;
e
<
n_element
;
e
++)
463
{
464
// Upcast from GeneralisedElement to the present element
465
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(mesh_pt()->element_pt(
e
));
466
//Set the Reynolds number
467
el_pt
->re_pt() = &
Global_Physical_Variables::Re
;
468
}
469
470
// Setup equation numbering scheme
471
cout
<<
"Number of equations: "
<<
assign_eqn_numbers
() << std::endl;
472
473
}
// end_of_constructor
474
475
476
477
478
//==start_of_doc_solution=================================================
479
/// Doc the solution
480
//========================================================================
481
template
<
class
ELEMENT>
482
void
ChannelSpineFlowProblem<ELEMENT>::doc_solution
(
DocInfo
&
doc_info
)
483
{
484
485
ofstream
some_file
;
486
char
filename
[100];
487
488
// Number of plot points
489
unsigned
npts
=5;
490
491
// Output solution
492
snprintf
(
filename
,
sizeof
(
filename
),
"%s/soln%i.dat"
,
doc_info
.directory().c_str(),
493
doc_info
.number());
494
some_file
.open(
filename
);
495
mesh_pt()->output(
some_file
,
npts
);
496
some_file
.close();
497
498
}
// end_of_doc_solution
499
500
501
502
//==start_of_main======================================================
503
/// Driver for channel flow problem with spine mesh.
504
//=====================================================================
505
int
main
()
506
{
507
508
// Set output directory
509
DocInfo
doc_info
;
510
doc_info
.set_directory(
"RESLT"
);
511
doc_info
.number()=0;
512
513
// Solve problem with Taylor Hood elements
514
//---------------------------------------
515
{
516
//Build problem
517
ChannelSpineFlowProblem<SpineElement<QTaylorHoodElement<2>
> >
518
problem
;
519
520
// Solve the problem with automatic adaptation
521
problem
.newton_solve();
522
523
//Output solution
524
problem
.doc_solution(
doc_info
);
525
// Step number
526
doc_info
.number()++;
527
528
}
// end of Taylor Hood elements
529
530
531
// Solve problem with Crouzeix Raviart elements
532
//--------------------------------------------
533
{
534
// Build problem
535
ChannelSpineFlowProblem<SpineElement<QCrouzeixRaviartElement<2>
> >
536
problem
;
537
538
// Solve the problem with automatic adaptation
539
problem
.newton_solve();
540
541
//Output solution
542
problem
.doc_solution(
doc_info
);
543
// Step number
544
doc_info
.number()++;
545
546
}
// end of Crouzeix Raviart elements
547
548
549
550
}
// end_of_main
551
552
553
554
555
//====================================================================
556
/// Create the files to illustrate the sparse node update operation
557
//====================================================================
558
void
doc_sparse_node_update
()
559
{
560
561
// Set output directory
562
DocInfo
doc_info
;
563
doc_info
.set_directory(
"RESLT"
);
564
565
// Setup mesh
566
567
// # of elements in x-direction in left region
568
unsigned
Nx0
=1;
569
// # of elements in x-direction in centre region
570
unsigned
Nx1
=5;
571
// # of elements in x-direction in right region
572
unsigned
Nx2
=1;
573
574
// # of elements in y-direction
575
unsigned
Ny
=5;
576
577
// Domain length in x-direction in left region
578
double
Lx0
=0.5;
579
// Domain length in x-direction in centre region
580
double
Lx1
=1.0;
581
// Domain length in x-direction in right region
582
double
Lx2
=0.5;
583
584
// Domain length in y-direction
585
double
Ly=1.0;
586
587
double
amplitude_upper
= -0.4*Ly;
588
double
zeta_min
=
Lx0
;
589
double
zeta_max
=
Lx0
+
Lx1
;
590
GeomObject*
UpperWall
=
591
new
SinusoidalWall
(Ly,
amplitude_upper
,
zeta_min
,
zeta_max
);
592
593
// Build and assign mesh
594
ChannelSpineMesh<SpineElement<QTaylorHoodElement<2>
> >* mesh_pt =
595
new
ChannelSpineMesh<SpineElement<QTaylorHoodElement<2>
> >(
Nx0
,
Nx1
,
Nx2
,
Ny
,
596
Lx0
,
Lx1
,
Lx2
,Ly,
597
UpperWall
);
598
599
// Update *all* nodal positions
600
mesh_pt->node_update();
601
602
// Change the amplitude
603
dynamic_cast<
SinusoidalWall
*
>
(mesh_pt->wall_pt())->
amplitude
()=0.5;
604
605
unsigned
count
=0;
606
ofstream
some_file
;
607
char
filename
[100];
608
609
// Number of plot points
610
unsigned
npts
=5;
611
612
// Output solution
613
snprintf
(
filename
,
sizeof
(
filename
),
"%s/mesh_update%i.dat"
,
doc_info
.directory().c_str(),
614
count
);
615
count
++;
616
617
// Loop over spines in centre
618
unsigned
n_node
= mesh_pt->nnode();
619
for
(
unsigned
inode
=0;
inode
<
n_node
;
inode
++)
620
{
621
SpineNode
*
node_pt
=
dynamic_cast<
SpineNode
*
>
(
622
mesh_pt->node_pt(
inode
));
623
if
(
node_pt
->node_update_fct_id()==1)
624
{
625
node_pt
->node_update();
626
// Output solution
627
some_file
.open(
filename
);
628
snprintf
(
filename
,
sizeof
(
filename
),
"%s/mesh_update%i.dat"
,
doc_info
.directory().c_str(),
629
count
);
630
count
++;
631
mesh_pt->output(
some_file
,
npts
);
632
some_file
.close();
633
}
634
}
635
636
}
637
638
639
640
641
642
643
644
645
646
647
648
649
650
ChannelSpineFlowProblem
Channel flow through a non-uniform channel whose geometry is defined by a spine mesh.
Definition
simple_spine_channel.cc:459
ChannelSpineFlowProblem::doc_solution
void doc_solution(DocInfo &doc_info)
Doc the solution.
ChannelSpineFlowProblem::ChannelSpineFlowProblem
ChannelSpineFlowProblem()
Constructor.
ChannelSpineFlowProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update the after solve (empty)
Definition
spine_channel.cc:335
ChannelSpineFlowProblem::Ly
double Ly
Width of channel.
Definition
simple_spine_channel.cc:494
ChannelSpineFlowProblem::mesh_pt
SimpleSpineMesh< ELEMENT > * mesh_pt()
Overload access to mesh.
Definition
simple_spine_channel.cc:485
ChannelSpineFlowProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update the problem specs before solve. Set velocity boundary conditions just to be on the safe side....
Definition
spine_channel.cc:326
ChannelSpineFlowProblem::~ChannelSpineFlowProblem
~ChannelSpineFlowProblem()
Destructor: (empty)
Definition
spine_channel.cc:322
SimpleSpineMesh
Simple spine mesh class derived from standard 2D mesh. Vertical lines of nodes are located on spines.
Definition
simple_spine_channel.cc:91
SimpleSpineMesh::SimpleSpineMesh
SimpleSpineMesh(const unsigned &nx, const unsigned &ny, const double &lx, const double &h, GeomObject *substrate_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass number of elements in x-direction, number of elements in y-direction,...
Definition
simple_spine_channel.cc:206
Global_Physical_Variables
Namespace for physical parameters.
Definition
simple_spine_channel.cc:408
Global_Physical_Variables::A
double A
Amplitude of indentation.
Definition
simple_spine_channel.cc:426
Global_Physical_Variables::height
double height(const double &x)
Height of domain.
Definition
simple_spine_channel.cc:429
Global_Physical_Variables::Re
double Re
Reynolds number.
Definition
simple_spine_channel.cc:411
Global_Physical_Variables::H
double H
Undeformed height of domain.
Definition
simple_spine_channel.cc:423
doc_sparse_node_update
void doc_sparse_node_update()
Create the files to illustrate the sparse node update operation.
Definition
spine_channel.cc:558
main
int main()
Driver for channel flow problem with spine mesh.
Definition
spine_channel.cc:505