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 -------------------------------------------------------------------------------
11 License
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 
33 inline const Foam::primitiveMesh& Foam::edgeFaceCirculator::mesh() const
34 {
35  return *meshPtr_;
36 }
37 
38 
39 void Foam::edgeFaceCirculator::setEnd()
40 {
41  faceLabel_ = -1;
42  index_ = -1;
43 }
44 
45 
46 void 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 
64 void 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 
100 Foam::edgeFaceCirculator::edgeFaceCirculator()
101 :
102  meshPtr_(nullptr),
103  ownerSide_(false),
104  isBoundaryEdge_(false),
105  faceLabel_(-1),
106  index_(-1),
107  startFaceLabel_(0)
108 {}
109 
110 
111 Foam::edgeFaceCirculator::edgeFaceCirculator
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 
129 Foam::edgeFaceCirculator::edgeFaceCirculator(const edgeFaceCirculator& circ)
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 
173 Foam::label Foam::edgeFaceCirculator::faceLabel() const
174 {
175  return faceLabel_;
176 }
177 
178 
180 {
181  return
182  (
183  faceLabel_ >= 0
184  && meshPtr_
185  && meshPtr_->isInternalFace(faceLabel_)
186  );
187 }
188 
191 {
192  return ownerSide_;
193 }
194 
196 Foam::label Foam::edgeFaceCirculator::index() const
197 {
198  return index_;
199 }
200 
201 
202 Foam::label Foam::edgeFaceCirculator::cellLabel() const
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 
217 bool 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  }
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 
341 void Foam::edgeFaceCirculator::operator=(const edgeFaceCirculator& circ)
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  }
421  return *this;
422 }
423 
424 
426 {
427  edgeFaceCirculator iter
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 // ************************************************************************* //
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:75
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
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.
void operator=(const edgeFaceCirculator &iter)
const edgeFaceCirculator end() const
Iterator set to beyond the end of the walk.
const cellList & cells() const
label otherFace(const primitiveMesh &mesh, const label celli, const label facei, const label edgeI)
Return face on cell using edgeI but not facei. Throws error.
Definition: meshTools.C:548
label cellLabel() const
Helper: get the neighbouring cell according to the ownerSide.
bool sameOrder(const label v0, const label v1) const
Helper: return true if normal of generated face points along.
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1078
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
label fcIndex(const label i) const noexcept
The forward circular index. The next index in the list which returns to the first at the end of the l...
Definition: UListI.H:97
bool isInternalFace() const
Return true if the face label corresponds to an internal face.
dynamicFvMesh & mesh
label faceLabel() const
Return the face label, -1 for end iterator.
const edgeFaceCirculator cend() const
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
errorManip< error > abort(error &err)
Definition: errorManip.H:139
label find(const T &val) const
Find index of the first occurrence of the value.
Definition: UList.C:173
edgeFaceCirculator & operator++()
Step to next face. Uses no edge addressing!
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
edgeFaceCirculator begin() const
Iterator set to the beginning face. For internal edges this is.
labelList f(nPoints)
bool operator!=(const edgeFaceCirculator &iter) const
constexpr auto cbegin(const C &c) -> decltype(c.begin())
Return const_iterator to the beginning of the container c.
Definition: stdFoam.H:190
Walks from starting face around edge.
void setCanonical()
Set edge to a unique state so different ones can be compared.
edgeFaceCirculator cbegin() const
label rcIndex(const label i) const noexcept
The reverse circular index. The previous index in the list which returns to the last at the beginning...
Definition: UListI.H:104
bool operator==(const edgeFaceCirculator &iter) const