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 | Copyright (C) 2011 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  (
49  "edgeFaceCirculator::setFace(const label, const label)"
50  ) << "Edge is not defined as boundary edge but still walked to"
51  << " boundary face:" << faceI << " on cell:" << cellI
52  << abort(FatalError);
53  }
54 }
55 
56 
57 void Foam::edgeFaceCirculator::otherFace(const label cellI)
58 {
59  const face& f = mesh_.faces()[faceLabel_];
60  label v0 = f[index_];
61  label v1 = f.nextLabel(index_);
62 
63  const cell& cFaces = mesh_.cells()[cellI];
64 
65  forAll(cFaces, i)
66  {
67  label faceB = cFaces[i];
68 
69  if (faceB != faceLabel_)
70  {
71  label fp = getMinIndex(mesh_.faces()[faceB], v0, v1);
72 
73  if (fp >= 0)
74  {
75  index_ = fp;
76  setFace(faceB, cellI);
77  return;
78  }
79  }
80  }
81 
82  FatalErrorIn("edgeFaceCirculator::otherFace(const label)")
83  << "Could not find next face stepping"
84  << " through cell along edge." << endl
85  << "face:" << faceLabel_ << " index in face:" << index_
86  << " edge:" << mesh_.points()[v0] << mesh_.points()[v1]
87  << abort(FatalError);
88 }
89 
90 
91 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
92 
93 //- Construct from components
95 (
96  const primitiveMesh& mesh,
97  const label faceLabel,
98  const bool ownerSide,
99  const label index,
100  const bool isBoundaryEdge
101 )
102 :
103  mesh_(mesh),
104  faceLabel_(faceLabel),
105  ownerSide_(ownerSide),
106  index_(index),
107  isBoundaryEdge_(isBoundaryEdge),
108  startFaceLabel_(faceLabel_)
109 {}
110 
111 
112 //- Construct copy
114 :
115  mesh_(circ.mesh_),
116  faceLabel_(circ.faceLabel_),
117  ownerSide_(circ.ownerSide_),
118  index_(circ.index_),
119  isBoundaryEdge_(circ.isBoundaryEdge_),
120  startFaceLabel_(circ.startFaceLabel_)
121 {}
122 
123 
124 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
125 
127 (
128  const face& f,
129  const label v0,
130  const label v1
131 )
132 {
133  label fp = findIndex(f, v0);
134 
135  if (fp != -1)
136  {
137  label fpMin1 = f.rcIndex(fp);
138 
139  if (f[fpMin1] == v1)
140  {
141  fp = fpMin1;
142  }
143  else
144  {
145  label fpPlus1 = f.fcIndex(fp);
146 
147  if (f[fpPlus1] != v1)
148  {
149  fp = -1;
150  }
151  }
152  }
153  return fp;
154 }
155 
156 
158 {
159  return faceLabel_;
160 }
161 
162 
164 {
165  return ownerSide_;
166 }
167 
168 
170 {
171  return index_;
172 }
173 
174 
176 {
177  if (ownerSide_)
178  {
179  return mesh_.faceOwner()[faceLabel_];
180  }
181  else if (mesh_.isInternalFace(faceLabel_))
182  {
183  return mesh_.faceNeighbour()[faceLabel_];
184  }
185  else
186  {
187  return -1;
188  }
189 }
190 
191 
192 bool Foam::edgeFaceCirculator::sameOrder(const label v0, const label v1) const
193 {
194  const face& f = mesh_.faces()[faceLabel_];
195 
196  label fp = getMinIndex(f, v0, v1);
197 
198  if (fp != index_)
199  {
201  (
202  "edgeFaceCirculator::sameOrder(const label, const label) const"
203  ) << "v0:" << v1 << " and v1:" << v1
204  << " not on position:" << index_ << " on face:" << faceLabel_
205  << " verts:" << f << " or not consecutive." << abort(FatalError);
206  }
207 
208  // If we are neighbour the face would point into us so the min index would
209  // be v0.
210  return ownerSide_ != (f[index_] == v0);
211 }
212 
213 
215 {
216  if (isBoundaryEdge_)
217  {
218  // Boundary edge. Step until we're on boundary face and ownerSide
219  label i = 0;
220 
221  while (true)
222  {
223  if (mesh_.isInternalFace(faceLabel_))
224  {
225  if (ownerSide_)
226  {
227  label cellI = mesh_.faceNeighbour()[faceLabel_];
228  otherFace(cellI);
229  // Maintain reverse direction of walking
230  ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
231  }
232  else
233  {
234  label cellI = mesh_.faceOwner()[faceLabel_];
235  otherFace(cellI);
236  // Maintain reverse direction of walking
237  ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
238  }
239  }
240  else if (ownerSide_)
241  {
242  break;
243  }
244  else
245  {
246  label cellI = mesh_.faceOwner()[faceLabel_];
247  otherFace(cellI);
248  // Maintain reverse direction of walking
249  ownerSide_ = (mesh_.faceOwner()[faceLabel_] == cellI);
250  }
251 
252  i++;
253 
254  if (i >= 1000)
255  {
256  const face& f = mesh_.faces()[faceLabel_];
257 
258  FatalErrorIn("Foam::edgeFaceCirculator::setCanonical()")
259  << "Walked " << i << " cells around edge "
260  << mesh_.points()[f[index_]]
261  << mesh_.points()[f.nextLabel(index_)]
262  << " without reaching a boundary face."
263  << " Are you sure this is a boundary edge?"
264  << abort(FatalError);
265  }
266  }
267 
268  // Set up for correct walking
269  ownerSide_ = true;
270  startFaceLabel_ = faceLabel_;
271  }
272  else
273  {
274  // Internal edge. Walk until we hit minimum face label.
275  label minFaceI = faceLabel_;
276  bool minOwnerSide = ownerSide_;
277  label minIndex = index_;
278 
279  while (true)
280  {
281  operator++();
282 
283  if (operator==(end()))
284  {
285  break;
286  }
287 
288  if (!mesh_.isInternalFace(faceLabel_))
289  {
290  const face& f = mesh_.faces()[faceLabel_];
291 
292  FatalErrorIn("Foam::edgeFaceCirculator::setCanonical()")
293  << "Reached boundary face " << faceLabel_
294  << " when walking around internal edge "
295  << mesh_.points()[f[index_]]
296  << mesh_.points()[f.nextLabel(index_)]
297  << "." << endl
298  << "Are you sure this is an internal edge?"
299  << abort(FatalError);
300  }
301 
302  if (faceLabel_ < minFaceI)
303  {
304  minFaceI = faceLabel_;
305  minOwnerSide = ownerSide_;
306  minIndex = index_;
307  }
308  }
309 
310  faceLabel_ = minFaceI;
311  ownerSide_ = minOwnerSide;
312  index_ = minIndex;
313  startFaceLabel_ = faceLabel_;
314  }
315 }
316 
317 
319 {
320  faceLabel_ = circ.faceLabel_;
321  ownerSide_ = circ.ownerSide_;
322  index_ = circ.index_;
323  isBoundaryEdge_ = circ.isBoundaryEdge_;
324  startFaceLabel_ = circ.startFaceLabel_;
325 }
326 
327 
329 {
330  return faceLabel_ == circ.faceLabel_ && index_ == circ.index_;
331 
334  //if (faceLabel_ == -1 && circ.faceLabel_ == -1)
335  //{
336  // // both endConstIter
337  // return true;
338  //}
339  //
340  //return
341  // faceLabel_ == circ.faceLabel_
342  // && ownerSide_ == circ.ownerSide_
343  // && index_ == circ.index_;
344  // && startFaceLabel_ == circ.startFaceLabel_;
345 }
346 
347 
349 {
350  return !(*this == circ);
351 }
352 
353 
354 //- Step to next face.
357 {
358  if (faceLabel_ == -1)
359  {
360  FatalErrorIn("edgeFaceCirculator::operator++()")
361  << "Already reached end(). Cannot walk any further."
362  << abort(FatalError);
363  }
364  else if (ownerSide_)
365  {
366  // Step to owner
367  label cellI = mesh_.faceOwner()[faceLabel_];
368  otherFace(cellI);
369  // Maintain direction of walking
370  ownerSide_ = (mesh_.faceOwner()[faceLabel_] != cellI);
371 
372  // Check for internal edge : ends on starting face.
373  if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
374  {
375  setEnd();
376  }
377  }
378  else if (mesh_.isInternalFace(faceLabel_))
379  {
380  // Step to neighbour
381  label cellI = mesh_.faceNeighbour()[faceLabel_];
382  otherFace(cellI);
383  // Maintain direction of walking
384  ownerSide_ = (mesh_.faceOwner()[faceLabel_] != cellI);
385 
386  // Check for internal edge : ends on starting face.
387  if (!isBoundaryEdge_ && faceLabel_ == startFaceLabel_)
388  {
389  setEnd();
390  }
391  }
392  else
393  {
394  // neighbour side of boundary face reached. Mark as endConstIter.
395  setEnd();
396  }
397 
398  return *this;
399 }
400 
401 
403 {
404  edgeFaceCirculator iter
405  (
406  mesh_,
407  faceLabel_,
408  ownerSide_,
409  index_,
410  isBoundaryEdge_
411  );
412 
413  if (isBoundaryEdge_)
414  {
415  iter.setCanonical();
416  }
417  return iter;
418 }
419 
420 
422 {
423  edgeFaceCirculator iter
424  (
425  mesh_,
426  faceLabel_,
427  ownerSide_,
428  index_,
429  isBoundaryEdge_
430  );
431 
432  if (isBoundaryEdge_)
433  {
434  iter.setCanonical();
435  }
436  return iter;
437 }
438 
439 
441 {
442  return endConstIter;
443 }
444 
446 {
447  return endConstIter;
448 }
449 
450 
451 // ************************************************************************* //
virtual const pointField & points() const =0
Return mesh points.
const edgeFaceCirculator & end() const
Iterator set to beyond the end of the walk.
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
label cellLabel() const
Helper: get the neighbouring cell according to the ownerSide.
edgeFaceCirculator begin() const
Iterator set to the beginning face. For internal edges this is.
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.
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
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
const cellList & cells() const
virtual const faceList & faces() const =0
Return faces.
label nextLabel(const label i) const
Next vertex on face.
Definition: faceI.H:117
edgeFaceCirculator & operator++()
Step to next face. Uses no edge addressing!
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:74
const edgeFaceCirculator & cend() const
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
edgeFaceCirculator(const primitiveMesh &mesh, const label faceLabel, const bool ownerSide, const label index, const bool isBoundaryEdge)
Construct from components.
edgeFaceCirculator cbegin() const
#define forAll(list, i)
Definition: UList.H:421
errorManip< error > abort(error &err)
Definition: errorManip.H:131
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
void operator=(const edgeFaceCirculator &iter)
error FatalError
bool sameOrder(const label v0, const label v1) const
Helper: return true if normal of generated face points along.
Walks from starting face around edge.
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
Definition: UListI.H:65
bool operator==(const edgeFaceCirculator &iter) const
virtual const labelList & faceOwner() const =0
Face face-owner addresing.
bool operator!=(const edgeFaceCirculator &iter) const
virtual const labelList & faceNeighbour() const =0
Face face-neighbour addressing.
bool isInternalFace(const label faceIndex) const
Return true if given face label is internal to the mesh.
void setCanonical()
Set edge to a unique state so different ones can be compared.