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
src
meshes
channel_with_leaflet_mesh.template.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
27
#ifndef OOMPH_CHANNEL_WITH_LEAFLET_MESH_TEMPLATE_HEADER
28
#define OOMPH_CHANNEL_WITH_LEAFLET_MESH_TEMPLATE_HEADER
29
30
#ifndef OOMPH_CHANNEL_WITH_LEAFLET_MESH_HEADER
31
#error __FILE__ should only be included from channel_with_leaflet_mesh.h.
32
#endif
// OOMPH_CHANNEL_WITH_LEAFLET_MESH_HEADER
33
34
// Include the headers file
35
36
namespace
oomph
37
{
38
//===================================================================
39
/// Constructor: Pass pointer to GeomObject that represents the leaflet,
40
/// the length of the domain to left and right of the leaflet, the
41
/// height of the leaflet and the overall height of the channel,
42
/// the number of element columns to the left and right of the leaflet,
43
/// the number of rows of elements from the bottom of the channel to
44
/// the end of the leaflet, the number of rows of elements above the
45
/// end of the leaflet. Timestepper defaults to Steady default
46
/// Timestepper defined in the Mesh base class
47
//===================================================================
48
template
<
class
ELEMENT>
49
ChannelWithLeafletMesh<ELEMENT>::ChannelWithLeafletMesh
(
50
GeomObject
* leaflet_pt,
51
const
double
& lleft,
52
const
double
& lright,
53
const
double
& hleaflet,
54
const
double
& htot,
55
const
unsigned
& nleft,
56
const
unsigned
& nright,
57
const
unsigned
&
ny1
,
58
const
unsigned
&
ny2
,
59
TimeStepper
*
time_stepper_pt
)
60
:
SimpleRectangularQuadMesh
<
ELEMENT
>(
61
nright + nleft,
ny1
+
ny2
, lright + lleft, htot,
time_stepper_pt
)
62
{
63
// Mesh can only be built with 2D Qelements.
64
MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
65
66
// Copy pointer to leaflet into private storage
67
Leaflet_pt
= leaflet_pt;
68
69
// Create the ChannelWithLeafletDomain with the wall
70
// represented by the geometric object
71
Domain_pt
=
new
ChannelWithLeafletDomain
(
72
leaflet_pt, lleft, lright, hleaflet, htot, nleft, nright,
ny1
,
ny2
);
73
74
// Total number of (macro/finite)elements
75
unsigned
nmacro
= (
ny1
+
ny2
) * (nleft + nright);
76
77
// Loop over all elements and set macro element pointer
78
for
(
unsigned
e
= 0;
e
<
nmacro
;
e
++)
79
{
80
// Get pointer to finite element
81
FiniteElement
*
el_pt
= this->
finite_element_pt
(
e
);
82
83
// Set pointer to macro element
84
el_pt
->set_macro_elem_pt(this->
Domain_pt
->macro_element_pt(
e
));
85
}
86
87
// Update the nodal positions corresponding to their
88
// macro element representations.
89
this->node_update();
90
91
// Change the numbers of boundaries
92
this->
set_nboundary
(7);
93
94
// Remove the nodes of boundary 0
95
this->
remove_boundary_nodes
(0);
96
97
// Get the number of nodes along the element edge from first element
98
unsigned
nnode_1d
= this->
finite_element_pt
(0)->nnode_1d();
99
100
// Boundary 0 will be before the wall, boundary 6 after it
101
for
(
unsigned
e
= 0;
e
< nleft;
e
++)
102
{
103
for
(
unsigned
i
= 0;
i
<
nnode_1d
;
i
++)
104
{
105
Node
*
nod_pt
= this->
finite_element_pt
(
e
)->node_pt(
i
);
106
// do not add the last node : it will go to boundary 6
107
if
(
e
!= nleft - 1 ||
i
!= 2)
108
{
109
this->
add_boundary_node
(0,
nod_pt
);
110
}
111
}
112
}
113
114
for
(
unsigned
e
= nleft;
e
< nleft + nright;
e
++)
115
{
116
for
(
unsigned
i
= 0;
i
<
nnode_1d
;
i
++)
117
{
118
Node
*
nod_pt
= this->
finite_element_pt
(
e
)->node_pt(
i
);
119
this->
add_boundary_node
(6,
nod_pt
);
120
}
121
}
122
123
// Vector of Lagrangian coordinates used as boundary coordinate
124
Vector<double>
zeta
(1);
125
126
// Set the wall as a boundary
127
for
(
unsigned
k
= 0;
k
<
ny1
;
k
++)
128
{
129
unsigned
e
= (nleft + nright) *
k
+ nleft - 1;
130
for
(
unsigned
i
= 0;
i
<
nnode_1d
;
i
++)
131
{
132
Node
*
nod_pt
=
133
this->
finite_element_pt
(
e
)->node_pt((
i
+ 1) *
nnode_1d
- 1);
134
this->
convert_to_boundary_node
(
nod_pt
);
135
this->
add_boundary_node
(4,
nod_pt
);
136
137
// Set coordinates
138
zeta
[0] =
double
(
k
) * hleaflet /
double
(
ny1
) +
139
double
(
i
) * hleaflet /
double
(
ny1
) /
double
(
nnode_1d
- 1);
140
nod_pt
->set_coordinates_on_boundary(4,
zeta
);
141
}
142
}
143
144
// Duplicate the nodes of the wall and assign then as a boundary.
145
// This will make one boundary for the east of the elements at the
146
// left of the wall, and one for the west of the elements at the right
147
// of the wall.
148
// This is necessary to use TaylorHoodElements, because it will allow
149
// a discontinuity of the pressure accross the wall.
150
// We separate the lower element from the rest as we do not want to
151
// add the same node twice to the boundary, and the upper element as its
152
// upper node must be the same one than the node of the upper element
153
// at the right of the wall
154
155
// Lower element
156
unsigned
e
= nleft - 1;
157
158
// Allocate storage for newly created node outside
159
// so we can refer to the most recently created one below.
160
Node
*
nod_pt
= 0;
161
162
// duplicate the east nodes and add them to the 6th boundary
163
// Add the first node to the 0th boundary (horizontal)
164
for
(
unsigned
i
= 0;
i
<
nnode_1d
;
i
++)
165
{
166
nod_pt
= this->
finite_element_pt
(
e
)->construct_boundary_node(
167
(
i
+ 1) *
nnode_1d
- 1,
time_stepper_pt
);
168
this->
add_boundary_node
(5,
nod_pt
);
169
if
(
i
== 0)
170
{
171
this->
add_boundary_node
(0,
nod_pt
);
172
}
173
this->
add_node_pt
(
nod_pt
);
174
// Set coordinates
175
zeta
[0] =
i
* hleaflet /
double
(
ny1
) /
double
(
nnode_1d
- 1);
176
nod_pt
->set_coordinates_on_boundary(5,
zeta
);
177
}
178
179
// Other elements just at the left of the wall
180
for
(
unsigned
k
= 1;
k
<
ny1
;
k
++)
181
{
182
e
= (nleft + nright) *
k
+ nleft - 1;
183
184
// add the upper node of the previous element
185
this->
finite_element_pt
(
e
)->node_pt(
nnode_1d
- 1) =
nod_pt
;
186
this->
add_boundary_node
(5,
nod_pt
);
187
// Set coordinates
188
zeta
[0] =
k
* hleaflet /
double
(
ny1
);
189
nod_pt
->set_coordinates_on_boundary(5,
zeta
);
190
191
// Loop over other nodes on element's eastern edge
192
for
(
unsigned
i
= 1;
i
<
nnode_1d
;
i
++)
193
{
194
// Don't duplicate the node at the very top of the "obstacle"
195
if
((
k
==
ny1
- 1) && (
i
==
nnode_1d
- 1))
196
{
197
// Get the node but don't do anything else
198
nod_pt
= this->
finite_element_pt
(
e
)->node_pt(
nnode_1d
*
nnode_1d
- 1);
199
}
200
else
201
{
202
// Overwrite the node with a boundary node
203
nod_pt
= this->
finite_element_pt
(
e
)->construct_boundary_node(
204
(
i
+ 1) *
nnode_1d
- 1,
time_stepper_pt
);
205
this->
add_node_pt
(
nod_pt
);
206
}
207
208
// Add node to boundary
209
this->
add_boundary_node
(5,
nod_pt
);
210
// Set coordinates
211
zeta
[0] =
double
(
k
) * hleaflet /
double
(
ny1
) +
212
double
(
i
) * hleaflet /
double
(
ny1
) /
double
(
nnode_1d
- 1);
213
nod_pt
->set_coordinates_on_boundary(5,
zeta
);
214
}
215
}
216
217
this->node_update();
218
219
// Re-setup lookup scheme that establishes which elements are located
220
// on the mesh boundaries (doesn't need to be wiped)
221
this->setup_boundary_element_info();
222
223
// We have parametrised boundary 4 and 5
224
this->
set_boundary_coordinate_exists
(4);
225
this->
set_boundary_coordinate_exists
(5);
226
227
}
// end of constructor
228
229
230
///////////////////////////////////////////////////////////////////////
231
//////////////////////////////////////////////////////////////////////
232
///////////////////////////////////////////////////////////////////////
233
234
//=================================================================
235
/// Setup algebraic node update. Leaflet is
236
/// assumed to be in its undeformed (straight vertical) position!
237
//=================================================================
238
template
<
class
ELEMENT>
239
void
AlgebraicChannelWithLeafletMesh<ELEMENT>::setup_algebraic_node_update
()
240
{
241
// Extract some reference lengths from the Domain.
242
double
hleaflet = this->domain_pt()->hleaflet();
243
double
htot = this->domain_pt()->htot();
244
double
lleft = this->domain_pt()->lleft();
245
double
lright = this->domain_pt()->lright();
246
247
// Loop over all nodes in mesh
248
unsigned
nnod
= this->
nnode
();
249
for
(
unsigned
j
= 0;
j
<
nnod
;
j
++)
250
{
251
// Get pointer to node
252
AlgebraicNode
*
nod_pt
=
node_pt
(
j
);
253
254
// Get coordinates
255
double
x =
nod_pt
->x(0);
256
double
y =
nod_pt
->x(1);
257
258
// Quick check to know if the wall is in its undeformed position
259
// It actually checks that the top of the wall is in (x_0,hleaflet)
260
Vector<double>
zeta
(1);
261
Vector<double>
r
(2);
262
zeta
[0] = Hleaflet;
263
this->Leaflet_pt->position(
zeta
,
r
);
264
if
((
r
[0] != X_0) || (
r
[1] != hleaflet))
265
{
266
std::ostringstream
error_stream
;
267
error_stream
<<
"Wall must be in its undeformed position when\n"
268
<<
"algebraic node update information is set up!\n "
269
<<
r
[0] <<
" "
<< X_0 <<
" "
<<
r
[1] <<
" "
<< hleaflet
270
<< std::endl;
271
throw
OomphLibError
(
272
error_stream
.str(),
OOMPH_CURRENT_FUNCTION
,
OOMPH_EXCEPTION_LOCATION
);
273
}
274
275
// The update function requires four parameters:
276
Vector<double>
ref_value
(4);
277
278
// Part I
279
if
((x <= X_0) && (y <= hleaflet))
280
{
281
// First reference value: y0
282
ref_value
[0] = y;
283
284
// zeta coordinate on wall : fourth reference value
285
//(needed for adaptativity)
286
Vector<double>
zeta
(1);
287
zeta
[0] = y;
288
ref_value
[3] =
zeta
[0];
289
290
// Sub-geomobject corresponding to the zeta coordinate on the wall
291
GeomObject
*
geom_obj_pt
;
292
Vector<double>
s
(1);
293
this->Leaflet_pt->locate_zeta(
zeta
,
geom_obj_pt
,
s
);
294
295
// Create vector of geomobject for add_node_update_info()
296
Vector<GeomObject*>
geom_object_pt
(1);
297
geom_object_pt
[0] =
geom_obj_pt
;
298
299
// Second reference value: Reference local coordinate
300
// in the sub-geomobject
301
ref_value
[1] =
s
[0];
302
303
// Third reference value:fraction of the horizontal line
304
// between the edge and the wall
305
ref_value
[2] = (lleft + x - X_0) / lleft;
306
307
// Setup algebraic update for node: Pass update information
308
// to AlgebraicNode:
309
nod_pt
->add_node_update_info(1,
// ID
310
this
,
// mesh
311
geom_object_pt
,
// vector of geom objects
312
ref_value
);
// vector of ref. values
313
}
314
// Part II
315
if
((x >= X_0) && (y <= hleaflet))
316
{
317
// First reference value: y0
318
ref_value
[0] = y;
319
320
// zeta coordinate on wall: fourth reference value
321
//(needed for adaptativity)
322
Vector<double>
zeta
(1);
323
zeta
[0] = y;
324
ref_value
[3] =
zeta
[0];
325
326
// Sub-geomobject corresponding to the zeta coordinate on the wall
327
GeomObject
*
geom_obj_pt
;
328
Vector<double>
s
(1);
329
this->Leaflet_pt->locate_zeta(
zeta
,
geom_obj_pt
,
s
);
330
331
// Create vector of geomobject for add_node_update_info()
332
Vector<GeomObject*>
geom_object_pt
(1);
333
geom_object_pt
[0] =
geom_obj_pt
;
334
335
// Second reference value: Reference local coordinate
336
// in the sub-geomobject
337
ref_value
[1] =
s
[0];
338
339
// Third reference value:fraction of the horizontal line
340
// between the edge and the wall
341
ref_value
[2] = (x - X_0) / lright;
342
343
// Setup algebraic update for node: Pass update information
344
// to AlgebraicNode:
345
nod_pt
->add_node_update_info(2,
// ID
346
this
,
// mesh
347
geom_object_pt
,
// vector of geom objects
348
ref_value
);
// vector of ref. values
349
}
350
// Part III
351
if
((x <= X_0) && (y >= hleaflet))
352
{
353
// First reference value: y0
354
ref_value
[0] = y;
355
356
// Second reference value: zeta coordinate on the middle line
357
ref_value
[1] = (y - hleaflet) / (htot - hleaflet);
358
359
// Third reference value:fraction of the horizontal line
360
// between the edge and the middle line
361
ref_value
[2] = (lleft + x - X_0) / lleft;
362
363
// geomobject
364
Vector<GeomObject*>
geom_object_pt
(1);
365
geom_object_pt
[0] = this->Leaflet_pt;
366
367
// Setup algebraic update for node: Pass update information
368
// to AlgebraicNode:
369
nod_pt
->add_node_update_info(3,
// ID
370
this
,
// mesh
371
geom_object_pt
,
// vector of geom objects
372
ref_value
);
// vector of ref. values
373
}
374
// Part IV
375
if
((x >= X_0) && (y >= hleaflet))
376
{
377
// First reference value: y0
378
ref_value
[0] = y;
379
380
// Second reference value: zeta coordinate on wall
381
ref_value
[1] = (y - hleaflet) / (htot - hleaflet);
382
383
// Third reference value:fraction of the horizontal line
384
// between the edge and the wall
385
ref_value
[2] = (x - X_0) / lright;
386
387
// geomobject
388
Vector<GeomObject*>
geom_object_pt
(1);
389
geom_object_pt
[0] = this->Leaflet_pt;
390
391
// Setup algebraic update for node: Pass update information
392
// to AlgebraicNode:
393
nod_pt
->add_node_update_info(4,
// ID
394
this
,
// mesh
395
geom_object_pt
,
// vector of geom objects
396
ref_value
);
// vector of ref. values
397
}
398
}
399
400
}
// end of setup_algebraic_node_update
401
402
//=================================================================
403
/// Perform algebraic node update
404
//=================================================================
405
template
<
class
ELEMENT>
406
void
AlgebraicChannelWithLeafletMesh<ELEMENT>::algebraic_node_update
(
407
const
unsigned
&
t
,
AlgebraicNode
*&
node_pt
)
408
{
409
unsigned
id
=
node_pt
->node_update_fct_id();
410
411
switch
(
id
)
412
{
413
case
1:
414
node_update_I(
t
,
node_pt
);
415
break
;
416
417
case
2:
418
node_update_II(
t
,
node_pt
);
419
break
;
420
421
case
3:
422
node_update_III(
t
,
node_pt
);
423
break
;
424
425
case
4:
426
node_update_IV(
t
,
node_pt
);
427
break
;
428
429
default
:
430
std::ostringstream
error_message
;
431
error_message
<<
"The node update fct id is "
<<
id
432
<<
", but it should only be one of "
<< 1 <<
", "
<< 2
433
<<
", "
<< 3 <<
" or "
<< 4 << std::endl;
434
std::string
function_name
=
435
"AlgebraicChannelWithLeafletMesh::algebraic_node_update()"
;
436
437
throw
OomphLibError
(
error_message
.str(),
438
OOMPH_CURRENT_FUNCTION
,
439
OOMPH_EXCEPTION_LOCATION
);
440
}
441
442
}
// end of algebraic_node_update()
443
444
//=================================================================
445
/// Node update for region I
446
//=================================================================
447
template
<
class
ELEMENT>
448
void
AlgebraicChannelWithLeafletMesh<ELEMENT>::node_update_I
(
449
const
unsigned
&
t
,
AlgebraicNode
*&
node_pt
)
450
{
451
// relevant data of the domain for part I
452
double
lleft = this->domain_pt()->lleft();
453
454
// Extract reference values for update by copy construction
455
Vector<double>
ref_value
(
node_pt
->vector_ref_value());
456
457
// Extract geometric objects for update by copy construction
458
Vector<GeomObject*>
geom_object_pt
(
node_pt
->vector_geom_object_pt());
459
460
// Pointer to wall geom object
461
GeomObject
* leaflet_pt =
geom_object_pt
[0];
462
463
// Coordinates of the steady node on the left boundary
464
// corresponding to the current node
465
double
y0
=
ref_value
[0];
466
double
x0
= -lleft + X_0;
467
468
// second reference value: local coordinate on wall
469
Vector<double>
s
(1);
470
s
[0] =
ref_value
[1];
471
472
// Get position vector to wall at timestep t
473
Vector<double>
r_wall
(2);
474
leaflet_pt->position(
t
,
s
,
r_wall
);
475
476
// Third reference value : fraction of the horizontal line
477
// between the edge and the wall
478
double
r
=
ref_value
[2];
479
480
// Assign new nodal coordinates
481
node_pt
->x(
t
, 0) =
x0
+
r
* (
r_wall
[0] -
x0
);
482
node_pt
->x(
t
, 1) =
y0
+
r
* (
r_wall
[1] -
y0
);
483
}
484
485
//=================================================================
486
/// Node update for region II
487
//=================================================================
488
template
<
class
ELEMENT>
489
void
AlgebraicChannelWithLeafletMesh<ELEMENT>::node_update_II
(
490
const
unsigned
&
t
,
AlgebraicNode
*&
node_pt
)
491
{
492
// relevant data of the domain for part II
493
double
lright = this->domain_pt()->lright();
494
495
// Extract reference values for update by copy construction
496
Vector<double>
ref_value
(
node_pt
->vector_ref_value());
497
498
// Extract geometric objects for update by copy construction
499
Vector<GeomObject*>
geom_object_pt
(
node_pt
->vector_geom_object_pt());
500
501
// Pointer to wall geom object
502
GeomObject
* leaflet_pt =
geom_object_pt
[0];
503
504
// Coordinates of the steady node on the right boundary
505
// corresponding to the current node
506
double
y0
=
ref_value
[0];
507
double
x0
= X_0 + lright;
508
509
// Second reference value: Zeta coordinate on wall
510
Vector<double>
s
(1);
511
s
[0] =
ref_value
[1];
512
513
// Get position vector to wall at timestep t
514
Vector<double>
r_wall
(2);
515
leaflet_pt->position(
t
,
s
,
r_wall
);
516
517
// Third reference value : fraction of the horizontal line
518
// between the wall and the right edge
519
double
r
=
ref_value
[2];
520
521
// Assign new nodal coordinates
522
node_pt
->x(
t
, 0) =
r_wall
[0] +
r
* (
x0
-
r_wall
[0]);
523
node_pt
->x(
t
, 1) =
r_wall
[1] +
r
* (
y0
-
r_wall
[1]);
524
}
525
526
//=================================================================
527
/// Slanted bound : helper function
528
//=================================================================
529
template
<
class
ELEMENT>
530
void
AlgebraicChannelWithLeafletMesh<ELEMENT>::slanted_bound_up
(
531
const
unsigned
&
t
,
const
Vector<double>
&
zeta
,
Vector<double>
&
r
)
532
{
533
/// Coordinates of the point on the boundary beetween the upper
534
/// and the lower part, in the same column, at the east.
535
double
htot = this->domain_pt()->htot();
536
537
Vector<double>
xi
(1);
538
xi
[0] = Hleaflet;
539
540
Vector<double>
r_join
(2);
541
542
this->Leaflet_pt->position(
t
,
xi
,
r_join
);
543
544
r
[0] =
r_join
[0] +
zeta
[0] * (X_0 -
r_join
[0]);
545
r
[1] =
r_join
[1] +
zeta
[0] * (htot -
r_join
[1]);
546
}
547
548
//=================================================================
549
/// Node update for region III
550
//=================================================================
551
template
<
class
ELEMENT>
552
void
AlgebraicChannelWithLeafletMesh<ELEMENT>::node_update_III
(
553
const
unsigned
&
t
,
AlgebraicNode
*&
node_pt
)
554
{
555
// relevant data of the domain for part I
556
double
lleft = this->domain_pt()->lleft();
557
558
// Extract reference values for update by copy construction
559
Vector<double>
ref_value
(
node_pt
->vector_ref_value());
560
561
// Coordinates of the steady node on the left boundary
562
// corresponding to the current node
563
double
y0
=
ref_value
[0];
564
double
x0
= -lleft + X_0;
565
566
Vector<double>
s
(1);
567
s
[0] =
ref_value
[1];
568
569
// Get position vector
570
Vector<double>
r_line
(2);
571
slanted_bound_up(
t
,
s
,
r_line
);
572
573
// Third reference value : fraction of the horizontal line
574
// between the edge and the middle line
575
double
r
=
ref_value
[2];
576
577
// Assign new nodal coordinates
578
node_pt
->x(
t
, 0) =
x0
+
r
* (
r_line
[0] -
x0
);
579
node_pt
->x(
t
, 1) =
y0
+
r
* (
r_line
[1] -
y0
);
580
}
581
582
//=================================================================
583
/// Node update for region IV
584
//=================================================================
585
template
<
class
ELEMENT>
586
void
AlgebraicChannelWithLeafletMesh<ELEMENT>::node_update_IV
(
587
const
unsigned
&
t
,
AlgebraicNode
*&
node_pt
)
588
{
589
// relevant data of the domain for part I
590
double
lright = this->domain_pt()->lright();
591
592
// Extract reference values for update by copy construction
593
Vector<double>
ref_value
(
node_pt
->vector_ref_value());
594
595
// Coordinates of the steady node on the left boundary
596
// corresponding to the current node
597
double
y0
=
ref_value
[0];
598
double
x0
= X_0 + lright;
599
600
// Second reference value: Zeta coordinate on the middle line
601
Vector<double>
s
(1);
602
s
[0] =
ref_value
[1];
603
604
// Get position vector at timestep t
605
Vector<double>
r_line
(2);
606
slanted_bound_up(
t
,
s
,
r_line
);
607
608
// Third reference value : fraction of the horizontal line
609
// between the middle line and the right edge
610
double
r
=
ref_value
[2];
611
612
// Assign new nodal coordinates
613
node_pt
->x(
t
, 0) =
r_line
[0] +
r
* (
x0
-
r_line
[0]);
614
node_pt
->x(
t
, 1) =
r_line
[1] +
r
* (
y0
-
r_line
[1]);
615
}
616
617
618
///////////////////////////////////////////////////////////////////////////
619
///////////////////////////////////////////////////////////////////////////
620
///////////////////////////////////////////////////////////////////////////
621
622
//===================================================================
623
/// Update the node update functions
624
//===================================================================
625
template
<
class
ELEMENT>
626
void
RefineableAlgebraicChannelWithLeafletMesh<ELEMENT>::update_node_update
(
627
AlgebraicNode
*&
node_pt
)
628
{
629
// Extract ID
630
unsigned
id
=
node_pt
->node_update_fct_id();
631
632
if
((
id
== 1) || (
id
== 2))
633
{
634
// Extract reference values for node update by copy construction
635
Vector<double>
ref_value
(
node_pt
->vector_ref_value());
636
637
// Get zeta coordinate on wall
638
Vector<double>
zeta_wall
(1);
639
zeta_wall
[0] =
ref_value
[3];
640
641
// Get the sub-geomobject and the local coordinate
642
Vector<double>
s
(1);
643
GeomObject
*
geom_obj_pt
;
644
this->Leaflet_pt->locate_zeta(
zeta_wall
,
geom_obj_pt
,
s
);
645
646
// Extract geometric objects for update by copy construction
647
Vector<GeomObject*>
geom_object_pt
(
node_pt
->vector_geom_object_pt());
648
649
// Update the pointer to the (sub-)GeomObject within which the
650
// reference point is located. (If the wall is simple GeomObject
651
// this is the same as Leaflet_pt; if it's a compound GeomObject
652
// this points to the sub-object)
653
geom_object_pt
[0] =
geom_obj_pt
;
654
655
// Update second reference value: Reference local coordinate
656
// in wall sub-element
657
ref_value
[1] =
s
[0];
658
659
if
(
id
== 1)
660
{
661
// Kill the existing node update info
662
node_pt
->kill_node_update_info(1);
663
664
// Setup algebraic update for node: Pass update information
665
node_pt
->add_node_update_info(1,
// id
666
this
,
// mesh
667
geom_object_pt
,
// vector of geom objects
668
ref_value
);
// vector of ref. values
669
}
670
else
if
(
id
== 2)
671
{
672
// Kill the existing node update info
673
node_pt
->kill_node_update_info(2);
674
675
// Setup algebraic update for node: Pass update information
676
node_pt
->add_node_update_info(2,
// id
677
this
,
// mesh
678
geom_object_pt
,
// vector of geom objects
679
ref_value
);
// vector of ref. values
680
}
681
}
682
}
683
684
}
// namespace oomph
685
686
#endif
oomph::AlgebraicChannelWithLeafletMesh::setup_algebraic_node_update
void setup_algebraic_node_update()
Function to setup the algebraic node update.
Definition
channel_with_leaflet_mesh.template.cc:239
oomph::AlgebraicChannelWithLeafletMesh::algebraic_node_update
void algebraic_node_update(const unsigned &t, AlgebraicNode *&node_pt)
Update nodal position at time level t (t=0: present; t>0: previous)
Definition
channel_with_leaflet_mesh.template.cc:406
oomph::AlgebraicChannelWithLeafletMesh::node_update_I
void node_update_I(const unsigned &t, AlgebraicNode *&node_pt)
Update function for nodes in lower left region (I)
Definition
channel_with_leaflet_mesh.template.cc:448
oomph::AlgebraicChannelWithLeafletMesh::node_update_III
void node_update_III(const unsigned &t, AlgebraicNode *&node_pt)
Update function for nodes in upper left region (III)
Definition
channel_with_leaflet_mesh.template.cc:552
oomph::AlgebraicChannelWithLeafletMesh::node_update_II
void node_update_II(const unsigned &t, AlgebraicNode *&node_pt)
Update function for nodes in lower right region (II)
Definition
channel_with_leaflet_mesh.template.cc:489
oomph::AlgebraicChannelWithLeafletMesh::slanted_bound_up
void slanted_bound_up(const unsigned &t, const Vector< double > &zeta, Vector< double > &r)
Helper function.
Definition
channel_with_leaflet_mesh.template.cc:530
oomph::AlgebraicChannelWithLeafletMesh::node_update_IV
void node_update_IV(const unsigned &t, AlgebraicNode *&node_pt)
Update function for nodes in upper right region (IV)
Definition
channel_with_leaflet_mesh.template.cc:586
oomph::ChannelWithLeafletDomain
Rectangular domain with a leaflet blocking the lower half.
Definition
channel_with_leaflet_domain.h:41
oomph::ChannelWithLeafletMesh::Domain_pt
ChannelWithLeafletDomain * Domain_pt
Pointer to domain.
Definition
channel_with_leaflet_mesh.h:88
oomph::ChannelWithLeafletMesh::Leaflet_pt
GeomObject * Leaflet_pt
Pointer to GeomObject that represents the leaflet.
Definition
channel_with_leaflet_mesh.h:91
oomph::ChannelWithLeafletMesh::ChannelWithLeafletMesh
ChannelWithLeafletMesh(GeomObject *leaflet_pt, const double &lleft, const double &lright, const double &hleaflet, const double &htot, const unsigned &nleft, const unsigned &nright, const unsigned &ny1, const unsigned &ny2, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to GeomObject that represents the leaflet, the length of the domain to left...
Definition
channel_with_leaflet_mesh.template.cc:49
oomph::RefineableAlgebraicChannelWithLeafletMesh::update_node_update
void update_node_update(AlgebraicNode *&node_pt)
Update the node update data for specified node following any mesh adapation.
Definition
channel_with_leaflet_mesh.template.cc:626
oomph::RefineableTriangleMesh
Unstructured refineable Triangle Mesh.
Definition
triangle_mesh.h:2225
oomph::SimpleRectangularQuadMesh
Simple rectangular 2D Quad mesh class. Nx : number of elements in the x direction.
Definition
simple_rectangular_quadmesh.h:58
oomph
Definition
annular_domain.h:35