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