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
generic
quad_mesh.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
#include <algorithm>
27
#include "
map_matrix.h
"
28
#include "
quad_mesh.h
"
29
30
31
namespace
oomph
32
{
33
//================================================================
34
/// Setup lookup schemes which establish which elements are located
35
/// next to which boundaries (Doc to outfile if it's open).
36
//================================================================
37
void
QuadMeshBase::setup_boundary_element_info
(std::ostream&
outfile
)
38
{
39
bool
doc =
false
;
40
if
(
outfile
) doc =
true
;
41
42
// Number of boundaries
43
unsigned
nbound
=
nboundary
();
44
45
// Wipe/allocate storage for arrays
46
Boundary_element_pt
.clear();
47
Face_index_at_boundary
.clear();
48
Boundary_element_pt
.resize(
nbound
);
49
Face_index_at_boundary
.resize(
nbound
);
50
51
// Temporary vector of vectors to pointers to elements on the boundaries:
52
// This is not a set to ensure UNIQUE ordering
53
Vector<Vector<FiniteElement*>
>
vector_of_boundary_element_pt
;
54
vector_of_boundary_element_pt
.resize(
nbound
);
55
56
// Matrix map for working out the fixed local coord for elements on boundary
57
MapMatrixMixed<unsigned, FiniteElement*, Vector<int>
*>
boundary_identifier
;
58
59
60
// Loop over elements
61
//-------------------
62
unsigned
nel
=
nelement
();
63
for
(
unsigned
e
= 0;
e
<
nel
;
e
++)
64
{
65
// Get pointer to element
66
FiniteElement
*
fe_pt
=
finite_element_pt
(
e
);
67
68
if
(doc)
outfile
<<
"Element: "
<<
e
<<
" "
<<
fe_pt
<< std::endl;
69
70
// Only include 2D elements! Some meshes contain interface elements too.
71
if
(
fe_pt
->
dim
() == 2)
72
{
73
// Loop over the element's nodes and find out which boundaries they're
74
// on
75
// ----------------------------------------------------------------------
76
unsigned
nnode_1d =
fe_pt
->
nnode_1d
();
77
78
// Loop over nodes in order
79
for
(
unsigned
i0
= 0;
i0
< nnode_1d;
i0
++)
80
{
81
for
(
unsigned
i1
= 0;
i1
< nnode_1d;
i1
++)
82
{
83
// Local node number
84
unsigned
j
=
i0
+
i1
* nnode_1d;
85
86
// Get pointer to vector of boundaries that this
87
// node lives on
88
std::set<unsigned>*
boundaries_pt
= 0;
89
fe_pt
->
node_pt
(
j
)->
get_boundaries_pt
(
boundaries_pt
);
90
91
// If the node lives on some boundaries....
92
if
(
boundaries_pt
!= 0)
93
{
94
// Loop over boundaries
95
// unsigned nbound=(*boundaries_pt).size();
96
for
(std::set<unsigned>::iterator
it
=
boundaries_pt
->begin();
97
it
!=
boundaries_pt
->end();
98
++
it
)
99
{
100
// Add pointer to finite element to vector for the appropriate
101
// boundary
102
103
// Does the pointer already exits in the vector
104
Vector<FiniteElement*>::iterator
b_el_it
=
105
std::find(
vector_of_boundary_element_pt
[*
it
].
begin
(),
106
vector_of_boundary_element_pt
[*
it
].
end
(),
107
fe_pt
);
108
// Only insert if we have not found it (i.e. got to the end)
109
if
(
b_el_it
==
vector_of_boundary_element_pt
[*
it
].
end
())
110
{
111
vector_of_boundary_element_pt
[*
it
].push_back(
fe_pt
);
112
}
113
114
// For the current element/boundary combination, create
115
// a vector that stores an indicator which element boundaries
116
// the node is located (boundary_identifier=-/+1 for nodes
117
// on the left/right boundary; boundary_identifier=-/+2 for
118
// nodes on the lower/upper boundary. We determine these indices
119
// for all corner nodes of the element and add them to a vector
120
// to a vector. This allows us to decide which face of the
121
// element coincides with the boundary since the (quad!) element
122
// must have exactly two corner nodes on the boundary.
123
if
(
boundary_identifier
(*
it
,
fe_pt
) == 0)
124
{
125
boundary_identifier
(*
it
,
fe_pt
) =
new
Vector<int>
;
126
}
127
128
// Are we at a corner node?
129
if
(((
i0
== 0) || (
i0
== nnode_1d - 1)) &&
130
((
i1
== 0) || (
i1
== nnode_1d - 1)))
131
{
132
// Create index to represent position relative to s_0
133
(*
boundary_identifier
(*
it
,
fe_pt
))
134
.
push_back
(1 * (2 *
i0
/ (nnode_1d - 1) - 1));
135
136
// Create index to represent position relative to s_1
137
(*
boundary_identifier
(*
it
,
fe_pt
))
138
.
push_back
(2 * (2 *
i1
/ (nnode_1d - 1) - 1));
139
}
140
}
141
}
142
// else
143
// {
144
// oomph_info << "...does not live on any boundaries " <<
145
// std::endl;
146
// }
147
}
148
}
149
}
150
// else
151
//{
152
// oomph_info << "Element " << e << " does not qualify" << std::endl;
153
//}
154
}
155
156
// Now copy everything across into permanent arrays
157
//-------------------------------------------------
158
159
// Note: vector_of_boundary_element_pt contains all elements
160
// that have (at least) one corner node on a boundary -- can't copy
161
// them across into Boundary_element_pt
162
// yet because some of them might have only one node on the
163
// the boundary in which case they don't qualify as
164
// boundary elements!
165
166
// Loop over boundaries
167
//---------------------
168
for
(
unsigned
i
= 0;
i
<
nbound
;
i
++)
169
{
170
// Number of elements on this boundary
171
// nel is unused, so I've commented it out - RWhite.
172
// unsigned nel=vector_of_boundary_element_pt[i].size();
173
174
// Allocate storage for the face identifiers
175
// Face_index_at_boundary[i].resize(nel);
176
177
// Loop over elements that have at least one corner node on this boundary
178
//-----------------------------------------------------------------------
179
// unsigned e_count=0;
180
typedef
Vector<FiniteElement*>::iterator
IT
;
181
for
(
IT
it
=
vector_of_boundary_element_pt
[
i
].
begin
();
182
it
!=
vector_of_boundary_element_pt
[
i
].end();
183
it
++)
184
{
185
// Recover pointer to element
186
FiniteElement
*
fe_pt
= *
it
;
187
188
// Initialise count for boundary identiers (-2,-1,1,2)
189
std::map<int, unsigned>
count
;
190
191
// Loop over coordinates
192
for
(
unsigned
ii
= 0;
ii
< 2;
ii
++)
193
{
194
// Loop over upper/lower end of coordinates
195
for
(
int
sign
= -1;
sign
< 3;
sign
+= 2)
196
{
197
count
[(
ii
+ 1) *
sign
] = 0;
198
}
199
}
200
201
// Loop over boundary indicators for this element/boundary
202
unsigned
n_indicators
= (*
boundary_identifier
(
i
,
fe_pt
)).size();
203
for
(
unsigned
j
= 0;
j
<
n_indicators
;
j
++)
204
{
205
count
[(*
boundary_identifier
(
i
,
fe_pt
))[
j
]]++;
206
}
207
delete
boundary_identifier
(
i
,
fe_pt
);
208
209
// Determine the correct boundary indicator by checking that it
210
// occurs twice (since two corner nodes of the element's boundary
211
// need to be located on the domain boundary
212
int
indicator
= -10;
213
214
// Check that we're finding exactly one boundary indicator
215
// bool found=false;
216
217
// Loop over coordinates
218
for
(
unsigned
ii
= 0;
ii
< 2;
ii
++)
219
{
220
// Loop over upper/lower end of coordinates
221
for
(
int
sign
= -1;
sign
< 3;
sign
+= 2)
222
{
223
// If an index occurs twice then that face is on the boundary
224
// But we can have multiple faces on the same boundary id, so just
225
// add all the ones that we have
226
if
(
count
[(
ii
+ 1) *
sign
] == 2)
227
{
228
// Check that we haven't found multiple boundaries
229
/*if (found)
230
{
231
std::string error_message=
232
"Trouble: Multiple boundary identifiers!\n";
233
error_message +=
234
"Elements should only have at most 2 corner ";
235
error_message +=
236
"nodes on any one boundary.\n";
237
238
throw OomphLibError(
239
error_message,
240
OOMPH_CURRENT_FUNCTION,
241
OOMPH_EXCEPTION_LOCATION);
242
}
243
found=true;*/
244
indicator
= (
ii
+ 1) *
sign
;
245
246
// Copy into the data structure
247
Boundary_element_pt
[
i
].push_back(*
it
);
248
Face_index_at_boundary
[
i
].push_back(
indicator
);
249
}
250
}
251
}
252
253
// Element has exactly two corner nodes on boundary
254
/*if (found)
255
{
256
// Add to permanent storage
257
Boundary_element_pt[i].push_back(fe_pt);
258
259
// Now convert boundary indicator into information required
260
// for FaceElements
261
switch (indicator)
262
{
263
//South face
264
case -2:
265
266
// s_1 is fixed at -1.0:
267
Face_index_at_boundary[i][e_count] = -2;
268
break;
269
270
//West face
271
case -1:
272
273
// s_0 is fixed at -1.0:
274
Face_index_at_boundary[i][e_count] = -1;
275
break;
276
277
//East face
278
case 1:
279
280
// s_0 is fixed at 1.0:
281
Face_index_at_boundary[i][e_count] = 1;
282
break;
283
284
//North face
285
case 2:
286
287
// s_1 is fixed at 1.0:
288
Face_index_at_boundary[i][e_count] = 2;
289
break;
290
291
default:
292
293
throw OomphLibError("Never get here",
294
OOMPH_CURRENT_FUNCTION,
295
OOMPH_EXCEPTION_LOCATION);
296
}
297
298
// Increment counter
299
e_count++;
300
}*/
301
}
302
}
303
304
305
// Doc?
306
//-----
307
if
(doc)
308
{
309
// Loop over boundaries
310
for
(
unsigned
i
= 0;
i
<
nbound
;
i
++)
311
{
312
unsigned
nel
=
Boundary_element_pt
[
i
].
size
();
313
outfile
<<
"Boundary: "
<<
i
<<
" is adjacent to "
<<
nel
<<
" elements"
314
<< std::endl;
315
316
// Loop over elements on given boundary
317
for
(
unsigned
e
= 0;
e
<
nel
;
e
++)
318
{
319
FiniteElement
*
fe_pt
=
Boundary_element_pt
[
i
][
e
];
320
outfile
<<
"Boundary element:"
<<
fe_pt
321
<<
" Face index on boundary is "
322
<<
Face_index_at_boundary
[
i
][
e
] << std::endl;
323
}
324
}
325
}
326
327
328
// Lookup scheme has now been setup
329
Lookup_for_elements_next_boundary_is_setup
=
true
;
330
}
331
332
}
// namespace oomph
e
e
Definition
cfortran.h:571
i
cstr elem_len * i
Definition
cfortran.h:603
oomph::FiniteElement
A general Finite Element class.
Definition
elements.h:1317
oomph::FiniteElement::size
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
Definition
elements.cc:4320
oomph::FiniteElement::dim
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition
elements.h:2615
oomph::FiniteElement::node_pt
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition
elements.h:2179
oomph::FiniteElement::nnode_1d
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
Definition
elements.h:2222
oomph::Mesh::Boundary_element_pt
Vector< Vector< FiniteElement * > > Boundary_element_pt
Vector of Vector of pointers to elements on the boundaries: Boundary_element_pt(b,...
Definition
mesh.h:91
oomph::Mesh::Lookup_for_elements_next_boundary_is_setup
bool Lookup_for_elements_next_boundary_is_setup
Flag to indicate that the lookup schemes for elements that are adjacent to the boundaries has been se...
Definition
mesh.h:87
oomph::Mesh::finite_element_pt
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition
mesh.h:477
oomph::Mesh::Face_index_at_boundary
Vector< Vector< int > > Face_index_at_boundary
For the e-th finite element on boundary b, this is the index of the face that lies along that boundar...
Definition
mesh.h:95
oomph::Mesh::nboundary
unsigned nboundary() const
Return number of boundaries.
Definition
mesh.h:835
oomph::Mesh::nelement
unsigned long nelement() const
Return number of elements in the mesh.
Definition
mesh.h:598
oomph::Node::get_boundaries_pt
virtual void get_boundaries_pt(std::set< unsigned > *&boundaries_pt)
Return a pointer to set of mesh boundaries that this node occupies; this will be overloaded by Bounda...
Definition
nodes.h:1365
oomph::QuadMeshBase::setup_boundary_element_info
void setup_boundary_element_info()
Setup lookup schemes which establish whic elements are located next to mesh's boundaries (wrapper to ...
Definition
quad_mesh.h:73
oomph::TAdvectionDiffusionReactionElement
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
Definition
Tadvection_diffusion_reaction_elements.h:66
oomph::Vector
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition
Vector.h:58
map_matrix.h
oomph
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition
advection_diffusion_elements.cc:30
quad_mesh.h