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
quarter_circle_sector_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
#ifndef OOMPH_QUARTER_CIRCLE_SECTOR_MESH_TEMPLATE_HEADER
27
#define OOMPH_QUARTER_CIRCLE_SECTOR_MESH_TEMPLATE_HEADER
28
29
#ifndef OOMPH_QUARTER_CIRCLE_SECTOR_MESH_HEADER
30
#error __FILE__ should only be included from quarter_circle_sector_mesh.h.
31
#endif
// OOMPH_QUARTER_CIRCLE_SECTOR_MESH_HEADER
32
33
namespace
oomph
34
{
35
//====================================================================
36
/// Constructor for deformable 2D Ring mesh class. Pass pointer to
37
/// geometric object that specifies the wall, start and end coordinates on the
38
/// geometric object, and the fraction along
39
/// which the dividing line is to be placed, and the timestepper
40
/// (defaults to (Steady) default timestepper defined in Mesh).
41
/// Nodal positions are determined via macro-element-based representation
42
/// of the Domain (as a QuarterCircleSectorDomain).
43
//====================================================================
44
template
<
class
ELEMENT>
45
QuarterCircleSectorMesh<ELEMENT>::QuarterCircleSectorMesh
(
46
GeomObject
* wall_pt,
47
const
double
&
xi_lo
,
48
const
double
&
fract_mid
,
49
const
double
&
xi_hi
,
50
TimeStepper
*
time_stepper_pt
)
51
: Wall_pt(wall_pt), Xi_lo(
xi_lo
), Fract_mid(
fract_mid
), Xi_hi(
xi_hi
)
52
{
53
// Mesh can only be built with 2D Qelements.
54
MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
55
56
// Build macro element-based domain
57
Domain_pt
=
new
QuarterCircleSectorDomain
(
wall_pt
,
xi_lo
,
fract_mid
,
xi_hi
);
58
59
// Set the number of boundaries
60
set_nboundary
(3);
61
62
// We have only bothered to parametrise boundary 1
63
set_boundary_coordinate_exists
(1);
64
65
// Allocate the store for the elements
66
Element_pt
.resize(3);
67
68
// Create first element
69
Element_pt
[0] =
new
ELEMENT
;
70
71
// Read out the number of linear points in the element
72
unsigned
n_p
=
dynamic_cast<
ELEMENT
*
>
(
finite_element_pt
(0))->
nnode_1d
();
73
74
// Can now allocate the store for the nodes
75
Node_pt
.resize(
n_p
*
n_p
+ (
n_p
- 1) *
n_p
+ (
n_p
- 1) * (
n_p
- 1));
76
77
Vector<double>
s
(2);
78
Vector<double>
r
(2);
79
80
// Storage for the intrinsic boundary coordinate
81
Vector<double>
zeta
(1);
82
83
// Set up geometrical data
84
//------------------------
85
86
// Initialise node counter
87
unsigned
long
node_count
= 0;
88
89
// Now assign the topology
90
// Boundaries are numbered 0 1 2 from the bottom proceeding anticlockwise
91
92
// FIRST ELEMENT (lower left corner)
93
//
94
95
// Set the corner node (on boundaries 0 and 2)
96
//-------------------------------------------
97
98
// Create the ll node
99
Node_pt
[
node_count
] =
100
finite_element_pt
(0)->construct_boundary_node(0,
time_stepper_pt
);
101
102
// Set the pointer from the element to the node
103
finite_element_pt
(0)->node_pt(0) =
Node_pt
[
node_count
];
104
105
// Set the position of the ll node
106
s
[0] = -1.0;
107
s
[1] = -1.0;
108
Domain_pt
->macro_element_pt(0)->macro_map(
s
,
r
);
109
Node_pt
[
node_count
]->x(0) =
r
[0];
110
Node_pt
[
node_count
]->x(1) =
r
[1];
111
112
// Add the node to the boundaries
113
add_boundary_node
(0,
Node_pt
[
node_count
]);
114
add_boundary_node
(2,
Node_pt
[
node_count
]);
115
116
// Increment the node number
117
node_count
++;
118
119
// First row is on boundary 0:
120
//---------------------------
121
for
(
unsigned
l1
= 1;
l1
<
n_p
;
l1
++)
122
{
123
// Local node number
124
unsigned
jnod_local
=
l1
;
125
126
// Create the node
127
Node_pt
[
node_count
] =
finite_element_pt
(0)->construct_boundary_node(
128
jnod_local
,
time_stepper_pt
);
129
130
// Set the pointer from the element to the node
131
finite_element_pt
(0)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
132
133
// Set the position of the node
134
s
[0] = -1.0 + 2.0 *
double
(
l1
) /
double
(
n_p
- 1);
135
s
[1] = -1.0;
136
Domain_pt
->macro_element_pt(0)->macro_map(
s
,
r
);
137
Node_pt
[
node_count
]->x(0) =
r
[0];
138
Node_pt
[
node_count
]->x(1) =
r
[1];
139
140
// Add the node to the boundary
141
add_boundary_node
(0,
Node_pt
[
node_count
]);
142
143
// Increment the node number
144
node_count
++;
145
}
146
147
// Loop over the other rows of nodes
148
//------------------------------------
149
for
(
unsigned
l2
= 1;
l2
<
n_p
;
l2
++)
150
{
151
// First node in this row is on boundary 2:
152
//-----------------------------------------
153
154
// Local node number
155
unsigned
jnod_local
=
n_p
*
l2
;
156
157
// Create the node
158
Node_pt
[
node_count
] =
finite_element_pt
(0)->construct_boundary_node(
159
jnod_local
,
time_stepper_pt
);
160
161
// Set the pointer from the element to the node
162
finite_element_pt
(0)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
163
164
// Set the position of the node
165
s
[0] = -1.0;
166
s
[1] = -1.0 + 2.0 *
double
(
l2
) /
double
(
n_p
- 1);
167
;
168
Domain_pt
->macro_element_pt(0)->macro_map(
s
,
r
);
169
Node_pt
[
node_count
]->x(0) =
r
[0];
170
Node_pt
[
node_count
]->x(1) =
r
[1];
171
172
// Add the node to the boundary
173
add_boundary_node
(2,
Node_pt
[
node_count
]);
174
175
// Increment the node number
176
node_count
++;
177
178
// The other nodes are in the interior
179
//------------------------------------
180
// Loop over the other node columns
181
for
(
unsigned
l1
= 1;
l1
<
n_p
;
l1
++)
182
{
183
// Local node number
184
unsigned
jnod_local
=
l1
+
n_p
*
l2
;
185
186
// Create the node
187
Node_pt
[
node_count
] =
188
finite_element_pt
(0)->construct_node(
jnod_local
,
time_stepper_pt
);
189
190
// Set the pointer from the element to the node
191
finite_element_pt
(0)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
192
193
// Set the position of the node
194
s
[0] = -1.0 + 2.0 *
double
(
l1
) /
double
(
n_p
- 1);
195
s
[1] = -1.0 + 2.0 *
double
(
l2
) /
double
(
n_p
- 1);
196
Domain_pt
->macro_element_pt(0)->macro_map(
s
,
r
);
197
Node_pt
[
node_count
]->x(0) =
r
[0];
198
Node_pt
[
node_count
]->x(1) =
r
[1];
199
200
// Increment the node number
201
node_count
++;
202
}
203
}
204
205
// SECOND ELEMENT (lower right corner)
206
//
207
// Create element
208
Element_pt
[1] =
new
ELEMENT
;
209
210
// Loop over the first column (already exists!)
211
//---------------------------------------------
212
for
(
unsigned
l2
= 0;
l2
<
n_p
;
l2
++)
213
{
214
// Node number in existing element
215
unsigned
jnod_local_old
= (
n_p
- 1) +
l2
*
n_p
;
216
217
// Set the pointer from the element to the node
218
finite_element_pt
(1)->node_pt(
l2
*
n_p
) =
219
finite_element_pt
(0)->node_pt(
jnod_local_old
);
220
}
221
222
// Loop over the other node columns (apart from last one)
223
//------------------------------------------------------
224
for
(
unsigned
l1
= 1;
l1
<
n_p
- 1;
l1
++)
225
{
226
// First node is at the bottom (on boundary 0)
227
//--------------------------------------------
228
229
// Local node number
230
unsigned
jnod_local
=
l1
;
231
232
// Create the node
233
Node_pt
[
node_count
] =
finite_element_pt
(1)->construct_boundary_node(
234
jnod_local
,
time_stepper_pt
);
235
236
// Set the pointer from the element to the node
237
finite_element_pt
(1)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
238
239
// Set the position of the node
240
s
[0] = -1.0 + 2.0 *
double
(
l1
) /
double
(
n_p
- 1);
241
s
[1] = -1.0;
242
Domain_pt
->macro_element_pt(1)->macro_map(
s
,
r
);
243
Node_pt
[
node_count
]->x(0) =
r
[0];
244
Node_pt
[
node_count
]->x(1) =
r
[1];
245
246
// Add the node to the boundary
247
add_boundary_node
(0,
Node_pt
[
node_count
]);
248
249
// Increment the node number
250
node_count
++;
251
252
// Now loop over the interior nodes in this column
253
//-------------------------------------------------
254
for
(
unsigned
l2
= 1;
l2
<
n_p
;
l2
++)
255
{
256
// Local node number
257
unsigned
jnod_local
=
l1
+
l2
*
n_p
;
258
259
// Create the node
260
Node_pt
[
node_count
] =
261
finite_element_pt
(1)->construct_node(
jnod_local
,
time_stepper_pt
);
262
263
// Set the pointer from the element to the node
264
finite_element_pt
(1)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
265
266
// Set the position of the node
267
s
[0] = -1.0 + 2.0 *
double
(
l1
) /
double
(
n_p
- 1);
268
s
[1] = -1.0 + 2.0 *
double
(
l2
) /
double
(
n_p
- 1);
269
Domain_pt
->macro_element_pt(1)->macro_map(
s
,
r
);
270
Node_pt
[
node_count
]->x(0) =
r
[0];
271
Node_pt
[
node_count
]->x(1) =
r
[1];
272
273
// Increment the node number
274
node_count
++;
275
}
276
}
277
278
// Last column (on boundary 1)
279
//----------------------------
280
281
// First node is at the bottom (and hence also on boundary 0)
282
//-----------------------------------------------------------
283
284
// Local node number
285
unsigned
jnod_local
=
n_p
- 1;
286
287
// Create the node
288
Node_pt
[
node_count
] =
finite_element_pt
(1)->construct_boundary_node(
289
jnod_local
,
time_stepper_pt
);
290
291
// Set the pointer from the element to the node
292
finite_element_pt
(1)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
293
294
// Set the position of the node
295
s
[0] = 1.0;
296
s
[1] = -1.0;
297
Domain_pt
->macro_element_pt(1)->macro_map(
s
,
r
);
298
Node_pt
[
node_count
]->x(0) =
r
[0];
299
Node_pt
[
node_count
]->x(1) =
r
[1];
300
301
// Add the node to the boundaries
302
add_boundary_node
(0,
Node_pt
[
node_count
]);
303
add_boundary_node
(1,
Node_pt
[
node_count
]);
304
305
// Set the intrinsic coordinate on the boundary 1
306
zeta
[0] =
Xi_lo
+ 0.5 * (1.0 +
s
[1]) *
Fract_mid
* (
Xi_hi
-
Xi_lo
);
307
Node_pt
[
node_count
]->set_coordinates_on_boundary(1,
zeta
);
308
309
// Increment the node number
310
node_count
++;
311
312
// Now do the remaining nodes in last column (only on boundary 1)
313
//---------------------------------------------------------------
314
for
(
unsigned
l2
= 1;
l2
<
n_p
;
l2
++)
315
{
316
// Local node number
317
unsigned
jnod_local
= (
n_p
- 1) +
l2
*
n_p
;
318
319
// Create the node
320
Node_pt
[
node_count
] =
finite_element_pt
(1)->construct_boundary_node(
321
jnod_local
,
time_stepper_pt
);
322
323
// Set the pointer from the element to the node
324
finite_element_pt
(1)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
325
326
// Set the position of the node
327
s
[0] = 1.0;
328
s
[1] = -1.0 + 2.0 *
double
(
l2
) /
double
(
n_p
- 1);
329
Domain_pt
->macro_element_pt(1)->macro_map(
s
,
r
);
330
Node_pt
[
node_count
]->x(0) =
r
[0];
331
Node_pt
[
node_count
]->x(1) =
r
[1];
332
333
// Add the node to the boundary
334
add_boundary_node
(1,
Node_pt
[
node_count
]);
335
336
// Set the intrinsic coordinate on the boundary 1
337
zeta
[0] =
Xi_lo
+ 0.5 * (1.0 +
s
[1]) *
Fract_mid
* (
Xi_hi
-
Xi_lo
);
338
Node_pt
[
node_count
]->set_coordinates_on_boundary(1,
zeta
);
339
340
// Increment the node number
341
node_count
++;
342
}
343
344
// THIRD ELEMENT (upper left corner)
345
//
346
// Create element
347
Element_pt
[2] =
new
ELEMENT
;
348
349
// Loop over the first row (has already been created via element 0)
350
//-----------------------------------------------------------------
351
for
(
unsigned
l1
= 0;
l1
<
n_p
;
l1
++)
352
{
353
// Node number in existing element
354
unsigned
jnod_local_old
=
n_p
* (
n_p
- 1) +
l1
;
355
356
// Local node number here
357
unsigned
jnod_local
=
l1
;
358
359
// Set the pointer from the element to the node
360
finite_element_pt
(2)->node_pt(
jnod_local
) =
361
finite_element_pt
(0)->node_pt(
jnod_local_old
);
362
}
363
364
// Loop over the remaining nodes in the last column (has already
365
//--------------------------------------------------------------
366
// been created via element 1)
367
//----------------------------
368
for
(
unsigned
l2
= 1;
l2
<
n_p
;
l2
++)
369
{
370
// Node number in existing element
371
unsigned
jnod_local_old
=
n_p
* (
n_p
- 1) +
l2
;
372
373
// Local node number here
374
unsigned
jnod_local
= (
n_p
- 1) +
l2
*
n_p
;
375
376
// Set the pointer from the element to the node
377
finite_element_pt
(2)->node_pt(
jnod_local
) =
378
finite_element_pt
(1)->node_pt(
jnod_local_old
);
379
}
380
381
// Loop over the nodes in rows (apart from last one which is on boundary 1)
382
//-------------------------------------------------------------------------
383
for
(
unsigned
l2
= 1;
l2
<
n_p
- 1;
l2
++)
384
{
385
// First node in this row is on boundary 2:
386
//-----------------------------------------
387
388
// Local node number
389
unsigned
jnod_local
=
n_p
*
l2
;
390
391
// Create the node
392
Node_pt
[
node_count
] =
finite_element_pt
(2)->construct_boundary_node(
393
jnod_local
,
time_stepper_pt
);
394
395
// Set the pointer from the element to the node
396
finite_element_pt
(2)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
397
398
// Set the position of the node
399
s
[0] = -1.0;
400
s
[1] = -1.0 + 2.0 *
double
(
l2
) /
double
(
n_p
- 1);
401
;
402
Domain_pt
->macro_element_pt(2)->macro_map(
s
,
r
);
403
Node_pt
[
node_count
]->x(0) =
r
[0];
404
Node_pt
[
node_count
]->x(1) =
r
[1];
405
406
// Add the node to the boundary
407
add_boundary_node
(2,
Node_pt
[
node_count
]);
408
409
// Increment the node number
410
node_count
++;
411
412
// The other nodes are in the interior
413
//------------------------------------
414
// Loop over the other node columns
415
for
(
unsigned
l1
= 1;
l1
<
n_p
- 1;
l1
++)
416
{
417
// Local node number
418
unsigned
jnod_local
=
l1
+
n_p
*
l2
;
419
420
// Create the node
421
Node_pt
[
node_count
] =
422
finite_element_pt
(2)->construct_node(
jnod_local
,
time_stepper_pt
);
423
424
// Set the pointer from the element to the node
425
finite_element_pt
(2)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
426
427
// Set the position of the node
428
s
[0] = -1.0 + 2.0 *
double
(
l1
) /
double
(
n_p
- 1);
429
s
[1] = -1.0 + 2.0 *
double
(
l2
) /
double
(
n_p
- 1);
430
Domain_pt
->macro_element_pt(2)->macro_map(
s
,
r
);
431
Node_pt
[
node_count
]->x(0) =
r
[0];
432
Node_pt
[
node_count
]->x(1) =
r
[1];
433
434
// Increment the node number
435
node_count
++;
436
}
437
}
438
439
// Top left corner is on boundaries 1 and 2:
440
//------------------------------------------
441
442
// Local node number
443
jnod_local
=
n_p
* (
n_p
- 1);
444
445
// Create the node
446
Node_pt
[
node_count
] =
finite_element_pt
(2)->construct_boundary_node(
447
jnod_local
,
time_stepper_pt
);
448
449
// Set the pointer from the element to the node
450
finite_element_pt
(2)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
451
452
// Set the position of the node
453
s
[0] = -1.0;
454
s
[1] = 1.0;
455
Domain_pt
->macro_element_pt(2)->macro_map(
s
,
r
);
456
Node_pt
[
node_count
]->x(0) =
r
[0];
457
Node_pt
[
node_count
]->x(1) =
r
[1];
458
459
// Add the node to the boundaries
460
add_boundary_node
(1,
Node_pt
[
node_count
]);
461
add_boundary_node
(2,
Node_pt
[
node_count
]);
462
463
// Set the intrinsic coordinate on the boundary 1
464
zeta
[0] =
Xi_hi
+ 0.5 * (
s
[0] + 1.0) * (1.0 -
Fract_mid
) * (
Xi_lo
-
Xi_hi
);
465
Node_pt
[
node_count
]->set_coordinates_on_boundary(1,
zeta
);
466
467
// Increment the node number
468
node_count
++;
469
470
// Rest of top row is on boundary 1 only:
471
//---------------------------------------
472
for
(
unsigned
l1
= 1;
l1
<
n_p
- 1;
l1
++)
473
{
474
// Local node number
475
unsigned
jnod_local
=
n_p
* (
n_p
- 1) +
l1
;
476
477
// Create the node
478
Node_pt
[
node_count
] =
finite_element_pt
(2)->construct_boundary_node(
479
jnod_local
,
time_stepper_pt
);
480
481
// Set the pointer from the element to the node
482
finite_element_pt
(2)->node_pt(
jnod_local
) =
Node_pt
[
node_count
];
483
484
// Set the position of the node
485
s
[0] = -1.0 + 2.0 *
double
(
l1
) /
double
(
n_p
- 1);
486
s
[1] = 1.0;
487
Domain_pt
->macro_element_pt(2)->macro_map(
s
,
r
);
488
Node_pt
[
node_count
]->x(0) =
r
[0];
489
Node_pt
[
node_count
]->x(1) =
r
[1];
490
491
// Add the node to the boundary
492
add_boundary_node
(1,
Node_pt
[
node_count
]);
493
494
// Set the intrinsic coordinate on the boundary 1
495
zeta
[0] =
496
Xi_hi
+ 0.5 * (
s
[0] + 1.0) * (1.0 -
Fract_mid
) * (
Xi_lo
-
Xi_hi
);
497
Node_pt
[
node_count
]->set_coordinates_on_boundary(1,
zeta
);
498
499
// Increment the node number
500
node_count
++;
501
}
502
503
// Loop over all elements and set macro element pointer
504
// to enable MacroElement-based node update
505
unsigned
n_element
= this->
nelement
();
506
for
(
unsigned
e
= 0;
e
<
n_element
;
e
++)
507
{
508
// Get pointer to full element type
509
ELEMENT
*
el_pt
=
dynamic_cast<
ELEMENT
*
>
(this->
element_pt
(
e
));
510
511
// Set pointer to macro element
512
el_pt
->set_macro_elem_pt(this->
Domain_pt
->macro_element_pt(
e
));
513
}
514
515
// Setup boundary element lookup schemes
516
setup_boundary_element_info();
517
}
518
519
520
///////////////////////////////////////////////////////////////////////
521
///////////////////////////////////////////////////////////////////////
522
// Algebraic-mesh-version of RefineableQuarterCircleSectorMesh
523
///////////////////////////////////////////////////////////////////////
524
///////////////////////////////////////////////////////////////////////
525
526
//======================================================================
527
/// Setup algebraic update operation, based on individual
528
/// blocks. Mesh is suspended from the `wall' GeomObject pointed to
529
/// by wall_pt. The lower right corner of the mesh is located at the
530
/// wall's coordinate xi_lo, the upper left corner at xi_hi;
531
/// The dividing line between the two blocks at the outer ring
532
/// is located at the fraction fract_mid between these two coordinates.
533
/// Node updating strategy:
534
/// - the shape of the central box remains rectangular; the position
535
/// of its top right corner is located at a fixed fraction
536
/// of the width and height of the domain. Nodes in this region
537
/// are located at fixed horizontal and vertical fractions of the box.
538
/// - Nodes in the two outer "ring" elements (bottom right and top left)
539
/// are located on straight lines running from the edges of the
540
/// central box to the outer wall.
541
//======================================================================
542
template
<
class
ELEMENT>
543
void
AlgebraicRefineableQuarterCircleSectorMesh
<
544
ELEMENT
>::setup_algebraic_node_update()
545
{
546
#ifdef PARANOID
547
/// Pointer to algebraic element in central box
548
AlgebraicElementBase
*
central_box_pt
=
549
dynamic_cast<
AlgebraicElementBase
*
>
(Mesh::element_pt(0));
550
551
if
(
central_box_pt
== 0)
552
{
553
std::ostringstream
error_message
;
554
error_message
555
<<
"Element in AlgebraicRefineableQuarterCircleSectorMesh must be\n "
;
556
error_message
<<
"derived from AlgebraicElementBase\n"
;
557
error_message
<<
"but it is of type: "
558
<<
typeid
(Mesh::element_pt(0)).
name
() << std::endl;
559
std::string
function_name
=
560
"AlgebraicRefineableQuarterCircleSectorMesh::"
;
561
function_name
+=
"setup_algebraic_node_update()"
;
562
throw
OomphLibError
(
563
error_message
.str(),
OOMPH_CURRENT_FUNCTION
,
OOMPH_EXCEPTION_LOCATION
);
564
}
565
#endif
566
567
// Number of nodes in elements
568
unsigned
nnodes
= Mesh::finite_element_pt(0)->nnode();
569
570
// Coordinates of central box
571
double
x_box
= Mesh::finite_element_pt(0)->node_pt(
nnodes
- 1)->x(0);
572
double
y_box
= Mesh::finite_element_pt(0)->node_pt(
nnodes
- 1)->x(1);
573
574
// Get wall position in bottom right corner
575
Vector<double>
r_br
(2);
576
Vector<double>
xi
(1);
577
xi
[0] =
QuarterCircleSectorMesh<ELEMENT>::Xi_lo
;
578
QuarterCircleSectorMesh<ELEMENT>::Wall_pt
->position(
xi
,
r_br
);
579
580
// Establish fractional width of central box
581
Lambda_x =
x_box
/
r_br
[0];
582
583
// Find corresponding wall element/local coordinate
584
GeomObject
*
obj_br_pt
;
585
Vector<double>
s_br
(1);
586
this->Wall_pt->locate_zeta(
xi
,
obj_br_pt
,
s_br
);
587
588
obj_br_pt
->position(
s_br
,
r_br
);
589
590
// Get wall position in top left corner
591
Vector<double>
r_tl
(2);
592
xi
[0] =
QuarterCircleSectorMesh<ELEMENT>::Xi_hi
;
593
QuarterCircleSectorMesh<ELEMENT>::Wall_pt
->position(
xi
,
r_tl
);
594
595
// Establish fractional height of central box
596
Lambda_y =
y_box
/
r_tl
[1];
597
598
// Find corresponding wall element/local coordinate
599
GeomObject
*
obj_tl_pt
;
600
Vector<double>
s_tl
(1);
601
this->Wall_pt->locate_zeta(
xi
,
obj_tl_pt
,
s_tl
);
602
603
// Element 0: central box
604
//-----------------------
605
{
606
unsigned
ielem
= 0;
607
FiniteElement
*
el_pt
= Mesh::finite_element_pt(
ielem
);
608
609
// Loop over all nodes in the element and give them the update
610
// info appropriate for the current element
611
for
(
unsigned
jnod
= 0;
jnod
<
nnodes
;
jnod
++)
612
{
613
// Nodal coordinates in undeformed mesh
614
double
x = Mesh::finite_element_pt(
ielem
)->node_pt(
jnod
)->x(0);
615
double
y = Mesh::finite_element_pt(
ielem
)->node_pt(
jnod
)->x(1);
616
617
// The update function requires two geometric objects
618
Vector<GeomObject*>
geom_object_pt
(2);
619
620
// The update function requires four parameters:
621
Vector<double>
ref_value
(4);
622
623
// First reference value: fractional x-position inside box
624
ref_value
[0] = x /
x_box
;
625
626
// Second reference value: fractional y-position inside box
627
ref_value
[1] = y /
y_box
;
628
629
// Wall element at bottom right end of wall mesh:
630
geom_object_pt
[0] =
obj_br_pt
;
631
632
// Local coordinate in this wall element (Note:
633
// we'll have to recompute this reference
634
// when the mesh is refined as we might fall off the element otherwise)
635
ref_value
[2] =
s_br
[0];
636
637
// Wall element at top left end of wall mesh:
638
geom_object_pt
[1] =
obj_tl_pt
;
639
640
// Local coordinate in this wall element. Note:
641
// we'll have to recompute this reference
642
// when the mesh is refined as we might fall off the element otherwise)
643
ref_value
[3] =
s_tl
[0];
644
645
// Setup algebraic update for node: Pass update information
646
dynamic_cast<
AlgebraicNode
*
>
(
el_pt
->node_pt(
jnod
))
647
->
add_node_update_info
(Central_box,
// enumerated ID
648
this
,
// mesh
649
geom_object_pt
,
// vector of geom objects
650
ref_value
);
// vector of ref. values
651
}
652
}
653
654
// Element 1: Bottom right box
655
//----------------------------
656
{
657
unsigned
ielem
= 1;
658
FiniteElement
*
el_pt
= Mesh::finite_element_pt(
ielem
);
659
660
// Loop over all nodes in the element and give them the update
661
// info appropriate for the current element
662
663
// Double loop over nodes
664
unsigned
nnod_lin
=
665
dynamic_cast<
ELEMENT
*
>
(Mesh::finite_element_pt(
ielem
))->
nnode_1d
();
666
for
(
unsigned
i0
= 0;
i0
<
nnod_lin
;
i0
++)
667
{
668
// Fraction in the s_0-direction
669
double
rho_0
=
double
(
i0
) /
double
(
nnod_lin
- 1);
670
671
for
(
unsigned
i1
= 0;
i1
<
nnod_lin
;
i1
++)
672
{
673
// Fraction in the s_1-direction
674
double
rho_1
=
double
(
i1
) /
double
(
nnod_lin
- 1);
675
676
// Node number
677
unsigned
jnod
=
i0
+
i1
*
nnod_lin
;
678
679
// The update function requires three geometric objects
680
Vector<GeomObject*>
geom_object_pt
(3);
681
682
// The update function requires five parameters:
683
Vector<double>
ref_value
(5);
684
685
// First reference value: fractional s0-position inside box
686
ref_value
[0] =
rho_0
;
687
688
// Second reference value: fractional s1-position inside box
689
ref_value
[1] =
rho_1
;
690
691
// Wall element at bottom right end of wall mesh:
692
geom_object_pt
[0] =
obj_br_pt
;
693
694
// Local coordinate in this wall element. Note:
695
// We'll have to recompute this reference
696
// when the mesh is refined as we might fall off the element
697
// otherwise
698
ref_value
[2] =
s_br
[0];
699
700
// Wall element at top left end of wall mesh:
701
geom_object_pt
[1] =
obj_tl_pt
;
702
703
// Local coordinate in this wall element. Note:
704
// We'll have to recompute this reference
705
// when the mesh is refined as we might fall off the element
706
// otherwise
707
ref_value
[3] =
s_tl
[0];
708
709
// Reference point on wall
710
Vector<double>
xi_wall
(1);
711
xi_wall
[0] =
QuarterCircleSectorMesh<ELEMENT>::Xi_lo
+
712
rho_1
*
QuarterCircleSectorMesh<ELEMENT>::Fract_mid
*
713
(
QuarterCircleSectorMesh<ELEMENT>::Xi_hi
-
714
QuarterCircleSectorMesh<ELEMENT>::Xi_lo
);
715
716
// Identify wall element number and local coordinate of
717
// reference point on wall
718
GeomObject
*
obj_wall_pt
;
719
Vector<double>
s_wall
(1);
720
this->Wall_pt->locate_zeta(
xi_wall
,
obj_wall_pt
,
s_wall
);
721
722
// Wall element at that contians reference point:
723
geom_object_pt
[2] =
obj_wall_pt
;
724
725
// Local coordinate in this wall element. Note:
726
// We'll have to recompute this reference
727
// when the mesh is refined as we might fall off the element
728
// otherwise
729
ref_value
[4] =
s_wall
[0];
730
731
// Setup algebraic update for node: Pass update information
732
dynamic_cast<
AlgebraicNode
*
>
(
el_pt
->node_pt(
jnod
))
733
->
add_node_update_info
(Lower_right_box,
// enumerated ID
734
this
,
// mesh
735
geom_object_pt
,
// vector of geom objects
736
ref_value
);
// vector of ref. vals
737
}
738
}
739
}
740
741
// Element 2: Top left box
742
//---------------------------
743
{
744
unsigned
ielem
= 2;
745
FiniteElement
*
el_pt
= Mesh::finite_element_pt(
ielem
);
746
747
// Double loop over nodes
748
unsigned
nnod_lin
=
749
dynamic_cast<
ELEMENT
*
>
(Mesh::finite_element_pt(
ielem
))->
nnode_1d
();
750
751
for
(
unsigned
i0
= 0;
i0
<
nnod_lin
;
i0
++)
752
{
753
// Fraction in the s_0-direction
754
double
rho_0
=
double
(
i0
) /
double
(
nnod_lin
- 1);
755
756
for
(
unsigned
i1
= 0;
i1
<
nnod_lin
;
i1
++)
757
{
758
// Fraction in the s_1-direction
759
double
rho_1
=
double
(
i1
) /
double
(
nnod_lin
- 1);
760
761
// Node number
762
unsigned
jnod
=
i0
+
i1
*
nnod_lin
;
763
764
// The update function requires three geometric objects
765
Vector<GeomObject*>
geom_object_pt
(3);
766
767
// The update function requires five parameters:
768
Vector<double>
ref_value
(5);
769
770
// First reference value: fractional s0-position inside box
771
ref_value
[0] =
rho_0
;
772
773
// Second reference value: fractional s1-position inside box
774
ref_value
[1] =
rho_1
;
775
776
// Wall element at bottom right end of wall mesh:
777
geom_object_pt
[0] =
obj_br_pt
;
778
779
// Local coordinate in this wall element. Note:
780
// We'll have to recompute this reference
781
// when the mesh is refined as we might fall off the element
782
// otherwise
783
ref_value
[2] =
s_br
[0];
784
785
// Wall element at top left end of wall mesh:
786
geom_object_pt
[1] =
obj_tl_pt
;
787
788
// Local coordinate in this wall element. Note:
789
// We'll have to recompute this reference
790
// when the mesh is refined as we might fall off the element
791
// otherwise
792
ref_value
[3] =
s_tl
[0];
793
794
// Reference point on wall
795
Vector<double>
xi_wall
(1);
796
xi_wall
[0] =
QuarterCircleSectorMesh<ELEMENT>::Xi_hi
+
797
rho_0
*
798
(1.0 -
QuarterCircleSectorMesh<ELEMENT>::Fract_mid
) *
799
(
QuarterCircleSectorMesh<ELEMENT>::Xi_lo
-
800
QuarterCircleSectorMesh<ELEMENT>::Xi_hi
);
801
802
// Identify wall element number and local coordinate of
803
// reference point on wall
804
GeomObject
*
obj_wall_pt
;
805
Vector<double>
s_wall
(1);
806
this->Wall_pt->locate_zeta(
xi_wall
,
obj_wall_pt
,
s_wall
);
807
808
// Wall element at that contians reference point:
809
geom_object_pt
[2] =
obj_wall_pt
;
810
811
// Local coordinate in this wall element. Note:
812
// We'll have to recompute this reference
813
// when the mesh is refined as we might fall off the element
814
// otherwise
815
ref_value
[4] =
s_wall
[0];
816
817
// Setup algebraic update for node: Pass update information
818
dynamic_cast<
AlgebraicNode
*
>
(
el_pt
->node_pt(
jnod
))
819
->
add_node_update_info
(Upper_left_box,
// Enumerated ID
820
this
,
// mesh
821
geom_object_pt
,
// vector of geom objects
822
ref_value
);
// vector of ref. vals
823
}
824
}
825
}
826
}
827
828
//======================================================================
829
/// Algebraic update function: Update in central box according
830
/// to wall shape at time level t (t=0: present; t>0: previous)
831
//======================================================================
832
template
<
class
ELEMENT>
833
void
AlgebraicRefineableQuarterCircleSectorMesh
<
834
ELEMENT
>::node_update_in_central_box(
const
unsigned
&
t
,
835
AlgebraicNode
*&
node_pt
)
836
{
837
#ifdef PARANOID
838
// We're updating the nodal positions (!) at time level t
839
// and determine them by evaluating the wall GeomObject's
840
// position at that gime level. I believe this only makes sense
841
// if the t-th history value in the positional timestepper
842
// actually represents previous values (rather than some
843
// generalised quantity). Hence if this function is called with
844
// t>nprev_values(), we issue a warning and terminate the execution.
845
// It *might* be possible that the code still works correctly
846
// even if this condition is violated (e.g. if the GeomObject's
847
// position() function returns the appropriate "generalised"
848
// position value that is required by the timestepping scheme but it's
849
// probably worth flagging this up and forcing the user to manually switch
850
// off this warning if he/she is 100% sure that this is kosher.
851
if
(
t
>
node_pt
->position_time_stepper_pt()->nprev_values())
852
{
853
std::string
error_message
=
854
"Trying to update the nodal position at a time level\n"
;
855
error_message
+=
"beyond the number of previous values in the nodes'\n"
;
856
error_message
+=
"position timestepper. This seems highly suspect!\n"
;
857
error_message
+=
"If you're sure the code behaves correctly\n"
;
858
error_message
+=
"in your application, remove this warning \n"
;
859
error_message
+=
"or recompile with PARNOID switched off.\n"
;
860
861
std::string
function_name
=
862
"AlgebraicRefineableQuarterCircleSectorMesh::"
;
863
function_name
+=
"node_update_in_central_box()"
,
864
throw
OomphLibError
(
865
error_message
,
OOMPH_CURRENT_FUNCTION
,
OOMPH_EXCEPTION_LOCATION
);
866
}
867
#endif
868
869
// Extract references for update in central box by copy construction
870
Vector<double>
ref_value
(
node_pt
->vector_ref_value(Central_box));
871
872
// Extract geometric objects for update in central box by copy construction
873
Vector<GeomObject*>
geom_object_pt
(
874
node_pt
->vector_geom_object_pt(Central_box));
875
876
// First reference value: fractional x-position of node inside box
877
double
rho_x
=
ref_value
[0];
878
879
// Second reference value: fractional y-position of node inside box
880
double
rho_y
=
ref_value
[1];
881
882
// Wall position in bottom right corner:
883
884
// Pointer to wall element:
885
GeomObject
*
obj_br_pt
=
geom_object_pt
[0];
886
887
// Eulerian dimension
888
unsigned
n_dim
=
obj_br_pt
->ndim();
889
890
// Local coordinate:
891
Vector<double>
s_br
(1);
892
s_br
[0] =
ref_value
[2];
893
894
// Get wall position
895
Vector<double>
r_br
(
n_dim
);
896
obj_br_pt
->position(
t
,
s_br
,
r_br
);
897
898
// Wall position in top left corner:
899
900
// Pointer to wall element:
901
GeomObject
*
obj_tl_pt
=
geom_object_pt
[1];
902
903
// Local coordinate:
904
Vector<double>
s_tl
(1);
905
s_tl
[0] =
ref_value
[3];
906
907
Vector<double>
r_tl
(
n_dim
);
908
obj_tl_pt
->position(
t
,
s_tl
,
r_tl
);
909
910
// Assign new nodal coordinate
911
node_pt
->x(
t
, 0) =
r_br
[0] * Lambda_x *
rho_x
;
912
node_pt
->x(
t
, 1) =
r_tl
[1] * Lambda_y *
rho_y
;
913
}
914
915
//====================================================================
916
/// Algebraic update function: Update in lower right box according
917
/// to wall shape at time level t (t=0: present; t>0: previous)
918
//====================================================================
919
template
<
class
ELEMENT>
920
void
AlgebraicRefineableQuarterCircleSectorMesh
<
921
ELEMENT
>::node_update_in_lower_right_box(
const
unsigned
&
t
,
922
AlgebraicNode
*&
node_pt
)
923
{
924
#ifdef PARANOID
925
// We're updating the nodal positions (!) at time level t
926
// and determine them by evaluating the wall GeomObject's
927
// position at that gime level. I believe this only makes sense
928
// if the t-th history value in the positional timestepper
929
// actually represents previous values (rather than some
930
// generalised quantity). Hence if this function is called with
931
// t>nprev_values(), we issue a warning and terminate the execution.
932
// It *might* be possible that the code still works correctly
933
// even if this condition is violated (e.g. if the GeomObject's
934
// position() function returns the appropriate "generalised"
935
// position value that is required by the timestepping scheme but it's
936
// probably worth flagging this up and forcing the user to manually switch
937
// off this warning if he/she is 100% sure that this is kosher.
938
if
(
t
>
node_pt
->position_time_stepper_pt()->nprev_values())
939
{
940
std::string
error_message
=
941
"Trying to update the nodal position at a time level"
;
942
error_message
+=
"beyond the number of previous values in the nodes'"
;
943
error_message
+=
"position timestepper. This seems highly suspect!"
;
944
error_message
+=
"If you're sure the code behaves correctly"
;
945
error_message
+=
"in your application, remove this warning "
;
946
error_message
+=
"or recompile with PARNOID switched off."
;
947
948
std::string
function_name
=
949
"AlgebraicRefineableQuarterCircleSectorMesh::"
;
950
function_name
+=
"node_update_in_lower_right_box()"
,
951
throw
OomphLibError
(
952
error_message
,
OOMPH_CURRENT_FUNCTION
,
OOMPH_EXCEPTION_LOCATION
);
953
}
954
#endif
955
956
// Extract references for update in central box by copy construction
957
Vector<double>
ref_value
(
node_pt
->vector_ref_value(Lower_right_box));
958
959
// Extract geometric objects for update in central box by copy construction
960
Vector<GeomObject*>
geom_object_pt
(
961
node_pt
->vector_geom_object_pt(Lower_right_box));
962
963
// First reference value: fractional s0-position of node inside box
964
double
rho_0
=
ref_value
[0];
965
966
// Second reference value: fractional s1-position of node inside box
967
double
rho_1
=
ref_value
[1];
968
969
// Wall position in bottom right corner:
970
971
// Pointer to wall element:
972
GeomObject
*
obj_br_pt
=
geom_object_pt
[0];
973
974
// Eulerian dimension
975
unsigned
n_dim
=
obj_br_pt
->ndim();
976
977
// Local coordinate:
978
Vector<double>
s_br
(1);
979
s_br
[0] =
ref_value
[2];
980
981
// Get wall position
982
Vector<double>
r_br
(
n_dim
);
983
obj_br_pt
->position(
t
,
s_br
,
r_br
);
984
985
// Wall position in top left corner:
986
987
// Pointer to wall element:
988
GeomObject
*
obj_tl_pt
=
geom_object_pt
[1];
989
990
// Local coordinate:
991
Vector<double>
s_tl
(1);
992
s_tl
[0] =
ref_value
[3];
993
994
Vector<double>
r_tl
(
n_dim
);
995
obj_tl_pt
->position(
t
,
s_tl
,
r_tl
);
996
997
// Position of the corner of the central box
998
Vector<double>
r_box
(
n_dim
);
999
r_box
[0] = Lambda_x *
r_br
[0];
1000
r_box
[1] = Lambda_y *
r_tl
[1];
1001
1002
// Position Vector to left end of box
1003
Vector<double>
r_left
(
n_dim
);
1004
r_left
[0] = Lambda_x *
r_br
[0] +
rho_1
* (
r_box
[0] - Lambda_x *
r_br
[0]);
1005
r_left
[1] = Lambda_x *
r_br
[1] +
rho_1
* (
r_box
[1] - Lambda_x *
r_br
[1]);
1006
1007
// Wall position
1008
1009
// Pointer to wall element:
1010
GeomObject
*
obj_wall_pt
=
geom_object_pt
[2];
1011
1012
// Local coordinate:
1013
Vector<double>
s_wall
(1);
1014
s_wall
[0] =
ref_value
[4];
1015
1016
Vector<double>
r_wall
(
n_dim
);
1017
obj_wall_pt
->position(
t
,
s_wall
,
r_wall
);
1018
1019
// Assign new nodal coordinate
1020
node_pt
->x(
t
, 0) =
r_left
[0] +
rho_0
* (
r_wall
[0] -
r_left
[0]);
1021
node_pt
->x(
t
, 1) =
r_left
[1] +
rho_0
* (
r_wall
[1] -
r_left
[1]);
1022
}
1023
//====================================================================
1024
/// Algebraic update function: Update in upper left box according
1025
/// to wall shape at time level t (t=0: present; t>0: previous)
1026
//====================================================================
1027
template
<
class
ELEMENT>
1028
void
AlgebraicRefineableQuarterCircleSectorMesh
<
1029
ELEMENT
>::node_update_in_upper_left_box(
const
unsigned
&
t
,
1030
AlgebraicNode
*&
node_pt
)
1031
{
1032
#ifdef PARANOID
1033
// We're updating the nodal positions (!) at time level t
1034
// and determine them by evaluating the wall GeomObject's
1035
// position at that gime level. I believe this only makes sense
1036
// if the t-th history value in the positional timestepper
1037
// actually represents previous values (rather than some
1038
// generalised quantity). Hence if this function is called with
1039
// t>nprev_values(), we issue a warning and terminate the execution.
1040
// It *might* be possible that the code still works correctly
1041
// even if this condition is violated (e.g. if the GeomObject's
1042
// position() function returns the appropriate "generalised"
1043
// position value that is required by the timestepping scheme but it's
1044
// probably worth flagging this up and forcing the user to manually switch
1045
// off this warning if he/she is 100% sure that this is kosher.
1046
if
(
t
>
node_pt
->position_time_stepper_pt()->nprev_values())
1047
{
1048
std::string
error_message
=
1049
"Trying to update the nodal position at a time level"
;
1050
error_message
+=
"beyond the number of previous values in the nodes'"
;
1051
error_message
+=
"position timestepper. This seems highly suspect!"
;
1052
error_message
+=
"If you're sure the code behaves correctly"
;
1053
error_message
+=
"in your application, remove this warning "
;
1054
error_message
+=
"or recompile with PARNOID switched off."
;
1055
1056
std::string
function_name
=
1057
"AlgebraicRefineableQuarterCircleSectorMesh::"
;
1058
function_name
+=
"node_update_in_upper_left_box()"
;
1059
1060
throw
OomphLibError
(
1061
error_message
,
OOMPH_CURRENT_FUNCTION
,
OOMPH_EXCEPTION_LOCATION
);
1062
}
1063
#endif
1064
1065
// Extract references for update in central box by copy construction
1066
Vector<double>
ref_value
(
node_pt
->vector_ref_value(Upper_left_box));
1067
1068
// Extract geometric objects for update in central box by copy construction
1069
Vector<GeomObject*>
geom_object_pt
(
1070
node_pt
->vector_geom_object_pt(Upper_left_box));
1071
1072
// First reference value: fractional s0-position of node inside box
1073
double
rho_0
=
ref_value
[0];
1074
1075
// Second reference value: fractional s1-position of node inside box
1076
double
rho_1
=
ref_value
[1];
1077
1078
// Wall position in bottom right corner:
1079
1080
// Pointer to wall element:
1081
GeomObject
*
obj_br_pt
=
geom_object_pt
[0];
1082
1083
// Eulerian dimension
1084
unsigned
n_dim
=
obj_br_pt
->ndim();
1085
1086
// Local coordinate:
1087
Vector<double>
s_br
(1);
1088
s_br
[0] =
ref_value
[2];
1089
1090
// Get wall position
1091
Vector<double>
r_br
(
n_dim
);
1092
obj_br_pt
->position(
t
,
s_br
,
r_br
);
1093
1094
// Wall position in top left corner:
1095
1096
// Pointer to wall element:
1097
GeomObject
*
obj_tl_pt
=
node_pt
->geom_object_pt(1);
1098
1099
// Local coordinate:
1100
Vector<double>
s_tl
(1);
1101
s_tl
[0] =
node_pt
->ref_value(3);
1102
1103
Vector<double>
r_tl
(
n_dim
);
1104
obj_tl_pt
->position(
t
,
s_tl
,
r_tl
);
1105
1106
// Position of the corner of the central box
1107
Vector<double>
r_box
(
n_dim
);
1108
r_box
[0] = Lambda_x *
r_br
[0];
1109
r_box
[1] = Lambda_y *
r_tl
[1];
1110
1111
// Position Vector to top face of central box
1112
Vector<double>
r_top
(
n_dim
);
1113
r_top
[0] = Lambda_y *
r_tl
[0] +
rho_0
* (
r_box
[0] - Lambda_y *
r_tl
[0]);
1114
r_top
[1] = Lambda_y *
r_tl
[1] +
rho_0
* (
r_box
[1] - Lambda_y *
r_tl
[1]);
1115
1116
// Wall position
1117
1118
// Pointer to wall element:
1119
GeomObject
*
obj_wall_pt
=
node_pt
->geom_object_pt(2);
1120
1121
// Local coordinate:
1122
Vector<double>
s_wall
(1);
1123
s_wall
[0] =
node_pt
->ref_value(4);
1124
1125
Vector<double>
r_wall
(
n_dim
);
1126
obj_wall_pt
->position(
t
,
s_wall
,
r_wall
);
1127
1128
// Assign new nodal coordinate
1129
node_pt
->x(
t
, 0) =
r_top
[0] +
rho_1
* (
r_wall
[0] -
r_top
[0]);
1130
node_pt
->x(
t
, 1) =
r_top
[1] +
rho_1
* (
r_wall
[1] -
r_top
[1]);
1131
}
1132
1133
//======================================================================
1134
/// Update algebraic update function for nodes in lower right box.
1135
//======================================================================
1136
template
<
class
ELEMENT>
1137
void
AlgebraicRefineableQuarterCircleSectorMesh
<
1138
ELEMENT
>::update_node_update_in_lower_right_box(
AlgebraicNode
*&
node_pt
)
1139
{
1140
// Extract references for update in central box by copy construction
1141
Vector<double>
ref_value
(
node_pt
->vector_ref_value(Lower_right_box));
1142
1143
// Extract geometric objects for updatein central box by copy construction
1144
Vector<GeomObject*>
geom_object_pt
(
1145
node_pt
->vector_geom_object_pt(Lower_right_box));
1146
1147
// Now remove the update info to allow overwriting below
1148
node_pt
->kill_node_update_info(Lower_right_box);
1149
1150
// Fixed reference value: Start coordinate on wall
1151
double
xi_lo
=
QuarterCircleSectorMesh<ELEMENT>::Xi_lo
;
1152
1153
// Fixed reference value: Fractional position of dividing line
1154
double
fract_mid
=
QuarterCircleSectorMesh<ELEMENT>::Fract_mid
;
1155
1156
// Fixed reference value: End coordinate on wall
1157
double
xi_hi
=
QuarterCircleSectorMesh<ELEMENT>::Xi_hi
;
1158
1159
// Second reference value: fractional s1-position of node inside box
1160
double
rho_1
=
ref_value
[1];
1161
1162
// Update reference to wall point in bottom right corner
1163
//------------------------------------------------------
1164
1165
// Wall position in bottom right corner:
1166
Vector<double>
xi
(1);
1167
xi
[0] =
xi_lo
;
1168
1169
// Find corresponding wall element/local coordinate
1170
GeomObject
*
obj_br_pt
;
1171
Vector<double>
s_br
(1);
1172
this->Wall_pt->locate_zeta(
xi
,
obj_br_pt
,
s_br
);
1173
1174
// Wall element at bottom right end of wall mesh:
1175
geom_object_pt
[0] =
obj_br_pt
;
1176
1177
// Local coordinate in this wall element. Note:
1178
// We'll have to recompute this reference
1179
// when the mesh is refined as we might fall off the element otherwise
1180
ref_value
[2] =
s_br
[0];
1181
1182
// Update reference to wall point in upper left corner
1183
//----------------------------------------------------
1184
1185
// Wall position in top left corner
1186
xi
[0] =
xi_hi
;
1187
1188
// Find corresponding wall element/local coordinate
1189
GeomObject
*
obj_tl_pt
;
1190
Vector<double>
s_tl
(1);
1191
this->Wall_pt->locate_zeta(
xi
,
obj_tl_pt
,
s_tl
);
1192
1193
// Wall element at top left end of wall mesh:
1194
geom_object_pt
[1] =
obj_tl_pt
;
1195
1196
// Local coordinate in this wall element. Note:
1197
// We'll have to recompute this reference
1198
// when the mesh is refined as we might fall off the element otherwise
1199
ref_value
[3] =
s_tl
[0];
1200
1201
// Update reference to reference point on wall
1202
//--------------------------------------------
1203
1204
// Reference point on wall
1205
Vector<double>
xi_wall
(1);
1206
xi_wall
[0] =
xi_lo
+
rho_1
*
fract_mid
* (
xi_hi
-
xi_lo
);
1207
1208
// Identify wall element number and local coordinate of
1209
// reference point on wall
1210
GeomObject
*
obj_wall_pt
;
1211
Vector<double>
s_wall
(1);
1212
this->Wall_pt->locate_zeta(
xi_wall
,
obj_wall_pt
,
s_wall
);
1213
1214
// Wall element at that contians reference point:
1215
geom_object_pt
[2] =
obj_wall_pt
;
1216
1217
// Local coordinate in this wall element. Note:
1218
// We'll have to recompute this reference
1219
// when the mesh is refined as we might fall off the element otherwise
1220
ref_value
[4] =
s_wall
[0];
1221
1222
// Setup algebraic update for node: Pass update information
1223
node_pt
->add_node_update_info(Lower_right_box,
// Enumerated ID
1224
this
,
// mesh
1225
geom_object_pt
,
// vector of geom objects
1226
ref_value
);
// vector of ref. vals
1227
}
1228
1229
//======================================================================
1230
/// Update algebraic update function for nodes in upper left box
1231
//======================================================================
1232
template
<
class
ELEMENT>
1233
void
AlgebraicRefineableQuarterCircleSectorMesh
<
1234
ELEMENT
>::update_node_update_in_upper_left_box(
AlgebraicNode
*&
node_pt
)
1235
{
1236
// Extract references for update in central box by copy construction
1237
Vector<double>
ref_value
(
node_pt
->vector_ref_value(Upper_left_box));
1238
1239
// Extract geometric objects for update in central box by copy construction
1240
Vector<GeomObject*>
geom_object_pt
(
1241
node_pt
->vector_geom_object_pt(Upper_left_box));
1242
1243
// Now remove the update info to allow overwriting below
1244
node_pt
->kill_node_update_info(Upper_left_box);
1245
1246
// Fixed reference value: Start coordinate on wall
1247
double
xi_lo
=
QuarterCircleSectorMesh<ELEMENT>::Xi_lo
;
1248
1249
// Fixed reference value: Fractional position of dividing line
1250
double
fract_mid
=
QuarterCircleSectorMesh<ELEMENT>::Fract_mid
;
1251
1252
// Fixed reference value: End coordinate on wall
1253
double
xi_hi
=
QuarterCircleSectorMesh<ELEMENT>::Xi_hi
;
1254
1255
// First reference value: fractional s0-position of node inside box
1256
double
rho_0
=
ref_value
[0];
1257
1258
// Update reference to wall point in bottom right corner
1259
//------------------------------------------------------
1260
1261
// Wall position in bottom right corner:
1262
Vector<double>
xi
(1);
1263
xi
[0] =
xi_lo
;
1264
1265
// Find corresponding wall element/local coordinate
1266
GeomObject
*
obj_br_pt
;
1267
Vector<double>
s_br
(1);
1268
this->Wall_pt->locate_zeta(
xi
,
obj_br_pt
,
s_br
);
1269
1270
// Wall element at bottom right end of wall mesh:
1271
geom_object_pt
[0] =
obj_br_pt
;
1272
1273
// Local coordinate in this wall element. Note:
1274
// We'll have to recompute this reference
1275
// when the mesh is refined as we might fall off the element otherwise
1276
ref_value
[2] =
s_br
[0];
1277
1278
// Update reference to wall point in upper left corner
1279
//----------------------------------------------------
1280
1281
// Wall position in top left corner
1282
xi
[0] =
xi_hi
;
1283
1284
// Find corresponding wall element/local coordinate
1285
GeomObject
*
obj_tl_pt
;
1286
Vector<double>
s_tl
(1);
1287
this->Wall_pt->locate_zeta(
xi
,
obj_tl_pt
,
s_tl
);
1288
1289
// Wall element at top left end of wall mesh:
1290
geom_object_pt
[1] =
obj_tl_pt
;
1291
1292
// Local coordinate in this wall element. Note:
1293
// We'll have to recompute this reference
1294
// when the mesh is refined as we might fall off the element otherwise
1295
ref_value
[3] =
s_tl
[0];
1296
1297
// Update reference to reference point on wall
1298
//--------------------------------------------
1299
1300
// Reference point on wall
1301
Vector<double>
xi_wall
(1);
1302
xi_wall
[0] =
xi_hi
+
rho_0
* (1.0 -
fract_mid
) * (
xi_lo
-
xi_hi
);
1303
1304
// Identify reference point on wall
1305
GeomObject
*
obj_wall_pt
;
1306
Vector<double>
s_wall
(1);
1307
this->Wall_pt->locate_zeta(
xi_wall
,
obj_wall_pt
,
s_wall
);
1308
1309
// Wall element at that contians reference point:
1310
geom_object_pt
[2] =
obj_wall_pt
;
1311
1312
// Local coordinate in this wall element. Note:
1313
// We'll have to recompute this reference
1314
// when the mesh is refined as we might fall off the element otherwise
1315
ref_value
[4] =
s_wall
[0];
1316
1317
// Setup algebraic update for node: Pass update information
1318
node_pt
->add_node_update_info(Upper_left_box,
// Enumerated ID
1319
this
,
// mesh
1320
geom_object_pt
,
// vector of geom objects
1321
ref_value
);
// vector of ref. vals
1322
}
1323
1324
}
// namespace oomph
1325
#endif
oomph::AlgebraicRefineableQuarterCircleSectorMesh
Algebraic version of RefineableQuarterCircleSectorMesh.
Definition
quarter_circle_sector_mesh.h:436
oomph::QuarterCircleSectorDomain
Circular sector as domain. Domain is bounded by curved boundary which is represented by a GeomObject....
Definition
quarter_circle_sector_domain.h:43
oomph::QuarterCircleSectorMesh
2D quarter ring mesh class. The domain is specified by the GeomObject that identifies boundary 1.
Definition
quarter_circle_sector_mesh.h:84
oomph::QuarterCircleSectorMesh::Fract_mid
double Fract_mid
Fraction along wall where outer ring is to be divided.
Definition
quarter_circle_sector_mesh.h:134
oomph::QuarterCircleSectorMesh::wall_pt
GeomObject *& wall_pt()
Access function to GeomObject representing wall.
Definition
quarter_circle_sector_mesh.h:102
oomph::QuarterCircleSectorMesh::Xi_hi
double Xi_hi
Upper limit for the (1D) coordinates along the wall.
Definition
quarter_circle_sector_mesh.h:137
oomph::QuarterCircleSectorMesh::QuarterCircleSectorMesh
QuarterCircleSectorMesh(GeomObject *wall_pt, const double &xi_lo, const double &fract_mid, const double &xi_hi, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to geometric object that specifies the wall, start and end coordinates on t...
Definition
quarter_circle_sector_mesh.template.cc:45
oomph::QuarterCircleSectorMesh::Domain_pt
QuarterCircleSectorDomain * Domain_pt
Pointer to Domain.
Definition
quarter_circle_sector_mesh.h:124
oomph::QuarterCircleSectorMesh::Xi_lo
double Xi_lo
Lower limit for the (1D) coordinates along the wall.
Definition
quarter_circle_sector_mesh.h:131
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