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
31namespace 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 //================================================================
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();
50
51 // Temporary vector of vectors to pointers to elements on the boundaries:
52 // This is not a set to ensure UNIQUE ordering
55
56 // Matrix map for working out the fixed local coord for elements on boundary
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
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;
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
107 fe_pt);
108 // Only insert if we have not found it (i.e. got to the end)
110 {
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 {
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
134 .push_back(1 * (2 * i0 / (nnode_1d - 1) - 1));
135
136 // Create index to represent position relative to s_1
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;
183 it++)
184 {
185 // Recover pointer to element
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 {
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);
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 {
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
330 }
331
332} // namespace oomph
e
Definition cfortran.h:571
cstr elem_len * i
Definition cfortran.h:603
A general Finite Element class.
Definition elements.h:1317
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
Definition elements.cc:4320
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition elements.h:2615
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition elements.h:2179
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
Vector< Vector< FiniteElement * > > Boundary_element_pt
Vector of Vector of pointers to elements on the boundaries: Boundary_element_pt(b,...
Definition mesh.h:91
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
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition mesh.h:477
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
unsigned nboundary() const
Return number of boundaries.
Definition mesh.h:835
unsigned long nelement() const
Return number of elements in the mesh.
Definition mesh.h:598
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
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
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition Vector.h:58
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).