edgeFaceCirculatorI.H
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2019 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "primitiveMesh.H"
30
31// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32
34{
35 return *meshPtr_;
36}
37
38
39void Foam::edgeFaceCirculator::setEnd()
40{
41 faceLabel_ = -1;
42 index_ = -1;
43}
44
45
46void Foam::edgeFaceCirculator::setFace
47(
48 const label facei,
49 const label celli
50)
51{
52 faceLabel_ = facei;
53
54 if (!isBoundaryEdge_ && !mesh().isInternalFace(facei))
55 {
57 << "Edge is not defined as boundary edge but still walked to"
58 << " boundary face:" << facei << " on cell:" << celli
59 << abort(FatalError);
60 }
61}
62
63
64void Foam::edgeFaceCirculator::otherFace(const label celli)
65{
66 const face& f = mesh().faces()[faceLabel_];
67 label v0 = f[index_];
68 label v1 = f.nextLabel(index_);
69
70 const cell& cFaces = mesh().cells()[celli];
71
72 forAll(cFaces, i)
73 {
74 label faceB = cFaces[i];
75
76 if (faceB != faceLabel_)
77 {
78 label fp = getMinIndex(mesh().faces()[faceB], v0, v1);
79
80 if (fp >= 0)
81 {
82 index_ = fp;
83 setFace(faceB, celli);
84 return;
85 }
86 }
87 }
88
90 << "Could not find next face stepping"
91 << " through cell along edge." << endl
92 << "face:" << faceLabel_ << " index in face:" << index_
93 << " edge:" << mesh().points()[v0] << mesh().points()[v1]
94 << abort(FatalError);
95}
96
97
98// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
99
101:
102 meshPtr_(nullptr),
103 ownerSide_(false),
104 isBoundaryEdge_(false),
105 faceLabel_(-1),
106 index_(-1),
107 startFaceLabel_(0)
108{}
109
110
112(
113 const primitiveMesh& mesh,
114 const label faceLabel,
115 const bool ownerSide,
116 const label index,
117 const bool isBoundaryEdge
118)
119:
120 meshPtr_(&mesh),
121 ownerSide_(ownerSide),
122 isBoundaryEdge_(isBoundaryEdge),
123 faceLabel_(faceLabel),
124 index_(index),
125 startFaceLabel_(faceLabel_)
126{}
127
128
130:
131 meshPtr_(circ.meshPtr_),
132 ownerSide_(circ.ownerSide_),
133 isBoundaryEdge_(circ.isBoundaryEdge_),
134 faceLabel_(circ.faceLabel_),
135 index_(circ.index_),
136 startFaceLabel_(circ.startFaceLabel_)
137{}
138
139
140// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
141
143(
144 const face& f,
145 const label v0,
146 const label v1
147)
148{
149 label fp = f.find(v0);
150
151 if (fp != -1)
152 {
153 label fpMin1 = f.rcIndex(fp);
154
155 if (f[fpMin1] == v1)
156 {
157 fp = fpMin1;
158 }
159 else
160 {
161 label fpPlus1 = f.fcIndex(fp);
162
163 if (f[fpPlus1] != v1)
164 {
165 fp = -1;
166 }
167 }
168 }
169 return fp;
170}
171
172
174{
175 return faceLabel_;
176}
177
178
180{
181 return
182 (
183 faceLabel_ >= 0
184 && meshPtr_
185 && meshPtr_->isInternalFace(faceLabel_)
186 );
187}
188
189
191{
192 return ownerSide_;
193}
194
195
197{
198 return index_;
199}
200
201
203{
204 if (ownerSide_)
205 {
206 return mesh().faceOwner()[faceLabel_];
207 }
208 else if (mesh().isInternalFace(faceLabel_))
209 {
210 return mesh().faceNeighbour()[faceLabel_];
211 }
212
213 return -1;
214}
215
216
217bool Foam::edgeFaceCirculator::sameOrder(const label v0, const label v1) const
218{
219 const face& f = mesh().faces()[faceLabel_];
220
221 label fp = getMinIndex(f, v0, v1);
222
223 if (fp != index_)
224 {
226 << "v0:" << v1 << " and v1:" << v1
227 << " not on position:" << index_ << " on face:" << faceLabel_
228 << " verts:" << f << " or not consecutive." << abort(FatalError);
229 }
230
231 // If we are neighbour the face would point into us so the min index would
232 // be v0.
233 return ownerSide_ != (f[index_] == v0);
234}
235
236
238{
239 if (isBoundaryEdge_)
240 {
241 // Boundary edge. Step until we're on boundary face and ownerSide
242 label i = 0;
243
244 while (true)
245 {
246 if (mesh().isInternalFace(faceLabel_))
247 {
248 if (ownerSide_)
249 {
250 label celli = mesh().faceNeighbour()[faceLabel_];
251 otherFace(celli);
252 // Maintain reverse direction of walking
253 ownerSide_ = (mesh().faceOwner()[faceLabel_] == celli);
254 }
255 else
256 {
257 label celli = mesh().faceOwner()[faceLabel_];
258 otherFace(celli);
259 // Maintain reverse direction of walking
260 ownerSide_ = (mesh().faceOwner()[faceLabel_] == celli);
261 }
262 }
263 else if (ownerSide_)
264 {
265 break;
266 }
267 else
268 {
269 label celli = mesh().faceOwner()[faceLabel_];
270 otherFace(celli);
271 // Maintain reverse direction of walking
272 ownerSide_ = (mesh().faceOwner()[faceLabel_] == celli);
273 }
274
275 i++;
276
277 if (i >= 1000)
278 {
279 const face& f = mesh().faces()[faceLabel_];
280
282 << "Walked " << i << " cells around edge "
283 << mesh().points()[f[index_]]
284 << mesh().points()[f.nextLabel(index_)]
285 << " without reaching a boundary face."
286 << " Are you sure this is a boundary edge?"
287 << abort(FatalError);
288 }
289 }
290
291 // Set up for correct walking
292 ownerSide_ = true;
293 startFaceLabel_ = faceLabel_;
294 }
295 else
296 {
297 // Internal edge. Walk until we hit minimum face label.
298 label minFacei = faceLabel_;
299 bool minOwnerSide = ownerSide_;
300 label minIndex = index_;
301
302 while (true)
303 {
304 operator++();
305
306 if (operator==(end()))
307 {
308 break;
309 }
310
311 if (!mesh().isInternalFace(faceLabel_))
312 {
313 const face& f = mesh().faces()[faceLabel_];
314
316 << "Reached boundary face " << faceLabel_
317 << " when walking around internal edge "
318 << mesh().points()[f[index_]]
319 << mesh().points()[f.nextLabel(index_)]
320 << "." << endl
321 << "Are you sure this is an internal edge?"
322 << abort(FatalError);
323 }
324
325 if (faceLabel_ < minFacei)
326 {
327 minFacei = faceLabel_;
328 minOwnerSide = ownerSide_;
329 minIndex = index_;
330 }
331 }
332
333 faceLabel_ = minFacei;
334 ownerSide_ = minOwnerSide;
335 index_ = minIndex;
336 startFaceLabel_ = faceLabel_;
337 }
338}
339
340
342{
343 ownerSide_ = circ.ownerSide_;
344 isBoundaryEdge_ = circ.isBoundaryEdge_;
345 faceLabel_ = circ.faceLabel_;
346 index_ = circ.index_;
347 startFaceLabel_ = circ.startFaceLabel_;
348}
349
350
352{
353 return faceLabel_ == circ.faceLabel_ && index_ == circ.index_;
354
357 //if (faceLabel_ == -1 && circ.faceLabel_ == -1)
358 //{
359 // // both endConstIter
360 // return true;
361 //}
362 //
363 //return
364 // faceLabel_ == circ.faceLabel_
365 // && ownerSide_ == circ.ownerSide_
366 // && index_ == circ.index_;
367 // && startFaceLabel_ == circ.startFaceLabel_;
368}
369
370
372{
373 return !(*this == circ);
374}
375
376
377//- Step to next face.
380{
381 if (faceLabel_ == -1)
382 {
384 << "Already reached end(). Cannot walk any further."
385 << abort(FatalError);
386 }
387 else if (ownerSide_)
388 {
389 // Step to owner
390 label celli = mesh().faceOwner()[faceLabel_];
391 otherFace(celli);
392 // Maintain direction of walking
393 ownerSide_ = (mesh().faceOwner()[faceLabel_] != celli);
394
395 // Check for internal edge : ends on starting face.
396 if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
397 {
398 setEnd();
399 }
400 }
401 else if (mesh().isInternalFace(faceLabel_))
402 {
403 // Step to neighbour
404 label celli = mesh().faceNeighbour()[faceLabel_];
405 otherFace(celli);
406 // Maintain direction of walking
407 ownerSide_ = (mesh().faceOwner()[faceLabel_] != celli);
408
409 // Check for internal edge : ends on starting face.
410 if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
411 {
412 setEnd();
413 }
414 }
415 else
416 {
417 // neighbour side of boundary face reached. Mark as endConstIter.
418 setEnd();
419 }
420
421 return *this;
422}
423
424
426{
428 (
429 *meshPtr_,
430 faceLabel_,
431 ownerSide_,
432 index_,
433 isBoundaryEdge_
434 );
435
436 if (isBoundaryEdge_)
437 {
438 iter.setCanonical();
439 }
440 return iter;
441}
442
443
445{
446 return cbegin();
447}
448
450{
451 return edgeFaceCirculator();
452}
453
455{
456 return edgeFaceCirculator();
457}
458
459
460// ************************************************************************* //
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
Definition: UList.C:212
label rcIndex(const label i) const noexcept
Definition: UListI.H:67
label fcIndex(const label i) const noexcept
Definition: UListI.H:60
Walks from starting face around edge.
void operator=(const edgeFaceCirculator &iter)
edgeFaceCirculator & operator++()
Step to next face. Uses no edge addressing!
bool isInternalFace() const
Return true if the face label corresponds to an internal face.
bool sameOrder(const label v0, const label v1) const
Helper: return true if normal of generated face points along.
label faceLabel() const
Return the face label, -1 for end iterator.
const edgeFaceCirculator cend() const
label cellLabel() const
Helper: get the neighbouring cell according to the ownerSide.
void setCanonical()
Set edge to a unique state so different ones can be compared.
static label getMinIndex(const face &f, const label v0, const label v1)
Helper: find index in face of edge or -1. Index is such that edge is.
edgeFaceCirculator cbegin() const
edgeFaceCirculator begin() const
Iterator set to the beginning face. For internal edges this is.
const edgeFaceCirculator end() const
Iterator set to beyond the end of the walk.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1108
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1121
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1127
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1083
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:79
const cellList & cells() const
friend bool operator!=(const refineCell &rc1, const refineCell &rc2)
Definition: refineCell.H:106
friend bool operator==(const refineCell &rc1, const refineCell &rc2)
Definition: refineCell.H:97
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333