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:434
label rcIndex(const label i) const
Return the reverse circular index, i.e. the previous index.
Definition: UListI.H:65
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
Walks from starting face around edge.
void operator=(const edgeFaceCirculator &iter)
const edgeFaceCirculator & end() const
Iterator set to beyond the end of the walk.
edgeFaceCirculator & operator++()
Step to next face. Uses no edge addressing!
bool sameOrder(const label v0, const label v1) const
Helper: return true if normal of generated face points along.
edgeFaceCirculator(const primitiveMesh &mesh, const label faceLabel, const bool ownerSide, const label index, const bool isBoundaryEdge)
Construct from components.
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.
bool operator!=(const edgeFaceCirculator &iter) const
bool operator==(const edgeFaceCirculator &iter) const
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
Cell-face mesh analysis engine.
Definition: primitiveMesh.H:75
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
label otherFace(const primitiveMesh &, const label celli, const label facei, const label edgeI)
Return face on cell using edgeI but not facei. Throws error.
Definition: meshTools.C:536
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
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
errorManip< error > abort(error &err)
Definition: errorManip.H:131
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
labelList f(nPoints)